/* Emplacement : css/style.css */
/* Les design tokens (variables) sont définis dans css/tokens.css (chargé avant). */

/* =========================================
   RESET & BASE
   ========================================= */
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: var(--font-sans);
    background-color: var(--bg-body);
    color: var(--text-main);
    display: flex;
    min-height: 100vh;
    line-height: 1.6;
}

/* Chiffres alignés (tableaux, KPI) */
.data-table td, .dashboard-value, .big-kpi, .mini-kpi-grid strong { font-variant-numeric: tabular-nums; }

/* Accessibilité : focus clavier visible */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

h1, h2, h3 { margin-bottom: 1rem; font-weight: 600; }
ul { list-style: none; }
a { text-decoration: none; color: inherit; }

/* =========================================
   LAYOUT (SIDEBAR & MAIN)
   ========================================= */
/* Emplacement : css/style.css */
/* =========================================
   LAYOUT (SIDEBAR & MAIN)
   ========================================= */
.sidebar {
    width: var(--sidebar-width);
    background-color: var(--sidebar-bg);
    background-image: linear-gradient(180deg, var(--sidebar-bg) 0%, var(--sidebar-bg-2) 100%);
    color: white;
    height: 100vh;
    position: fixed;
    display: flex;
    flex-direction: column;
    padding: 1.5rem;
    z-index: 100;
    overflow-y: auto; /* Permet de scroller dans le menu */
}

/* Personnalisation de la barre de scroll du menu */
.sidebar::-webkit-scrollbar { width: 6px; }
.sidebar::-webkit-scrollbar-track { background: rgba(0,0,0,0.1); }
.sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 10px; }
.sidebar::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.3); }

.sidebar-header {
    padding-bottom: 1rem;
    flex-shrink: 0; /* Empêche le header de s'écraser au scroll */
}

.brand-link {
    display: block;
    background: #ffffff;
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 0.9rem;
    box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
.brand-logo {
    width: 100%;
    height: auto;
    display: block;
    margin-bottom: 6px;
}
.brand-logo[hidden] { display: none; }
/* Repli texte d'une filiale sans logo (lot L9) : toujours présent, jamais
   remplacé silencieusement par la marque d'une autre filiale. */
.brand-text {
    display: block;
    text-align: center;
    font-weight: 800;
    font-size: var(--text-base);
    line-height: 1.25;
    color: var(--primary, #2059A6);
    word-break: break-word;
}

.sidebar-header h2 { font-size: var(--text-xl); margin-bottom: 0.5rem; }

/* NOUVEAU : Le style unifié pour les séparateurs du menu */
.sidebar-divider {
    margin: 1.5rem 0 0.5rem 0;
    font-size: var(--text-xs);
    text-transform: uppercase;
    color: #bdc3c7;
    font-weight: bold;
    letter-spacing: 1px;
    padding-bottom: 5px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
}

.sidebar-header h2 { font-size: var(--text-xl); margin-bottom: 0.5rem; }

.badge {
    display: inline-block;
    background: var(--primary);
    color: #fff;
    padding: 3px 9px;
    border-radius: 4px;
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.main-nav li { margin-bottom: 0.5rem; }

.main-nav a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0.7rem 1rem;
    border-radius: var(--radius);
    transition: var(--transition);
    font-size: var(--text-base);
    color: var(--sidebar-text);
    opacity: 1;
}

.nav-icon {
    width: 19px;
    height: 19px;
    flex-shrink: 0;
    opacity: 0.9;
}

.main-nav a:hover .nav-icon,
.main-nav a.active .nav-icon { opacity: 1; }

.main-nav a:hover, .main-nav a.active {
    background-color: var(--primary);
    color: #fff;
    opacity: 1;
    transform: translateX(5px);
}

.main-content {
    margin-left: var(--sidebar-width);
    flex: 1;
    padding: 2rem;
    max-width: calc(100vw - var(--sidebar-width));
}

/* =========================================
   PAGES & CARDS
   ========================================= */
.page {
    animation: fadeIn 0.4s ease-out;
    max-width: 1200px;
    margin: 0 auto;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

.dashboard-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 2rem;
}

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 1.5rem;
}

.dashboard-card {
    background: var(--bg-card);
    padding: 1.5rem;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    border-top: 4px solid var(--primary);
}

/* -----------------------------------------------------------------------------
   « card » et « muted » — deux classes EMPLOYÉES ET NON DÉFINIES
   -----------------------------------------------------------------------------
   Trois écrans livrés les 18 et 19/09/2026 — campagnes, ateliers EBIOS RM,
   échelles de cotation — composent leurs blocs avec `class="card"` et leurs
   phrases d'appoint avec `class="muted"`. Aucune des deux n'existait dans cette
   feuille : les trois écrans se rendaient à plat, sans fond, sans ombre et sans
   séparation, au milieu d'un produit qui en a partout.

   ⚠️ **Le défaut ne se voit pas d'un essai, et il ne se voit pas non plus d'une
   relecture du module** : le balisage est correct, la classe est écrite, et rien
   ne dit qu'elle ne mène nulle part. Il s'est vu en REGARDANT l'écran sur la
   recette — ce que `docs/REPRISE.md` §4 range parmi les quatre leçons de méthode
   du chantier.

   On définit donc les classes plutôt que de réécrire trois modules : c'est
   corriger la classe et non l'instance, et le quatrième écran qui emploiera
   `card` sera juste sans qu'on y pense. `.card` reprend `.dashboard-card` à
   l'identique — un seul aspect de bloc dans le produit, pas deux.
   -------------------------------------------------------------------------- */
.card {
    background: var(--bg-card);
    padding: 1.5rem;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    border-top: 4px solid var(--primary);
    margin-bottom: 1.5rem;
}

.muted { color: var(--text-muted); font-size: var(--text-sm); }

.wide-card { grid-column: 1 / -1; }
.highlight-card { background: linear-gradient(135deg, #ffffff 0%, var(--primary-tint) 100%); }
.alert-card { border-top-color: var(--color-danger); }

/* =========================================
   COMPONENTS (KPI, PROGRESS, BUTTONS)
   ========================================= */
.dashboard-value { font-size: var(--text-3xl); font-weight: bold; color: var(--primary); margin: 0.5rem 0; }

.progress-bar {
    background: #eee;
    height: 12px;
    border-radius: 6px;
    overflow: hidden;
    margin: 1rem 0;
}

.progress-fill {
    height: 100%;
    background: var(--primary);
    transition: width 1s ease-in-out;
}

.progress-fill.success { background: var(--color-success); }

.mini-kpi-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-top: 1rem;
    text-align: center;
}

.mini-kpi-grid div { display: flex; flex-direction: column; }
.mini-kpi-grid strong { font-size: var(--text-lg); }
.mini-kpi-grid span { font-size: var(--text-xs); color: var(--text-muted); }

button {
    padding: 0.6rem 1.2rem;
    border-radius: var(--radius);
    border: none;
    cursor: pointer;
    font-weight: 600;
    transition: var(--transition);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background-color: var(--primary);
    color: #fff;
}

button#save, button#addExigenceBtn, button#addRisqueBtn, button#addActionBtn, button#saveAction {
    background-color: var(--color-success);
    color: white;
}

button#cancel { background-color: var(--color-gray); color: white; }
button#exportExcelBtn { background-color: #1d6f42; color: white; }
button#exportPdfBtn { background-color: #c0392b; color: white; }

button:hover { opacity: 0.9; transform: translateY(-1px); }
button:active { transform: translateY(0); }

/* =========================================
   TABLES & DATA
   ========================================= */
.data-table {
    width: 100%;
    border-collapse: collapse;
    background: white;
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow);
    margin-top: 1.5rem;
}

.data-table th, .data-table td {
    padding: 1rem;
    text-align: left;
    border-bottom: 1px solid var(--border);
}

.data-table th { background: #f8f9fa; font-weight: 600; text-transform: uppercase; font-size: var(--text-sm); letter-spacing: 1px; }
.clickable-row:hover { background-color: #f0f7ff; cursor: pointer; }

/* Status Badges */
.status {
    padding: 4px 10px;
    border-radius: 20px;
    font-size: var(--text-sm);
    font-weight: 600;
    text-transform: capitalize;
    white-space: nowrap;
}

.status-conforme { background: #d4edda; color: #155724; }
.status-partiellement-conforme { background: #fff3cd; color: #856404; }
.status-non-conforme { background: #f8d7da; color: #721c24; }
.status-non-applicable { background: #e2e3e5; color: #383d41; }

/* =========================================
   FORMS
   ========================================= */
.form-group { margin-bottom: 1.2rem; display: flex; flex-direction: column; }
.form-group label { margin-bottom: 0.5rem; font-weight: 600; font-size: var(--text-base); }
.form-group input, .form-group select, .form-group textarea {
    padding: 0.8rem;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    font-size: var(--text-md);
}

.form-group textarea { min-height: 100px; resize: vertical; }

.checkbox-line { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; cursor: pointer; }
.checkbox-group { background: #f9f9f9; padding: 1rem; border-radius: var(--radius); max-height: 200px; overflow-y: auto; }

/* =========================================
   MATRICE DES RISQUES
   ========================================= */
.risk-matrix { border-collapse: separate; border-spacing: 5px; margin: 2rem 0; width: 100%; }
.matrix-axis { padding: 10px; background: var(--primary); color: white; border-radius: 4px; font-size: var(--text-sm); text-transform: capitalize; text-align: center; }
.matrix-cell { width: 18%; height: 100px; border-radius: 4px; vertical-align: top; padding: 5px; transition: var(--transition); }

.matrix-low { background-color: #c8e6c9; }
.matrix-medium { background-color: #fff9c4; }
.matrix-high { background-color: #ffccbc; }

.matrix-risk {
    background: white;
    padding: 4px 8px;
    border-radius: 3px;
    margin-bottom: 4px;
    font-size: var(--text-xs);
    box-shadow: 0 1px 2px rgba(0,0,0,0.1);
    cursor: pointer;
    border-left: 3px solid var(--primary);
}

.matrix-legend { display: flex; gap: 20px; margin-top: 1rem; }
.legend { display: flex; align-items: center; gap: 8px; font-size: var(--text-base); }
.legend::before { content: ""; width: 20px; height: 20px; border-radius: 3px; }
.legend.low::before { background: #c8e6c9; }
.legend.medium::before { background: #fff9c4; }
.legend.high::before { background: #ffccbc; }

/* =========================================
   SYNTHESE DIRECTION
   ========================================= */
.synthese-message {
    padding: 1.5rem;
    border-radius: var(--radius);
    margin-bottom: 2rem;
    font-weight: 600;
    font-size: var(--text-lg);
    border-left: 6px solid;
}

.synthese-message.info { background: #e3f2fd; color: #0d47a1; border-color: #2196f3; }
.synthese-message.warning { background: #fff3e0; color: #e65100; border-color: #ff9800; }
.synthese-message.danger { background: #ffebee; color: #b71c1c; border-color: #f44336; }

.big-kpi { font-size: 3.5rem; font-weight: 800; color: var(--primary); line-height: 1; margin-bottom: 0.5rem; }

/* =========================================
   TOAST NOTIFICATIONS
   ========================================= */
#toast-container {
    position: fixed;
    top: 20px;
    right: 20px;
    z-index: 9999;
}

.toast {
    background: var(--primary);
    color: white;
    padding: 1rem 1.5rem;
    border-radius: var(--radius);
    margin-bottom: 10px;
    box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1);
    display: flex;
    align-items: center;
    gap: 12px;
    animation: slideIn 0.3s ease-out;
}

@keyframes slideIn {
    from { transform: translateX(100%); opacity: 0; }
    to { transform: translateX(0); opacity: 1; }
}

.toast.success { border-left: 5px solid var(--color-success); }
.toast.error { border-left: 5px solid var(--color-danger); }
.toast.info { border-left: 5px solid var(--color-info); }
.toast.warning { border-left: 5px solid var(--color-warning); }

/* =========================================
   BANDEAU DE RAPPEL (SAUVEGARDE)
   ========================================= */
#global-banner:empty { display: none; }
.reminder-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    background: #fff7ed;
    border: 1px solid #fed7aa;
    color: #9a3412;
    border-radius: var(--radius);
    padding: 10px 14px;
    margin-bottom: 1.5rem;
    font-size: var(--text-base);
}
.reminder-banner .reminder-ico {
    flex-shrink: 0;
    width: 22px; height: 22px;
    border-radius: 50%;
    background: var(--primary);
    color: #fff;
    font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
}
.reminder-banner .reminder-text { flex: 1; }
.reminder-banner .reminder-btn {
    background: var(--primary); color: #fff;
    padding: 7px 14px; font-size: var(--text-sm); flex-shrink: 0;
}
.reminder-banner .reminder-close {
    background: transparent; color: #9a3412;
    font-size: var(--text-xl); line-height: 1; padding: 2px 8px; flex-shrink: 0;
}

/* =========================================
   ÉCRAN DE VERROUILLAGE (chiffrement opt-in)
   ========================================= */
.lock-overlay {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: linear-gradient(180deg, var(--sidebar-bg) 0%, var(--sidebar-bg-2) 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.lock-card {
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 20px 50px rgba(0,0,0,0.3);
    padding: 34px 32px;
    width: 100%;
    max-width: 400px;
    text-align: center;
}
.lock-logo { width: 220px; max-width: 80%; height: auto; display: block; margin: 0 auto 22px; }
/* Écran de démarrage (lot L9) : nom de produit neutre, jamais le logo d'une
   filiale — aucune filiale n'est encore connue avant réponse de /api/session. */
.lock-brand { font-weight: 800; font-size: var(--text-xl); color: var(--primary, #2059A6); margin-bottom: 18px; letter-spacing: 0.02em; }
.lock-title { font-size: var(--text-xl); margin-bottom: 6px; }
.lock-sub { color: var(--text-muted); font-size: var(--text-base); margin-bottom: 20px; line-height: 1.5; }
.lock-warn {
    background: #fdecea; color: var(--color-danger);
    border-radius: 6px; padding: 10px 12px; font-size: var(--text-sm);
    margin-bottom: 18px; text-align: left; line-height: 1.45;
}
.lock-input {
    width: 100%; padding: 0.8rem 1rem; font-size: var(--text-md);
    border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 12px;
}
.lock-input:focus { outline: 2px solid var(--primary); border-color: var(--primary); }
.lock-btn { background: var(--primary); color: #fff; width: 100%; justify-content: center; padding: 0.8rem; font-size: var(--text-md); }
.lock-error { color: var(--color-danger); font-size: var(--text-sm); min-height: 20px; margin-bottom: 8px; }

/* =========================================
   ENCART PÉDAGOGIQUE (aide contextuelle)
   ========================================= */
.help-note {
    background: var(--primary-tint, #fdefe4);
    border-left: 3px solid var(--primary);
    border-radius: 6px;
    padding: 10px 14px;
    font-size: var(--text-sm);
    color: var(--text-main);
    line-height: 1.5;
}

/* =========================================
   TOOLTIP PÉDAGOGIQUE (ⓘ)
   ========================================= */
.help-tip {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px; height: 16px;
    margin-left: 5px;
    border-radius: 50%;
    border: 1px solid var(--text-muted);
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-style: italic;
    font-weight: 700;
    cursor: help;
    vertical-align: middle;
    flex-shrink: 0;
    background: var(--bg-card);
}
.help-tip:hover, .help-tip:focus-visible { border-color: var(--primary); color: var(--primary); outline: none; }
.help-tip__pop {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    width: max-content;
    max-width: 260px;
    background: #1f2d3d;
    color: #fff;
    text-align: left;
    font-size: var(--text-xs);
    font-style: normal;
    font-weight: 400;
    line-height: 1.45;
    padding: 8px 10px;
    border-radius: 6px;
    box-shadow: var(--shadow-md);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.15s ease;
    z-index: 500;
    pointer-events: none;
}
.help-tip__pop::after {
    content: "";
    position: absolute;
    top: 100%; left: 50%;
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-top-color: #1f2d3d;
}
.help-tip:hover .help-tip__pop,
.help-tip:focus-visible .help-tip__pop,
.help-tip.open .help-tip__pop { opacity: 1; visibility: visible; }

/* =========================================
   BADGES SÉMANTIQUES (statuts)
   ========================================= */
.badge--ok   { background: var(--tint-ok);   color: var(--color-ok); }
.badge--warn { background: var(--tint-warn); color: var(--color-warn); }
.badge--crit { background: var(--tint-crit); color: var(--color-crit); }
.badge--na   { background: var(--tint-na);   color: var(--color-na); }

/* =========================================
   FIL D'ARIANE
   ========================================= */
.breadcrumb {
    font-size: var(--text-sm);
    color: var(--text-muted);
    margin-bottom: 0.5rem;
}
.breadcrumb b { color: var(--text-main); }
#breadcrumb:empty { display: none; }

/* =========================================
   ÉTAT VIDE
   ========================================= */
.empty-state {
    text-align: center;
    padding: 3rem 1.5rem;
    color: var(--text-muted);
}
.empty-state h3 { color: var(--text-main); margin-bottom: 0.5rem; }
.empty-state p { margin-bottom: 1.2rem; }

/* =========================================
   BOUTON MENU MOBILE + RESPONSIVE
   ========================================= */
.menu-toggle {
    display: none;
    position: fixed;
    top: 12px; left: 12px;
    z-index: 200;
    width: 42px; height: 42px;
    padding: 0;
    background: var(--sidebar-bg);
    color: #fff;
    border-radius: var(--radius);
    align-items: center;
    justify-content: center;
}
.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.4);
    z-index: 99;
}

@media (max-width: 900px) {
    .menu-toggle { display: inline-flex; }
    .sidebar {
        transform: translateX(-100%);
        transition: transform 0.25s ease;
        box-shadow: var(--shadow-md);
    }
    .sidebar.open { transform: translateX(0); }
    .sidebar-backdrop.show { display: block; }
    .main-content {
        margin-left: 0;
        max-width: 100vw;
        padding: 3.5rem 1rem 1.5rem;
    }
    .dashboard-header { flex-direction: column; align-items: flex-start; gap: 12px; }
    .dashboard-grid { grid-template-columns: 1fr; }
}

/* =========================================
   PRINT / PDF STYLES
   ========================================= */
/* En-tête de document réservé à l'impression : masqué à l'écran, révélé au print.
   Sert aux annuaires imprimables (cellule de crise, prestataires & tiers). */
.print-head { display: none; }
/* Logo de la filiale active dans une entête imprimable (lot L9) : posé par
   `Identite.brancherLogos()` une fois l'image obtenue — `hidden` tant qu'aucun
   logo n'est disponible, auquel cas la raison sociale (toujours présente en
   texte) reste seule. Partagé par `.print-head` et `.soa-print-head`. */
.print-brand-logo { display: block; max-height: 42px; width: auto; margin-bottom: 6px; }
.print-brand-logo[hidden] { display: none; }

@media print {
    @page {
        size: A4;
        margin: 1.5cm 2cm;
    }

    .no-print, #toast-container, .sidebar {
        display: none !important;
    }

    body {
        background: white !important;
        color: #000 !important;
        font-size: 11pt;
    }

    .main-content {
        margin-left: 0 !important;
        width: 100% !important;
        padding: 0 !important;
        max-width: none !important;
    }

    /* Force l'impression de toutes les couleurs (fonds, badges, alertes) */
    * {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
        color-adjust: exact !important;
    }

    /* Ajustements pour éviter les coupures disgracieuses */
    .dashboard-card {
        box-shadow: none !important;
        border: 1px solid #ddd !important;
        page-break-inside: avoid;
        break-inside: avoid;
        margin-bottom: 1.5rem !important;
    }

    .synthese-message {
        page-break-inside: avoid;
        break-inside: avoid;
    }

    .synthese-page {
        max-width: 100% !important;
        margin: 0 !important;
    }

    /* En-tête de document imprimé (titre + marque + date) */
    .print-head {
        display: block !important;
        border-bottom: 2px solid var(--primary);
        padding-bottom: 8px;
        margin-bottom: 1.2rem;
    }
    .print-head h1 { margin: 0 0 4px; font-size: 18pt; }
    .print-head p { margin: 0; color: #555; font-size: 10pt; }
}

/* =========================================
   RÉFÉRENTIELS & AUTO-ÉVALUATION
   ========================================= */
/* Badge de statut « non évalué » (complète les statuts sémantiques existants) */
.status-non-evaluee { background: var(--tint-na); color: var(--color-na); }

/* --- Cartes de la liste des référentiels --- */
.ref-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 1.5rem; }
.ref-card__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.ref-kpis { display: flex; gap: 1rem; margin: 4px 0; }
.ref-kpis--stack { flex-direction: column; gap: 0.6rem; }
.ref-kpi { flex: 1; text-align: center; background: var(--bg-body); border-radius: var(--radius); padding: 10px 6px; }
.ref-kpis--stack .ref-kpi { display: flex; align-items: baseline; justify-content: space-between; text-align: left; padding: 8px 12px; }
.ref-kpi__val { font-size: var(--text-2xl); font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; line-height: 1; }
.ref-kpi__val span { font-size: var(--text-base); font-weight: 600; color: var(--text-muted); }
.ref-kpi__lbl { font-size: var(--text-xs); color: var(--text-muted); margin-top: 6px; text-transform: uppercase; letter-spacing: 0.4px; }
.ref-kpis--stack .ref-kpi__lbl { margin-top: 0; }

/* --- Radar --- */
.ref-radar { width: 100%; margin: 0.5rem 0 1rem; }
.ref-radar-svg { width: 100%; height: auto; display: block; }

/* --- Détail : radar + synthèse --- */
.ref-detail-grid { grid-template-columns: 2fr 1fr; align-items: start; }
.ref-scorecard { min-width: 0; }
@media (max-width: 900px) { .ref-detail-grid { grid-template-columns: 1fr; } }

/* --- Domaines repliables --- */
.ref-domain { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); margin-bottom: 1rem; overflow: hidden; }
.ref-domain > summary { list-style: none; cursor: pointer; padding: 0.9rem 1.1rem; display: flex; justify-content: space-between; align-items: center; gap: 12px; font-weight: 600; color: var(--text-main); }
.ref-domain > summary::-webkit-details-marker { display: none; }
.ref-domain > summary::before { content: "▸"; color: var(--primary); font-size: var(--text-base); margin-right: 2px; transition: var(--transition); }
.ref-domain[open] > summary::before { transform: rotate(90deg); }
.ref-domain > summary:hover { background: var(--primary-tint); }
.ref-domain__name { flex: 1; }
.ref-domain__score { display: flex; align-items: center; gap: 14px; font-weight: 600; }
.ref-domain__mat { font-variant-numeric: tabular-nums; }
.ref-domain__count { font-size: var(--text-xs); color: var(--text-muted); font-weight: 500; white-space: nowrap; }

/* --- Table des mesures --- */
.ref-table { margin-top: 0; box-shadow: none; border-top: 1px solid var(--border); }
.ref-table th, .ref-table td { padding: 0.6rem 0.9rem; vertical-align: middle; }
.ref-table tbody tr:last-child td { border-bottom: none; }
.ref-row:hover { background: #f7fafd; }
select.ref-statut { width: 100%; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: var(--text-sm); background: #fff; }
select.ref-mat { width: 64px; padding: 6px 4px; border: 1px solid var(--border); border-radius: var(--radius-sm); text-align: center; }
select.ref-statut.sel-status-conforme { color: #155724; border-color: #b7dfc2; }
select.ref-statut.sel-status-partiellement-conforme { color: #856404; border-color: #f3e0a8; }
select.ref-statut.sel-status-non-conforme { color: #721c24; border-color: #eab8bd; }
select.ref-statut.sel-status-non-applicable { color: #383d41; border-color: var(--border); }
select.ref-statut.sel-status-non-evaluee { color: var(--text-muted); border-color: var(--border); }

.ref-toggle { background: transparent; color: var(--accent); border: 1px solid var(--border); padding: 4px 10px; font-size: var(--text-sm); border-radius: var(--radius-sm); }
.ref-toggle:hover { background: var(--primary-tint); border-color: var(--primary); color: var(--primary-dark); }
.ref-badge-count { display: inline-block; min-width: 16px; padding: 0 5px; background: var(--accent); color: #fff; border-radius: 10px; font-size: var(--text-xs); text-align: center; }
/* Rappel du numéro officiel d'une mesure quand il diffère de celui du catalogue
   (constat Q-192). Discret par construction : c'est une note de bas de page, pas
   un avertissement — il ne doit pas concurrencer le code lui-même. */
.ref-code-officiel { margin-left: 4px; font-size: var(--text-xs); font-weight: 400; color: var(--text-muted); white-space: nowrap; }

/* --- Panneau de détail d'une mesure --- */
.ref-detail-row > td { background: #f7fafd; padding: 0 !important; }
.ref-detail-panel { padding: 1rem 1.1rem 1.2rem; }
.ref-detail-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
@media (max-width: 720px) { .ref-detail-grid2 { grid-template-columns: 1fr; } }
.ref-detail-panel textarea { min-height: 64px; }
.ref-actions-block { border-top: 1px dashed var(--border); padding-top: 0.9rem; }
.ref-actions-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 6px; }
.ref-actions-list { list-style: none; padding: 0; margin: 6px 0; }
.ref-actions-list li { padding: 6px 0; border-bottom: 1px solid var(--border); display: flex; align-items: center; }
.ref-actions-list li:last-child { border-bottom: none; }
.ref-action-form { margin-top: 10px; }
.ref-action-form__row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.ref-action-form__row .ref-act-titre { flex: 1 1 240px; padding: 7px 9px; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.ref-action-form__row select, .ref-action-form__row input[type="date"] { padding: 7px 9px; border: 1px solid var(--border); border-radius: var(--radius-sm); }

/* --- Lien vers une mesure de sécurité (pivot) --- */
.ref-mesure-row { border-top: 1px dashed var(--border); padding-top: 0.9rem; margin-bottom: 0.9rem; }
.ref-mesure-row > label { display: block; font-weight: 600; font-size: var(--text-base); margin-bottom: 6px; }
.ref-mesure-controls { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ref-mesure-controls select { flex: 1 1 240px; padding: 7px 9px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: #fff; }
.ref-new-mesure { background: transparent; color: var(--accent); border: 1px solid var(--border); padding: 7px 12px; border-radius: var(--radius-sm); font-size: var(--text-sm); white-space: nowrap; }
.ref-new-mesure:hover { background: var(--primary-tint); border-color: var(--primary); color: var(--primary-dark); }
.ref-mesure-link { color: var(--accent); font-size: var(--text-sm); white-space: nowrap; }

/* =========================================
   CONFORMITÉ TRANSVERSE (couverture croisée + SoA)
   ========================================= */
.btn-secondary { background: transparent; color: var(--accent); border: 1px solid var(--border); padding: 8px 14px; border-radius: var(--radius-sm); text-decoration: none; font-size: var(--text-base); display: inline-block; }
.btn-secondary:hover { background: var(--primary-tint); border-color: var(--primary); color: var(--primary-dark); }

.cov-cell { display: inline-block; min-width: 22px; padding: 2px 7px; background: var(--primary-tint); color: var(--primary-dark); border-radius: 10px; font-weight: 600; font-size: var(--text-sm); }
.cov-cell--multi { background: var(--accent); color: #fff; }
.cov-matrix th, .cov-matrix td { padding: 0.6rem 0.8rem; }

.soa-summary { display: flex; gap: 1rem; flex-wrap: wrap; margin: 1rem 0 1.4rem; }
.soa-summary > div { flex: 1; min-width: 110px; text-align: center; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; box-shadow: var(--shadow); }
.soa-summary strong { display: block; font-size: var(--text-2xl); color: var(--text-main); font-variant-numeric: tabular-nums; }
.soa-summary span { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.4px; }
.soa-table th, .soa-table td { padding: 0.5rem 0.7rem; font-size: var(--text-base); }
.soa-domain-row td { background: var(--bg-body); font-size: var(--text-base); }

/* --- Incidents --- */
.status-critique { background: #a5281b; color: #fff; }
.decl-ok { background: var(--tint-ok); color: var(--color-ok); }
.decl-todo { background: var(--tint-warn); color: var(--color-warn); }
.decl-na { background: var(--tint-na); color: var(--color-na); }
.inc-actifs { display: flex; flex-wrap: wrap; gap: 8px; }
.inc-checkbox { display: inline-flex; align-items: center; gap: 6px; background: var(--bg-body); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 10px; font-size: var(--text-base); cursor: pointer; }

/* --- Métadonnées AirCyber : niveau de label, priorité, domaine CL --- */
.ref-badges { display: inline-flex; gap: 5px; vertical-align: middle; flex-wrap: wrap; }
.niv-badge, .prio-badge, .cl-badge { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: var(--text-xs); font-weight: 700; white-space: nowrap; }
.niv-bronze { background: #f0ddc8; color: #8a5320; }
.niv-silver { background: #e5e7eb; color: #4b5563; }
.niv-gold   { background: #fbeec2; color: #9a7209; }
.prio-badge { font-weight: 600; }
.prio-high   { background: var(--tint-crit); color: var(--color-crit); }
.prio-medium { background: var(--tint-warn); color: var(--color-warn); }
.prio-low    { background: var(--tint-na);   color: var(--color-na); }
.cl-badge { background: #e7effa; color: #2059A6; font-weight: 600; }

/* Sélecteur de niveau du radar AirCyber (Global / Bronze / Argent / Or).
   Le bouton actif prend la teinte du niveau, comme le tracé du radar. */
.ref-radar-levels { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin: 0 0 10px; }
.ref-radar-levels .ref-filter-niv.active[data-niv="bronze"] { background: #8a5320; border-color: #8a5320; }
.ref-radar-levels .ref-filter-niv.active[data-niv="silver"] { background: #4b5563; border-color: #4b5563; }
.ref-radar-levels .ref-filter-niv.active[data-niv="gold"]   { background: #9a7209; border-color: #9a7209; }

.ref-filters { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); padding: 10px 14px; margin-bottom: 1rem; }
.ref-filters__lbl { font-size: var(--text-sm); font-weight: 600; color: var(--text-muted); }
.ref-filter-nivs { display: inline-flex; gap: 4px; }
.ref-filter-niv { background: transparent; color: var(--text-main); border: 1px solid var(--border); padding: 5px 12px; font-size: var(--text-sm); border-radius: 20px; }
.ref-filter-niv.active { background: var(--primary); color: #fff; border-color: var(--primary); }
.ref-filter-niv:hover { border-color: var(--primary); }
#ref-filter-cl { padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: #fff; font-size: var(--text-sm); }
.ref-filter-count { font-size: var(--text-sm); color: var(--text-muted); margin-left: auto; }

.ref-readiness { border-top: 1px solid var(--border); margin-top: 14px; padding-top: 6px; }
.ref-readiness h4 { font-size: var(--text-base); }
.ref-niv-row { display: flex; align-items: center; margin-bottom: 8px; font-size: var(--text-sm); }
.ref-niv-pct { font-variant-numeric: tabular-nums; font-weight: 700; min-width: 42px; text-align: right; }
.ref-niv-cnt { color: var(--text-muted); font-size: var(--text-xs); min-width: 48px; text-align: right; margin-left: 8px; }
@media print {
    .soa-print-head { display: block !important; }
    .soa-summary > div { box-shadow: none; }
    .soa-table { font-size: var(--text-xs); box-shadow: none; }
    .soa-table th, .soa-table td { padding: 4px 6px; }
}

/* =========================================
   CORRESPONDANCES INTER-RÉFÉRENTIELS (/mapping)
   ========================================= */
/* Cartographie (part de chaque référentiel cité dans une correspondance) */
.map-cov-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.map-toolbar { display: flex; align-items: center; gap: 10px; }
.map-hidden-note { font-size: var(--text-xs); color: var(--text-muted); }
.map-cov-chips { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.map-cov-chip { background: var(--bg-body); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 12px; }
.map-cov-chip__top { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 6px; font-size: var(--text-sm); }
.map-cov-chip__top strong { color: var(--text-main); }
.map-cov-chip__top span { color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }

/* Liste des groupes */
.map-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(440px, 1fr)); gap: 1.2rem; align-items: start; }
@media (max-width: 620px) { .map-list { grid-template-columns: 1fr; } }
.map-group { display: flex; flex-direction: column; }
.map-group__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.map-group__title { min-width: 0; }
.map-group__title h3 { margin: 0 0 6px; font-size: var(--text-md); }
.map-group__conf { text-align: center; flex: 0 0 auto; }
.map-conf-val { font-size: var(--text-xl); font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1; }
.map-conf-lbl { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.4px; }

.map-origin { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.3px; }
.map-origin--seed { background: var(--tint-na); color: var(--text-muted); }
.map-origin--edited { background: var(--primary-tint); color: var(--primary-dark); }
.map-origin--custom { background: #e7effa; color: var(--accent); }

/* Lignes par référentiel */
.map-refs { margin: 12px 0; border-top: 1px solid var(--border); padding-top: 10px; }
.map-ref-row { display: flex; align-items: flex-start; gap: 10px; padding: 5px 0; }
.map-ref-name { flex: 0 0 90px; font-size: var(--text-xs); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.3px; padding-top: 3px; }
.map-ref-clauses { flex: 1; display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.map-empty { color: var(--border); padding: 2px 4px; }

/* Badge de clause (couleur = statut d'évaluation, via les classes .status-*) */
.map-clause { display: inline-flex; align-items: center; padding: 1px 7px; border-radius: 10px; font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums; text-decoration: none; border: 1px solid transparent; transition: var(--transition); }
.map-clause:hover { filter: brightness(0.95); text-decoration: none; }
.map-clause--linked { box-shadow: inset 0 0 0 2px var(--accent); }
.map-clause--unknown { border: 1px dashed var(--color-danger); color: var(--color-danger); background: transparent; }

/* Pied : couverture + actions */
.map-group__foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: auto; padding-top: 8px; }
.map-cover { font-size: var(--text-sm); color: var(--text-muted); }
.map-mesure-link { color: var(--accent); }
.map-actions { display: flex; gap: 6px; }
.map-edit, .map-del { background: transparent; border: 1px solid var(--border); padding: 4px 10px; font-size: var(--text-sm); border-radius: var(--radius-sm); color: var(--accent); }
.map-edit:hover { background: var(--primary-tint); border-color: var(--primary); color: var(--primary-dark); }
.map-del { color: var(--color-danger); }
.map-del:hover { background: var(--tint-crit); border-color: var(--color-danger); }

/* Panneau de propagation (repliable) */
.map-propagate { margin-top: 10px; border-top: 1px dashed var(--border); padding-top: 8px; }
.map-propagate > summary { list-style: none; cursor: pointer; font-size: var(--text-sm); font-weight: 600; color: var(--accent); }
.map-propagate > summary::-webkit-details-marker { display: none; }
.map-propagate > summary::before { content: "▸"; margin-right: 6px; color: var(--primary); }
.map-propagate[open] > summary::before { content: "▾"; }
.map-prop-panel { padding: 10px 2px 2px; }
.map-prop-row { margin-bottom: 10px; }
.map-prop-row > label { display: block; font-size: var(--text-sm); font-weight: 600; margin-bottom: 6px; }
.map-prop-controls { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.map-prop-controls select { flex: 1 1 180px; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: #fff; font-size: var(--text-sm); }
.map-prop-controls select.map-prop-mat { flex: 0 0 60px; text-align: center; }
.map-prop-controls button { background: var(--accent); color: #fff; border: none; padding: 6px 14px; border-radius: var(--radius-sm); font-size: var(--text-sm); white-space: nowrap; }
.map-prop-controls .map-prop-newmesure { background: transparent; color: var(--accent); border: 1px solid var(--border); }
.map-prop-controls .map-prop-newmesure:hover { background: var(--primary-tint); border-color: var(--primary); color: var(--primary-dark); }
.map-prop-hint { font-size: var(--text-xs); color: var(--text-muted); margin: 4px 0 0; }

/* Éditeur */
.map-editor { border-left: 3px solid var(--primary); margin-bottom: 1.2rem; }
.map-edit-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin: 10px 0 14px; }
.map-edit-field label { display: block; font-weight: 600; font-size: var(--text-sm); margin-bottom: 5px; }
.map-edit-hint { font-weight: 400; color: var(--text-muted); font-size: var(--text-xs); }
.map-edit-codes { width: 100%; padding: 4px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: var(--text-sm); background: #fff; }
.map-edit-codes option { padding: 2px 4px; }
.map-edit-actions { display: flex; gap: 10px; }

/* =========================================
   TABLEAU DE BORD — TENDANCES (courbes d'évolution)
   ========================================= */
.trend-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.trend-clear { background: transparent; color: var(--text-muted); border: 1px solid var(--border); padding: 5px 12px; font-size: var(--text-sm); border-radius: var(--radius-sm); }
.trend-clear:hover { color: var(--color-danger); border-color: var(--color-danger); background: var(--tint-crit); }
.trend-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; }
.trend-tile { background: var(--bg-body); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; }
.trend-tile__lbl { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.4px; font-weight: 600; }
.trend-tile__val { font-size: var(--text-2xl); font-weight: 700; color: var(--text-main); font-variant-numeric: tabular-nums; margin: 4px 0 8px; line-height: 1.1; }
.trend-tile__val small { font-size: var(--text-sm); font-weight: 600; color: var(--text-muted); margin-left: 1px; }
.trend-delta { font-size: var(--text-xs); font-weight: 700; margin-left: 6px; white-space: nowrap; }
.trend-tile__spark { height: 54px; }
.trend-spark { width: 100%; height: 54px; display: block; }
.trend-empty { font-size: var(--text-xs); color: var(--text-muted); font-style: italic; display: block; padding-top: 16px; }
.trend-hint { font-size: var(--text-sm); color: var(--text-muted); margin: 12px 0 0; }

/* =========================================
   BANDEAU D'ALERTE : STOCKAGE SATURÉ (quota)
   ========================================= */
.quota-banner {
    display: flex; align-items: center; gap: 12px;
    background: var(--tint-crit); border: 1px solid #eab8bd; color: #7a1f18;
    border-radius: var(--radius); padding: 10px 14px; margin-bottom: 1.5rem; font-size: var(--text-base);
}
.quota-banner .quota-ico {
    flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%;
    background: var(--color-danger); color: #fff; font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
}
.quota-banner .quota-text { flex: 1; }
.quota-banner .reminder-btn { background: var(--color-danger); color: #fff; padding: 7px 14px; font-size: var(--text-sm); flex-shrink: 0; }
.quota-banner .reminder-close { background: transparent; color: #7a1f18; font-size: var(--text-xl); line-height: 1; padding: 2px 8px; flex-shrink: 0; }

/* --- Bandeau « installation de découverte » (lot L18.2 b) ---
   Teinte « à surveiller » et non « critique » : rien n'est cassé, l'installation
   est incomplète. Le rouge est réservé à ce qui l'est vraiment, et un bandeau
   permanent en rouge finit par ne plus se lire.
   ⚠️ **Il n'a PAS de classe `no-print`, et ce n'est pas un oubli** : une pièce
   tirée d'une installation de découverte doit porter la mention sur le papier
   aussi — voir `js/app.js`. La version imprimée passe en noir et blanc avec un
   filet, pour rester lisible sans aplat de couleur. */
.decouverte-banner {
    display: flex; align-items: center; gap: 12px;
    background: var(--tint-warn); border: 1px solid #e5c98a; color: #6b4a05;
    border-radius: var(--radius); padding: 10px 14px; margin-bottom: 1.5rem; font-size: var(--text-base);
}
.decouverte-banner .decouverte-ico {
    flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%;
    background: var(--color-warning); color: #fff; font-weight: 800;
    display: inline-flex; align-items: center; justify-content: center;
}
.decouverte-banner .decouverte-text { flex: 1; }

@media print {
    .decouverte-banner {
        background: #fff; border: 2px solid #000; color: #000;
        border-radius: 0; margin-bottom: 1rem;
    }
    .decouverte-banner .decouverte-ico {
        background: #fff; color: #000; border: 1.5px solid #000;
    }
}

/* =========================================
   TABLEAU DE BORD ENRICHI — COCKPIT GRC
   (bandeau posture, KPI strip, donut/bars/heatmap SVG,
    liste de veille, tuiles de couverture du dispositif)
   ========================================= */

/* --- Sous-titres de section --- */
.dash-section-title {
    font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 1px;
    color: var(--text-muted); font-weight: 700;
    margin: 2.2rem 0 0.9rem; display: flex; align-items: center; gap: 8px;
}
.dash-section-title::after { content: ""; flex: 1; height: 1px; background: var(--border); }

/* --- Bandeau de posture (lecture direction immédiate) --- */
.posture-banner {
    display: flex; align-items: flex-start; gap: 14px;
    padding: 14px 18px; border-radius: var(--radius); margin-bottom: 1.5rem;
    box-shadow: var(--shadow); background: var(--bg-card);
    border-left: 5px solid var(--color-info);
}
.posture-banner .pb-dot { width: 12px; height: 12px; border-radius: 50%; margin-top: 5px; flex-shrink: 0; background: var(--color-info); }
.posture-banner h2 { font-size: var(--text-md); margin: 0 0 3px; color: var(--text-main); }
.posture-banner p { margin: 0; color: var(--text-muted); font-size: var(--text-base); line-height: 1.4; }
.posture-banner.is-danger  { border-left-color: var(--color-danger);  background: linear-gradient(90deg, var(--tint-crit), var(--bg-card) 55%); }
.posture-banner.is-danger  .pb-dot { background: var(--color-danger); }
.posture-banner.is-warning { border-left-color: var(--color-warning); background: linear-gradient(90deg, var(--tint-warn), var(--bg-card) 55%); }
.posture-banner.is-warning .pb-dot { background: var(--color-warning); }
.posture-banner.is-success { border-left-color: var(--color-success); background: linear-gradient(90deg, var(--tint-ok), var(--bg-card) 55%); }
.posture-banner.is-success .pb-dot { background: var(--color-success); }

/* --- Bandeau d'indicateurs clés (KPI strip) --- */
.kpi-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: 1rem; margin-bottom: 1.5rem; }
.kpi-tile { background: var(--bg-card); border-radius: var(--radius); box-shadow: var(--shadow); padding: 0.9rem 1.1rem; border-left: 4px solid var(--primary); }
.kpi-tile .kt-val { font-size: var(--text-2xl); font-weight: bold; line-height: 1.1; color: var(--text-main); font-variant-numeric: tabular-nums; }
.kpi-tile .kt-val small { font-size: var(--text-md); font-weight: 600; color: var(--text-muted); }
.kpi-tile .kt-lbl { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-top: 3px; }
.kpi-tile .kt-sub { font-size: var(--text-xs); color: var(--text-muted); margin-top: 4px; }
.kpi-tile.is-danger  { border-left-color: var(--color-danger); }
.kpi-tile.is-danger  .kt-val { color: var(--color-danger); }
.kpi-tile.is-warning { border-left-color: var(--color-warning); }
.kpi-tile.is-warning .kt-val { color: var(--color-warning); }
.kpi-tile.is-success { border-left-color: var(--color-success); }
.kpi-tile.is-success .kt-val { color: var(--color-success); }

/* --- Titres de cartes graphiques --- */
.chart-card h3 { margin-top: 0; display: flex; align-items: center; gap: 6px; }
.chart-empty { color: var(--text-muted); font-size: var(--text-base); text-align: center; padding: 1.5rem 0.5rem; }

/* --- Donut (SVG) + légende --- */
.donut-card { display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; }
.dash-donut { display: block; flex-shrink: 0; margin: 0 auto; }
.donut-legend { display: flex; flex-direction: column; gap: 7px; flex: 1; min-width: 140px; }
.lg-row { display: flex; align-items: center; gap: 8px; font-size: var(--text-sm); }
.lg-dot { width: 11px; height: 11px; border-radius: 3px; flex-shrink: 0; }
.lg-lbl { color: var(--text-muted); flex: 1; }
.lg-val { font-weight: bold; font-variant-numeric: tabular-nums; }

/* --- Barres horizontales (HTML) --- */
.hbar { margin-bottom: 12px; }
.hbar:last-child { margin-bottom: 0; }
.hbar-top { display: flex; justify-content: space-between; gap: 8px; font-size: var(--text-sm); margin-bottom: 4px; }
.hbar-lbl { color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hbar-val { font-weight: bold; flex-shrink: 0; font-variant-numeric: tabular-nums; }
.hbar-track { background: #eef1f5; height: 9px; border-radius: 5px; overflow: hidden; }
.hbar-fill { height: 100%; border-radius: 5px; transition: width 0.9s ease; }
.hbar-cap { font-size: var(--text-xs); color: var(--text-muted); margin-top: 3px; }

/* --- Heatmap risques (SVG matrice F×G) --- */
.heat-wrap { text-align: center; cursor: pointer; }
.dash-heat-svg { display: block; margin: 0 auto; max-width: 100%; height: auto; }
.heat-cap { font-size: var(--text-xs); color: var(--text-muted); margin-top: 8px; }

/* --- Liste de veille (actions en retard / à échéance) --- */
.watch-list { list-style: none; padding: 0; margin: 0.6rem 0 0; }
.watch-item { display: flex; align-items: center; gap: 10px; padding: 9px 4px; border-bottom: 1px solid var(--border); cursor: pointer; }
.watch-item:last-child { border-bottom: none; }
.watch-item:hover { background: #f8f9fa; }
.wi-prio { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.wi-body { flex: 1; min-width: 0; }
.wi-title { display: block; font-weight: 600; font-size: var(--text-base); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wi-meta { font-size: var(--text-xs); color: var(--text-muted); }
.wi-badge { font-size: var(--text-xs); font-weight: bold; padding: 3px 9px; border-radius: 20px; white-space: nowrap; flex-shrink: 0; }
.wi-badge.late { background: var(--tint-crit); color: var(--color-danger); }
.wi-badge.soon { background: var(--tint-warn); color: var(--color-warn); }

/* --- Tuiles de couverture du dispositif GRC --- */
.cov-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 0.4rem; }
.cov-tile { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; background: var(--bg-body); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 14px; cursor: pointer; text-align: left; color: inherit; font: inherit; transition: var(--transition); }
.cov-tile:hover { background: #fff; transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--primary-light); }
.cov-val { font-size: var(--text-xl); font-weight: bold; line-height: 1; font-variant-numeric: tabular-nums; color: var(--text-main); }
.cov-lbl { font-size: var(--text-sm); color: var(--text-main); font-weight: 600; }
.cov-sub { font-size: var(--text-xs); color: var(--text-muted); }

/* --- Cartes larges à deux colonnes (responsive) --- */
.split-card { display: flex; gap: 2rem; flex-wrap: wrap; }
.split-card > .split-col { flex: 1 1 300px; min-width: 0; }
.split-card > .split-col + .split-col { border-left: 1px solid var(--border); padding-left: 2rem; }
@media (max-width: 720px) {
    .split-card > .split-col + .split-col { border-left: none; padding-left: 0; border-top: 1px solid var(--border); padding-top: 1.2rem; }
}

/* =========================================================================
   ÉCHÉANCIER (module /echeances) + badge de la barre latérale
========================================================================= */
.nav-badge {
    display: inline-block;
    min-width: 18px;
    margin-left: auto;
    padding: 0 6px;
    background: var(--color-danger);
    color: #fff;
    border-radius: 10px;
    font-size: var(--text-xs);
    font-weight: 700;
    line-height: 18px;
    text-align: center;
}

.ech-counters { display: flex; flex-wrap: wrap; gap: 12px; margin: 0 0 18px; }
.ech-counter { flex: 1 1 120px; background: #fff; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px 16px; }
.ech-counter .n { font-size: var(--text-2xl); font-weight: 700; line-height: 1; }
.ech-counter .l { font-size: var(--text-sm); color: var(--text-muted); margin-top: 5px; }

.ech-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 16px; }
.ech-fbtn { background: transparent; color: var(--accent); border: 1px solid var(--border); padding: 5px 12px; border-radius: var(--radius-sm); font-size: var(--text-sm); cursor: pointer; }
.ech-fbtn:hover { border-color: var(--accent); }
.ech-fbtn.active { background: var(--accent); color: #fff; border-color: var(--accent); }

.ech-group { margin-bottom: 20px; }
.ech-group-h { font-size: var(--text-base); margin: 0 0 10px; padding-left: 10px; }
.ech-count { display: inline-block; background: var(--border); color: var(--text-main); border-radius: 10px; padding: 0 8px; font-size: var(--text-xs); margin-left: 6px; font-weight: 600; }

.ech-row { display: flex; align-items: center; gap: 14px; padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--radius-sm); margin-bottom: 7px; text-decoration: none; color: var(--text-main); background: #fff; transition: background 0.15s, border-color 0.15s; }
.ech-row:hover { background: #f5f8fc; border-color: var(--accent); }
.ech-urg { flex: 0 0 auto; min-width: 108px; }
.ech-main { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.ech-title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ech-sub { font-size: var(--text-sm); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ech-date { flex: 0 0 auto; font-size: var(--text-sm); color: var(--text-muted); white-space: nowrap; }
@media (max-width: 720px) {
    .ech-date { display: none; }
    .ech-urg { min-width: 92px; }
}
/* Bascule Liste / Calendrier (segmenté) */
.ech-viewtoggle { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; margin-right: 6px; }
.ech-vbtn { background: transparent; color: var(--accent); border: none; padding: 5px 14px; font-size: var(--text-sm); cursor: pointer; }
.ech-vbtn + .ech-vbtn { border-left: 1px solid var(--border); }
.ech-vbtn.active { background: var(--accent); color: #fff; }

/* Vue calendrier mensuel */
.ech-cal-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.ech-cal-head .btn-secondary { padding: 4px 12px; }
.ech-cal-title { font-weight: 600; font-size: var(--text-md); min-width: 170px; text-align: center; text-transform: capitalize; }
.ech-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.ech-cal-dow { text-align: center; font-size: var(--text-xs); color: var(--text-muted); font-weight: 600; padding: 4px 0; text-transform: uppercase; }
.ech-cal-cell { min-height: 94px; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 4px 5px; background: #fff; display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.ech-cal-cell.empty { background: transparent; border: none; }
.ech-cal-cell.today { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.ech-cal-daynum { font-size: var(--text-xs); color: var(--text-muted); font-weight: 600; }
.ech-cal-cell.today .ech-cal-daynum { color: var(--accent); }
.ech-chip { display: block; font-size: var(--text-xs); padding: 2px 6px; border-radius: 4px; color: #fff; text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ech-chip:hover { opacity: 0.88; }
.ech-more { font-size: var(--text-xs); color: var(--text-muted); }
@media (max-width: 720px) {
    .ech-cal-cell { min-height: 62px; padding: 3px; }
    .ech-chip { font-size: var(--text-xs); padding: 1px 4px; }
    .ech-cal-dow { font-size: var(--text-xs); }
}

.print-only { display: none; }
@media print {
    .print-only { display: block !important; }
    .ech-row, .ech-group, .ech-cal-cell { break-inside: avoid; }
    .ech-row { border-color: #ccc; }
}

/* =========================================================================
   CHAMP MULTI-PERSONNES (chips) — cf. UI.multiPersonHtml (v11)
========================================================================= */
.mp-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.mp-chip { display: inline-flex; align-items: center; gap: 4px; background: #e7effa; color: var(--accent); border: 1px solid var(--border); border-radius: 14px; padding: 3px 6px 3px 12px; font-size: var(--text-sm); }
.mp-remove { background: transparent; border: none; color: var(--accent); cursor: pointer; font-size: var(--text-md); line-height: 1; padding: 0 3px; }
.mp-remove:hover { color: var(--color-danger); }
.mp-add { display: flex; gap: 8px; }
.mp-add .mp-input { flex: 1; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: var(--text-base); }
.mp-add .mp-addbtn { background: transparent; color: var(--accent); border: 1px solid var(--border); padding: 6px 12px; border-radius: var(--radius-sm); font-size: var(--text-sm); cursor: pointer; white-space: nowrap; }
.mp-add .mp-addbtn:hover { border-color: var(--accent); }

/* =========================================================================
   VISION GROUPE (/groupe) — consolidation multi-filiales, lot L4
   Ajouté en fin de fichier, sans toucher à l'existant. Tokens seuls
   (css/tokens.css) : aucune couleur écrite en dur, sémantique stricte des
   statuts — vert = conforme, orange = partiel, rouge = critique, gris = NA.
========================================================================= */
.grp-carte { margin-bottom: var(--space-5); }
.grp-h3 { margin: 0 0 var(--space-3); font-size: var(--text-md); color: var(--text-main); }

/* Bandeau de périmètre : ce que la session ouvre, dit avant tout chiffre. */
.grp-perimetre {
    display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
    margin-bottom: var(--space-4); padding: var(--space-3) var(--space-4);
    background: var(--bg-card); border-radius: var(--radius);
    border-left: 4px solid var(--primary); box-shadow: var(--shadow);
    font-size: var(--text-base); color: var(--text-main);
}

/* ── LE TIRET QUI N'EST PAS UN ZÉRO ──────────────────────────────────────
   Un bloc à `null` veut dire « vous n'avez pas le droit de le savoir », jamais
   « il n'y en a pas ». Le pointillé et le curseur d'aide le signalent : ce
   n'est pas une case vide, c'est une case fermée.                          */
.grp-nd {
    color: var(--color-gray); font-weight: 600; cursor: help;
    border-bottom: 1px dotted var(--color-gray);
}
.grp-nd-bloc {
    margin: 0; padding: var(--space-3) var(--space-4);
    background: var(--tint-na); color: var(--text-muted);
    border-left: 3px solid var(--color-gray); border-radius: var(--radius-sm);
    font-size: var(--text-base);
}
/* Une donnée simplement absente — pas de droit en cause. */
.grp-vide { color: var(--text-muted); }

/* Tableau comparatif. Il déborde volontiers : on le fait défiler plutôt que
   de rogner des colonnes qui portent chacune un indicateur distinct. */
.grp-defilement { overflow-x: auto; }
.grp-table th[scope="row"] { text-align: left; background: var(--bg-card); font-weight: 600; }
.grp-table td, .grp-table th { white-space: nowrap; }
.grp-table tbody tr { cursor: pointer; }
.grp-table tbody tr:hover { background: var(--primary-tint); }
.grp-table tbody tr.grp-ligne--active th[scope="row"] { border-left: 3px solid var(--primary); }
.grp-table tbody tr.grp-ligne--vue { background: var(--primary-tint); }
.grp-table tfoot td, .grp-table tfoot th {
    border-top: 2px solid var(--border); font-weight: 700; background: #f8f9fa;
}
.grp-nom { font-weight: 600; color: var(--text-main); }
.grp-sous { font-size: var(--text-xs); color: var(--text-muted); font-weight: 400; }
.grp-active {
    display: inline-block; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.5px;
    background: var(--primary-tint); color: var(--primary-dark);
    border: 1px solid var(--primary); border-radius: 10px; padding: 0 6px; vertical-align: middle;
}

/* Barres comparatives de conformité — HTML/CSS, sans dépendance. */
.grp-barres { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-4); }
.grp-barre-tete { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); font-size: var(--text-sm); }
.grp-barre-tete span:last-child { font-weight: 700; font-variant-numeric: tabular-nums; }
.grp-barre-piste { background: var(--tint-na); height: 9px; border-radius: 5px; overflow: hidden; margin-top: var(--space-1); }
.grp-barre-part { height: 100%; border-radius: 5px; }
.grp-barre-note { font-size: var(--text-xs); color: var(--text-muted); margin-top: 3px; }

/* Répartitions découvertes : le vocabulaire vient du serveur, pas d'ici. */
.grp-reps { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-4); }
.grp-rep h4 {
    margin: 0 0 var(--space-2); font-size: var(--text-xs); text-transform: uppercase;
    letter-spacing: 1px; color: var(--text-muted);
}
.grp-puces { display: flex; flex-wrap: wrap; gap: 6px; }
.grp-puce { display: inline-flex; align-items: center; gap: 4px; }
.grp-puce b { font-variant-numeric: tabular-nums; color: var(--text-main); }
.grp-puce .status { text-transform: none; }

/* Coordonnées de la filiale active (constat Q-160). Une coordonnée absente
   ne laisse pas de libellé orphelin : la ligne entière disparaît. */
.grp-coord { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-3); margin: 0; }
.grp-coord-l dt { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
.grp-coord-l dd { margin: 2px 0 0; color: var(--text-main); font-size: var(--text-base); word-break: break-word; }
.grp-coord-l dd a { color: var(--accent); }

.grp-tuiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-3); }

.grp-erreur {
    margin: var(--space-3) 0; padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm); background: var(--tint-warn); color: #856404;
    border-left: 4px solid var(--color-warning); font-size: var(--text-base);
}
.grp-erreur-geste { margin-top: var(--space-3); }

@media print {
    .grp-table tbody tr { cursor: auto; }
    .grp-defilement { overflow-x: visible; }
}

/* =====================================================================
   APPROBATIONS — circuit de validation (lot L8, js/modules/approbations.js)
   ---------------------------------------------------------------------
   Uniquement des tokens de css/tokens.css, et la sémantique stricte des
   statuts : vert = franchi, orange = en attente, rouge = refusé ou périmé,
   gris = neutre. Aucune couleur nouvelle n'est introduite.
===================================================================== */

/* ── L'avertissement de péremption ────────────────────────────────────
   Il est rouge parce qu'il dit qu'une preuve d'audit ne vaut plus, ce qui
   est le seul message vraiment grave de cet écran. Rien d'autre ici ne
   porte cette teinte, pour qu'elle continue de vouloir dire quelque chose. */
.apr-peremption {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    background: var(--tint-crit);
    border-left: 4px solid var(--color-danger);
    border-radius: var(--radius-sm);
    color: var(--text-main);
}
.apr-peremption p { margin: var(--space-2) 0 0; font-size: var(--text-base); }
.apr-peremption-liste { margin: var(--space-2) 0 0; padding-left: var(--space-5); font-size: var(--text-base); }
.apr-peremption-liste li { margin-bottom: var(--space-1); }

/* ── Note d'information : un droit manquant N'EST PAS une panne ───────
   Neutre à dessein. Un profil qui ne valide pas n'est pas en faute, et un
   bandeau rouge le lui reprocherait. */
.apr-note {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    background: var(--tint-na);
    border-left: 4px solid var(--color-info);
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
    color: var(--text-main);
}
.apr-note p { margin: var(--space-2) 0 0; }

/* ── Résumé de l'état du circuit ─────────────────────────────────────── */
.apr-resume {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-5);
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.apr-resume-bloc { display: flex; flex-direction: column; gap: var(--space-1); }
.apr-etiquette {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
}
.apr-valeur { font-size: var(--text-base); font-weight: 600; color: var(--text-main); }

/* ── Le tableau des étapes ────────────────────────────────────────────
   `.status` porte `text-transform: capitalize`, ce qui défigure « En
   attente » en « En Attente ». Les COULEURS sémantiques sont conservées
   telles quelles — seule la capitalisation est neutralisée, et seulement
   dans les tableaux de cet écran. Même arbitrage que le journal d'audit. */
.apr-table td { vertical-align: top; font-size: var(--text-base); }
.apr-table .status { text-transform: none; }
.apr-rang { width: 2.5rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.apr-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--text-sm);
}
.apr-vide { color: var(--text-muted); }

.apr-etape--attendue { background: var(--primary-tint); }
/* Une étape périmée est barrée : elle a été prise, et elle ne vaut plus. */
.apr-etape--perimee { background: var(--tint-crit); }
.apr-etape--perimee td:nth-child(2) strong { text-decoration: line-through; }

.apr-marque {
    display: inline-block;
    margin-left: var(--space-2);
    padding: 1px var(--space-2);
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    background: var(--primary-tint);
    color: var(--primary-dark);
}
.apr-marque--alerte { background: var(--tint-crit); color: var(--color-danger); }

/* ── Le formulaire de décision ────────────────────────────────────────── */
.apr-decision {
    margin: var(--space-5) 0;
    padding: var(--space-4);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-left: 4px solid var(--primary);
    border-radius: var(--radius);
}
.apr-decision h3 { margin: 0 0 var(--space-2); font-size: var(--text-md); }
.apr-cycle-attendu { margin: 0 0 var(--space-3); color: var(--text-muted); font-size: var(--text-sm); }
.apr-decision label { display: block; margin-bottom: var(--space-1); font-size: var(--text-sm); font-weight: 600; }
.apr-facultatif { font-weight: 400; color: var(--text-muted); }
.apr-decision textarea {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    resize: vertical;
}
.apr-boutons { display: flex; gap: var(--space-3); margin-top: var(--space-3); flex-wrap: wrap; }

/* ── Messages d'issue ─────────────────────────────────────────────────── */
.apr-message {
    margin: var(--space-4) 0;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    border-left: 4px solid var(--color-gray);
    background: var(--tint-na);
    font-size: var(--text-base);
}
.apr-message--succes { border-left-color: var(--color-success); background: var(--tint-ok); }
.apr-message--erreur { border-left-color: var(--color-danger); background: var(--tint-crit); }
.apr-message--info   { border-left-color: var(--color-info);   background: var(--tint-na); }
.apr-recharger { margin-left: var(--space-2); }

/* ── Tours précédents et étapes hors circuit ──────────────────────────── */
.apr-historique { margin-top: var(--space-6); }
.apr-historique h3 { font-size: var(--text-md); margin-bottom: var(--space-3); }
.apr-cycle { margin-bottom: var(--space-5); }
.apr-cycle h4 {
    margin: 0 0 var(--space-2);
    font-size: var(--text-sm);
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
}
.apr-hors-circuit {
    margin: var(--space-5) 0;
    padding: var(--space-3) var(--space-4);
    background: var(--tint-warn);
    border-left: 4px solid var(--color-warning);
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
}
.apr-lien-objet { margin-top: var(--space-5); }
.apr-lien-objet a { color: var(--accent); font-weight: 600; }

/* ── La liste : ce qui attend une décision ────────────────────────────── */
.apr-groupe { margin-bottom: var(--space-6); }
.apr-groupe h2 { font-size: var(--text-md); margin-bottom: var(--space-1); }
.apr-compte {
    display: inline-block;
    min-width: 1.6rem;
    padding: 1px var(--space-2);
    border-radius: 999px;
    background: var(--tint-na);
    color: var(--text-muted);
    font-size: var(--text-xs);
    text-align: center;
}
.apr-explication { margin: 0 0 var(--space-3); color: var(--text-muted); font-size: var(--text-sm); }
.apr-groupe--alerte h2 { color: var(--color-danger); }
.apr-groupe--alerte .apr-compte { background: var(--tint-crit); color: var(--color-danger); }
.apr-groupe--action .apr-compte { background: var(--primary-tint); color: var(--primary-dark); }

.apr-ligne { cursor: pointer; }
.apr-ligne:hover { background: var(--primary-tint); }
.apr-ligne:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* ── L'encart intégré aux fiches Document / Risque / Audit ────────────── */
.apr-encart { margin-top: var(--space-5); }
.apr-encart h2 { font-size: var(--text-md); margin-bottom: var(--space-3); }

/* ═══════════════════════════════════════════════════════════════════════════
   SOCLE DE RISQUES DU GROUPE (/socle) et RÉFÉRENTIELS APPLICABLES
   (/referentiels-actifs) — chantier Groupe, schéma v13.

   Ajouté EN FIN DE FICHIER, sans toucher une seule règle existante : trois
   autres agents écrivent en parallèle, et une retouche au milieu du fichier
   serait un conflit garanti.

   Seuls les tokens de `css/tokens.css` sont employés — aucune couleur littérale
   n'est introduite ici, et la sémantique des statuts (vert = conforme,
   orange = partiel, rouge = critique, gris = non applicable) n'est pas
   détournée : ces deux écrans ne portent pas de statut de conformité.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Bandeaux d'explication communs aux deux écrans ────────────────────────
   Ils ne sont pas décoratifs : chacun porte une distinction que le cadrage
   range parmi les « pièges à ne pas rouvrir », et qu'un RSSI qui ouvre l'écran
   pour la première fois n'a aucune raison de connaître. */
.grp-note {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-left: 4px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--bg-card);
    box-shadow: var(--shadow);
    font-size: var(--text-base);
    color: var(--text-main);
    line-height: 1.5;
}
.grp-note strong { color: var(--accent); }
.grp-note--reserve { border-left-color: var(--color-warning); }
.grp-note--reserve strong { color: var(--color-warning); }
.grp-note p { margin: 0 0 var(--space-2); }
.grp-note p:last-child { margin-bottom: 0; }

/* Message de résultat d'une action (succès, refus du serveur, conflit). */
.grp-message {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
    border-left: 4px solid var(--color-gray);
    background: var(--tint-na);
    color: var(--text-main);
}
.grp-message--ok     { border-left-color: var(--color-success); background: var(--tint-ok); }
.grp-message--refus  { border-left-color: var(--color-danger);  background: var(--tint-crit); }
.grp-message--alerte { border-left-color: var(--color-warning); background: var(--tint-warn); }

.grp-barre {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: flex-end;
    margin: 0 0 var(--space-4);
}
.grp-barre label {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    font-size: var(--text-sm);
    color: var(--text-muted);
}
.grp-barre input, .grp-barre select {
    padding: 6px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    font-family: var(--font-sans);
}

/* Panneau de saisie replié dans la liste : ces deux routes n'ont pas de vue
   « détail » (`js/app.js` ne câble que `renderList`), la saisie vit donc DANS
   la liste plutôt que dans un écran que le routeur n'atteindrait pas. */
.grp-panneau {
    margin: 0 0 var(--space-5);
    padding: var(--space-4);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-top: 3px solid var(--primary);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
}
.grp-panneau h2 { font-size: var(--text-md); margin: 0 0 var(--space-3); }
.grp-panneau--groupe { border-top-color: var(--accent); }
.grp-panneau--groupe h2 { color: var(--accent); }
.grp-grille-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
}
.grp-actions { display: flex; gap: var(--space-3); margin-top: var(--space-4); flex-wrap: wrap; }

@media (max-width: 768px) {
    .grp-grille-2 { grid-template-columns: 1fr; }
}

/* ── /socle — le catalogue ─────────────────────────────────────────────── */
.soc-table td { vertical-align: top; font-size: var(--text-base); }
.soc-nom { font-weight: 600; }
.soc-desc { display: block; color: var(--text-muted); font-size: var(--text-sm); margin-top: 2px; }
.soc-ref {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--text-sm);
    color: var(--text-muted);
}
.soc-vide { color: var(--text-muted); }
.soc-outils { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.soc-outils button {
    padding: 4px 10px;
    font-size: var(--text-sm);
    background: transparent;
    color: var(--accent);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.soc-outils button:hover { background: var(--primary-tint); border-color: var(--primary); color: var(--primary-dark); }
.soc-outils button.soc-danger { color: var(--color-danger); }
.soc-outils button.soc-danger:hover { background: var(--tint-crit); border-color: var(--color-danger); color: var(--color-danger); }

/* ── /referentiels-actifs — une carte par référentiel du catalogue ──────── */
.rfa-grille {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--space-4);
}
.rfa-carte {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-left: 4px solid var(--color-gray);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}
.rfa-carte--actif { border-left-color: var(--color-success); }
.rfa-carte--inconnu { border-left-color: var(--color-warning); }
.rfa-titre { font-size: var(--text-md); font-weight: 600; margin: 0; }
.rfa-editeur { color: var(--text-muted); font-size: var(--text-sm); }
.rfa-lignes { list-style: none; margin: var(--space-2) 0 0; padding: 0; font-size: var(--text-sm); }
.rfa-lignes li { display: flex; justify-content: space-between; gap: var(--space-3); padding: 2px 0; }
.rfa-lignes span:first-child { color: var(--text-muted); }
.rfa-motif { font-size: var(--text-sm); color: var(--text-muted); font-style: italic; }
.rfa-verrou { font-size: var(--text-sm); color: var(--color-warning); }
.rfa-pied { margin-top: auto; padding-top: var(--space-3); display: flex; gap: var(--space-2); flex-wrap: wrap; }
.rfa-pied button { padding: 6px 12px; font-size: var(--text-sm); }
.rfa-pied button[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ===== Import généralisé (js/modules/imports.js) ===== */
.imp-proprietes { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-3) 0 var(--space-5);
    padding: var(--space-4); background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
    font-size: var(--text-base); color: var(--text-main); }
.imp-proprietes li { margin-left: 1.1em; }
.imp-bloc-entite, .imp-bloc-fichier { margin-bottom: var(--space-4); }
.imp-select-entite { max-width: 480px; width: 100%; margin: var(--space-2) 0 var(--space-3); }
.imp-details { margin-top: var(--space-2); }
.imp-details summary { cursor: pointer; font-weight: 600; padding: var(--space-1) 0; }
.imp-table-scroll { overflow-x: auto; }
.imp-colonnes-table td, .imp-colonnes-table th { font-size: var(--text-sm); }
.imp-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: var(--text-sm); }
.imp-vide { color: var(--text-muted); }
.imp-gabarit-actions { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-3); }
.imp-depot { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; margin-top: var(--space-2); }
.imp-etat { margin-top: var(--space-2); font-size: var(--text-sm); color: var(--text-muted); min-height: 1.2em; }
.imp-etat-pret { color: var(--color-success); }
.imp-etat-refus { color: var(--color-danger); }
.imp-etat-apercu { color: var(--color-warning); }
.imp-etat-info { color: var(--color-info); }
h3.imp-etat-pret, h3.imp-etat-refus, h3.imp-etat-apercu, h3.imp-etat-info { margin: 0 0 var(--space-2); font-size: var(--text-md); }
.imp-rapport { margin-top: var(--space-4); padding: var(--space-4); border-radius: var(--radius);
    border: 1px solid var(--border); background: var(--bg-card); }
.imp-rapport-refus { border-left: 4px solid var(--color-danger); }
.imp-resume { display: flex; flex-wrap: wrap; gap: var(--space-4); margin: var(--space-2) 0 var(--space-3); font-size: var(--text-base); }
.imp-resume strong { font-variant-numeric: tabular-nums; }
.imp-erreurs-table td, .imp-erreurs-table th { font-size: var(--text-sm); vertical-align: top; }
.imp-erreurs-table .imp-valeur { max-width: 240px; word-break: break-word; color: var(--text-muted); font-style: italic; }
.imp-erreur-bandeau { margin: var(--space-3) 0; padding: var(--space-3) var(--space-4); border-radius: var(--radius-sm);
    background: var(--tint-warn); color: var(--color-warning); border-left: 4px solid var(--color-warning);
    font-size: var(--text-base); }
.imp-note { font-size: var(--text-xs); color: var(--text-muted); margin-top: var(--space-2); line-height: 1.5; }

/* ── `.status` porte `text-transform: capitalize` ─────────────────────────
   Ce qui convient à un statut d'un mot (« active », « conforme ») défigure une
   locution : « Hors périmètre » s'affichait « Hors Périmètre ». Même défaut, même
   remède que `js/modules/journal.js` (« Refus De Droit ») — on neutralise la
   CAPITALISATION, et elle seule : les couleurs sémantiques du design system
   restent celles des tokens. Vu sur capture d'écran, pas déduit. */
.rfa-carte .status { text-transform: none; }

/* ── Gestion documentaire — la version qui fait foi (action D1, vague 9) ──
   Deux classes seulement, et la seconde compte plus qu'elle n'en a l'air :
   `.doc-verrouille` marque un champ passé en LECTURE parce qu'une pièce jointe
   lui donne sa valeur. Il reste envoyé par le formulaire (`readOnly`, jamais
   `disabled` — un champ désactivé ne part pas, et l'enregistrement suivant
   effacerait la version en silence) ; il doit donc se DISTINGUER à l'œil d'un
   champ saisissable, sinon l'utilisateur croit à une panne de clavier. */
.doc-note { font-size: var(--text-xs); color: var(--text-muted); margin: 4px 0 0; line-height: 1.5; }
.doc-verrouille { background: var(--bg-body); color: var(--text-muted); cursor: default; }


/* =========================================================================
   CLASSIFICATION DOCUMENTAIRE (migration 027)
   ⚠️ AUCUNE couleur sémantique de statut ici, et c'est le §2 du `CLAUDE.md` :
   vert, orange, rouge et gris qualifient une CONFORMITÉ. Un document restreint
   n'est pas « critique », un document public n'est pas « non applicable ».
   L'échelle est bâtie sur le BLEU DE STRUCTURE, dont l'encre s'épaissit à
   mesure que la diffusion se ferme — ce qui la garde lisible à l'impression en
   noir et blanc, où toutes les teintes se valent.
   ========================================================================= */
.diffusion {
    display: inline-block; padding: 2px 9px; border-radius: 11px;
    font-size: var(--text-xs); font-weight: 600; white-space: nowrap;
    border: 1px solid var(--border);
}
.diffusion-public       { background: var(--bg-body);   color: var(--text-muted); }
.diffusion-interne      { background: var(--tint-info); color: var(--accent); border-color: var(--tint-info); }
.diffusion-confidentiel { background: var(--accent);    color: #fff; border-color: var(--accent); }
.diffusion-restreint    { background: var(--accent-hover); color: #fff; border-color: var(--accent-hover);
                          box-shadow: inset 0 0 0 2px rgba(255,255,255,0.35); }

/* Marqueur « données personnelles » — une lettre, pas une couleur de statut. */
.marqueur-dp {
    display: inline-block; margin-left: 4px; padding: 1px 6px;
    border: 1px solid var(--accent); border-radius: var(--radius-sm);
    color: var(--accent); font-size: var(--text-xs); font-weight: 800; letter-spacing: 0.5px;
}

/* Étiquettes libres, sous le titre d'un document. */
.etiquettes { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-left: 8px; vertical-align: middle; }
.etiquette {
    background: var(--tint-na); color: var(--text-muted); border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: 1px 7px; font-size: var(--text-xs); font-weight: 600;
}

/* Le bloc de classification du formulaire. */
.bloc-classification {
    border: 1px solid var(--border); border-radius: var(--radius);
    padding: 14px 16px 4px; margin: 0 0 1rem;
}
.bloc-classification legend {
    font-size: var(--text-sm); text-transform: uppercase; letter-spacing: 1px;
    color: var(--text-muted); font-weight: 700; padding: 0 6px;
}

/* Bandeau d'attention — il SIGNALE, il n'accuse pas : la combinaison qu'il
   montre a des cas légitimes, et le texte le dit. D'où le bleu d'information
   plutôt que l'orange d'un statut « partiel ». */
.bandeau-attention {
    background: var(--tint-info); border: 1px solid var(--accent);
    border-left-width: 5px; border-radius: var(--radius);
    padding: 12px 16px; margin-bottom: 1.25rem; font-size: var(--text-base); color: var(--text-main);
}
.lien-bandeau {
    background: transparent; border: none; color: var(--accent);
    font: inherit; font-weight: 700; text-decoration: underline; cursor: pointer; padding: 0 0 0 4px;
}

/* Le registre du produit lui-même (/rgpd) — une pièce à montrer, donc
   imprimable et dense. */
.registre-produit .data-table td { font-size: var(--text-sm); vertical-align: top; }
.registre-produit .rp-colonne { font-family: ui-monospace, Menlo, Consolas, monospace; white-space: nowrap; }
.rp-nature-personnelle   { color: var(--accent); font-weight: 700; }
.rp-nature-non_personnelle { color: var(--text-muted); }

/* =====================================================================
   MENU REPLIABLE — lot L17, action A2
   ---------------------------------------------------------------------
   La barre latérale portait 32 entrées à plat, dont 17 sous un seul
   intertitre. Les en-têtes deviennent des boutons : même densité quand
   tout est ouvert, et une navigation quand on replie.

   ⚠️ Les couleurs viennent des TOKENS (`css/tokens.css`), jamais d'une
   valeur écrite ici — c'est la règle du §2 du `CLAUDE.md`.
   ===================================================================== */

.main-nav .nav-section { margin: 1.1rem 0 0.15rem; }
.main-nav .nav-section:first-child { margin-top: 0; }

.main-nav .nav-section-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 0.35rem 0.75rem;
    background: none;
    border: 0;
    color: var(--text-muted);
    font: inherit;
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-align: left;
    cursor: pointer;
    border-radius: 4px;
}

.main-nav .nav-section-btn:hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }

/* La cible tactile fait 32 px de haut au minimum : un chevron de 8 px ne se
   vise pas au doigt, et la barre latérale sert aussi sur tablette. */
.main-nav .nav-section-btn { min-height: 32px; }

.main-nav .nav-section-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

.main-nav .nav-chevron {
    width: 0;
    height: 0;
    margin-left: 0.5rem;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid currentColor;
    transition: transform 0.15s ease;
    flex: 0 0 auto;
}

.main-nav .nav-section.replie .nav-chevron { transform: rotate(-90deg); }

@media (prefers-reduced-motion: reduce) {
    .main-nav .nav-chevron { transition: none; }
}

/* Une entrée d'une section repliée. ⚠️ Une CLASSE, et non l'attribut
   « hidden » : `appliquerDroitsAuMenu()` écrit `hidden` à chaque navigation
   pour cacher ce que le profil n'a pas le droit de lire. Les deux couches se
   disputaient l'attribut, et le menu se redépliait. Avec une classe, elles se
   composent : visible si le droit existe ET si la section est ouverte. */
.main-nav li.nav-repliee { display: none; }

/* =====================================================================
   PALETTE DE RECHERCHE — lot L17, action A3
   ---------------------------------------------------------------------
   ⚠️ Volontairement sobre : le frontend sera refait (arbitrage du
   15/09/2026). On habille pour que ce soit utilisable, pas pour que ce
   soit fini. Tokens seulement, aucune couleur écrite en dur.
   ===================================================================== */

.palette-declencheur {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: calc(100% - 1.5rem);
    margin: 0 0.75rem 0.75rem;
    padding: 0.5rem 0.65rem;
    min-height: 34px;
    background: rgba(255, 255, 255, 0.07);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 6px;
    color: var(--text-muted);
    font: inherit;
    font-size: var(--text-sm);
    text-align: left;
    cursor: pointer;
}

.palette-declencheur:hover { color: var(--text); background: rgba(255, 255, 255, 0.12); }
.palette-declencheur:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.palette-declencheur kbd {
    font-size: var(--text-xs);
    padding: 0.1rem 0.35rem;
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: 3px;
    white-space: nowrap;
}

.palette-fond {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 12vh;
}

/* ⚠️ SANS CETTE RÈGLE, LA PALETTE NE SE FERME JAMAIS. Le `display: flex`
   ci-dessus est une règle de CLASSE ; `[hidden] { display: none }` vient de la
   feuille du navigateur, et une règle d'auteur l'emporte toujours sur elle.
   `racine.hidden = true` passait donc bien à `true` — et l'overlay restait à
   l'écran.

   ⚠️ **Et l'essai ne pouvait pas le voir** : il vérifiait
   `document.querySelector('.palette-fond').hidden === true`, c'est-à-dire la
   PROPRIÉTÉ, qui était exacte. Il mesurait le drapeau, pas ce que l'utilisateur
   voit — la classe même des constats Q-201 / Q-207. Il mesure désormais la
   visibilité réelle. Signalé par l'utilisateur, pas par le banc. */
.palette-fond[hidden] { display: none; }

.palette {
    width: min(640px, 92vw);
    background: var(--surface, #fff);
    color: var(--text);
    border-radius: 10px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35);
    overflow: hidden;
}

.palette-champ {
    width: 100%;
    padding: 1rem 1.1rem;
    border: 0;
    border-bottom: 1px solid var(--border, rgba(0, 0, 0, 0.12));
    font: inherit;
    font-size: var(--text-md);
    background: transparent;
    color: inherit;
}

.palette-champ:focus { outline: none; }

.palette-corps { max-height: 52vh; overflow-y: auto; }

.palette-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.6rem 1.1rem;
    cursor: pointer;
    min-height: 34px;
}

.palette-item:hover,
.palette-item:focus-visible { background: rgba(0, 0, 0, 0.05); outline: none; }

/* Un résultat sans route connue ne se clique pas : il ne doit pas se
   présenter comme cliquable. La dégradation reste VISIBLE. */
.palette-item:not([data-href]) { cursor: default; opacity: 0.75; }

.palette-libelle { font-weight: 500; }
.palette-entite { color: var(--text-muted); font-size: var(--text-xs); white-space: nowrap; }

.palette-vide { padding: 0.9rem 1.1rem; color: var(--text-muted); font-size: var(--text-base); }

.palette-pied {
    padding: 0.5rem 1.1rem;
    border-top: 1px solid var(--border, rgba(0, 0, 0, 0.12));
    color: var(--text-muted);
    font-size: var(--text-xs);
}

/* =====================================================================
   PASSE DE STYLE PROFESSIONNELLE — 16/09/2026
   ---------------------------------------------------------------------
   Demandée par l'utilisateur : « rendre le logiciel plus professionnel ».
   Arbitrée avec la skill projet `ui-ux-pro-max` (base locale, aucun
   réseau), et bornée par ce que le projet a déjà décidé :

     · la charte reste celle du §2 — orange #E9631B pour l'action et la
       marque, bleu #2059A6 pour la structure, quatre couleurs sémantiques
       réservées aux statuts. La skill ARBITRE, elle n'impose pas de
       palette ;
     · aucune police n'est chargée depuis un réseau (voir `tokens.css`) ;
     · aucun gestionnaire en ligne, aucune dépendance neuve.

   Ce qui est traité, dans l'ordre d'impact mesuré par la skill :
     1. accessibilité (priorité 1) — cibles, focus, contraste ;
     2. lisibilité des TABLEAUX DENSES, qui sont l'essentiel de ce produit ;
     3. échelle typographique et longueur de ligne ;
     4. impression — la sortie papier de cet outil est une PIÈCE D'AUDIT.
   ===================================================================== */

/* ── 1. Rendu du texte ──────────────────────────────────────────────── */

body {
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    /* Le lissage sous-pixel épaissit le texte clair sur fond clair et le rend
       sale sur un écran à forte densité. */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

h1 { font-size: var(--text-xl);  line-height: var(--leading-tight); letter-spacing: -0.01em; }
h2 { font-size: var(--text-lg);  line-height: var(--leading-tight); letter-spacing: -0.005em; }
h3 { font-size: var(--text-md);  line-height: var(--leading-tight); }

/* La prose se borne. Une note d'aide sur 1 800 px de large se relit mal :
   l'œil perd sa ligne au retour (65-75 signes, règle de la skill). */
.help-note, .page > p, .dashboard-header p { max-width: var(--mesure-texte); }

/* ── 2. Ce qui se recopie se lit en CHASSE FIXE ─────────────────────── */
/* Un identifiant, une empreinte, une référence d'audit : c'est ce qu'un
   auditeur recopie dans son rapport. En proportionnelle, le 1 et le l se
   confondent, le 0 et le O aussi — et l'erreur ne se voit qu'à la relecture. */
code, kbd, samp, pre, .mono, .empreinte, .identifiant-technique {
    font-family: var(--font-mono);
    font-size: 0.92em;
    font-variant-ligatures: none;
}

/* ── 3. Les TABLEAUX : le cœur de ce produit ────────────────────────── */

/* Un tableau large ne casse plus la page : il défile dans son propre cadre.
   (Règle « Table Handling » de la skill, sévérité moyenne.) */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.data-table {
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}

/* L'en-tête SUIT le défilement. Sur une table de conformité à 200 lignes, on
   perd sinon le nom des colonnes au premier écran — et c'est exactement là
   qu'on lit un statut sans savoir de quoi il est le statut. */
.data-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: #f8f9fa;
    /* La bordure d'une cellule « sticky » ne suit pas : on la peint en ombre. */
    box-shadow: inset 0 -1px 0 var(--border);
}

/* ⚠️ Les capitales espacées à 1 px étaient datées ET moins lisibles : en
   capitales, l'œil perd les hampes qui distinguent les mots, et 1 px de plus
   sépare les lettres au point de disloquer l'étiquette. On garde la casse
   haute — elle distingue l'en-tête du contenu sans une ligne de plus — avec
   un espacement mesuré et un gris qui recule. */
.data-table th {
    letter-spacing: 0.04em;
    font-size: var(--text-xs);
    color: var(--text-muted);
    font-weight: 600;
    white-space: nowrap;
}

/* Une ligne survolée se désigne. Sans cela, sur douze colonnes, l'œil saute
   de ligne entre la première et la dernière. */
.data-table tbody tr { transition: background-color 0.12s ease; }
.data-table tbody tr:hover { background: var(--tint-info); }

/* Les nombres s'alignent à DROITE et se comparent par la colonne des unités.
   Alignés à gauche, « 9 » et « 1 200 » n'ont plus de rapport visible. */
.data-table td.num, .data-table th.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── 4. Contrôles : cibles et confort ───────────────────────────────── */
/* 44 px est le plancher de la règle « Touch & Interaction » (priorité 2 de la
   skill). On ne l'applique pas aux actions de ligne d'un tableau dense, qui
   perdraient leur densité — mais à tout ce qui se clique isolément. */
.btn, .btn-primary, .btn-secondary, .btn-danger {
    min-height: 38px;
    font-size: var(--text-base);
    line-height: var(--leading-tight);
}

input, select, textarea {
    font-family: inherit;
    font-size: var(--text-md);
    line-height: var(--leading-normal);
}

/* Le focus ne disparaît JAMAIS — priorité 1. La règle générale existe déjà en
   tête de fichier ; celle-ci ferme les composants qui la neutralisaient. */
.help-tip:focus-visible,
.nav-section-btn:focus-visible,
.palette-item:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* ── 5. L'IMPRESSION : ce que l'outil produit comme PREUVE ──────────── */
/* Une fiche de risque, un registre RGPD, une déclaration d'incident sortent de
   cet écran et circulent. Trois défauts se voient à l'impression et jamais à
   l'écran, et ils déprécient la pièce plus que tout le reste. */
@media print {
    /* Une ligne coupée entre deux pages est une ligne qu'on relit deux fois. */
    .data-table tr, .dashboard-card, .help-note { break-inside: avoid; }
    /* L'en-tête se répète en tête de chaque page : sans lui, la page 2 d'un
       tableau de conformité est une colonne de statuts anonymes. */
    .data-table thead { display: table-header-group; }
    .data-table tfoot { display: table-footer-group; }
    /* Le « sticky » n'a pas de sens sur papier et décale l'en-tête d'une ligne. */
    .data-table thead th { position: static; box-shadow: none; }
    /* Fond blanc, texte noir : une impression en niveaux de gris avale les
       aplats clairs, et un statut « conforme » devient illisible. */
    body { background: #fff; color: #000; }
    a[href^="#"]::after { content: ""; }
}

/* =====================================================================
   ATTESTATION DE LECTURE (L19 · 19.1) et HORLOGE RÉGLEMENTAIRE (L20 · 20.1)
   ---------------------------------------------------------------------
   Deux panneaux, un seul jeu de règles : ils vivent côte à côte sur le
   tableau de bord et se ressemblent assez pour qu'un écart se voie.

   ⚠️ **Aucune couleur nouvelle.** Les tons viennent de `css/tokens.css`, et
   les badges réutilisent les quatre classes `.status-*` du produit : vert =
   conforme, orange = partiel, rouge = critique, gris = non applicable. Un
   cinquième jeu de teintes affaiblirait les quatre qui existent.

   ⚠️ **Aucune police chargée depuis un réseau** : `--font-sans` et
   `--font-mono` sont des piles système, et cette règle ne se rediscute pas.
===================================================================== */

.att-encart, .reg-encart { margin-top: var(--space-5); }
.att-encart h2, .reg-encart h2 { font-size: var(--text-lg); margin-bottom: var(--space-3); }

/* ── Le taux de couverture : un chiffre qu'on lit de loin ─────────────
   Il répond à une question d'auditeur (« combien de personnes ont lu ? »),
   et il doit se lire sans être cherché. La jauge n'est pas décorative : un
   pourcentage seul ne dit pas si 90 % vaut 18 sur 20 ou 900 sur 1 000. */
.att-couverture {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin-bottom: var(--space-4);
    flex-wrap: wrap;
}
.att-taux {
    font-size: var(--text-2xl);
    font-weight: 700;
    line-height: var(--leading-tight);
    font-variant-numeric: tabular-nums;
    min-width: 4.5ch;
}
.att-taux--ok   { color: var(--color-success); }
.att-taux--warn { color: var(--color-warning); }
.att-taux--crit { color: var(--color-danger); }
.att-taux--na   { color: var(--color-gray); }

.att-jauge-zone { flex: 1 1 220px; min-width: 200px; }
.att-jauge {
    height: 8px;
    border-radius: var(--radius-sm);
    background: var(--tint-na);
    overflow: hidden;
}
.att-jauge-part { display: block; height: 100%; border-radius: var(--radius-sm); }
.att-jauge-part--ok   { background: var(--color-success); }
.att-jauge-part--warn { background: var(--color-warning); }
.att-jauge-part--crit { background: var(--color-danger); }
.att-jauge-part--na   { background: var(--color-gray); }
.att-jauge-legende {
    margin: var(--space-2) 0 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
}

/* ── Le geste qui engage ───────────────────────────────────────────────
   Il se distingue du reste de la fiche par un fond, parce qu'il inscrit une
   déclaration au journal inaltérable. Ce n'est pas un champ de plus. */
.att-action {
    display: flex;
    align-items: flex-end;
    gap: var(--space-3);
    flex-wrap: wrap;
    padding: var(--space-3) var(--space-4);
    background: var(--primary-tint);
    border-radius: var(--radius);
    border: 1px solid var(--border);
}
.att-reserve-label {
    flex: 0 0 100%;
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text-muted);
}
.att-reserve { flex: 1 1 260px; min-width: 200px; }
.att-version-note {
    margin: var(--space-2) 0 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
    max-width: var(--mesure-texte);
}
.att-mention, .reg-mention {
    margin: var(--space-2) 0 var(--space-3);
    font-size: var(--text-xs);
    color: var(--text-muted);
    max-width: var(--mesure-texte);
}
.reg-mention--alerte { color: var(--color-danger); font-weight: 600; }

.att-table .status, .reg-table .status { text-transform: none; }

/* ── Les listes du tableau de bord ─────────────────────────────────────
   Deux niveaux : l'intitulé, puis la raison. La raison est ce qui distingue
   « jamais lue » de « révisée depuis » — deux situations qui n'appellent pas
   la même réaction, et qu'un simple compteur confondrait. */
.dash-list { list-style: none; margin: 0; padding: 0; }
.att-a-faire-item, .reg-bloc-item {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-3) var(--space-2);
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    transition: background-color 0.12s ease;
}
.att-a-faire-item:last-child, .reg-bloc-item:last-child { border-bottom: none; }
.att-a-faire-item:hover, .reg-bloc-item:hover { background: var(--tint-info); }
.att-a-faire-titre, .reg-bloc-titre {
    font-weight: 600;
    font-size: var(--text-base);
    line-height: var(--leading-tight);
}
.att-a-faire-meta, .reg-bloc-meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-xs);
    color: var(--text-muted);
    flex-wrap: wrap;
}

/* ── L'origine de l'horloge ────────────────────────────────────────────
   Elle est écrite AU-DESSUS du tableau, et non en note de bas de panneau :
   une horloge dont on ignore l'origine ne se défend pas devant l'ANSSI, et
   une mention qu'on lit après les chiffres arrive trop tard. */
.reg-origine {
    margin: 0 0 var(--space-3);
    font-size: var(--text-xs);
    color: var(--text-muted);
    max-width: var(--mesure-texte);
}
.reg-origine--approx {
    color: var(--color-warning);
    font-weight: 600;
}

/* Une échéance dépassée se voit sur la LIGNE, pas seulement dans son badge :
   sur quatre paliers, l'œil balaie la colonne de gauche et manque le badge. */
.reg-ligne--crit td:first-child { box-shadow: inset 3px 0 0 var(--color-danger); }
.reg-ligne--warn td:first-child { box-shadow: inset 3px 0 0 var(--color-warning); }
.reg-ligne--ok   td:first-child { box-shadow: inset 3px 0 0 var(--color-success); }
.reg-fait-le { display: block; font-size: var(--text-xs); color: var(--text-muted); }

.reg-consigner {
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--bg-body);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.reg-consigner-titre {
    display: block;
    font-size: var(--text-sm);
    margin-bottom: var(--space-2);
}
.reg-consigner-ligne {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
    align-items: center;
}
.reg-consigner-ligne select { flex: 0 1 260px; }
.reg-consigner-ligne input  { flex: 1 1 200px; min-width: 160px; }

/* Une étiquette lue par les lecteurs d'écran et par eux seuls. Le champ
   qu'elle désigne porte déjà un « placeholder », mais un placeholder n'est
   PAS une étiquette : il disparaît à la saisie, et il n'est pas annoncé. */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* =====================================================================
   DÉROGATIONS — écarts de conformité assumés (L19 · 19.2)
   ---------------------------------------------------------------------
   ⚠️ Aucune couleur nouvelle : les badges réutilisent les quatre classes
   `.status-*` du produit, et les bandeaux les teintes `--tint-*` qui leur
   correspondent. Un cinquième jeu affaiblirait les quatre qui existent.
===================================================================== */

.der-encart { margin-top: var(--space-5); }
.der-encart h2 { font-size: var(--text-lg); margin-bottom: var(--space-3); }

/* ── Le bandeau : la réponse à la seule question qui compte ───────────
   « Cet écart est-il couvert, oui ou non ? » Elle se lit avant le tableau,
   parce qu'un tableau de quatre lignes ne répond pas à une question binaire. */
.der-bandeau {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    border-left: 4px solid transparent;
}
.der-bandeau--couvert {
    background: var(--tint-ok);
    border-left-color: var(--color-success);
}
.der-bandeau--decouvert {
    background: var(--tint-crit);
    border-left-color: var(--color-danger);
}

.der-table .status { text-transform: none; }
.der-motif { max-width: 34ch; }
.der-compensation {
    display: block;
    margin-top: var(--space-1);
    font-size: var(--text-xs);
    color: var(--text-muted);
}

/* Une ligne se désigne par son bord, pas seulement par son badge : sur cinq
   colonnes, l'œil balaie la gauche et manque le badge. */
.der-ligne--crit td:first-child { box-shadow: inset 3px 0 0 var(--color-danger); }
.der-ligne--warn td:first-child { box-shadow: inset 3px 0 0 var(--color-warning); }
.der-ligne--ok   td:first-child { box-shadow: inset 3px 0 0 var(--color-success); }

.der-circuit-hote { padding: var(--space-2) 0; }
.der-circuit-btn { font-size: var(--text-xs); padding: 4px 10px; }

/* La légende ne liste que les états PRÉSENTS : un glossaire complet se lirait
   comme un avertissement général, et un avertissement général n'est pas lu. */
.der-legende {
    margin: var(--space-3) 0 0;
    padding-left: var(--space-5);
    font-size: var(--text-xs);
    color: var(--text-muted);
    max-width: var(--mesure-texte);
}
.der-legende li { margin-bottom: var(--space-1); }

/* ── La demande ───────────────────────────────────────────────────────
   Étiquette au-dessus du champ, en grille : les quatre saisies n'ont pas la
   même hauteur, et un alignement à gauche les ferait danser. */
.der-demande {
    margin-top: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--bg-body);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.der-demande-titre { display: block; font-size: var(--text-sm); margin-bottom: var(--space-3); }
.der-demande-grille {
    display: grid;
    grid-template-columns: minmax(10rem, 14rem) 1fr;
    gap: var(--space-2) var(--space-4);
    align-items: start;
}
.der-demande-grille label {
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--text-muted);
    padding-top: 0.55rem;
}
.der-demande-grille textarea { resize: vertical; }
.der-facultatif { font-weight: 400; }
.der-demande button { margin-top: var(--space-3); }
.der-mention {
    margin: var(--space-2) 0 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
    max-width: var(--mesure-texte);
}

/* Sur un écran étroit, l'étiquette passe au-dessus de son champ plutôt que de
   comprimer les deux colonnes jusqu'à l'illisible. */
@media (max-width: 720px) {
    .der-demande-grille { grid-template-columns: 1fr; }
    .der-demande-grille label { padding-top: 0; }
}

/* ── Le badge de la liste des exigences ───────────────────────────────
   Il s'ajoute à côté du code, jamais à la place : le code est ce qu'on cherche
   dans cette colonne, et un badge qui le pousse hors de vue le cacherait. */
.der-badge {
    display: inline-block;
    margin-left: var(--space-2);
    padding: 2px 8px;
    border-radius: 20px;
    background: var(--tint-warn);
    color: var(--color-warning);
    font-size: var(--text-xs);
    font-weight: 600;
    white-space: nowrap;
    vertical-align: middle;
}

/* =====================================================================
   LE GABARIT D'ÉCRAN — `UI.enteteHtml()`
   ---------------------------------------------------------------------
   Un seul en-tête pour les trente écrans, là où chacun recomposait le sien.
   ⚠️ Toutes les tailles viennent de l'échelle de `css/tokens.css` : c'est le
   but du composant, et le mesurer était le diagnostic — 278 `font-size` en
   dur portant 42 valeurs distinctes, dont huit entre 0,70 et 0,78 rem.
===================================================================== */

.page-entete {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-bottom: var(--space-5);
}
.page-entete h1 { margin: 0; }

/* Le sous-titre dit DE QUOI on parle — le périmètre, le filtre, le compte.
   Il se borne en largeur : une ligne de 1 800 px se relit mal (règle de
   mesure de la skill, 65-75 signes). */
.page-contexte {
    margin: var(--space-2) 0 0;
    color: var(--text-muted);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    max-width: var(--mesure-texte);
}

.page-actions {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
    align-items: center;
}

/* ── Les onglets ──────────────────────────────────────────────────────
   Ce sont des LIENS : ils se partagent, ils reviennent avec le bouton
   « Précédent », et ils sont au clavier sans une ligne de script. L'onglet
   courant porte `aria-current="page"` — la couleur seule ne dit rien à qui
   ne la voit pas (règle « Color Only », sévérité haute). */
.page-onglets {
    margin: 0 0 var(--space-5);
    border-bottom: 1px solid var(--border);
}
.page-onglets ul {
    display: flex;
    gap: var(--space-1);
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-x: auto;
}
.page-onglets a {
    display: block;
    padding: var(--space-3) var(--space-4);
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--text-muted);
    text-decoration: none;
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    /* Le trait ne doit pas faire sauter la ligne quand il apparaît. */
    margin-bottom: -1px;
    transition: color 0.12s ease, border-color 0.12s ease;
}
.page-onglets a:hover { color: var(--text-main); border-bottom-color: var(--border); }
.page-onglets a.page-onglet--actif {
    color: var(--primary-dark);
    border-bottom-color: var(--primary);
}
.page-onglets a:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

/* À l'impression, l'onglet courant se lit comme un intertitre : la pièce
   doit dire QUELLE vue elle porte, et les autres onglets n'ont rien à y faire. */
@media print {
    .page-entete { margin-bottom: var(--space-4); }
}

/* ── Les deux classes de bouton qui manquaient ────────────────────────
   `.btn-secondary` existait ; `.btn-danger` et `.btn-accent` étaient posés
   trente fois en style EN LIGNE — `style="background:var(--color-danger)"` —,
   ce qui explique qu'ils n'aient jamais eu ni survol, ni focus, ni taille de
   cible cohérente. Les nommer, c'est pouvoir les corriger une fois. */
.btn-danger { background: var(--color-danger); }
.btn-danger:hover { background: #a5281b; }
.btn-accent { background: var(--accent); }
.btn-accent:hover { background: var(--accent-hover); }

/* Un bouton d'en-tête et un lien d'en-tête doivent avoir la MÊME hauteur :
   sinon la barre d'actions dandine, et c'est le premier détail qui fait
   « amateur » sur un écran par ailleurs soigné. */
.page-actions .btn-secondary,
.page-actions button {
    min-height: 38px;
    display: inline-flex;
    align-items: center;
    font-size: var(--text-base);
    line-height: var(--leading-tight);
}

/* ── L'ANCIEN EN-TÊTE ADOPTE LES RÈGLES DU NOUVEAU ────────────────────
   Quarante-sept `dashboard-header` subsistent dans vingt-sept modules, et les
   convertir un par un prendrait plus de temps que ce que l'incohérence mérite.
   On fait donc d'abord ce qui coûte trois règles : **les deux en-têtes suivent
   les mêmes**. La conversion vers `UI.enteteHtml()` reste souhaitable — elle
   apporte les onglets et supprime le balisage recopié —, mais elle n'est plus
   un préalable à la cohérence visuelle.

   ⚠️ `justify-content` et `align-items` étaient déjà là ; ce qui manquait est
   l'ESPACEMENT (posé en `rem` arbitraires), le retour à la ligne sur écran
   étroit, et le fait qu'un sous-titre d'en-tête ne ressemblait à rien de
   précis — chaque module posait sa couleur et sa marge à la main. */
.dashboard-header {
    gap: var(--space-4);
    flex-wrap: wrap;
    align-items: flex-start;
    margin-bottom: var(--space-5);
}
.dashboard-header > div:first-child > h1 { margin: 0; }
/* Le sous-titre : même taille, même gris, même mesure que `.page-contexte`,
   quelles que soient les valeurs posées en ligne — celles-ci restent, mais
   elles portent sur la couleur et la marge, que l'on reprend ici. */
.dashboard-header > div:first-child > p {
    margin: var(--space-2) 0 0;
    color: var(--text-muted);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    max-width: var(--mesure-texte);
}
/* La barre d'actions : deuxième bloc de l'en-tête quand il y en a deux. Les
   modules y posaient `display:flex; gap:10px` en ligne, trente fois, avec
   trois valeurs d'espacement différentes. */
.dashboard-header > div + div {
    display: flex;
    gap: var(--space-3);
    flex-wrap: wrap;
    align-items: center;
}
.dashboard-header > div + div > button,
.dashboard-header > div + div > .btn-secondary,
.dashboard-header > div + div > a {
    min-height: 38px;
    display: inline-flex;
    align-items: center;
    font-size: var(--text-base);
    line-height: var(--leading-tight);
}

/* La note qui accompagne le registre de l'outil : de la prose, donc bornée. */
.rgpd-note {
    margin: 0 0 var(--space-4);
    color: var(--text-muted);
    font-size: var(--text-base);
    line-height: var(--leading-relaxed);
    max-width: var(--mesure-texte);
}

/* =====================================================================
   DOCUMENTS ↔ CONTRÔLES (L19 · 19.3) — `js/modules/preuves.js`
   ---------------------------------------------------------------------
   Le même panneau des deux côtés du lien : une liste, une portée, un geste.
   Rien de neuf en couleur — un rattachement n'est pas un statut, et lui en
   donner un ferait croire qu'il vaut évaluation.
===================================================================== */

.prv-encart { margin-top: var(--space-5); }
.prv-encart h2 { font-size: var(--text-lg); margin-bottom: var(--space-3); }

.prv-liste { list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.prv-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--border);
}
.prv-item:last-child { border-bottom: none; }
.prv-nom { font-weight: 600; font-size: var(--text-base); color: var(--accent); text-decoration: none; }
.prv-nom:hover { text-decoration: underline; }
/* Un identifiant qu'on ne sait pas résoudre se LIT, il ne disparaît pas : une
   ligne effacée ferait croire au lien absent. */
.prv-inconnu { color: var(--text-muted); font-family: var(--font-mono); font-weight: 400; }
.prv-portee {
    font-size: var(--text-xs);
    color: var(--text-muted);
    background: var(--tint-na);
    padding: 2px 8px;
    border-radius: 20px;
    white-space: nowrap;
}
.prv-retirer {
    margin-left: auto;
    font-size: var(--text-xs);
    padding: 4px 10px;
    background: transparent;
    color: var(--color-danger);
    border: 1px solid var(--border);
}
.prv-retirer:hover { background: var(--tint-crit); border-color: var(--color-danger); }

.prv-ajout {
    display: flex;
    gap: var(--space-3);
    align-items: center;
    flex-wrap: wrap;
    padding: var(--space-3) var(--space-4);
    background: var(--bg-body);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.prv-ajout select { flex: 1 1 260px; min-width: 200px; }

.prv-mention {
    margin: var(--space-2) 0 0;
    font-size: var(--text-xs);
    color: var(--text-muted);
    max-width: var(--mesure-texte);
}

/* ── Efficacité et contrôle périodique (L19 · 19.5 et 19.6) ───────────
   Deux blocs encadrés, et l'encadrement est le propos : la maturité dit à quel
   point un contrôle est institutionnalisé, l'efficacité s'il protège. Les
   poser côte à côte dans la même grille inviterait à les lire comme deux notes
   de la même chose — c'est le défaut classique des tableaux de bord GRC. */
.mes-efficacite, .mes-controle {
    margin: var(--space-4) 0 0;
    padding: var(--space-3) var(--space-4) var(--space-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}
.mes-efficacite legend, .mes-controle legend {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--text-muted);
    padding: 0 var(--space-2);
}
.mes-echeance {
    margin: 0 0 var(--space-2);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--color-success);
}
.mes-echeance--retard { color: var(--color-danger); }

/* =====================================================================
   ANALYSE D'IMPACT — RGPD article 35 (action 20.3)
   ---------------------------------------------------------------------
   Sobriété : aucune couleur qui ne soit un statut. « Présumée requise » est
   un statut — une non-conformité qui s'ignore —, « non présumée » n'en est
   pas un, et il se rend en texte atténué.
   ===================================================================== */
.aipd-encart { margin-top: 1.5rem; max-width: 900px; }
.aipd-table td { vertical-align: middle; font-size: var(--text-sm); }
.aipd-table .status { text-transform: none; }
.aipd-motif td {
    font-size: var(--text-sm);
    color: var(--text-muted);
    background: var(--surface-alt, rgba(0, 0, 0, 0.02));
}
.aipd-vide { font-size: var(--text-base); margin: 0 0 .5rem; }
.aipd-presomption {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.55;
    max-width: 78ch;
    margin: .25rem 0 1rem;
}
.aipd-neant { color: var(--text-muted); font-style: italic; }
.aipd-form {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border, #e3e6ea);
    display: grid;
    grid-template-columns: repeat(3, minmax(9rem, 1fr));
    gap: .75rem 1rem;
    align-items: end;
}
.aipd-form-ligne { display: flex; flex-direction: column; gap: .25rem; }
.aipd-form-ligne label { font-size: var(--text-xs); color: var(--text-muted); }
.aipd-form-large { grid-column: 1 / -1; }
.aipd-avertissement {
    grid-column: 1 / -1;
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.55;
    max-width: 78ch;
    margin: 0;
}
.aipd-vue-ligne, .aipd-manque { cursor: pointer; }
.aipd-form-actions { grid-column: 1 / -1; display: flex; gap: .5rem; align-items: center; }
/* La décision enregistrée et l'état dérivé se contredisent en apparence : la
   phrase qui les réconcilie doit se distinguer de l'avertissement ordinaire. */
.aipd-contradiction {
    border-left: 3px solid var(--color-warning, #e0a800);
    padding-left: .75rem;
}

/* =====================================================================
   DEMANDES D'EXERCICE DE DROITS — RGPD art. 15 à 22 (action 20.4)
   ===================================================================== */
.dro-note {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.55;
    max-width: 82ch;
    margin: .25rem 0 1rem;
}
.dro-proroge { text-transform: none; margin-left: .35rem; cursor: help; }
.dro-form {
    margin-top: 1.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border, #e3e6ea);
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .75rem 1rem;
    align-items: end;
}
.dro-form-ligne { display: flex; flex-direction: column; gap: .25rem; }
.dro-form-ligne label { font-size: var(--text-xs); color: var(--text-muted); }
.dro-avertissement {
    grid-column: 1 / -1;
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.55;
    max-width: 82ch;
    margin: 0;
}
.dro-form button { grid-column: 1 / -1; justify-self: start; }

/* =====================================================================
   MAIN COURANTE DE CRISE — en ajout seul (action 20.5)
   ===================================================================== */
.mc-encart { margin-top: 1.5rem; max-width: 900px; }
.mc-verdict {
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.55;
    max-width: 82ch;
    margin: 0 0 1rem;
}
.mc-verdict .status { text-transform: none; margin-right: .35rem; }
.mc-verdict--rompu {
    border-left: 3px solid var(--color-danger, #c62828);
    padding-left: .75rem;
    color: var(--text);
}
.mc-verdict--rompu ul { margin: .5rem 0 0; padding-left: 1.1rem; }
.mc-liste { list-style: none; margin: 0; padding: 0; }
.mc-entree {
    border-left: 2px solid var(--border, #e3e6ea);
    padding: .5rem 0 .75rem .85rem;
    margin-left: .25rem;
}
.mc-entete {
    display: flex;
    gap: .6rem;
    align-items: baseline;
    flex-wrap: wrap;
    font-size: var(--text-xs);
    color: var(--text-muted);
}
.mc-heure { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.mc-categorie { text-transform: none; }
.mc-texte { font-size: var(--text-sm); margin-top: .2rem; white-space: pre-wrap; }
.mc-form {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border, #e3e6ea);
    display: grid;
    grid-template-columns: 12rem 1fr;
    gap: .5rem 1rem;
    align-items: end;
}
.mc-form-ligne { display: flex; flex-direction: column; gap: .25rem; }
.mc-form-ligne label { font-size: var(--text-xs); color: var(--text-muted); }
.mc-form-large { grid-column: 1 / -1; }
.mc-avertissement, .mc-note {
    grid-column: 1 / -1;
    font-size: var(--text-xs);
    color: var(--text-muted);
    line-height: 1.55;
    max-width: 82ch;
    margin: 0;
}
.mc-form button { grid-column: 1 / -1; justify-self: start; }


/* =========================================================================
   Lots L22 et L23 — l'ouverture technique et la collecte automatique
   -------------------------------------------------------------------------
   ⚠️ **Ces six classes sont définies PARCE QU'ELLES SONT ÉCRITES.** Les écrans
   livrés les 18 et 19/09 se rendaient à plat : `card` et `muted` étaient
   écrites dans le balisage et définies dans AUCUNE feuille, et rien ne le
   disait — ni le banc, ni le rendu, qui affiche simplement une page sans
   style. *Une classe écrite n'est pas une classe définie*, et c'est la
   quatrième fois que le défaut revient. Le vérifier fait partie de la
   livraison d'un écran neuf.
   ========================================================================= */

/* Un formulaire en grille : libellé au-dessus du champ, qui se replie en une
   colonne sous 640 px — c'est la largeur d'un téléphone en portrait. */
.form-grid {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-3, 12px);
    margin-top: var(--space-4, 16px);
}
.form-grid > label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: var(--text-sm);
    color: var(--text-muted);
    min-width: 180px;
    flex: 1 1 180px;
}
.form-grid > label > input,
.form-grid > label > select {
    padding: 6px 8px;
    border: 1px solid var(--border, #d7dde5);
    border-radius: var(--radius-sm, 4px);
    font: inherit;
    color: var(--text, #1c2430);
}
.form-grid > button { flex: 0 0 auto; }

/* Le groupe de cases à cocher des domaines d'un jeton. */
.cases {
    flex: 1 1 100%;
    border: 1px solid var(--border, #d7dde5);
    border-radius: var(--radius-sm, 4px);
    padding: var(--space-2, 8px) var(--space-3, 12px);
    margin: 0;
}
.cases > legend { font-size: var(--text-sm); color: var(--text-muted); padding: 0 4px; }
.case-en-ligne {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 4px 14px 4px 0;
    font-size: var(--text-sm);
    white-space: nowrap;
}

/* Les cartes de description des genres de connecteurs. */
.cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: var(--space-3, 12px);
}
.cards-grid > .card { margin: 0; }

/* Le détail d'un constat : des couples « clé : valeur », serrés. */
.liste-detail { margin: 0; padding-left: 1.1em; font-size: var(--text-sm); }
.liste-detail > li { margin: 2px 0; }

/* L'encart du secret d'un jeton — il n'apparaît qu'UNE fois, et il doit se
   voir : c'est la seule occasion de le copier. */
.encart-alerte {
    border-left: 4px solid var(--accent, #E9631B);
    background: var(--tint-accent, #fdf1e9);
}
.secret-jeton {
    display: inline-block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--text-sm);
    background: #fff;
    border: 1px solid var(--border, #d7dde5);
    border-radius: var(--radius-sm, 4px);
    padding: 6px 10px;
    /* ⚠️ Un secret de 43 caractères ne doit ni déborder, ni être coupé à la
       copie : on autorise le retour à la ligne SANS césure ajoutée. */
    word-break: break-all;
    user-select: all;
}

/* Un bouton de tableau : la même identité, en plus petit. */
.btn-sm { padding: 3px 8px; font-size: var(--text-sm); }

/* =========================================================================
   Lot L27 — l'assistance par IA
   -------------------------------------------------------------------------
   ⚠️ **Vérifié classe par classe avant la livraison**, et c'est la leçon de la
   vague E : huit classes y avaient été écrites et définies dans aucune
   feuille, deux fois le même jour. *Une classe écrite n'est pas une classe
   définie, et aucun essai ne le dit.*
   ========================================================================= */

/* Le bandeau du mode externe — barrière n° 6. PERMANENT, sans bouton de
   fermeture : même mécanique que le bandeau du profil découverte, pour la même
   raison — ce qu'on ne voit pas devient une habitude. */
.bandeau-alerte {
    border-left: 4px solid var(--color-danger, #a5281b);
    background: var(--tint-danger, #fdeceb);
    color: var(--text, #1c2430);
    padding: var(--space-3, 12px);
    border-radius: var(--radius-sm, 4px);
    margin: var(--space-3, 12px) 0;
    font-weight: 600;
}

/* La matière d'une demande : des couples étiquette / valeur. */
.matiere { margin-top: var(--space-3, 12px); }
.matiere-ligne {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2, 8px);
    margin-bottom: var(--space-2, 8px);
}
.matiere-ligne > input {
    padding: 6px 8px;
    border: 1px solid var(--border, #d7dde5);
    border-radius: var(--radius-sm, 4px);
    font: inherit;
}
.matiere-etiquette { flex: 1 1 200px; }
.matiere-valeur { flex: 2 1 320px; }

/* Le texte EXACT qui part, et celui qui revient. ⚠️ Rendu tel quel, en
   `pre` : le reformater viderait la barrière n° 4 de son sens — l'utilisateur
   doit voir ce qui part, pas une mise en page de ce qui part. */
.invite {
    white-space: pre-wrap;
    word-break: break-word;
    background: #fff;
    border: 1px solid var(--border, #d7dde5);
    border-radius: var(--radius-sm, 4px);
    padding: var(--space-3, 12px);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--text-sm);
    max-height: 22em;
    overflow-y: auto;
}

/* =====================================================================
   KANBAN DU PLAN D'ACTIONS  (lot L17, action A5)

   ⚠️ Aucune couleur n'est posée en dur : tout vient de `tokens.css`, et les
   quatre couleurs sémantiques restent réservées aux statuts (décision §2 du
   `CLAUDE.md`). Le bord gauche d'une carte porte la PRIORITÉ, qui n'est pas
   un statut de conformité — c'est pourquoi il emprunte `--color-info` et non
   le vert de « conforme ».
   ===================================================================== */

.bascule-vue {
    display: inline-flex;
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
}

.bascule-vue button {
    background: var(--surface);
    color: var(--text-main);
    border: 0;
    padding: 7px 16px;
    font-size: var(--text-sm);
    cursor: pointer;
}

.bascule-vue button + button { border-left: 1px solid var(--border); }
.bascule-vue button:hover { background: var(--surface-alt, var(--bg)); }

.bascule-vue button.actif {
    background: var(--primary);
    color: #fff;
}

.kanban {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 14px;
    align-items: start;
}

.kanban-colonne {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px;
}

.kanban-titre {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 10px;
    font-size: var(--text-base);
    text-transform: uppercase;
    letter-spacing: .02em;
    color: var(--text-muted);
}

.kanban-compte {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 1px 9px;
    font-size: var(--text-xs);
    color: var(--text-main);
}

/* La pile garde une hauteur minimale : une colonne vide doit rester une
   CIBLE DE DÉPÔT, sinon on ne peut jamais y ramener la première carte. */
.kanban-pile {
    min-height: 90px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    border-radius: 6px;
    padding: 2px;
}

.kanban-pile.survol {
    outline: 2px dashed var(--primary);
    outline-offset: 2px;
}

.kanban-vide {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0;
    padding: 6px 2px;
}

.kanban-carte {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 10px 12px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.kanban-carte.en-vol { opacity: .45; }
.kanban-carte[draggable="true"] { cursor: grab; }

/* Le titre est un BOUTON, pas un div cliquable : il prend le focus au
   clavier et s'annonce comme actionnable. */
.kanban-ouvrir {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: 0;
    padding: 0;
    font-size: var(--text-base);
    font-weight: 700;
    color: var(--text-main);
    cursor: pointer;
}

.kanban-ouvrir:hover { color: var(--primary); text-decoration: underline; }

.kanban-meta {
    margin: 6px 0 0;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.kanban-deplacer {
    display: flex;
    gap: 6px;
    margin-top: 8px;
}

.kanban-deplacer button {
    background: var(--bg);
    color: var(--text-main);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 2px 10px;
    font-size: var(--text-sm);
    line-height: 1.6;
    cursor: pointer;
}

.kanban-deplacer button:disabled {
    opacity: .35;
    cursor: not-allowed;
}

@media print {
    .kanban { grid-template-columns: repeat(3, 1fr); }
    .kanban-deplacer, .bascule-vue { display: none; }
}

/* =====================================================================
   FORMULAIRE DE NOTIFICATION AUX AUTORITÉS  (lot L20, action 20.2)

   ⚠️ Ce document est destiné à être IMPRIMÉ et relu sur papier : c'est
   ainsi qu'il sera vérifié avant d'être déposé. Les rubriques en creux
   doivent donc rester visibles à l'impression — elles ne sont pas un
   ornement d'écran, elles sont ce qui empêche un envoi incomplet.
   ===================================================================== */

.notif-document {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 22px 26px;
    max-width: 52rem;
}

.notif-entete h2 {
    margin: 0 0 6px;
    font-size: var(--text-xl);
}

.notif-delai {
    margin: 0 0 14px;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.notif-avertissement {
    border-left: 4px solid var(--color-warning);
    background: var(--bg);
    padding: 10px 14px;
    margin: 0 0 14px;
    font-size: var(--text-sm);
}

.notif-compte {
    font-weight: 700;
    margin: 0 0 14px;
    color: var(--color-warning);
}

.notif-compte.notif-complet { color: var(--color-success); }

.notif-table th[scope="row"] {
    width: 34%;
    text-align: left;
    vertical-align: top;
    font-weight: 700;
}

.notif-table td { vertical-align: top; }

.notif-manque td em {
    color: var(--color-danger);
    font-style: normal;
    font-weight: 700;
    letter-spacing: .03em;
}

.notif-attendu {
    margin: 4px 0 0;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.notif-pied {
    margin-top: 18px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
    font-size: var(--text-sm);
    color: var(--text-muted);
}

@media print {
    .notif-document { border: 0; padding: 0; max-width: none; }
    /* Une rubrique en creux doit sauter aux yeux sur le papier : c'est là
       qu'on relit avant d'envoyer. */
    .notif-manque td em { text-decoration: underline; }
}

/* Astérisque de champ obligatoire — voir le token dans `tokens.css`. */
.champ-requis {
    color: var(--marque-requis);
    font-weight: 700;
    margin-left: 2px;
}

/* Bouton « retirer une ligne » d'un tableau de saisie (grille d'audit).
   ⚠️ Il portait `color:red` en dur ; il prend le rouge SÉMANTIQUE, lui,
   parce qu'il désigne bien une destruction — la nuance avec l'astérisque
   de champ obligatoire est le sujet même du token `--marque-requis`. */
.bouton-retirer {
    background: none;
    color: var(--color-danger);
    border: none;
    font-size: var(--text-xl);
    line-height: 1;
    cursor: pointer;
}

/* =====================================================================
   CLASSES UTILITAIRES  (passe de style du 21/09/2026)

   ⚠️ **Elles ne remplacent PAS le système de composants** : chacune reprend
   un motif de `style="…"` qui se répétait plus de quinze fois dans
   `js/modules/`, à l'identique. Le gain n'est pas cosmétique — c'est que le
   prochain changement de densité, de gouttière ou de couleur de lien se
   fasse à UN endroit au lieu de vingt-sept.

   ⚠️ Mesuré avant la passe : 1 205 attributs `style` pour 565 motifs
   DISTINCTS. Les onze classes ci-dessous en couvrent environ 235 — les plus
   répétés. Le reste est spécifique à son écran, et le convertir de force
   produirait des classes à un seul usage, c'est-à-dire des noms à retenir
   sans rien en échange.
   ===================================================================== */

.t-droite   { text-align: right; }
.t-centre   { text-align: center; }
.m0         { margin: 0; }
.mt0        { margin-top: 0; }
.mt-20      { margin-top: 20px; }
.txt-sm     { font-size: var(--text-sm); }
.txt-muted  { color: var(--text-muted); }
.lien-accent { color: var(--accent); }

/* Le sous-titre d'un entête d'écran : gris, légèrement décollé du titre. */
.sous-titre { color: var(--text-muted); margin-top: 5px; }

/* Mention secondaire : grise ET petite. */
.txt-muted-sm { color: var(--text-muted); font-size: var(--text-sm); }

/* La grille à deux colonnes des formulaires. Elle se replie d'elle-même
   sous 640 px : sans cela, deux colonnes de 1fr sur un téléphone donnent
   deux colonnes illisibles plutôt qu'une lisible. */
.grille-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 15px;
}

@media (max-width: 640px) {
    .grille-2 { grid-template-columns: 1fr; }
}
