/* ============================================================
   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 */
    --text-primary:   #1a1a2e;
    --text-secondary: #6b7084;
    --text-muted:     #9ca3b4;

    /* Accent */
    --accent:         #006838;
    --accent-soft:    rgba(0, 104, 56, 0.10);
    --accent-glow:    rgba(0, 104, 56, 0.16);
    --accent-gradient: linear-gradient(135deg, #006838, #0b9b54);

    /* Brouillon — violet. Volontairement distinct du vert d'une approbation : un brouillon
       n'est ni validé ni transmis, la confusion visuelle serait coûteuse. (Norme reprise
       de Chronos.) */
    --draft:      #7c3aed;
    --draft-soft: rgba(124, 58, 237, 0.10);

    /* 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, 104, 56, 0.10) 0%, rgba(0, 104, 56, 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;

    /* « Machine au travail » — délibérément NEUTRE. Le vert de marque est réservé à une seule
       chose dans le pilotage Forge : signaler qu'un HUMAIN est requis. Tout ce que les agents
       font seuls se rend en gris, pour que l'œil apprenne la convention sans lire les libellés. */
    --machine:      #8b93a5;
    --machine-soft: rgba(139, 147, 165, 0.12);

    /* Chevron des <select>. En jeton parce qu'une image de fond ne peut pas hériter
       currentColor : la seule façon d'avoir la bonne couleur dans les deux thèmes est
       d'échanger l'image elle-même. */
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7084' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}

[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;

    --text-primary:   #e6edf3;
    --text-secondary: #9aa4b1;
    --text-muted:     #6b7280;

    /* Brighten the brand accent on dark backgrounds so text/links stay legible. */
    --accent:      #1c9c5d;
    --accent-glow: rgba(0, 104, 56, 0.32);
    --accent-soft: rgba(28, 156, 93, 0.16);

    /* Violet éclairci pour rester lisible sur fond sombre. */
    --draft:      #a78bfa;
    --draft-soft: rgba(167, 139, 250, 0.16);

    --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);

    --machine:      #79839a;
    --machine-soft: rgba(121, 131, 154, 0.16);

    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa4b1' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");

    /* color-scheme: dark fait aussi dessiner à l'OS ses widgets natifs en sombre — c'est ce qui
       empêche la liste déroulante d'un <select> de s'ouvrir en blanc sur un thème sombre. */
    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;
}

.appbar {
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    gap: 16px;
    height: 56px;
    padding: 0 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-center   { flex: 1; }

.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; }

.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); }

/* ---- 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. */
@media (max-width: 640px) {
    .appbar   { padding: 0 14px; gap: 10px; }
    .app-main { padding: 18px 14px; }
}

.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;
}

/* ---- 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);
}

/* ---- <select> : le navigateur en dessine une partie, comme <input type="file"> ----

   La BOÎTE FERMÉE obéit à .input depuis toujours. Ce qui restait natif, c'est la flèche (que
   le navigateur peint lui-même) et la LISTE OUVERTE (que dessine le système d'exploitation —
   d'où le surlignage bleu de Windows au milieu d'une interface verte).

   La flèche se règle partout : appearance:none la supprime, et on remet la nôtre.
   La liste ouverte, elle, n'est stylable que depuis `appearance: base-select` (Chrome/Edge ;
   Firefox et Safari ne l'ont pas encore). D'où le @supports plus bas : amélioration
   progressive, jamais une condition de bon fonctionnement.

   ⚠️ Ne PAS remplacer <select> par un composant maison. On y perd la navigation au clavier,
   le sélecteur natif du mobile et le support des lecteurs d'écran — trois choses difficiles à
   refaire correctement, pour gagner une bordure. */
select.input {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 34px;                 /* la place de notre chevron */
    background-image: var(--select-chevron);
    background-repeat: no-repeat;
    background-position: right 11px center;
    background-size: 15px 15px;
    cursor: pointer;
}
select.input:disabled {
    cursor: not-allowed;
    opacity: 0.55;
    background-image: none;              /* désactivé : rien à dérouler, pas de chevron */
}

/* Chrome/Edge : la liste déroulante devient un élément de la page, donc enfin la nôtre.
   Partout ailleurs ce bloc est ignoré et la liste native — parfaitement fonctionnelle et
   accessible — reste en place. */
@supports (appearance: base-select) {
    select.input {
        appearance: base-select;
        /* On GARDE notre chevron en image de fond : le glyphe que le navigateur fournit dans
           ce mode est un triangle plein, qui jure avec le reste des icônes (traits fins). */
    }
    select.input::picker-icon { display: none; }

    select.input::picker(select) {
        appearance: base-select;
        margin-top: 4px;
        padding: 4px;
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        background: var(--bg-elevated);
        box-shadow: var(--shadow-md);
    }
    select.input option {
        padding: 8px 10px;
        border-radius: 6px;
        font-size: 14px;
        color: var(--text-primary);
    }
    select.input option:hover { background: var(--bg-glass-hover); }
    select.input option:checked { background: var(--accent-soft); color: var(--accent); }
    /* La coche que le navigateur ajoute devant l'option choisie : superflue, on garde la
       couleur d'accent comme seule marque. */
    select.input option::checkmark { display: none; }
}

/* Les grilles resserrent le padding des champs avec le raccourci `padding:` — plus
   spécifique, il écraserait la place réservée au chevron. On la re-réserve pour les
   <select> concernés. */
.data-table td select.input,
.entry-table tbody td select.input { padding-right: 28px; }

/* ============================================================
   Buttons
   ============================================================ */
.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  { transform: translateY(-1px); box-shadow: 0 6px 14px var(--accent-glow), 0 2px 4px rgba(0, 0, 0, 0.06); }
.btn-primary:active { 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;
    transition: var(--transition);
}
.btn-secondary:hover { border-color: var(--text-secondary); color: var(--text-primary); }

/* Bouton « brouillon » — même poids visuel que btn-secondary (il ne doit pas concurrencer
   l'action principale), mais teinté violet pour rattacher l'action au brouillon plutôt
   qu'à une validation. (Norme reprise de Chronos.) */
.btn-draft {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    padding: 8px 16px;
    background: var(--draft-soft);
    color: var(--draft);
    border: 1px solid var(--draft);
    border-radius: var(--radius-sm);
    font: 500 13px/1 'Inter', system-ui, sans-serif;
    cursor: pointer;
    transition: var(--transition);
}
.btn-draft:hover { background: var(--draft); color: #fff; }
.btn-draft:disabled { opacity: 0.45; cursor: default; background: var(--draft-soft); color: var(--draft); }

/* ============================================================
   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);
    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);
    border-color: var(--accent);
    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.tag-success { color: #22c55e; background: rgba(34, 197, 94, 0.14); }
.tag.tag-info    { color: #6b7084; background: var(--bg-tertiary); }
.tag.warn        { color: #b45309; background: rgba(245, 158, 11, 0.16); }
.tag.error       { color: #b91c1c; background: rgba(239, 68, 68, 0.14); }
/* Brouillon — violet : ni validé ni transmis, à ne pas confondre avec un statut approuvé (vert). */
.tag.tag-draft   { color: var(--draft); background: var(--draft-soft); }
[data-theme="dark"] .tag.warn  { color: #fbbf24; }
[data-theme="dark"] .tag.error { color: #f87171; }

/* ── Nuancier de teintes distinctives (norme reprise de Chronos) ────────────
   Huit teintes à attribuer par un condensé stable de la valeur (même catégorie,
   même couleur partout et à chaque démarrage). Elles sont DISTINCTIVES, pas
   sémantiques : contrairement à vert/ambre/rouge ailleurs dans l'app, la teinte
   ne dit rien de bon ou de mauvais — elle sert uniquement à repérer une
   catégorie sans lire chaque ligne.

   ⚠ AUCUN ROUGE dans ce nuancier, et ce n'est pas un choix esthétique : dans le
   reste de l'app le rouge signale une erreur (ligne bloquante, tag `error`,
   suppression). Une catégorie teintée en rouge se lit comme un élément en
   défaut. Rose et corail sont écartés pour la même raison : de loin, ils sont
   du rouge. Toute teinte ajoutée ici doit passer le même test. */
.tag.cat-color-1 { color: #7c3aed; background: rgba(124, 58, 237, 0.14); }  /* violet */
.tag.cat-color-2 { color: #2563eb; background: rgba(37, 99, 235, 0.14); }   /* bleu */
.tag.cat-color-3 { color: #0d9488; background: rgba(13, 148, 136, 0.16); }  /* sarcelle */
.tag.cat-color-4 { color: #a16207; background: rgba(161, 98, 7, 0.16); }    /* ocre */
.tag.cat-color-5 { color: #4338ca; background: rgba(67, 56, 202, 0.14); }   /* indigo */
.tag.cat-color-6 { color: #a21caf; background: rgba(162, 28, 175, 0.13); }  /* magenta */
.tag.cat-color-7 { color: #0369a1; background: rgba(3, 105, 161, 0.14); }   /* cyan */
.tag.cat-color-8 { color: #4d7c0f; background: rgba(77, 124, 15, 0.16); }   /* olive */
/* En thème sombre, seules les teintes de TEXTE sont éclaircies : les fonds translucides
   restent lisibles tels quels sur le fond sombre. */
[data-theme="dark"] .tag.cat-color-1 { color: #c4b5fd; }
[data-theme="dark"] .tag.cat-color-2 { color: #93c5fd; }
[data-theme="dark"] .tag.cat-color-3 { color: #5eead4; }
[data-theme="dark"] .tag.cat-color-4 { color: #fcd34d; }
[data-theme="dark"] .tag.cat-color-5 { color: #a5b4fc; }
[data-theme="dark"] .tag.cat-color-6 { color: #f0abfc; }
[data-theme="dark"] .tag.cat-color-7 { color: #7dd3fc; }
[data-theme="dark"] .tag.cat-color-8 { color: #bef264; }

/* ============================================================
   Cards / details
   ============================================================ */
.card {
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: 18px 20px;
}
.detail-description { font-size: 15px; line-height: 1.6; color: var(--text-primary); }

.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); }

/* ---- 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;
}
.data-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--bg-tertiary);
    text-align: center;
    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);
}
/* Valeurs centrées dans toutes les grilles (les cellules d'action restent à droite).
   (Norme reprise de Chronos.) */
.data-table tbody td {
    padding: 9px 14px;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
    text-align: center;
}
.data-table td.cell-action { text-align: right; }
.data-table thead th .th-sort { justify-content: center; }
.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;
    text-align: center;
}
.data-table .num { text-align: center; font-variant-numeric: tabular-nums; }
/* Police des nombres agrandie dans le corps et le pied des grilles (pas dans l'en-tête). */
.data-table td.num { font-size: 15px; font-weight: 600; }
/* Colonne Commentaire : largeur plafonnée + retour à la ligne, pour garder toute la grille
   visible sans défilement horizontal excessif. */
.data-table td.cell-comment {
    max-width: 380px;
    white-space: normal;
    overflow-wrap: anywhere;
}

/* Champs d'édition en ligne dans les grilles (édition directe cellule par cellule). */
.data-table td .input {
    padding: 5px 8px;
    font-size: 13px;
    color: var(--text-primary);
    width: 100%;
    min-width: 0;
}

/* Cellule en cours d'édition : toute la cellule s'illumine (liseré accent + fond doux) pour
   repérer d'un coup d'œil où l'on saisit — le liseré de la cellule fait office de contour. */
.data-table tbody td:has(.input):focus-within,
.entry-table tbody td:has(.input):focus-within {
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 2px var(--accent);
}
/* Le contour est porté par la cellule : on neutralise l'anneau propre du champ dans la grille
   pour éviter un double anneau (le champ garde son bord accent via .input:focus).
   Repli sans :has() → le champ garde simplement son bord accent, sans surbrillance de cellule. */
.data-table td .input:focus,
.entry-table td .input:focus {
    box-shadow: none;
}
/* Commentaire éditable en ligne : zone de texte qui grandit pour montrer TOUT le texte,
   avec retours à la ligne (field-sizing pour l'auto-hauteur sur navigateurs récents). */
.data-table td.cell-comment .cell-comment-input {
    min-width: 300px;
    field-sizing: content;
    min-height: 2.4em;
    max-height: 16em;
    line-height: 1.45;
    resize: vertical;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    vertical-align: top;
}
.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; }

/* hour chips inside the labour-report detail cell */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 2px 4px 2px 0;
    padding: 2px 9px;
    border-radius: var(--radius-full);
    background: var(--bg-tertiary);
    font-size: 12px;
    color: var(--text-secondary);
    white-space: nowrap;
}
.chip strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* 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 ---- */
/* Bouton « Voir détails » / « Masquer » de chaque ligne parent. */
.btn-link {
    border: none;
    background: none;
    padding: 0;
    font-weight: 500; font-size: 12px; font-family: inherit;
    color: var(--accent);
    cursor: pointer;
    white-space: nowrap;
}
.btn-link:hover { text-decoration: underline; }
/* 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; }
/* Variante pour des valeurs qui sont des PHRASES et non des champs (le règlement applicable
   d'une ville, la façon dont son zonage est organisé). En colonnes de 200 px elles se lisent
   en accordéon, et la grille prend la hauteur de la plus longue en laissant les autres vides.
   Une seule colonne : tout le reste du style — fond, séparateurs, libellé en capitales — est
   celui de .detail-grid. */
.detail-grid.wide { grid-template-columns: 1fr; }
.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); 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: 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); }
.chip-toggle {
    padding: 4px 12px;
    border-radius: var(--radius-full);
    border: 1px solid var(--border);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    font-weight: 500; font-size: 12.5px; font-family: inherit;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.chip-toggle:hover { border-color: var(--accent); color: var(--text-primary); }
.chip-toggle.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.chip-more { font-weight: 600; }
.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); }
/* Bandeau lié au brouillon (ex. « élément rappelé ») — violet, surtout pas le vert de succès :
   repasser en brouillon n'est pas une validation. */
.form-banner.draft { background: var(--draft-soft); color: var(--draft); border: 1px solid var(--draft); }
.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; }

/* « Information non disponible » : ce que la fiche ne dit pas, et ce que le calcul en a fait.
   Ambre de vigilance et non rouge d'erreur — une donnée absente n'est pas une faute, c'est une
   question à poser. Bordure pleine à gauche pour qu'elle se repère aussi à l'impression. */
.info-manquante {
    padding: 11px 14px;
    margin: 10px 0 14px;
    border-radius: var(--radius-sm);
    border-left: 4px solid var(--pt-vigilance);
    background: var(--pt-vigilance-soft);
    font-size: 13.5px;
    color: var(--text-primary);
}
.info-manquante ul { margin: 6px 0 0 18px; padding: 0; }
.info-manquante li { margin: 2px 0; }

/* ---- 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); 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; }
.row-remove {
    background: none;
    border: 0;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 14px;
    padding: 4px 6px;
    border-radius: var(--radius-sm);
}
.row-remove:hover { color: #dc2626; background: var(--bg-glass-hover); }

/* ── Feuille de temps : zone de dépôt + pastilles de statut ─────────────────── */
/* Zone de dépôt de fichier.

   Le <input type="file"> natif dessine SON propre bouton (« Choose File »), carré, gris, et
   dans la langue du navigateur — le navigateur ne laisse pas le styler. On ne le cache pas :
   on l'étale, TRANSPARENT, sur toute la zone. Le clic et le glisser-déposer marchent donc
   partout dans le cadre, le focus clavier reste réel, et ce qui s'affiche est notre bouton.
   Le cacher (display:none, ou 1×1 px) casserait le dépôt par glissement — précisément ce que
   la zone annonce à l'utilisateur. */
.dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 32px 24px;
    border: 2px dashed var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-glass);
    color: var(--text-secondary);
    text-align: center;
    cursor: pointer;
    transition: border-color 0.18s ease, background-color 0.18s ease, color 0.18s ease;
}
.dropzone:hover { border-color: var(--text-secondary); background: var(--bg-glass-hover); }

/* focus-within et non :focus : c'est l'input invisible qui reçoit le focus clavier, jamais le
   cadre. Sans ça, tabuler jusqu'à la zone ne montrerait rigoureusement rien. */
.dropzone:focus-within {
    border-color: var(--accent);
    background: var(--accent-soft);
    color: var(--accent);
    outline: none;
}

/* Cette règle DOIT rester globale : l'input est rendu par le composant <InputFile>, donc il
   n'hérite pas de l'attribut de portée du composant parent, et un sélecteur dans un
   *.razor.css ne l'atteindrait pas sans ::deep. C'est aussi ce qui garantit que toutes les
   zones de dépôt de l'app se comportent pareil — il n'y a qu'une mécanique, écrite une fois. */
.dropzone input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}
/* Pendant l'analyse d'une capture, l'input est désactivé : le curseur doit le dire, sinon la
   zone a l'air cliquable alors qu'elle ne répond plus. */
.dropzone input[type="file"]:disabled { cursor: progress; }

.dropzone-icon { color: var(--text-muted); margin-bottom: 6px; line-height: 0; }
.dropzone:hover .dropzone-icon,
.dropzone:focus-within .dropzone-icon { color: var(--accent); }
.dropzone-title { font-weight: 600; font-size: 14px; font-family: inherit; color: var(--text-primary); }
.dropzone:focus-within .dropzone-title { color: var(--accent); }
.dropzone-hint { font-size: 12.5px; color: var(--text-muted); }

.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: #15803d; }
.pill-warn { background: rgba(234, 179, 8, 0.16);  color: #a16207; }

.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); }

/* ── Menu de configuration — norme Chronos ─────────────────────────────────
   Une barre latérale GROUPÉE plutôt qu'une rangée d'onglets : les intertitres
   disent à quoi sert chaque écran, et un écran de plus n'aggrave rien. */
.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: 76px;                      /* 56 px de barre d'app collante + une respiration */
}
.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;
    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);
}

/* La variante « zone de danger » : même géométrie, couleur d'alerte. */
.config-nav-danger { color: var(--status-danger); }
.config-nav-danger:hover { color: var(--status-danger); }
.config-nav-danger.is-active { color: var(--status-danger); border-left-color: var(--status-danger); }

/* 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); }
    .config-nav-danger.is-active { border-left-color: transparent; border-bottom-color: var(--status-danger); }
}

.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); }
.config-inline { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.config-inline .input { max-width: 140px; }

/* =====================================================
   Opti — potentiel constructible d'un terrain
   ------------------------------------------------------------
   Ces composants vivent ici plutôt qu'en CSS de portée (.razor.css) parce
   qu'ils sont partagés entre la page et ses composants enfants : le CSS de
   portée Blazor ne traverse PAS la frontière d'un composant, et dupliquer
   les couleurs de gravité dans trois fichiers, c'est garantir qu'elles
   divergeront.

   RÈGLE D'ACCESSIBILITÉ tenue partout ci-dessous : la couleur ne porte
   jamais seule une information. Chaque pastille garde son mot ("Bloquant"),
   chaque icône a une forme distincte. Un daltonien perd la nuance, pas le
   sens.
   ============================================================ */

:root {
    --pt-favorable:      #0b7a3e;
    --pt-favorable-soft: rgba(11, 122, 62, 0.10);
    --pt-vigilance:      #b45309;
    --pt-vigilance-soft: rgba(180, 83, 9, 0.10);
    --pt-bloquant:       #dc2626;
    --pt-bloquant-soft:  rgba(220, 38, 38, 0.10);
}
[data-theme="dark"] {
    --pt-favorable:      #34d399;
    --pt-favorable-soft: rgba(52, 211, 153, 0.14);
    --pt-vigilance:      #fbbf24;
    --pt-vigilance-soft: rgba(251, 191, 36, 0.14);
    --pt-bloquant:       #f87171;
    --pt-bloquant-soft:  rgba(248, 113, 113, 0.14);
}

/* ---- Un point réglementaire ---- */
.pt-liste { display: flex; flex-direction: column; gap: 10px; }

.pt {
    display: flex;
    gap: 13px;
    padding: 14px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    /* La barre de gauche est le repère qu'on balaie du regard : elle donne la
       gravité de toute la liste en un coup d'œil, sans lire un mot. */
    border-left: 3px solid var(--border);
    border-radius: var(--radius-md);
}
.pt.is-favorable { border-left-color: var(--pt-favorable); }
.pt.is-vigilance { border-left-color: var(--pt-vigilance); }
.pt.is-bloquant  { border-left-color: var(--pt-bloquant); }

.pt-icone {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px;
    border-radius: 50%;
    margin-top: 1px;
}
.pt.is-favorable .pt-icone { background: var(--pt-favorable-soft); color: var(--pt-favorable); }
.pt.is-vigilance .pt-icone { background: var(--pt-vigilance-soft); color: var(--pt-vigilance); }
.pt.is-bloquant  .pt-icone { background: var(--pt-bloquant-soft);  color: var(--pt-bloquant); }

.pt-corps { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.pt-titre {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    font-weight: 600; font-size: 14.5px; color: var(--text-primary);
}
.pt-constat { font-size: 13.5px; line-height: 1.55; color: var(--text-secondary); }

/* La question à poser est le livrable : elle se détache du constat, sinon
   elle se lit comme une remarque de plus et personne ne la pose. */
.pt-verifier {
    display: flex; gap: 8px; align-items: flex-start;
    font-size: 13px; line-height: 1.5;
    padding: 8px 11px;
    background: var(--accent-soft);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
}
.pt-verifier svg { flex: 0 0 auto; margin-top: 2px; color: var(--accent); }
.pt-source { font-size: 12px; color: var(--text-muted); }

.etiq {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 1px 9px; border-radius: 999px;
    font-size: 11px; font-weight: 600; letter-spacing: .02em;
    text-transform: uppercase;
}
.etiq.is-favorable { background: var(--pt-favorable-soft); color: var(--pt-favorable); }
.etiq.is-vigilance { background: var(--pt-vigilance-soft); color: var(--pt-vigilance); }
.etiq.is-bloquant  { background: var(--pt-bloquant-soft);  color: var(--pt-bloquant); }

/* ---- Le bilan : combien de chaque gravité ---- */
.bilan { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.bilan-item {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 7px 13px; border-radius: var(--radius-sm);
    font-size: 13px; font-weight: 500;
    border: 1px solid var(--border);
}
.bilan-item .n { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.bilan-item.is-favorable { background: var(--pt-favorable-soft); color: var(--pt-favorable); border-color: transparent; }
.bilan-item.is-vigilance { background: var(--pt-vigilance-soft); color: var(--pt-vigilance); border-color: transparent; }
.bilan-item.is-bloquant  { background: var(--pt-bloquant-soft);  color: var(--pt-bloquant);  border-color: transparent; }

/* ---- La carte ---- */
.carte { margin: 0 0 16px; }
.carte-cadre {
    display: block; width: 100%; height: 320px;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-secondary);
}
.carte-legende {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
    margin-top: 7px; font-size: 12.5px; color: var(--text-muted);
}
.carte-google { margin-left: auto; text-decoration: none; padding: 6px 12px; font-size: 12.5px; }
.carte-absente {
    display: flex; align-items: center; gap: 11px;
    padding: 22px; margin-bottom: 16px;
    background: var(--bg-secondary);
    border: 1px dashed var(--border);
    border-radius: var(--radius-md);
    font-size: 13.5px; color: var(--text-muted);
}
.carte-absente-icone { color: var(--text-muted); line-height: 0; }

/* ---- La fiche du terrain (saisie) ---- */
.fiche-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 12px;
}
.fiche-grille .form-field.large { grid-column: 1 / -1; }
.fiche-soustitre {
    grid-column: 1 / -1;
    display: flex; align-items: center; gap: 10px;
    margin-top: 6px;
    font-weight: 600; font-size: 12px; letter-spacing: .06em;
    text-transform: uppercase; color: var(--text-muted);
}
.fiche-soustitre::after {
    content: ""; flex: 1; height: 1px; background: var(--border-subtle);
}

/* Complétude de la fiche : une barre, pas un anneau — elle se lit à la même
   vitesse et reste nette à toutes les tailles d'écran. */
.jauge { display: flex; align-items: center; gap: 11px; margin-top: 14px; }
.jauge-piste {
    flex: 1; height: 7px; border-radius: 999px;
    background: var(--border-subtle); overflow: hidden;
}
.jauge-remplie { height: 100%; border-radius: 999px; background: var(--accent-gradient); }
.jauge-txt { font-size: 12.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* ---- Tuile KPI mise en avant : le chiffre qui commande ---- */
.kpi-card.is-vedette { border-color: var(--accent); background: var(--accent-soft); }
.kpi-card.is-vedette .kpi-value { color: var(--accent); }
.kpi-note {
    font-size: 11.5px; color: var(--text-muted); line-height: 1.45;
    margin-top: 2px;
}

/* ---- Bandeau « ceci est un exemple » ---- */
.exemple-bandeau {
    display: flex; align-items: flex-start; gap: 11px;
    padding: 11px 14px; margin-bottom: 14px;
    background: var(--pt-vigilance-soft);
    border-left: 3px solid var(--pt-vigilance);
    border-radius: var(--radius-sm);
    font-size: 13px; line-height: 1.5; color: var(--text-primary);
}
.exemple-bandeau svg { flex: 0 0 auto; margin-top: 2px; color: var(--pt-vigilance); }

@media (max-width: 640px) {
    .carte-cadre { height: 240px; }
    .pt { padding: 12px 13px; gap: 11px; }
}

/* ---- Intégration dans le cadre bâti (volume conforme) ---- */
.volu-reglages {
    display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px; margin-bottom: 14px; align-items: end;
}
.volu-curseur { width: 100%; accent-color: var(--accent); }
.volu-alerte {
    margin: 12px 0; padding: 10px 14px; border-radius: var(--radius-md, 8px);
    border-left: 3px solid var(--pt-vigilance); background: var(--pt-vigilance-soft);
    color: var(--text-primary); font-size: 13.5px;
}
.volu-3d { margin: 0 0 12px; }
.volu-3d-cadre {
    position: relative; width: 100%; height: 460px; border-radius: var(--radius-md, 8px);
    overflow: hidden; border: 1px solid var(--border); background: var(--bg-secondary);
}
.volu-3d-cadre gmp-map-3d { width: 100%; height: 100%; display: block; }
.vue3d-attente, .vue3d-erreur {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 20px;
    color: var(--text-muted); font-size: 13.5px; text-align: center;
}
.volu-svg { width: 100%; max-height: 380px; display: block; }
.volu-lot { fill: var(--bg-secondary); stroke: var(--border); stroke-width: 1.5; }
.volu-volume { stroke: var(--accent); stroke-width: 1.5; stroke-linejoin: round; }
.volu-volume.volu-dessus { fill: var(--accent-soft); }
.volu-volume.volu-facade { fill: var(--accent); fill-opacity: .55; }
.volu-volume.volu-cote   { fill: var(--accent); fill-opacity: .35; }
.volu-voisin { fill: var(--text-muted); fill-opacity: .12; stroke: var(--text-muted); stroke-width: 1.2; stroke-dasharray: 4 3; }
.volu-etage { fill: none; stroke: var(--bg-primary, #fff); stroke-opacity: .7; stroke-width: 1; }
.volu-3d .env-puce { display: inline-block; vertical-align: -1px; margin: 0 4px 0 10px; }
.volu-puce-volume { background: var(--accent); }
.volu-puce-lot { background: transparent; border: 2px solid #facc15; }
.volu-puce-voisin { background: transparent; border: 1.5px dashed var(--text-muted); }
.volu-cote-facade { fill: #fff; font-size: 12px; font-weight: 600; font-family: inherit; }
.volu-hypotheses { font-size: 12.5px; margin: 6px 0 0; }
.patrimoine-encadre { margin: 0 0 16px; }
.patrimoine-secteur + .patrimoine-secteur { margin-top: 10px; }
@media (max-width: 760px) {
    .volu-reglages { grid-template-columns: 1fr; }
    .volu-3d-cadre { height: 320px; }
}

/* ---- L'enveloppe constructible (schéma SVG) ---- */
.enveloppe { margin: 0 0 16px; }
.enveloppe-svg {
    display: block;
    width: 100%;
    max-width: 460px;
    height: auto;
    margin: 0 auto;
    overflow: visible;   /* les cotes et « rue » sortent du lot */
}
.env-lot { stroke: var(--border); stroke-width: 1.5; }
.env-hachure-trait { stroke: var(--border-subtle); stroke-width: 1.5; }
.env-batir { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; }
.env-cote { fill: var(--text-muted); font-size: 11px; font-family: inherit; }
.env-etiq {
    fill: var(--accent); font-size: 12.5px; font-weight: 600; font-family: inherit;
}
.env-etiq-sub { fill: var(--text-secondary); font-size: 11.5px; font-family: inherit; }
.env-cote-trait { stroke: var(--text-muted); stroke-width: 1; }
.env-cote-marge { fill: var(--text-secondary); font-size: 10.5px; font-family: inherit; }
.env-rue { fill: var(--text-secondary); font-size: 11px; font-weight: 500; font-family: inherit; }

.enveloppe-legende {
    display: flex; flex-wrap: wrap; gap: 8px 18px;
    margin-top: 10px; font-size: 12.5px; color: var(--text-secondary);
}
.enveloppe-legende > span { display: inline-flex; align-items: center; gap: 7px; }
.env-puce { width: 12px; height: 12px; border-radius: 3px; flex: 0 0 auto; }
.env-puce-lot { background: var(--bg-secondary); border: 1.5px solid var(--border); }
.env-puce-batir { background: var(--accent-soft); border: 1.5px solid var(--accent); }
.env-puce-cote { height: 0; border-top: 1px solid var(--text-muted); border-radius: 0; }

/* ---- Le stationnement implanté et le plan d'étage (schémas SVG) ---- */
.stat-svg { max-width: 520px; }
.stat-initiale { fill: none; stroke: var(--text-muted); stroke-width: 1.2; stroke-dasharray: 5 4; }
.stat-asphalte { fill: var(--bg-tertiary); stroke: var(--text-muted); stroke-width: 0.6; }
.stat-case { fill: var(--bg-secondary); stroke: var(--text-secondary); stroke-width: 1; }
.stat-fleche { stroke: var(--text-secondary); stroke-width: 1.4; }
.stat-fleche-pointe { fill: var(--text-secondary); }
.stat-entree { stroke: var(--status-warning); stroke-width: 5; stroke-linecap: butt; }
.stat-entree-txt { fill: var(--status-warning); font-size: 10.5px; font-weight: 600; font-family: inherit; }
.stat-allee-txt { fill: var(--text-secondary); font-size: 9.5px; font-family: inherit; }
.stat-puce-initiale { background: transparent; border: 1.2px dashed var(--text-muted); }
.stat-puce-asphalte { background: var(--bg-tertiary); border: 1px solid var(--text-muted); }
.stat-puce-case { background: var(--bg-secondary); border: 1px solid var(--text-secondary); }
.stat-puce-entree { background: var(--status-warning); height: 5px; border-radius: 0; }

.plan-mur { fill: none; stroke: var(--text-primary); stroke-width: 2.5; }
.plan-suite { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1; }
.plan-corridor { fill: var(--bg-tertiary); stroke: var(--text-muted); stroke-width: 0.8; }
.plan-noyau { fill: var(--machine-soft); stroke: var(--machine); stroke-width: 1; }
.plan-escalier { fill: var(--draft-soft); stroke: var(--draft); stroke-width: 1.2; }
.plan-commun { fill: var(--bg-glass-hover); stroke: var(--text-secondary); stroke-width: 1; stroke-dasharray: 3 2; }
.plan-marche { stroke: var(--draft); stroke-width: 0.6; opacity: 0.6; }
.plan-porte { fill: var(--bg-secondary); stroke: var(--text-primary); stroke-width: 1.2; }
.plan-porte-ko { fill: var(--status-danger); stroke: var(--status-danger); }
.plan-lien { stroke: var(--accent); stroke-width: 1; stroke-dasharray: 2 2; }
.plan-parcours { stroke: var(--accent); stroke-width: 1.6; }
.plan-parcours-pointe { fill: var(--accent); }
.plan-parcours-ko { stroke: var(--status-danger); stroke-width: 1.6; }
.plan-parcours-ko-pointe { fill: var(--status-danger); }
.plan-etiq { fill: var(--text-primary); font-size: 10px; font-weight: 600; font-family: inherit; }
.plan-etiq-sub { fill: var(--text-secondary); font-size: 9px; font-family: inherit; }
.plan-sortie { fill: var(--draft); font-size: 9.5px; font-weight: 700; font-family: inherit; }
.plan-puce-suite { background: var(--accent-soft); border: 1px solid var(--accent); }
.plan-puce-escalier { background: var(--draft-soft); border: 1px solid var(--draft); }
.plan-puce-noyau { background: var(--machine-soft); border: 1px solid var(--machine); }
.plan-puce-parcours { height: 0; border-top: 2px solid var(--accent); border-radius: 0; }
.plan-puce-ko { background: var(--status-danger); border-radius: 50%; }

.vue-bascule { display: inline-flex; gap: 2px; margin: 4px 0 10px; border-bottom: 1px solid var(--border); }
.vue-bascule > button {
    background: none; border: none; border-bottom: 2px solid transparent;
    padding: 7px 13px; font: inherit; font-size: 13.5px; font-weight: 500;
    color: var(--text-muted); cursor: pointer;
}
.vue-bascule > button:hover { color: var(--text-primary); }
.vue-bascule > button.is-active { color: var(--accent); border-bottom-color: var(--accent); }

.verrou-terrain { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; color: var(--text-secondary); }

/* ---- La coupe du volume (deux coupes SVG côte à côte) ---- */
.coupes {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 12px; margin: 0 0 12px;
}
.coupe {
    margin: 0; padding: 12px;
    background: var(--bg-secondary);
    border: 1.5px solid var(--border-subtle); border-radius: 10px;
}
.coupe.is-recommandee { border-color: var(--pt-favorable); }
.coupe-titre {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px;
    margin-bottom: 8px; font-size: 13px; font-weight: 600; color: var(--text-primary);
}
.coupe-svg { display: block; width: 100%; height: auto; overflow: visible; }
.coupe-terre { stroke: none; }
.coupe-sol { stroke: var(--text-secondary); stroke-width: 2; }
.coupe-soussol { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; stroke-dasharray: 5 3; }
.coupe-toit { fill: var(--border); stroke: var(--border); }
.coupe-limite { stroke: var(--pt-vigilance); stroke-width: 1.5; stroke-dasharray: 6 4; }
.coupe-limite-code { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 2 3; }
.coupe-etiq { fill: var(--accent); font-size: 10.5px; font-weight: 600; font-family: inherit; }
.coupe-cote-rdc { fill: var(--accent); font-size: 11px; font-weight: 600; font-family: inherit; }
.coupe-chiffres {
    display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px;
    margin: 10px 0 0; font-size: 12.5px;
}
.coupe-chiffres dt { color: var(--text-muted); font-size: 11.5px; }
.coupe-chiffres dd { margin: 0; color: var(--text-primary); font-weight: 600; }
.coupe-chiffres .coupe-mordante { grid-column: 1 / -1; }
.coupe-chiffres .coupe-mordante dd { font-weight: 400; color: var(--text-secondary); }

/* Le relevé cadastral et l'orientation d'un lot de coin. */
.releve-cadastre { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 0 0 12px; }
.orientation-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin: 10px 0; }
.orientation-option { padding: 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-secondary); }
.orientation-option.is-recommandee { border-color: var(--accent); background: var(--accent-soft); }
.orientation-option h4 { margin: 0 0 6px; font-size: 14px; }
.orientation-option ul { margin: 0; padding-left: 18px; font-size: 13px; color: var(--text-secondary); }

/* ---- Le tableau des scénarios ---- */
.scenarios { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; }
.scenario {
    display: flex; flex-direction: column; gap: 9px;
    padding: 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-top: 3px solid var(--border);
    border-radius: var(--radius-md);
}
.scenario.is-favorable { border-top-color: var(--pt-favorable); }
.scenario.is-vigilance { border-top-color: var(--pt-vigilance); }
.scenario.is-bloquant  { border-top-color: var(--pt-bloquant); }

.scenario-nom { font-weight: 700; font-size: 16px; color: var(--text-primary); }
.scenario-hypothese { font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); }
.scenario-chiffre {
    font-size: 28px; font-weight: 700; letter-spacing: -0.02em;
    color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.scenario-chiffre-sub { font-size: 12px; color: var(--text-muted); margin-top: -6px; }
.scenario-lignes { display: flex; flex-direction: column; gap: 5px; margin-top: 2px; }
.scenario-ligne {
    display: flex; justify-content: space-between; gap: 10px;
    font-size: 12.5px; color: var(--text-secondary);
    padding-bottom: 4px; border-bottom: 1px solid var(--border-subtle);
}
.scenario-ligne b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.scenario-ecarts { display: flex; flex-direction: column; gap: 4px; }
.scenario-ecart {
    font-size: 11.5px; color: var(--text-muted);
    padding-left: 13px; position: relative;
}
.scenario-ecart::before {
    content: "→"; position: absolute; left: 0; color: var(--text-muted);
}
.scenario-delai { font-size: 11.5px; color: var(--text-muted); }

/* ---- Le pro forma ---- */
.proforma-ligne {
    display: flex; justify-content: space-between; gap: 12px;
    padding: 8px 0; font-size: 13.5px;
    border-bottom: 1px solid var(--border-subtle);
}
.proforma-ligne b { font-variant-numeric: tabular-nums; }
.proforma-ligne.is-total {
    border-bottom: none; border-top: 2px solid var(--border);
    margin-top: 4px; padding-top: 11px;
    font-size: 15px; font-weight: 600;
}
.proforma-verdict {
    display: flex; align-items: center; gap: 10px;
    margin-top: 12px; padding: 12px 15px;
    border-radius: var(--radius-sm); font-size: 13.5px; font-weight: 500;
}
.proforma-verdict.is-favorable { background: var(--pt-favorable-soft); color: var(--pt-favorable); }
.proforma-verdict.is-bloquant  { background: var(--pt-bloquant-soft);  color: var(--pt-bloquant); }
.proforma-verdict.is-vigilance { background: var(--pt-vigilance-soft); color: var(--pt-vigilance); }

/* Un scénario qui ne rapporte rien de plus l'explique — c'est un constat utile,
   pas un trou d'affichage. Teinte « vigilance » : ça mérite d'être lu. */
.scenario-remarque {
    font-size: 12px; line-height: 1.5;
    padding: 8px 10px;
    background: var(--pt-vigilance-soft);
    color: var(--pt-vigilance);
    border-radius: var(--radius-sm);
}

/* ---- La couverture d'une ville ----
   Un bandeau discret, pas une alerte : ne pas couvrir une ville n'est pas une panne,
   c'est un état de fait que l'utilisateur doit connaître avant de saisir. */
.profil-ville {
    display: flex; flex-direction: column; gap: 6px;
    padding: 12px 14px; margin-bottom: 12px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--border);
    border-radius: var(--radius-md);
}
.profil-ville.is-favorable { border-left-color: var(--pt-favorable); }
.profil-ville.is-vigilance { border-left-color: var(--pt-vigilance); }
.profil-ville.is-bloquant { border-left-color: var(--pt-bloquant); }
.contraintes-encadre { margin-top: 12px; }
.contraintes-detail { margin-top: 8px; font-size: 12.5px; }
.contraintes-detail summary { cursor: pointer; color: var(--text-muted); }
.contraintes-detail ul { margin: 6px 0 0; padding-left: 4px; list-style: none; }
.contraintes-detail li { margin: 2px 0; }
.profil-ville-titre {
    display: flex; align-items: center; gap: 8px;
    font-size: 14px; font-weight: 600; color: var(--text-primary);
}
.profil-ville-resume { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--text-secondary); }
.profil-ville-manque {
    margin: 2px 0 0; padding-left: 18px;
    font-size: 12px; line-height: 1.55; color: var(--text-muted);
}

/* ---- Le plaidoyer d'un scénario ----
   Ce qui plaide pour, ce qu'on va nous opposer. Deux marques nettement différentes
   (« + » vert, « ! » ambre) plutôt que deux teintes du même bloc : la couleur seule
   perdrait un daltonien, et c'est précisément la colonne qu'on lit en diagonale. */
.scenario-code {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; margin-right: 7px;
    border-radius: 50%; background: var(--text-primary); color: var(--surface);
    font-size: 12px; font-weight: 700; vertical-align: middle;
}
.scenario-plaidoyer {
    display: flex; flex-direction: column; gap: 6px;
    padding-top: 9px; border-top: 1px solid var(--border-subtle);
}
.scenario-reception {
    font-size: 11.5px; font-weight: 600; color: var(--text-secondary);
    text-transform: uppercase; letter-spacing: 0.04em;
}
.plaide {
    font-size: 11.5px; line-height: 1.5;
    padding-left: 15px; position: relative;
}
.plaide::before { position: absolute; left: 0; font-weight: 700; }
.plaide-pour { color: var(--text-secondary); }
.plaide-pour::before { content: "+"; color: var(--pt-favorable); }
.plaide-contre { color: var(--text-secondary); }
.plaide-contre::before { content: "!"; color: var(--pt-vigilance); }

/* ---- Le seuil du code de construction ----
   Un encadré, pas une ligne de plus dans la liste : c'est une bascule de régime, et
   elle se voit de loin ou elle ne sert à rien. */
.cadre-cnb {
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--surface-subtle, transparent);
}
.cadre-cnb.is-favorable { border-left-color: var(--pt-favorable); }
.cadre-cnb.is-vigilance { border-left-color: var(--pt-vigilance); }
.cadre-cnb-entete { display: flex; flex-direction: column; gap: 3px; }
.cadre-cnb-partie {
    font-size: 15px; font-weight: 700; color: var(--text-primary);
}
.cadre-cnb-motif { font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); }
.cadre-cnb-avis {
    margin: 9px 0 2px; font-size: 11.5px; line-height: 1.5;
    color: var(--text-muted); font-style: italic;
}

/* ---- Mix de logements ---- */
.mix { display: flex; flex-direction: column; gap: 8px; }
.mix-entete, .mix-ligne {
    display: grid;
    grid-template-columns: 1.1fr 0.8fr 1.2fr 0.7fr;
    gap: 10px; align-items: center;
}
.mix-entete {
    font-size: 11px; font-weight: 500; letter-spacing: .05em;
    text-transform: uppercase; color: var(--text-muted);
}
.mix-resultat {
    text-align: right; font-variant-numeric: tabular-nums;
    font-weight: 600; color: var(--text-primary);
}
.mix-pied {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    margin-top: 4px; font-size: 12.5px;
}
.mix-total { margin-left: auto; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.mix-total.is-vigilance { color: var(--pt-vigilance); font-weight: 600; }

/* ---- Zone réglementaire : la grille municipale branchée ---- */
.zone-branchee {
    display: flex; align-items: flex-start; gap: 11px;
    padding: 11px 14px; margin-bottom: 14px;
    background: var(--accent-soft);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    font-size: 13px; line-height: 1.5;
}
.zone-branchee svg { flex: 0 0 auto; margin-top: 2px; color: var(--accent); }
.role-evaluation { margin-bottom: 12px; }
.role-faits { margin: 6px 0 4px; padding-left: 18px; }
.role-faits li { margin: 2px 0; }
.zone-resultats { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 8px; }
.zone-puce {
    padding: 4px 11px; border-radius: 999px;
    border: 1px solid var(--border); background: var(--bg-secondary);
    font-size: 12.5px; font-variant-numeric: tabular-nums; cursor: pointer;
}
.zone-puce:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 640px) {
    .mix-entete { display: none; }
    .mix-ligne { grid-template-columns: 1fr 1fr; }
}

/* ---- Valeurs sourcées : lues, pas saisies ----
   Une valeur venue du rôle ou de la grille s'affiche comme un relevé, avec sa source,
   et non dans un champ modifiable qui la ferait passer pour une hypothèse. */
.champ-libelle { font-weight: 500; font-size: 12px; color: var(--text-secondary); }
.valeur-sourcee {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    min-height: 36px; padding: 6px 10px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--pt-favorable);
    border-radius: var(--radius-sm);
}
.valeur-sourcee-nombre { font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.source-puce {
    display: inline-flex; align-items: center; gap: 3px; flex: 0 0 auto;
    padding: 1px 7px; border-radius: 999px;
    background: var(--pt-favorable-soft); color: var(--pt-favorable);
    font-size: 11px; font-weight: 600; letter-spacing: .02em; white-space: nowrap;
}
.valeur-sourcee-origine { font-size: 11.5px; line-height: 1.4; color: var(--text-muted); }
.valeur-sourcee-origine .btn-link { font-size: 11.5px; margin-left: 4px; }
.valeur-sourcee-origine.is-corrigee { color: var(--pt-vigilance); }
/* ---- Sources des données ----
   Une couleur par nature, la même dans le bilan, la pastille et le filet de gauche :
   vert fait foi, ambre se confirme, bleu a été saisi, gris vient d'un référentiel. */
:root { --pt-info: #2563eb; --pt-info-soft: rgba(37, 99, 235, 0.10); }
[data-theme="dark"] { --pt-info: #60a5fa; --pt-info-soft: rgba(96, 165, 250, 0.14); }

.nature-externe    { --nature: var(--pt-favorable); --nature-soft: var(--pt-favorable-soft); }
.nature-a-confirmer { --nature: var(--pt-vigilance); --nature-soft: var(--pt-vigilance-soft); }
.nature-saisie     { --nature: var(--pt-info);      --nature-soft: var(--pt-info-soft); }
.nature-embarquee  { --nature: var(--text-secondary); --nature-soft: var(--bg-tertiary); }

.sources-bilan { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 16px; }
.sources-bilan .nature-pastille { padding: 4px 11px; font-size: 12.5px; }

.nature-pastille {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 2px 9px; border-radius: 999px;
    background: var(--nature-soft); color: var(--nature);
    font-size: 11.5px; font-weight: 500; line-height: 1.5; white-space: nowrap;
}
.nature-pastille strong { font-weight: 700; font-variant-numeric: tabular-nums; }
.nature-point { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }

.sources-liste {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr));
    gap: 10px;
}
.source-item {
    display: flex; gap: 12px;
    padding: 13px 15px;
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    box-shadow: inset 3px 0 0 var(--nature);
    break-inside: avoid;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.source-item:hover { border-color: color-mix(in srgb, var(--nature) 40%, var(--border)); }
.source-icone {
    flex: 0 0 auto; display: grid; place-items: center;
    width: 32px; height: 32px; border-radius: 9px;
    background: var(--nature-soft); color: var(--nature);
}
.source-corps { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.source-entete { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.source-titre { font-weight: 600; font-size: 14px; color: var(--text-primary); }
.source-nom { font-size: 13px; line-height: 1.45; color: var(--text-secondary); overflow-wrap: anywhere; }
.source-note { font-size: 12px; line-height: 1.4; color: var(--text-muted); }
.source-fourni { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 5px; }
.source-fourni li {
    padding: 2px 8px; border-radius: 6px;
    background: var(--bg-tertiary); color: var(--text-secondary);
    font-size: 11.5px; line-height: 1.5;
}

/* ---- La maquette 3D du voisinage (OpenStreetMap, rendu canvas) ---- */
.volu-maquette { cursor: grab; }
.volu-maquette:active { cursor: grabbing; }
/* pan-y : au doigt, le geste vertical fait toujours défiler la page ; l'horizontal tourne. */
.maquette-canvas { display: block; width: 100%; height: 100%; touch-action: pan-y; }
.maquette-commandes {
    position: absolute; left: 10px; top: 10px; display: flex; flex-direction: column; gap: 4px;
}
.maquette-bouton {
    width: 30px; height: 30px; border-radius: var(--radius-sm);
    border: 1px solid var(--border); background: var(--bg-elevated); color: var(--text-primary);
    font-size: 15px; line-height: 1; cursor: pointer; box-shadow: var(--shadow-sm);
}
.maquette-bouton:hover { background: var(--bg-tertiary); }
.volu-puce-mitoyen { background: #e6c480; }
.volu-puce-osm { background: #c4c9d2; }
.volu-source { margin: 6px 0 0; }
@media print { .maquette-commandes { display: none; } }
.volu-puce-ecart { background: transparent; border: 2px solid #ef4444; }
.volu-lidar-ok { color: var(--status-success); }
.volu-lidar-ecart { color: var(--status-danger); font-weight: 600; }
.volu-puce-confirmer { background: transparent; border: 2px solid #f59e0b; }
.volu-lidar-confirmer { color: var(--status-warning); font-weight: 600; }
=======
/* ═══════════════════════════════════════════════════════════════════════════
   USAGERS & ACCÈS — liste des usagers, fiche dans un tiroir (STYLE_GUIDE §5.23),
   confirmation (§5.22), mot de passe révélé une fois, rôles par zone, matrice.
   Le même bloc dans toutes les applications du kit : seuls les jetons changent.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Libellés et textes discrets — bornés aux écrans d'accès, pour ne rien changer ailleurs. */
.acces-ecran .field-label {
    display: block;
    font-size: 12px;
    font-weight: 500;
    color: var(--text-secondary);
    margin-bottom: 6px;
}
.acces-ecran .text-muted { color: var(--text-muted); font-size: 12.5px; }
.acces-ecran .champ + .champ { margin-top: 12px; }
.acces-ecran .actions-ligne { display: flex; flex-wrap: wrap; gap: 6px; }

/* Boutons : la petite taille des lignes de tableau, et le rouge des gestes destructifs. */
.btn-sm { padding: 6px 12px; font-size: 12.5px; }
.btn-primary.btn-danger { background: var(--status-danger); }
.btn-primary.btn-danger:hover { box-shadow: 0 6px 14px rgba(239, 68, 68, 0.3), 0 2px 4px rgba(0, 0, 0, 0.06); }
.btn-secondary.btn-danger { color: var(--status-danger); }
.btn-secondary.btn-danger:hover { border-color: var(--status-danger); color: var(--status-danger); }

/* Pastilles d'état d'un compte (EtatCompte). */
.etat-compte { display: inline-flex; flex-wrap: wrap; gap: 4px; }

/* Modale de confirmation — STYLE_GUIDE §5.22. */
.modal-backdrop {
    position: fixed; inset: 0;
    background: rgba(15, 23, 42, 0.45);
    display: flex;
    align-items: center; justify-content: center;
    z-index: 1000;
    animation: modal-backdrop-in 0.18s ease-out;
}
@keyframes modal-backdrop-in { from { opacity: 0; } to { opacity: 1; } }
.modal-card {
    width: 460px;
    max-width: calc(100vw - 32px);
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 22px 24px 18px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.22), 0 4px 12px rgba(0, 0, 0, 0.08);
    animation: modal-card-in 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}
.modal-card:focus { outline: none; }
@keyframes modal-card-in {
    from { opacity: 0; transform: scale(0.96) translateY(10px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}
.modal-title { margin: 0 0 10px; font-weight: 600; font-size: 17px; line-height: 1.3; font-family: inherit; letter-spacing: -0.01em; color: var(--text-primary); }
.modal-body  { margin: 0 0 22px; font-size: 14px; line-height: 1.55; color: var(--text-secondary); }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* Tiroir latéral — STYLE_GUIDE §5.23. Pleine largeur sur un téléphone. */
.tiroir-fond {
    position: fixed; inset: 0;
    background: rgba(20, 22, 30, 0.45);
    z-index: 900;
    animation: modal-backdrop-in 0.18s ease-out;
}
.tiroir {
    position: fixed; top: 0; right: 0; bottom: 0;
    width: min(560px, 100vw);
    display: flex; flex-direction: column;
    background: var(--bg-elevated);
    color: var(--text-primary);
    box-shadow: var(--shadow-lg), -12px 0 40px rgba(0, 0, 0, 0.12);
    z-index: 910;
    animation: tiroir-entree 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}
.tiroir:focus { outline: none; }
@keyframes tiroir-entree { from { transform: translateX(100%); } to { transform: translateX(0); } }
.tiroir-tete {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
    padding: 20px 24px 14px;
    border-bottom: 1px solid var(--border-subtle);
}
.tiroir-titre { margin: 0; font-weight: 600; font-size: 17px; letter-spacing: -0.01em; color: var(--text-primary); }
.tiroir-sous-titre { margin: 4px 0 0; font-size: 13px; color: var(--text-muted); }
.tiroir-fermer {
    border: 0; background: none; cursor: pointer;
    color: var(--text-muted); font-size: 16px; line-height: 1;
    padding: 6px; border-radius: var(--radius-sm);
}
.tiroir-fermer:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.tiroir-corps { flex: 1; overflow-y: auto; padding: 18px 24px; }
.tiroir-pied {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 14px 24px;
    border-top: 1px solid var(--border-subtle);
}
@media (prefers-reduced-motion: reduce) {
    .tiroir, .tiroir-fond, .modal-card, .modal-backdrop { animation: none; }
}

/* Choix de rôles dans le tiroir : une case, le nom, et ce que le rôle ouvre. */
.choix-role {
    display: flex; gap: 10px; align-items: flex-start;
    padding: 10px 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.choix-role + .choix-role { margin-top: 6px; }
.choix-role:hover { border-color: var(--border); }
.choix-role input { margin-top: 3px; accent-color: var(--accent); }
.choix-role-nom { font-weight: 500; font-size: 13.5px; color: var(--text-primary); }
.choix-role-quoi {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden;
    font-size: 12.5px; color: var(--text-muted);
}

/* Le mot de passe généré, montré une fois (RevelationSecret). */
.revelation-secret { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; scroll-margin-top: 80px; }
.revelation-secret:focus { outline: 2px solid var(--accent); outline-offset: 2px; }
.revelation-tete { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.revelation-tete .text-muted { color: var(--text-muted); font-size: 12px; }
.revelation-valeur { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.revelation-code {
    display: inline-block;
    padding: 6px 10px;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 15px;
    color: var(--text-primary);
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    user-select: all;
    overflow-wrap: anywhere;
}
.revelation-consigne { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); }

/* Les onglets de la configuration sont des LIENS (une adresse par onglet) : même allure que
   les anciens boutons. */
a.config-nav-item { display: block; text-decoration: none; }

/* DataTable : une ligne qui ouvre quelque chose (OnRowClick). */
.data-table tbody tr.ligne-cliquable { cursor: pointer; }
.data-table tbody tr.ligne-selectionnee td { background: var(--accent-soft); }

/* Usagers : l'entête de la liste (titre + « Nouvel usager »), les filtres rapides. */
.entete-liste { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.entete-liste .section-titre { margin-bottom: 0; }
.filtres-acces { display: flex; flex-wrap: wrap; gap: 6px; margin: 14px 0 12px; }
.lien-compte { font-size: 13.5px; font-weight: 600; font-family: 'JetBrains Mono', ui-monospace, monospace; }
.lien-registre { display: block; margin-top: 4px; font-size: 12px; color: var(--accent); }

/* La fiche d'un usager, dans le tiroir : quatre sections dans le même ordre partout. */
.fiche-section + .fiche-section { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border-subtle); }
.fiche-titre {
    margin: 0 0 10px;
    font-size: 12px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
    color: var(--text-muted);
}
.fiche-dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0 0 12px; font-size: 13.5px; }
.fiche-dl dt { color: var(--text-muted); }
.fiche-dl dd { margin: 0; color: var(--text-primary); overflow-wrap: anywhere; }
.fiche-dl code { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12.5px; }
.fiche-etat { margin-bottom: 10px; }
.fiche-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.fiche-actions a.btn-secondary { text-decoration: none; }
.champ-ligne { display: flex; gap: 8px; align-items: center; }
.champ-ligne .input { flex: 1; min-width: 0; }
.fiche-historique { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; font-size: 12.5px; color: var(--text-secondary); }
.fiche-historique li { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.fiche-historique .mono { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11.5px; color: var(--text-muted); }
@media (max-width: 480px) {
    .fiche-dl { grid-template-columns: 1fr; gap: 2px; }
    .fiche-dl dd { margin-bottom: 8px; }
}

/* Création : les sortes de compte en cartes cliquables. */
.choix-sorte { display: grid; gap: 8px; }
.choix-sorte-carte {
    display: flex; flex-direction: column; gap: 4px; text-align: left;
    padding: 12px 14px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font: inherit; font-size: 13.5px; color: var(--text-primary);
    cursor: pointer;
    transition: border-color 0.12s ease, background-color 0.12s ease;
}
.choix-sorte-carte:hover, .choix-sorte-carte:focus-visible { border-color: var(--accent); background: var(--accent-soft); }
.choix-sorte-carte .text-muted { font-size: 12.5px; }

/* La liste des usagers garde le tableau de l'app (centré, sans retour à la ligne), sauf deux
   colonnes : l'identifiant, qu'on lit à gauche, et dont la description tient en deux lignes ;
   les rôles, qui passent à la ligne plutôt que de pousser l'état hors de l'écran. */
.data-table td.cellule-compte { text-align: left; white-space: normal; min-width: 180px; max-width: 320px; }
.data-table td.cellule-compte .description-compte {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden;
    font-size: 12.5px;
}
.data-table td.cellule-roles { white-space: normal; max-width: 240px; }
.data-table td.cellule-texte { text-align: left; white-space: normal; min-width: 280px; }

/* Les droits d'un rôle, rangés par zone (ListeDroitsParZone). */
.droits-par-zone { display: grid; gap: 14px; }
.droit-tout { display: flex; gap: 10px; align-items: flex-start; padding: 10px 12px; border: 1px solid var(--status-danger); border-radius: var(--radius-sm); cursor: pointer; }
.zone-droits { border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); padding: 8px 12px 10px; margin: 0; }
.zone-droits legend { padding: 0 6px; font-size: 12px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }
.famille-droits + .famille-droits { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--border-subtle); }
.famille-entete { display: flex; gap: 8px; align-items: center; font-size: 12.5px; color: var(--text-secondary); margin-bottom: 4px; cursor: pointer; }
.droit { display: flex; gap: 10px; align-items: flex-start; padding: 5px 0 5px 12px; cursor: pointer; font-size: 13px; color: var(--text-primary); }
.droit code, .famille-entete code, .droit-tout code { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px; }
.droit .tag { margin-left: 4px; }
.droit .text-muted { font-size: 12px; }
.droit-herite { opacity: 0.75; cursor: default; }
.droit input, .famille-entete input, .droit-tout input { margin-top: 3px; accent-color: var(--accent); }

/* ── Fil de retour des sous-pages de « Mon compte » (/compte/mot-de-passe, /compte/double-authentification) ── */
.fil-retour {
    display: inline-block;
    margin-bottom: 6px;
    font-size: 0.8125rem;
    color: var(--accent);
    text-decoration: none;
}
.fil-retour:hover { text-decoration: underline; }

/* La matrice « Accès par rôle » (Configuration → Qui a accès à quoi) : une colonne par rôle.
   Au-delà de la largeur de la feuille, elle défile DANS son cadre au lieu d'élargir la page. */
.acces-defilement { overflow-x: auto; }

/* Usagers : le titre de la liste et « + Nouvel usager » sur une ligne. */
.usagers-tete { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.lien-compte { padding: 0; border: none; background: none; cursor: pointer; text-align: left; }
.lien-compte code { color: var(--accent); }
