/* =============================================================================
   SINI School Management — feuille de style applicative
   Variables CSS branchées sur l'identité visuelle de l'école courante
   (TenantContext peut les réécrire via une balise <style> servie en SSR).
   ============================================================================= */

/* ----- Bandeau MODE DÉMO ----- */
.demo-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 999;
    background: linear-gradient(90deg, #F97316, #FBBF24);
    color: #0F172A;
    padding: 8px 16px;
    font-size: 13px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
.demo-banner a {
    color: #0F172A;
    text-decoration: underline;
    font-weight: 700;
}

:root {
    --primary: #1E5F8A;
    --primary-dark: #144460;
    --accent: #E6A817;
    --bg: #F5F7FA;
    --card: #FFFFFF;
    --border: #E2E8F0;
    --text: #1A202C;
    --muted: #64748B;
    --success: #16A34A;
    --danger: #DC2626;
    --warning: #D97706;
    --info: #2563EB;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body { font-family: 'Segoe UI', Roboto, sans-serif; background: var(--bg); color: var(--text); font-size: 14px; }

/* Pas de contour bleu de focus au clic souris sur les liens / boutons
   (ex. « Accueil », « À propos », « Connexion »). On le conserve uniquement
   pour la navigation clavier (:focus-visible) afin de rester accessible. */
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
[role="button"]:focus:not(:focus-visible),
summary:focus:not(:focus-visible) { outline: none; box-shadow: none; }

/* ===== Login ===== */
.login-screen {
    min-height: 100vh; display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
}
.login-card {
    background: white; padding: 40px; border-radius: 12px;
    box-shadow: 0 20px 50px rgba(0,0,0,0.2); width: 380px;
}
.logo-row { display: flex; align-items: center; gap: 12px; margin-bottom: 24px; }
.logo-circle {
    width: 48px; height: 48px; border-radius: 50%;
    background: var(--primary); color: white;
    display: flex; align-items: center; justify-content: center;
    font-weight: bold; font-size: 18px;
}
.school-name { font-size: 14px; font-weight: bold; }
.domain { font-size: 11px; color: var(--muted); margin-top: 4px; }

/* ===== App shell ===== */
/* Layout viewport-locké : la barre latérale et l'entête restent visibles, seul le contenu défile. */
html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; }
.app-shell {
    display: grid;
    grid-template-columns: 240px 1fr;
    grid-template-rows: 56px 1fr 32px;
    grid-template-areas: 'side header' 'side main' 'side foot';
    height: 100vh;
    overflow: hidden;
    box-sizing: border-box;
}
/* Quand un bandeau fixe (mode démo, mode visite AdminCentral ou AdminGroupe)
   occupe les 40px en haut du viewport, on REDUIT la hauteur effective du
   shell ET on le pousse vers le bas. Sans ça, .sidebar (height: 100vh) et
   la zone 'foot' du grid dépassent en bas du viewport et sont clipsés par
   body { overflow: hidden } — symptôme : footer Compte/Logout invisible,
   menu mobile coupé sous le bandeau. */
.app-shell.with-banner {
    margin-top: 40px;
    height: calc(100vh - 40px);
}
.app-shell.with-banner .sidebar {
    height: calc(100vh - 40px);
}
.sidebar {
    grid-area: side; background: var(--primary-dark); color: white;
    /* Padding-top à 0 (de 16px historique, puis 6px, maintenant 0) pour coller
       le logo en haut absolu du panneau — la demande UX étant un logo « bien
       remonté » et non plus juste un peu décollé du bord. */
    padding: 0 0 16px;
    /* Layout flex-column : header (.brand) et footer (.sidebar-footer) restent
       FIXES en haut et en bas, seule la <nav> du milieu défile. Sans ce flex,
       le scroll global de .sidebar emportait aussi la marque et le footer. */
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;   /* le scroll se fait dans .sidebar nav, pas ici */
}
/* Header (marque) : taille naturelle, jamais réduit ni étiré.
   Padding-top: 4px et padding-bottom: 6px pour un header très compact
   (l'image SVG porte déjà un margin-bottom: 8px côté inline-style dans
   MainLayout.razor pour aérer entre logo et nom d'école). */
.sidebar .brand {
    flex: none;
    padding: 4px 16px 6px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
}
.sidebar .brand .name { font-weight: bold; font-size: 13px; }
.sidebar .brand .domain { font-size: 11px; color: rgba(255,255,255,0.6); margin-top: 4px; }
/* Zone scrollable au milieu — prend toute la place restante entre header et
   footer. min-height: 0 est nécessaire pour que overflow-y:auto fonctionne
   dans un parent flex (sinon le contenu pousse au-delà du viewport). */
.sidebar nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Scrollbar Firefox : fine, blanche translucide sur fond transparent —
       cohérent avec le fond bleu foncé de la sidebar (la scrollbar grise par
       défaut du navigateur tranche violemment). */
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,0.18) transparent;
}
/* Scrollbar WebKit (Chrome / Edge / Safari) — équivalent visuel de scrollbar-color. */
.sidebar nav::-webkit-scrollbar {
    width: 6px;
}
.sidebar nav::-webkit-scrollbar-track {
    background: transparent;
}
.sidebar nav::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.15);
    border-radius: 3px;
}
.sidebar nav:hover::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,0.28);
}
.sidebar nav::-webkit-scrollbar-thumb:hover {
    background: rgba(255,255,255,0.4);
}
.sidebar nav .section {
    padding: 16px 16px 4px; font-size: 10px; text-transform: uppercase;
    color: rgba(255,255,255,0.4); letter-spacing: 1px;
}
.sidebar nav a {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 16px; color: rgba(255,255,255,0.85);
    text-decoration: none; font-size: 13px; border-left: 3px solid transparent;
}
.sidebar nav a:hover { background: rgba(255,255,255,0.08); }
.sidebar nav a.active { background: var(--primary); border-left-color: var(--accent); }
/* Conteneur fixe d'icônes dans la sidebar — garantit un alignement vertical
   parfait entre tous les NavLink, même si certaines icônes ont des proportions
   légèrement différentes. La taille 18px évite la concurrence visuelle avec
   le texte 13px. */
.sidebar nav a .sb-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; flex: none;
    color: rgba(255,255,255,0.75);
}
.sidebar nav a:hover .sb-icon,
.sidebar nav a.active .sb-icon { color: #fff; }

/* Footer sidebar — petit pavé discret toujours visible en bas. Comme la
   sidebar est en flex-column et que .sidebar nav est la seule zone
   scrollable, ce footer reste collé au bas de l'écran indépendamment du
   scroll. Le bordure-top sert de séparateur visuel avec le dernier NavLink. */
.sidebar-footer {
    flex: none;
    padding: 12px 16px 14px;
    border-top: 1px solid rgba(255,255,255,0.08);
    background: var(--primary-dark);   /* couvre tout flash de fond */
    text-align: center;
    color: rgba(255,255,255,0.45);
    font-size: 11px;
    line-height: 1.5;
}
.sidebar-footer .sb-foot-brand {
    font-weight: 600;
    letter-spacing: 0.5px;
    color: rgba(255,255,255,0.6);
}
.sidebar-footer .sb-foot-ver {
    margin-left: 4px;
    color: rgba(255,255,255,0.35);
    font-weight: 400;
}
.sidebar-footer .sb-foot-copy {
    margin-top: 2px;
    font-size: 10px;
    color: rgba(255,255,255,0.3);
}

.topbar {
    grid-area: header; background: white; border-bottom: 1px solid var(--border);
    display: flex; align-items: center; justify-content: space-between; padding: 0 24px;
}
.topbar h2 { font-size: 16px; }
.user-info { display: flex; align-items: center; gap: 12px; }
.user-info .avatar {
    width: 32px; height: 32px; border-radius: 50%;
    background: var(--accent); color: white;
    display: flex; align-items: center; justify-content: center;
    font-weight: bold; font-size: 12px;
}
.user-info .name { font-size: 12px; font-weight: bold; }
.user-info .role { font-size: 10px; color: var(--muted); }
.logout { color: var(--danger); cursor: pointer; font-size: 12px; text-decoration: none; }

.content {
    grid-area: main;
    padding: 24px;
    overflow-y: auto;
    /* Hauteur exacte = viewport − topbar (56) − footer (32). Quand un bandeau
       fixe est présent (mode démo, impersonation), .app-shell.with-banner
       réduit déjà la hauteur du shell de 40 px et applique margin-top: 40px ;
       il faut donc compenser sur .content aussi sinon le bas du scroll devient
       inaccessible (cas vu : derniers apprenants invisibles en mode grille). */
    height: calc(100vh - 56px - 32px);
    /* Scroll fluide iOS — surtout utile en mode grille où les cartes peuvent
       descendre loin et où le tap-scroll natif est attendu. */
    -webkit-overflow-scrolling: touch;
    /* Évite que la dernière ligne de cartes soit collée contre le bord. */
    scroll-padding-bottom: 16px;
}
.app-shell.with-banner .content {
    /* 88 px = topbar 56 + footer 32, + 40 px du bandeau fixe = 128 px. */
    height: calc(100vh - 128px);
}

/* ===== Footer applicatif ===== */
/* Bandeau bas compact : statut système + branding + badge conformité + liens utiles.
   32 px de hauteur pour rester discret sur les écrans denses, intégré dans le grid
   app-shell (zone 'foot') donc reste visible quel que soit le scroll de .content. */
.appfoot {
    grid-area: foot;
    background: #FAFAFA;
    border-top: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 0 16px;
    font-size: 11px;
    color: var(--muted, #6B7280);
    overflow: hidden;
    white-space: nowrap;
}
.appfoot .foot-left  { display: flex; align-items: center; gap: 14px; flex: 1 1 auto; min-width: 0; overflow: hidden; }
.appfoot .foot-right { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; }
.appfoot .foot-sep   { color: #D1D5DB; }
.appfoot a           { color: var(--primary, #1E5F8A); text-decoration: none; }
.appfoot a:hover     { text-decoration: underline; }
.appfoot .foot-status { display: inline-flex; align-items: center; gap: 6px; }
.appfoot .foot-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: #10B981;
    box-shadow: 0 0 0 2px rgba(16,185,129,.18);
    animation: foot-pulse 2.4s ease-in-out infinite;
}
.appfoot .foot-badge {
    background: #EFF6FF; color: #1E5F8A; padding: 1px 7px; border-radius: 10px;
    font-weight: 600; font-size: 10px; letter-spacing: .3px;
}
.appfoot .foot-version { color: #9CA3AF; font-variant-numeric: tabular-nums; }
@keyframes foot-pulse {
    0%, 100% { box-shadow: 0 0 0 2px rgba(16,185,129,.18); }
    50%      { box-shadow: 0 0 0 5px rgba(16,185,129,.05); }
}
@media (max-width: 640px) {
    .appfoot { font-size: 10px; padding: 0 10px; gap: 8px; }
    .appfoot .foot-badge,
    .appfoot .foot-version { display: none; }
}

/* ===== Spinner réutilisable =====
   Petit anneau qui tourne, à mettre dans un bouton pendant une action longue
   (génération PDF, envoi multi-canal…). Hérite de currentColor donc s'adapte
   à la couleur du bouton. Tailles : .spinner (14px) / .spinner-lg (24px). */
.spinner, .spinner-lg {
    display: inline-block; vertical-align: -2px;
    border: 2px solid currentColor; border-right-color: transparent;
    border-radius: 50%; animation: spin 0.7s linear infinite;
}
.spinner    { width: 14px; height: 14px; margin-right: 6px; }
.spinner-lg { width: 24px; height: 24px; margin-right: 8px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Overlay de chargement positionné par-dessus une zone preview pendant la
   génération PDF. Bloque visuellement la zone, montre un spinner centré. */
.preview-loading-overlay {
    position: absolute; inset: 0; background: rgba(255,255,255,0.7);
    display: flex; align-items: center; justify-content: center;
    z-index: 10; backdrop-filter: blur(1px);
}
.preview-loading-overlay .loading-box {
    background: white; border: 1px solid #E2E8F0; border-radius: 8px;
    padding: 16px 24px; box-shadow: 0 4px 12px rgba(0,0,0,0.08);
    display: flex; align-items: center; gap: 12px; color: #1E5F8A;
    font-weight: 500; font-size: 14px;
}

/* ===== Headings ===== */
h1 { font-size: 22px; margin-bottom: 4px; color: var(--text); }
h2 { font-size: 16px; margin-bottom: 12px; }
h3 { font-size: 14px; margin-bottom: 8px; color: var(--muted); }
.muted { color: var(--muted); margin-bottom: 16px; }

/* ===== Cards ===== */
.card {
    background: var(--card); border-radius: 8px; border: 1px solid var(--border);
    padding: 20px; margin-bottom: 16px;
}
.card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }

/* ===== Stats ===== */
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }
.stat-card { background: var(--card); padding: 20px; border-radius: 8px; border: 1px solid var(--border); }
.stat-card .label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.stat-card .value { font-size: 28px; font-weight: bold; margin: 8px 0 4px; color: var(--primary-dark); }
.stat-card .change { font-size: 11px; color: var(--muted); }

/* ===== Tables ===== */
table.table { width: 100%; border-collapse: collapse; font-size: 13px; }
table.table th {
    background: #F8FAFC; padding: 10px 12px; text-align: left;
    font-weight: 600; border-bottom: 2px solid var(--border);
    color: var(--muted); text-transform: uppercase; font-size: 10px; letter-spacing: 0.5px;
}
table.table td { padding: 10px 12px; border-bottom: 1px solid var(--border); }
table.table tr:hover { background: #F8FAFC; }
table.table .amount { text-align: right; font-variant-numeric: tabular-nums; }
table.table tr.total { background: #F8FAFC; font-weight: 700; }
table.table tr.total td { border-top: 2px solid var(--primary); }

/* ===== Badges ===== */
.badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; }
.badge-success { background: #DCFCE7; color: #166534; }
.badge-danger  { background: #FEE2E2; color: #991B1B; }
.badge-warning { background: #FEF3C7; color: #92400E; }
.badge-info    { background: #DBEAFE; color: #1E40AF; }

/* =====================================================================
   MODALES — Styles globaux (R32)
   =====================================================================
   Deux patterns supportés pour rétro-compatibilité avec les ~35 pages
   existantes qui les redéfinissaient localement :

     Pattern legacy  : .modal-overlay + .modal-content
                       (1 conteneur unique, padding inline, simple)
     Pattern moderne : .modal-overlay + .modal-box (+ .modal-header /
                       .modal-body / .modal-footer / .modal-close)
                       (structure en 3 zones avec séparations)

   Toute NOUVELLE modale doit utiliser le pattern moderne. Les composants
   qui redéfinissent encore localement peuvent supprimer leur bloc sans
   risque tant qu'ils n'ont pas customisé (padding, max-width, etc.).
   ===================================================================== */

.modal-overlay {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, .55);
    z-index: 9999;
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
}

/* ----- Pattern legacy ----- */
.modal-content {
    background: #fff; padding: 24px; border-radius: 8px;
    max-width: 600px; width: 90%; max-height: 90vh; overflow-y: auto;
}

/* ----- Pattern moderne ----- */
.modal-box {
    background: #fff; border-radius: 10px;
    max-height: 90vh; max-width: 640px; width: 100%;
    display: flex; flex-direction: column;
    box-shadow: 0 10px 30px rgba(0, 0, 0, .2);
}
.modal-small { max-width: 480px; }

.modal-header {
    display: flex; justify-content: space-between; align-items: center;
    padding: 14px 18px; border-bottom: 1px solid #E5E7EB;
}
.modal-header h2 {
    margin: 0; font-size: 15px; color: var(--primary);
    display: inline-flex; align-items: center; gap: 6px;
}
.modal-close {
    background: none; border: none; cursor: pointer;
    color: #6B7280; padding: 4px; line-height: 1;
    display: inline-flex; align-items: center; font-size: 22px;
}
.modal-close:hover { color: var(--primary); }
.modal-body { padding: 16px 18px; overflow-y: auto; flex: 1; }
.modal-footer {
    padding: 12px 18px; border-top: 1px solid #E5E7EB;
    display: flex; gap: 8px; justify-content: flex-end;
}

/* ----- Formulaires dans les modales ----- */
.form-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
}
.form-grid .form-group.full { grid-column: 1 / -1; }
.form-grid .form-group label {
    display: block; font-size: 13px; font-weight: 600;
    margin-bottom: 4px; color: #374151;
}
.form-grid .form-control,
.form-grid .form-select {
    width: 100%; padding: 6px 10px;
    border: 1px solid #D1D5DB; border-radius: 6px;
    font-size: 14px; background: white;
}
.form-grid .form-control:focus,
.form-grid .form-select:focus {
    outline: none; border-color: var(--primary);
}
.required { color: var(--danger); }

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

/* ===== Buttons ===== */
.btn-primary, .btn-secondary, .btn-danger {
    padding: 8px 16px; border: none; border-radius: 6px;
    font-weight: 600; cursor: pointer; font-size: 13px;
    display: inline-flex; align-items: center; gap: 6px; text-decoration: none;
}
.btn-primary { background: var(--primary); color: white; }
.btn-primary:hover:not(:disabled) { background: var(--primary-dark); }
.btn-primary:disabled { opacity: 0.6; cursor: not-allowed; }
.btn-secondary { background: white; color: var(--primary); border: 1px solid var(--primary); }
.btn-secondary:hover { background: var(--primary); color: white; }
.btn-danger { background: var(--danger); color: white; }
.btn-sm { padding: 4px 10px; font-size: 11px; }

/* ===== Form ===== */
.form-group { margin-bottom: 12px; }
.form-group label { display: block; font-size: 12px; margin-bottom: 4px; font-weight: 600; }
.form-control, .form-group input, .form-group select, .form-group textarea {
    width: 100%; padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px;
}
.form-control:focus, .form-group input:focus, .form-group select:focus { outline: none; border-color: var(--primary); }
.form-control.inline { width: auto; padding: 4px 6px; }
.form-control.inline.w-80 { width: 80px; }
.form-control.inline.w-100 { width: 100px; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.form-grid .full { grid-column: 1 / -1; }
.filter-row { display: flex; gap: 12px; margin-bottom: 16px; }
.filter-row > * { flex: 1; padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px; }

/* ===== Grade input (autosave) ===== */
.grade { width: 60px; padding: 4px 6px; border: 1px solid var(--border); border-radius: 4px; text-align: center; font-size: 12px; }
.grade:focus { border-color: var(--primary); outline: none; }
.grade.saved { background: #DCFCE7; border-color: var(--success); }

/* ===== Layout helpers ===== */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.row { display: flex; gap: 12px; }
.col { flex: 1; }
.text-success { color: var(--success); }
.text-danger { color: var(--danger); }

/* ===== Alerts ===== */
.alert { padding: 12px 16px; border-radius: 6px; margin-bottom: 12px; font-size: 13px; }
.alert-success { background: #DCFCE7; color: #166534; border-left: 3px solid var(--success); }
.alert-danger  { background: #FEE2E2; color: #991B1B; border-left: 3px solid var(--danger); }

/* ===== Pager ===== */
.pager { display: flex; align-items: center; justify-content: space-between; padding: 12px; }
.pager span { font-size: 12px; color: var(--muted); }

/* ===== Sections (settings) ===== */
.cycle-section, .level-section { margin-bottom: 24px; }
.cycle-section header, .level-section header {
    display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;
}
.cycle-section .count { color: var(--muted); font-weight: normal; font-size: 12px; }


/* =============================================================================
   RESPONSIVE MOBILE & TABLET (chantier 2B — PWA)
   =============================================================================
   On garde le layout desktop intact tel quel et on l'écrase à partir de
   768px. Stratégie :
     - sidebar repliée par défaut, hamburger dans la topbar
     - tables transformées en cartes (1 ligne = 1 carte avec libellés)
     - form-grid en 1 colonne
     - boutons à 44px de hauteur minimum (Apple HIG / Material)
     - card padding réduit pour gagner de l'espace
   La tablette (769-1024px) voit une version intermédiaire avec sidebar
   visible mais formulaires en 2 colonnes.
   ============================================================================= */

/* ===== Hamburger button (mobile uniquement) ===== */
.hamburger-btn {
    display: none;   /* visible seulement <= 768px */
    background: none;
    border: none;
    cursor: pointer;
    padding: 8px;
    margin-right: 8px;
    width: 44px; height: 44px;
    flex-direction: column;
    justify-content: space-around;
    align-items: stretch;
}
.hamburger-btn span {
    display: block;
    height: 2px;
    background: var(--text);
    border-radius: 2px;
    transition: all 0.2s;
}
.sidebar-overlay {
    display: none;   /* visible quand body.sidebar-open en mobile */
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.5);
    z-index: 100;
    backdrop-filter: blur(2px);
}

/* ===== TABLETTE : 769-1024px ===== */
@media (max-width: 1024px) {
    .form-grid { grid-template-columns: 1fr 1fr; }
    .stat-grid { grid-template-columns: repeat(2, 1fr); }
    .grid-2 { grid-template-columns: 1fr; }
}

/* ===== MOBILE : <= 768px ===== */
@media (max-width: 768px) {
    /* ----- Layout général ----- */
    /* On lève l'overflow:hidden imposé en desktop pour que le scroll natif marche */
    html, body { overflow-y: auto; height: auto; }

    .app-shell {
        display: block;     /* on sort du grid 2 colonnes */
        height: auto;
        min-height: 100vh;
    }

    /* ----- Sidebar : hors-écran par défaut, slide-in via .sidebar-open ----- */
    .sidebar {
        position: fixed;
        top: 0; left: 0;
        height: 100vh;
        width: 280px;
        max-width: 85vw;
        z-index: 101;
        transform: translateX(-100%);
        transition: transform 0.25s ease-out;
        box-shadow: 2px 0 12px rgba(0,0,0,0.15);
    }
    body.sidebar-open .sidebar { transform: translateX(0); }
    body.sidebar-open .sidebar-overlay { display: block; }

    .app-shell .sidebar { padding-top: 16px; }

    /* Quand un bandeau fixe (mode démo orange, mode visite AdminCentral bleu,
       vue réseau AdminGroupe violet) occupe le haut du viewport, on décale la
       sidebar mobile pour qu'elle commence SOUS le bandeau — sinon les
       premiers items du menu ("Tableau de bord" en tête) restent invisibles
       derrière la barre. La classe .with-banner est posée par MainLayout
       quand l'un quelconque des bandeaux est actif. */
    .app-shell.with-banner .sidebar {
        top: 40px;
        height: calc(100vh - 40px);
    }
    .app-shell.with-banner .sidebar-overlay {
        top: 40px;
    }

    /* ----- Topbar : compacte + hamburger ----- */
    .topbar {
        padding: 0 12px;
        position: sticky;
        top: 0;
        z-index: 50;
        height: 56px;
        gap: 8px;
    }
    .topbar h2 { font-size: 14px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .hamburger-btn { display: flex; }

    .user-info { gap: 6px; }
    .user-info > div:not(.avatar) { display: none; }   /* on masque nom + role pour gagner de la place */
    .topbar .logout { font-size: 11px; }

    /* ----- Contenu : padding réduit + scroll natif ----- */
    .content {
        padding: 16px 12px;
        height: auto;
        overflow-y: visible;
    }
    h1 { font-size: 20px; }
    h2 { font-size: 14px; }
    .card { padding: 16px; }

    /* ----- Form grids : 1 colonne ----- */
    .form-grid { grid-template-columns: 1fr; gap: 8px; }
    .form-grid .full { grid-column: auto; }
    .filter-row { flex-direction: column; gap: 8px; }
    .filter-row > * { width: 100%; }

    /* ----- Stats : 2 colonnes ----- */
    .stat-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
    .stat-card { padding: 12px; }
    .stat-card .value { font-size: 22px; }

    /* ----- Boutons : tap-targets 44px ----- */
    .btn-primary, .btn-secondary, .btn-danger {
        padding: 12px 16px;
        font-size: 14px;
        min-height: 44px;
    }
    .btn-sm { padding: 8px 12px; font-size: 12px; min-height: 36px; }

    /* ----- Inputs : tap-targets 44px + zoom navigateur stoppé via 16px font-size ----- */
    /* iOS zoom auto si font-size < 16px → on force 16px sur mobile */
    .form-control,
    .form-group input, .form-group select, .form-group textarea,
    input[type=text], input[type=email], input[type=password], input[type=number],
    input[type=date], input[type=tel], textarea, select {
        font-size: 16px;
        min-height: 44px;
    }

    /* ----- TABLES → CARDS ----- */
    /* On masque thead et on transforme chaque ligne en carte. Les valeurs
       reçoivent l'intitulé de la colonne via data-label (à fournir dans le HTML
       quand on veut bénéficier de la transformation, sinon on tombe en scroll). */
    .table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; }

    table.table {
        display: block;
        width: 100%;
    }
    table.table thead {
        display: none;
    }
    table.table tbody, table.table tr {
        display: block;
        width: 100%;
    }
    table.table tr {
        background: var(--card);
        border: 1px solid var(--border);
        border-radius: 8px;
        margin-bottom: 8px;
        padding: 8px 12px;
    }
    table.table tr:hover { background: var(--card); }
    table.table td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 8px;
        padding: 6px 0;
        border-bottom: 1px solid var(--border);
        text-align: right;
    }
    table.table td:last-child { border-bottom: none; }
    /* Si la cellule a un attribut data-label, on l'affiche en pseudo-élément.
       Sans data-label, le th caché ne s'affichera pas → c'est OK pour les
       tables où la colonne se comprend d'elle-même (login, code, etc.). */
    table.table td[data-label]::before {
        content: attr(data-label) " :";
        font-weight: 600;
        color: var(--muted);
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        text-align: left;
        flex-shrink: 0;
    }
    table.table td.amount { text-align: right; }

    /* Lignes "total" qui agrègent : on les affiche bloc-plein avec fond ocre */
    table.table tr.total {
        background: #FFF7ED;
        border-color: var(--accent);
    }

    /* ----- Modals : full-width avec safe-area iOS ----- */
    .modal-content {
        max-width: 95vw !important;
        max-height: 90vh;
        padding: 16px !important;
        margin: 16px;
    }

    /* ----- Login : padding réduit ----- */
    .login-card { padding: 24px 20px; width: auto; max-width: 380px; }

    /* ----- Demo banner : empilé, plus compact ----- */
    .demo-banner {
        font-size: 11px;
        padding: 6px 12px;
        flex-wrap: wrap;
    }
    .demo-banner a { margin-left: 4px; }

    /* ----- Charts : hauteur réduite ----- */
    canvas { max-height: 240px !important; }
}

/* ===== TRÈS PETITS ÉCRANS : <= 360px ===== */
@media (max-width: 360px) {
    .stat-grid { grid-template-columns: 1fr; }
    .topbar h2 { display: none; }   /* place trop chère, on l'enlève */
}

/* =============================================================================
   COCKPIT DIRECTEUR (Dashboard refactor 2026-05-14)
   Tuiles KPI compactes avec sparklines, leaderboard, panneau d'alertes,
   heatmap d'activité, raccourcis. Le but : faire tenir « tout ce qui compte
   ce matin » au-dessus de la pliure sans surcharger.
   ============================================================================= */

/* ----- En-tête contextualisé ----- */
.cockpit-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}
.cockpit-header .title-block h1 { margin: 0; font-size: 20px; }
.cockpit-header .title-block .subtitle {
    color: var(--muted);
    font-size: 12px;
    margin-top: 2px;
}
.cockpit-header .period-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 4px 12px;
    font-size: 11px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.cockpit-header .period-pill strong { color: var(--text); font-weight: 600; }

/* Flash discret quand une valeur KPI change réellement (auto-refresh des
   dashboards, cf. scolapro.initDashFx dans app.js). */
@keyframes dashFlash {
    0%   { background-color: rgba(22, 163, 74, .16); }
    100% { background-color: transparent; }
}
.dash-flash { animation: dashFlash 1.2s ease-out; }

/* ----- Grille KPI cockpit (4 tuiles) ----- */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
.kpi-tile {
    position: relative;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 14px 16px 8px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    min-height: 120px;
}
.kpi-tile .kpi-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--muted);
}
.kpi-tile .kpi-value {
    font-size: 28px;
    font-weight: 700;
    color: var(--primary-dark);
    line-height: 1.1;
    margin: 6px 0 2px;
    font-variant-numeric: tabular-nums;
}
.kpi-tile .kpi-value .suffix {
    font-size: 14px;
    font-weight: 500;
    color: var(--muted);
    margin-left: 2px;
}
.kpi-tile .kpi-delta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    padding: 2px 6px;
    border-radius: 4px;
    background: #F1F5F9;
    color: var(--muted);
    width: fit-content;
    margin-top: 2px;
    font-weight: 500;
}
.kpi-tile.trend-up .kpi-delta    { background: #DCFCE7; color: #166534; }
.kpi-tile.trend-down .kpi-delta  { background: #FEE2E2; color: #991B1B; }
.kpi-tile.trend-warning .kpi-delta { background: #FEF3C7; color: #92400E; }

/* Bande verticale colorée à gauche selon la tendance */
.kpi-tile::before {
    content: '';
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    background: transparent;
}
.kpi-tile.trend-up::before      { background: var(--success); }
.kpi-tile.trend-down::before    { background: var(--danger); }
.kpi-tile.trend-warning::before { background: var(--warning); }
.kpi-tile.trend-flat::before    { background: #CBD5E1; }

.kpi-tile .kpi-spark {
    height: 36px;
    margin-top: auto;
    margin-right: -10px;     /* déborde un peu à droite : effet « infinite » */
    margin-bottom: -4px;
}
.kpi-tile .kpi-spark canvas { display: block; }

/* ----- Layout principal cockpit : leaderboard + panneau alertes ----- */
.cockpit-grid {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 16px;
}

/* ----- Leaderboard classes ----- */
.leaderboard {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
}
.leaderboard h2 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.leaderboard h2 .scope {
    font-size: 11px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 500;
}
.lb-row {
    display: grid;
    grid-template-columns: 24px 1fr auto 90px auto;
    align-items: center;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid #F1F5F9;
    font-size: 13px;
}
.lb-row:last-child { border-bottom: none; }
.lb-row .lb-rank {
    font-size: 11px;
    font-weight: 700;
    color: var(--muted);
    width: 24px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.lb-row .lb-rank.top-1 { color: #B45309; }
.lb-row .lb-rank.top-2 { color: #475569; }
.lb-row .lb-rank.top-3 { color: #92400E; }
.lb-row .lb-label { font-weight: 500; }
.lb-row .lb-effectif {
    font-size: 11px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.lb-row .lb-bar {
    height: 6px;
    background: #F1F5F9;
    border-radius: 3px;
    overflow: hidden;
}
.lb-row .lb-bar .fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.5s ease;
}
.lb-row .lb-mean {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-align: right;
    min-width: 50px;
}

/* ----- Panneau alertes ----- */
.alerts-panel {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
}
.alerts-panel h2 {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 12px;
}
.alert-card {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    background: #F8FAFC;
    border-left: 3px solid var(--muted);
    margin-bottom: 8px;
}
.alert-card:last-child { margin-bottom: 0; }
.alert-card.sev-danger  { border-left-color: var(--danger);  background: #FEF2F2; }
.alert-card.sev-warning { border-left-color: var(--warning); background: #FFFBEB; }
.alert-card.sev-info    { border-left-color: var(--info);    background: #EFF6FF; }
.alert-card .alert-ico {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    background: white;
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.alert-card .alert-body { flex: 1; min-width: 0; }
.alert-card .alert-title {
    font-weight: 600;
    font-size: 13px;
    color: var(--text);
}
.alert-card .alert-detail {
    font-size: 11px;
    color: var(--muted);
    margin-top: 2px;
}
.alert-card .alert-cta {
    align-self: center;
    font-size: 11px;
    color: var(--primary);
    font-weight: 600;
    text-decoration: none;
    padding: 4px 8px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: white;
    white-space: nowrap;
}
.alert-card .alert-cta:hover { background: var(--primary); color: white; border-color: var(--primary); }
.alerts-panel .empty {
    text-align: center;
    color: var(--muted);
    font-size: 12px;
    padding: 16px 0;
}

/* ----- Départs de l'année ----- */
.departures-strip {
    background: var(--card);
    border: 1px solid var(--border);
    border-left: 3px solid var(--warning);
    border-radius: 10px;
    padding: 14px 16px;
    margin-top: 16px;
}
.departures-strip header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
    flex-wrap: wrap;
    gap: 8px;
}
.departures-strip header h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 6px;
}
.departures-strip header .hint { font-size: 11px; color: var(--muted); }
.departures-body {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 24px;
    align-items: start;
}
.departures-counts {
    display: flex;
    gap: 16px;
}
.dep-stat {
    background: #FFFBEB;
    padding: 10px 14px;
    border-radius: 6px;
    min-width: 90px;
    text-align: center;
}
.dep-stat .lab {
    display: block;
    font-size: 10px;
    color: #92400E;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin-bottom: 2px;
}
.dep-stat strong {
    font-size: 20px;
    color: #92400E;
    font-variant-numeric: tabular-nums;
}
.departures-motifs .lab {
    display: block;
    font-size: 10px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin-bottom: 4px;
}
.departures-motifs ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.departures-motifs li {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    padding: 3px 8px;
    background: #F8FAFC;
    border-radius: 4px;
}
.departures-motifs .motif { color: var(--text); }
.departures-motifs .nb {
    font-weight: 600;
    color: var(--warning);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
    .departures-body { grid-template-columns: 1fr; gap: 12px; }
    .departures-counts { justify-content: space-around; }
}

/* ----- Heatmap activité 7 jours ----- */
.activity-strip {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 14px 16px;
    margin-top: 16px;
}
.activity-strip header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
}
.activity-strip header h3 {
    margin: 0;
    font-size: 13px;
    color: var(--text);
    font-weight: 600;
}
.activity-strip header .hint { font-size: 11px; color: var(--muted); }
.activity-cells {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
}
.activity-cell {
    aspect-ratio: 4 / 3;
    border-radius: 6px;
    background: #F1F5F9;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    font-size: 10px;
    color: var(--muted);
    border: 1px solid transparent;
    transition: transform 0.15s ease;
}
.activity-cell:hover { transform: translateY(-1px); border-color: var(--primary); }
.activity-cell.level-1 { background: #DBEAFE; }
.activity-cell.level-2 { background: #93C5FD; color: #0F172A; }
.activity-cell.level-3 { background: #3B82F6; color: white; }
.activity-cell.level-4 { background: #1E40AF; color: white; }
.activity-cell strong { font-size: 14px; font-weight: 700; line-height: 1; }
.activity-cell.today { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ----- Raccourcis ----- */
.quick-actions {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin-top: 16px;
}
.quick-action {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    text-decoration: none;
    color: var(--text);
    transition: border-color 0.15s ease, transform 0.15s ease;
}
.quick-action:hover {
    border-color: var(--primary);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(30, 95, 138, 0.08);
}
.quick-action .qa-ico {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    background: #EFF6FF;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--primary);
    flex-shrink: 0;
}
.quick-action .qa-text { display: flex; flex-direction: column; min-width: 0; }
.quick-action .qa-text strong { font-size: 13px; font-weight: 600; }
.quick-action .qa-text span { font-size: 11px; color: var(--muted); }

/* ----- Événements à venir (compact) ----- */
.events-strip {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 14px 16px;
    margin-top: 16px;
}
.events-strip header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.events-strip header h3 { margin: 0; font-size: 13px; font-weight: 600; }
.events-strip header a { font-size: 11px; color: var(--primary); text-decoration: none; }
.events-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.events-list li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border-radius: 6px;
    font-size: 12px;
}
.events-list li:hover { background: #F8FAFC; }
.events-list .ev-date {
    background: var(--primary);
    color: white;
    padding: 4px 8px;
    border-radius: 6px;
    font-weight: 600;
    font-size: 11px;
    min-width: 56px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.events-list .ev-type {
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 4px;
    background: #F1F5F9;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.events-list .ev-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ----- Responsive cockpit ----- */
@media (max-width: 1100px) {
    .kpi-grid { grid-template-columns: repeat(2, 1fr); }
    .cockpit-grid { grid-template-columns: 1fr; }
    .quick-actions { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
    .kpi-grid { grid-template-columns: 1fr; }
    .kpi-tile { min-height: 100px; }
    .kpi-tile .kpi-value { font-size: 24px; }
    .quick-actions { grid-template-columns: 1fr; }
    .lb-row { grid-template-columns: 20px 1fr auto 60px; gap: 8px; }
    .lb-row .lb-effectif { display: none; }
}

/* =============================================================================
   COCKPIT AVANCÉ (DashboardAdvanced refactor 2026-05-14)
   Vue pilotage : 8 KPIs étendus, distribution notes, matrice matières × niveaux,
   tableau classes enrichi, top fortes/faibles, funnel financier, signaux auto.
   ============================================================================= */

/* Barre de filtres avec sélecteur de période + bouton actualiser */
.adv-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}
.adv-toolbar .title-block h1 { margin: 0; font-size: 20px; }
.adv-toolbar .title-block .subtitle {
    color: var(--muted);
    font-size: 12px;
    margin-top: 2px;
}
.adv-toolbar .controls {
    display: flex;
    align-items: center;
    gap: 8px;
}
.adv-period-tabs {
    display: inline-flex;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 3px;
    gap: 2px;
}
.adv-period-tabs button {
    background: transparent;
    border: 0;
    padding: 6px 12px;
    font-size: 12px;
    font-weight: 600;
    border-radius: 6px;
    cursor: pointer;
    color: var(--muted);
    transition: all 0.15s ease;
}
.adv-period-tabs button:hover { color: var(--text); }
.adv-period-tabs button.active {
    background: var(--primary);
    color: white;
}

/* Grille KPI avancé : 4 colonnes (et 2 rangées de 4) */
.adv-kpi-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}
.adv-kpi-tile {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 12px 14px;
    position: relative;
    overflow: hidden;
    min-height: 92px;
}
.adv-kpi-tile .kpi-label {
    font-size: 10px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-bottom: 4px;
}
.adv-kpi-tile .kpi-value {
    font-size: 22px;
    font-weight: 700;
    color: var(--primary-dark);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}
.adv-kpi-tile .kpi-value .suffix {
    font-size: 12px;
    color: var(--muted);
    font-weight: 500;
    margin-left: 2px;
}
.adv-kpi-tile .kpi-delta {
    font-size: 10px;
    color: var(--muted);
    margin-top: 3px;
    font-weight: 500;
}
.adv-kpi-tile.trend-up    { border-top: 3px solid var(--success); }
.adv-kpi-tile.trend-up    .kpi-delta { color: var(--success); }
.adv-kpi-tile.trend-down  { border-top: 3px solid var(--danger); }
.adv-kpi-tile.trend-down  .kpi-delta { color: var(--danger); }
.adv-kpi-tile.trend-warning { border-top: 3px solid var(--warning); }
.adv-kpi-tile.trend-warning .kpi-delta { color: var(--warning); }
.adv-kpi-tile.trend-flat  { border-top: 3px solid #CBD5E1; }

/* Cards en deux colonnes pour la zone analytique */
.adv-grid-3 {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 16px;
    margin-bottom: 16px;
}

/* ----- Distribution des notes (histogramme + stats latérales) ----- */
.distribution-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
}
.distribution-card header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.distribution-card header h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}
.distribution-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    margin-bottom: 12px;
}
.distribution-stats .stat {
    text-align: center;
    padding: 8px 4px;
    background: #F8FAFC;
    border-radius: 6px;
}
.distribution-stats .stat .lab {
    font-size: 9px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.distribution-stats .stat .val {
    font-size: 16px;
    font-weight: 700;
    color: var(--primary-dark);
    font-variant-numeric: tabular-nums;
}
.distribution-canvas-wrap {
    height: 180px;
    position: relative;
}

/* ----- Matrice matières × niveaux ----- */
.matrix-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
    overflow-x: auto;
}
.matrix-card header { margin-bottom: 12px; }
.matrix-card header h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}
.matrix-card header .hint {
    display: block;
    font-size: 11px;
    color: var(--muted);
    margin-top: 2px;
}
.subject-matrix {
    width: 100%;
    border-collapse: separate;
    border-spacing: 2px;
    font-size: 11px;
}
.subject-matrix th, .subject-matrix td {
    padding: 6px 8px;
    text-align: center;
    border-radius: 4px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.subject-matrix th {
    background: #F8FAFC;
    color: var(--muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    font-size: 10px;
}
.subject-matrix th.row-label, .subject-matrix td.row-label {
    text-align: left;
    background: #F1F5F9;
    color: var(--text);
    font-weight: 600;
    position: sticky;
    left: 0;
    z-index: 1;
}
.subject-matrix td.cell {
    color: white;
    font-weight: 600;
    min-width: 48px;
}
.subject-matrix td.cell.empty {
    background: #F1F5F9 !important;
    color: var(--muted);
    font-weight: 400;
}
.matrix-legend {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    font-size: 10px;
    color: var(--muted);
}
.matrix-legend .gradient {
    flex: 1;
    height: 8px;
    border-radius: 4px;
    background: linear-gradient(to right, #DC2626 0%, #F59E0B 33%, #84CC16 66%, #16A34A 100%);
}

/* ----- Tableau classes enrichi ----- */
.adv-classes-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}
.adv-classes-table thead th {
    background: #F8FAFC;
    padding: 8px 10px;
    text-align: left;
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 0.4px;
    border-bottom: 1px solid var(--border);
}
.adv-classes-table tbody td {
    padding: 8px 10px;
    border-bottom: 1px solid #F1F5F9;
    font-variant-numeric: tabular-nums;
}
.adv-classes-table tbody tr:hover { background: #F8FAFC; }
.adv-classes-table .num { text-align: right; }
.adv-classes-table .stat-bar {
    display: inline-block;
    width: 80px;
    height: 6px;
    background: #F1F5F9;
    border-radius: 3px;
    overflow: hidden;
    vertical-align: middle;
    margin-right: 6px;
}
.adv-classes-table .stat-bar .fill {
    height: 100%;
    border-radius: 3px;
}
.adv-classes-table .delta {
    display: inline-block;
    padding: 1px 5px;
    border-radius: 3px;
    font-size: 10px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.adv-classes-table .delta.pos { background: #DCFCE7; color: #166534; }
.adv-classes-table .delta.neg { background: #FEE2E2; color: #991B1B; }
.adv-classes-table .delta.flat { background: #F1F5F9; color: var(--muted); }

/* ----- Top fortes / faibles côte à côte ----- */
.adv-grid-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-bottom: 16px;
}
.subject-list {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
}
.subject-list h3 {
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}
.subject-list ul { list-style: none; padding: 0; margin: 0; }
.subject-list li {
    display: grid;
    grid-template-columns: 1fr auto 60px auto;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid #F1F5F9;
    font-size: 12px;
}
.subject-list li:last-child { border-bottom: none; }
.subject-list .matiere { font-weight: 500; }
.subject-list .count { font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums; }
.subject-list .bar {
    height: 5px;
    background: #F1F5F9;
    border-radius: 3px;
    overflow: hidden;
}
.subject-list .bar .fill { height: 100%; border-radius: 3px; }
.subject-list .moy {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: right;
    min-width: 44px;
}

/* ----- Liste élèves à risque ----- */
.at-risk-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
    margin-bottom: 16px;
}
.at-risk-card header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.at-risk-card header h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}
.at-risk-list { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.at-risk-list li {
    display: grid;
    grid-template-columns: 24px 1fr auto auto;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: #FEF2F2;
    border-radius: 6px;
    border-left: 3px solid var(--danger);
    font-size: 12px;
}
.at-risk-list .rank {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--danger);
    color: white;
    font-size: 10px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}
.at-risk-list .who { display: flex; flex-direction: column; min-width: 0; }
.at-risk-list .who strong { font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.at-risk-list .who small { font-size: 10px; color: var(--muted); }
.at-risk-list .mean {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--danger);
    min-width: 36px;
    text-align: right;
}
.at-risk-list .trend {
    font-size: 10px;
    padding: 2px 5px;
    border-radius: 3px;
    font-weight: 600;
}
.at-risk-list .trend.down  { background: #FEE2E2; color: #991B1B; }
.at-risk-list .trend.up    { background: #DCFCE7; color: #166534; }
.at-risk-list .trend.flat  { background: #F1F5F9; color: var(--muted); }

/* ----- Funnel financier ----- */
.funnel-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
    margin-bottom: 16px;
}
.funnel-card header { margin-bottom: 12px; }
.funnel-card header h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}
.funnel {
    display: flex;
    align-items: stretch;
    gap: 4px;
    margin-bottom: 16px;
}
.funnel .step {
    flex: 1;
    padding: 12px;
    border-radius: 6px;
    background: var(--card);
    border: 1px solid var(--border);
    position: relative;
}
.funnel .step .label {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--muted);
}
.funnel .step .amount {
    font-size: 18px;
    font-weight: 700;
    color: var(--primary-dark);
    margin: 4px 0 2px;
    font-variant-numeric: tabular-nums;
}
.funnel .step .meta {
    font-size: 11px;
    color: var(--muted);
}
.funnel .step.facture { border-left: 4px solid var(--info); }
.funnel .step.encaisse { border-left: 4px solid var(--success); }
.funnel .step.impaye { border-left: 4px solid var(--danger); }
.funnel-evolution {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
}
.funnel-evolution .label {
    font-size: 11px;
    color: var(--muted);
}
.funnel-evolution-bars {
    flex: 1;
    display: flex;
    align-items: flex-end;
    gap: 4px;
    height: 40px;
}
.funnel-evolution-bars .bar {
    flex: 1;
    background: var(--primary);
    opacity: 0.6;
    border-radius: 3px 3px 0 0;
    min-height: 4px;
    position: relative;
    transition: opacity 0.15s ease;
}
.funnel-evolution-bars .bar:hover { opacity: 1; }
.funnel-evolution-bars .bar.current { opacity: 1; background: var(--accent); }

/* ----- Signaux automatiques (insights) ----- */
.signals-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 16px;
    margin-bottom: 16px;
}
.signals-card header { margin-bottom: 12px; }
.signals-card header h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}
.signals-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
}
.signal-card {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    border-left: 3px solid var(--muted);
    background: #F8FAFC;
}
.signal-card.lvl-positif { border-left-color: var(--success); background: #ECFDF5; }
.signal-card.lvl-warning { border-left-color: var(--warning); background: #FFFBEB; }
.signal-card.lvl-danger  { border-left-color: var(--danger);  background: #FEF2F2; }
.signal-card.lvl-info    { border-left-color: var(--info);    background: #EFF6FF; }
.signal-card .ico {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    background: white;
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.signal-card .text { flex: 1; min-width: 0; }
.signal-card .title {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
}
.signal-card .desc {
    font-size: 11px;
    color: var(--muted);
    margin-top: 2px;
}

/* ----- Responsive ----- */
@media (max-width: 1100px) {
    .adv-kpi-grid { grid-template-columns: repeat(2, 1fr); }
    .adv-grid-3 { grid-template-columns: 1fr; }
    .adv-grid-2 { grid-template-columns: 1fr; }
    .signals-list { grid-template-columns: 1fr; }
    .at-risk-list { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
    .adv-kpi-grid { grid-template-columns: 1fr; }
    .funnel { flex-direction: column; }
    .distribution-stats { grid-template-columns: repeat(2, 1fr); }
}

/* ─────────────────────────────────────────────────────────────────────
   RAPPORTS TRIMESTRIELS (chantier 2026-05-15)
   Page /rapports/trimestriels — sélecteur de trimestre, aperçu live et
   liste des rapports générés. Cf. docs/16-Rapports-Trimestriels.md.
   ─────────────────────────────────────────────────────────────────── */
.qr-page { display: flex; flex-direction: column; gap: 16px; padding: 12px; }
.qr-page .card { background: #fff; border: 1px solid #E5E7EB; border-radius: 8px; padding: 14px; }
.qr-page .card-title { font-weight: 600; color: #1E5F8A; font-size: 14px; margin-bottom: 8px; }
.qr-page .card-subtitle { font-weight: 600; color: #374151; font-size: 12px; margin: 12px 0 6px; }
.qr-page .muted { color: #6B7280; font-size: 13px; }

/* Sélecteur de trimestre — pills cliquables */
.qr-pills { display: flex; gap: 8px; flex-wrap: wrap; }
.qr-pill { display: flex; flex-direction: column; align-items: flex-start;
           padding: 8px 14px; border: 1px solid #E5E7EB; border-radius: 999px;
           background: #fff; cursor: pointer; min-width: 200px; transition: all .15s; }
.qr-pill:hover { border-color: #1E5F8A; background: #F0F7FB; }
.qr-pill.active { border-color: #1E5F8A; background: #1E5F8A; color: #fff; }
.qr-pill .pill-label { font-weight: 600; font-size: 13px; }
.qr-pill .pill-meta  { font-size: 11px; opacity: .8; }

.qr-actions { display: flex; gap: 8px; margin-top: 12px; }

/* KPI grid (aperçu live) */
.qr-kpi-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin: 8px 0; }
.qr-kpi { border: 1px solid #E5E7EB; border-radius: 6px; padding: 10px; display: flex; flex-direction: column; gap: 4px; }
.qr-kpi-label { font-size: 11px; color: #6B7280; }
.qr-kpi-value { font-size: 20px; font-weight: 700; color: #1E5F8A; }
.qr-kpi-value small { font-size: 11px; color: #6B7280; font-weight: 400; margin-left: 2px; }
.qr-kpi-success .qr-kpi-value { color: #2E7D32; }
.qr-kpi-warning .qr-kpi-value { color: #EF6C00; }
.qr-kpi-danger  .qr-kpi-value { color: #C62828; }
.qr-kpi-primary .qr-kpi-value { color: #1E5F8A; }

/* Avancement des chantiers */
.qr-progress { margin-top: 12px; }
.qr-progress-row { display: grid; grid-template-columns: 140px 1fr 50px; gap: 8px;
                   align-items: center; padding: 4px 0; }
.qr-progress-row .prog-label { font-size: 12px; color: #374151; }
.qr-progress-row .prog-bar   { background: #F3F4F6; border-radius: 999px; height: 10px; overflow: hidden; }
.qr-progress-row .prog-fill  { height: 100%; border-radius: 999px; transition: width .3s; }
.qr-progress-row .prog-fill.prog-termine  { background: #2E7D32; }
.qr-progress-row .prog-fill.prog-en-cours { background: #1E5F8A; }
.qr-progress-row .prog-fill.prog-en-retard { background: #EF6C00; }
.qr-progress-row .prog-pct { font-size: 12px; font-weight: 600; text-align: right; color: #374151; }

/* Signaux */
.qr-signals { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.qr-signals .signal { padding: 8px 10px; border-left: 3px solid #1E5F8A; background: #F9FAFB; border-radius: 4px; }
.qr-signals .signal-title { font-weight: 600; font-size: 12px; color: #1E5F8A; }
.qr-signals .signal-desc  { font-size: 11px; color: #374151; margin-top: 2px; }
.qr-signals .signal-positif { border-left-color: #2E7D32; }
.qr-signals .signal-positif .signal-title { color: #2E7D32; }
.qr-signals .signal-warning { border-left-color: #EF6C00; }
.qr-signals .signal-warning .signal-title { color: #EF6C00; }
.qr-signals .signal-danger  { border-left-color: #C62828; }
.qr-signals .signal-danger  .signal-title { color: #C62828; }

/* Tableau des rapports générés */
.qr-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.qr-table thead th { text-align: left; font-size: 11px; color: #6B7280; font-weight: 600;
                     border-bottom: 1px solid #E5E7EB; padding: 6px 8px; }
.qr-table tbody td { padding: 8px; border-bottom: 1px solid #F3F4F6; }
.qr-table tbody tr:hover { background: #F9FAFB; }
.qr-row-archived { opacity: .55; }
.qr-actions-cell { display: flex; gap: 8px; flex-wrap: wrap; }
.qr-actions-cell .btn-link { background: transparent; border: 1px solid #E5E7EB;
                              border-radius: 4px; padding: 4px 8px; cursor: pointer;
                              font-size: 12px; color: #374151; }
.qr-actions-cell .btn-link:hover { background: #F0F7FB; border-color: #1E5F8A; color: #1E5F8A; }
.qr-actions-cell .btn-link-primary { background: #1E5F8A; color: #fff; border-color: #1E5F8A; }
.qr-actions-cell .btn-link-primary:hover { background: #144A6E; }

.status-badge { display: inline-block; padding: 2px 8px; border-radius: 999px;
                font-size: 11px; font-weight: 600; }
.status-badge.status-draft     { background: #FEF3C7; color: #92400E; }
.status-badge.status-published { background: #D1FAE5; color: #065F46; }
.status-badge.status-archived  { background: #E5E7EB; color: #4B5563; }

@media (max-width: 1100px) {
    .qr-kpi-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 600px) {
    .qr-kpi-grid { grid-template-columns: repeat(2, 1fr); }
    .qr-pill { min-width: 100%; }
    .qr-table { font-size: 11px; }
}

/* ─────────────────────────────────────────────────────────────────────
   EXPORT DGI MALI (chantier 2026-05-15)
   Page /declarations/dgi — sélecteur année, aperçu KPIs, liste exports.
   Cf. docs/17-Export-DGI-Mali.md.
   ─────────────────────────────────────────────────────────────────── */
.dgi-page { display: flex; flex-direction: column; gap: 16px; padding: 12px; }
.dgi-page .card { background: #fff; border: 1px solid #E5E7EB; border-radius: 8px; padding: 14px; }
.dgi-page .card-title { font-weight: 600; color: #1E5F8A; font-size: 14px; margin-bottom: 8px; }
.dgi-page .muted { color: #6B7280; font-size: 13px; }

.dgi-year-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.dgi-year-row label { font-weight: 600; color: #374151; font-size: 13px; }
.dgi-year-row .form-select { padding: 6px 10px; border: 1px solid #D1D5DB; border-radius: 4px;
                              font-size: 14px; min-width: 100px; }

.dgi-banner-warn { margin-top: 10px; padding: 8px 10px; background: #FEF3C7; border-left: 3px solid #C9A227;
                    border-radius: 4px; font-size: 13px; color: #78350F; }

.dgi-kpi-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin: 8px 0; }
.dgi-kpi { border: 1px solid #E5E7EB; border-radius: 6px; padding: 10px; display: flex;
            flex-direction: column; gap: 4px; background: #FAFAFA; }
.dgi-kpi .lbl { font-size: 10px; color: #6B7280; text-transform: uppercase; letter-spacing: .5px; }
.dgi-kpi .val { font-size: 16px; font-weight: 700; color: #1E5F8A; }
.dgi-kpi .val small { font-size: 10px; color: #6B7280; font-weight: 400; margin-left: 2px; }

.dgi-note { margin-top: 12px; padding: 8px 10px; background: #F0F9FF; border-left: 3px solid #1E5F8A;
            border-radius: 4px; font-size: 12px; color: #1E3A5F; }

.dgi-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.dgi-table thead th { text-align: left; font-size: 11px; color: #6B7280; font-weight: 600;
                       border-bottom: 1px solid #E5E7EB; padding: 6px 6px; }
.dgi-table tbody td { padding: 6px 6px; border-bottom: 1px solid #F3F4F6; white-space: nowrap; }
.dgi-table tbody tr:hover { background: #F9FAFB; }
.dgi-row-archived { opacity: .55; }
.dgi-actions-cell { display: flex; gap: 6px; flex-wrap: wrap; }
.dgi-actions-cell .btn-link { background: transparent; border: 1px solid #E5E7EB;
                               border-radius: 4px; padding: 3px 8px; cursor: pointer;
                               font-size: 11px; color: #374151; }
.dgi-actions-cell .btn-link:hover { background: #F0F7FB; border-color: #1E5F8A; color: #1E5F8A; }
.dgi-actions-cell .btn-link-primary { background: #1E5F8A; color: #fff; border-color: #1E5F8A; }
.dgi-actions-cell .btn-link-primary:hover { background: #144A6E; }
.dgi-actions-cell .btn-link-warn { background: #C9A227; color: #fff; border-color: #C9A227; }
.dgi-actions-cell .btn-link-warn:hover { background: #A6841E; }

@media (max-width: 1100px) { .dgi-kpi-grid { grid-template-columns: repeat(4, 1fr); } }
@media (max-width: 700px)  { .dgi-kpi-grid { grid-template-columns: repeat(2, 1fr); } .dgi-table { font-size: 10px; } }

/* ─────────────────────────────────────────────────────────────────────
   MOUVEMENTS BANCAIRES (refonte 2026-05-15)
   Page /mouvements — KPIs + mini-cartes comptes + filtres + table paginée + modal détail.
   ─────────────────────────────────────────────────────────────────── */
.mvt-page { display: flex; flex-direction: column; gap: 14px; padding: 12px; }
.mvt-page .card { background: #fff; border: 1px solid #E5E7EB; border-radius: 8px; padding: 14px; }
.mvt-page h2 { margin: 0 0 8px; font-size: 14px; color: #1E5F8A; }
.mvt-page .muted { color: #6B7280; font-size: 13px; }
.mvt-page .text-success { color: #2E7D32; }
.mvt-page .text-danger  { color: #C62828; }

/* — Bandeau KPI 4 tuiles — */
.mvt-kpi-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.mvt-kpi { background: #fff; border: 1px solid #E5E7EB; border-radius: 8px; padding: 12px;
           display: flex; flex-direction: column; gap: 4px; border-left: 4px solid #1E5F8A; }
.mvt-kpi.mvt-kpi-success { border-left-color: #2E7D32; }
.mvt-kpi.mvt-kpi-danger  { border-left-color: #C62828; }
.mvt-kpi.mvt-kpi-warning { border-left-color: #EF6C00; }
.mvt-kpi .lbl  { font-size: 10px; color: #6B7280; text-transform: uppercase; letter-spacing: .5px; }
.mvt-kpi .val  { font-size: 22px; font-weight: 700; color: #1E5F8A; }
.mvt-kpi .val small { font-size: 11px; color: #6B7280; font-weight: 400; margin-left: 4px; }
.mvt-kpi .meta { font-size: 11px; color: #6B7280; }
.mvt-kpi.mvt-kpi-success .val { color: #2E7D32; }
.mvt-kpi.mvt-kpi-danger  .val { color: #C62828; }
.mvt-kpi.mvt-kpi-warning .val { color: #EF6C00; }

/* — Mini-cartes comptes avec sparkline — */
.mvt-account-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
.mvt-account-card { background: #fff; border: 1px solid #E5E7EB; border-radius: 8px;
                     padding: 12px; cursor: pointer; text-align: left; transition: all .15s;
                     display: flex; flex-direction: column; gap: 6px; }
.mvt-account-card:hover { border-color: #1E5F8A; box-shadow: 0 2px 6px rgba(0,0,0,.06); }
.mvt-account-card.active { border-color: #1E5F8A; background: #F0F7FB; }
.mvt-account-card .acc-banque  { font-weight: 700; color: #1E5F8A; font-size: 13px; }
.mvt-account-card .acc-libelle { font-size: 11px; color: #6B7280; margin-left: 4px; }
.mvt-account-card .acc-solde   { font-size: 18px; font-weight: 700; color: #1E5F8A; }
.mvt-account-card .acc-solde small { font-size: 10px; color: #6B7280; font-weight: 400; }
.mvt-account-card .acc-spark   { height: 36px; }
.mvt-account-card .acc-spark canvas { display: block; width: 100%; height: 36px; }
.mvt-account-card .acc-tendance { font-size: 11px; }
.mvt-account-card.tendance-up      .acc-tendance { color: #2E7D32; }
.mvt-account-card.tendance-down    .acc-tendance { color: #C62828; }
.mvt-account-card.tendance-warning .acc-tendance { color: #EF6C00; font-weight: 600; }
.mvt-account-card.tendance-warning { border-left: 3px solid #EF6C00; }
.mvt-account-card-clear { background: #F3F4F6; border-style: dashed; align-items: center; justify-content: center; }
.mvt-account-card-clear .acc-clear { font-weight: 600; color: #1E5F8A; }

/* — Filtres pliables — */
.filters-toolbar { display: flex; justify-content: space-between; align-items: center;
                    cursor: pointer; padding: 4px 0; font-weight: 600; color: #1E5F8A; }
.filters-toggle { font-size: 12px; color: #6B7280; }
.filters-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
                 gap: 10px; margin-top: 12px; padding-top: 12px; border-top: 1px solid #E5E7EB; }
.filters-grid .filter { display: flex; flex-direction: column; gap: 4px; }
.filters-grid .filter label { font-size: 11px; color: #6B7280; }
.filters-grid .filter input, .filters-grid .filter select {
    padding: 6px 8px; border: 1px solid #D1D5DB; border-radius: 4px; font-size: 13px; }
.filters-grid .filter-search { grid-column: span 2; }
.filters-grid .filter-actions { display: flex; align-items: flex-end; }

/* — Table paginée — */
.table-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; }
.table-meta { font-size: 12px; color: #6B7280; }
.mvt-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.mvt-table thead th { text-align: left; padding: 8px 6px; font-size: 11px; color: #6B7280;
                       border-bottom: 2px solid #E5E7EB; font-weight: 600; }
.mvt-table thead th.amount { text-align: right; }
.mvt-table thead th.sortable { cursor: pointer; user-select: none; }
.mvt-table thead th.sortable:hover { color: #1E5F8A; }
.mvt-table tbody td { padding: 8px 6px; border-bottom: 1px solid #F3F4F6; }
.mvt-table tbody td.amount { text-align: right; font-variant-numeric: tabular-nums; }
.mvt-table tbody tr:hover { background: #F9FAFB; cursor: pointer; }
.mvt-table .auto-badge { display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px;
                          background: #DBEAFE; color: #1E40AF; font-size: 10px; font-weight: 600; letter-spacing: .5px; }
.mvt-table .btn-link { background: transparent; border: 1px solid #E5E7EB; padding: 4px 6px;
                        border-radius: 4px; cursor: pointer; }
.mvt-table .btn-link:hover { background: #F0F7FB; border-color: #1E5F8A; }

/* Pagination */
.paginator { display: flex; gap: 12px; align-items: center; justify-content: center;
              margin-top: 12px; padding-top: 12px; border-top: 1px solid #E5E7EB; }
.paginator .btn-secondary { padding: 6px 12px; }
.paginator select { padding: 4px 8px; border: 1px solid #D1D5DB; border-radius: 4px; }

/* Modal détail */
.mvt-detail-box { max-width: 560px; }
.detail-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.detail-table th { text-align: left; padding: 6px 8px; color: #6B7280; font-weight: 600; width: 35%; vertical-align: top; }
.detail-table td { padding: 6px 8px; }
.detail-section { margin-top: 14px; padding-top: 12px; border-top: 1px solid #E5E7EB; }
.detail-section h3 { margin: 0 0 6px; font-size: 13px; color: #1E5F8A; }
.detail-section .auto-badge { display: inline-block; margin-right: 6px; padding: 1px 6px; border-radius: 999px;
                               background: #DBEAFE; color: #1E40AF; font-size: 10px; font-weight: 600; }
.detail-section .btn-link { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px;
                             color: #1E5F8A; text-decoration: none; font-size: 12px; }
.detail-section .btn-link:hover { text-decoration: underline; }

@media (max-width: 1100px) { .mvt-kpi-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px)  { .mvt-kpi-grid { grid-template-columns: 1fr; }
                              .filters-grid .filter-search { grid-column: span 1; }
                              .mvt-table { font-size: 11px; } }

/* ═════════════════════════════════════════════════════════════════════
   LISTES DÉROULANTES — restyle global (refonte juin 2026)
   Remplace le rendu natif hétérogène des <select> par un style maison
   cohérent : chevron SVG personnalisé, padding confortable, états hover /
   focus / disabled. Placé en FIN de fichier pour gagner la cascade sur
   les règles historiques (.form-select, .form-group select, etc.).
   Les <select multiple> et <select size> gardent leur rendu liste.
   ═════════════════════════════════════════════════════════════════════ */

select,
.form-select,
.form-control select,
.form-group select {
    /* Reset du rendu natif (flèche système supprimée) */
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;

    /* Style maison */
    padding: 8px 34px 8px 12px;
    border: 1px solid var(--border, #E2E8F0);
    border-radius: 8px;
    background-color: #fff;
    color: var(--text, #1A202C);
    font-size: 13px;
    font-family: inherit;
    line-height: 1.4;
    cursor: pointer;
    transition: border-color .15s, box-shadow .15s;

    /* Chevron SVG (couleur muted), calé à droite */
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 11px center;
}

select:hover,
.form-select:hover,
.form-group select:hover {
    border-color: #B9C7D4;
}

select:focus,
.form-select:focus,
.form-group select:focus {
    outline: none;
    border-color: var(--primary, #1E5F8A);
    box-shadow: 0 0 0 3px rgba(30, 95, 138, .14);
    /* Chevron passé en couleur primaire au focus */
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%231E5F8A' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

select:disabled,
.form-select:disabled,
.form-group select:disabled {
    background-color: #F8FAFC;
    color: #94A3B8;
    cursor: not-allowed;
    border-color: #EDF1F5;
}

/* Les listes multi-sélection / déroulées gardent un rendu liste natif :
   pas de chevron ni de padding réservé à droite. */
select[multiple],
select[size]:not([size="1"]) {
    appearance: auto;
    -webkit-appearance: auto;
    -moz-appearance: auto;
    background-image: none;
    padding-right: 12px;
    cursor: default;
}

/* Harmonisation : les inputs au contact des selects reçoivent le même
   focus ring pour que les barres de filtres restent homogènes. */
.form-control:focus,
.form-group input:focus,
.form-group textarea:focus {
    box-shadow: 0 0 0 3px rgba(30, 95, 138, .14);
}

/* Mobile : confort tactile + pas de zoom iOS (cf. règles 44px plus haut). */
@media (max-width: 640px) {
    select, .form-select, .form-group select {
        min-height: 44px;
        font-size: 16px;
        padding-right: 38px;
    }
}

/* ═════════════════════════════════════════════════════════════════════
   SIDEBAR — groupes repliables (refonte navigation juin 2026)
   Chaque section devient un .nav-group : en-tête bouton (icône + libellé +
   chevron) et conteneur .nav-group-items. Le JS (window.scolapro.
   installNavGroups dans app.js) gère le repli, la persistance et le
   masquage des groupes vides. Les anciennes règles .section restent en
   place pour les layouts qui les utilisent encore (GroupLayout, etc.).
   ═════════════════════════════════════════════════════════════════════ */

.sidebar nav .nav-group { margin: 2px 8px; }
.sidebar nav .nav-group + .nav-group { margin-top: 4px; }

/* En-tête de groupe */
.sidebar nav .nav-group-head {
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    padding: 8px 8px 8px 10px;
    background: transparent; border: none; border-radius: 8px;
    color: rgba(255, 255, 255, 0.55);
    font-size: 10.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 1px;
    cursor: pointer; text-align: left;
    transition: background .12s, color .12s;
}
.sidebar nav .nav-group-head:hover {
    background: rgba(255, 255, 255, 0.06);
    color: rgba(255, 255, 255, 0.85);
}
.sidebar nav .nav-group-head .nav-group-ico {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; flex: none;
    color: rgba(255, 255, 255, 0.45);
}
.sidebar nav .nav-group-head:hover .nav-group-ico { color: rgba(255, 255, 255, 0.85); }
.sidebar nav .nav-group-head .nav-group-label { flex: 1; }
.sidebar nav .nav-group-head .nav-group-chev {
    display: inline-flex; line-height: 0;
    color: rgba(255, 255, 255, 0.35);
    transition: transform .18s;
}
.sidebar nav .nav-group.collapsed .nav-group-head .nav-group-chev { transform: rotate(-90deg); }

/* Items : indentés sous l'en-tête, avec un fil vertical discret */
.sidebar nav .nav-group-items {
    margin-left: 18px;
    padding-left: 6px;
    border-left: 1px solid rgba(255, 255, 255, 0.10);
}
.sidebar nav .nav-group.collapsed .nav-group-items { display: none; }
.sidebar nav .nav-group-empty { display: none; }

/* Liens : pastille arrondie moderne (remplace le border-left historique
   à l'intérieur des groupes) */
.sidebar nav .nav-group-items a {
    border-left: none;
    border-radius: 7px;
    margin: 1px 4px 1px 0;
    padding: 7px 10px;
    font-size: 12.5px;
    color: rgba(255, 255, 255, 0.78);
}
.sidebar nav .nav-group-items a:hover {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
}
.sidebar nav .nav-group-items a.active {
    background: var(--primary);
    color: #fff;
    box-shadow: inset 3px 0 0 var(--accent);
}

/* Le formulaire « Visiter une école » (console SaaS) hérite de l'indentation */
.sidebar nav .nav-group-items form { padding: 8px 10px 4px 0; }

/* ───────────────────────────────────────────────────────────────────────
   COULEURS DE FAMILLES — extension de la charte (proposition juin 2026)
   Chaque famille métier de la navigation reçoit une teinte pastel calibrée
   pour le fond bleu nuit de la sidebar. Même logique que les pastilles par
   famille de la vitrine (charte docs/60) : bleu = pilotage, vert = vie des
   apprenants, or = finances, etc. Les icônes des liens héritent de la
   teinte de leur groupe via currentColor — aucun Tone à poser lien par lien.
   Tokens exposés en :root pour réutilisation (badges, futurs dashboards).
   ─────────────────────────────────────────────────────────────────────── */
:root {
    /* ── Déclinaisons « deep » des familles : pour FOND CLAIR (texte, trait
       d'icône, pastille tonale de titre de page). La version pastel sert le
       fond sombre (sidebar), la deep sert les pages. Contraste AA garanti
       sur blanc. ── */
    --fam-pilotage-deep:   #2C6E9E;
    --fam-apprenants-deep: #2F8A4C;
    --fam-admissions-deep: #1E8077;
    --fam-pedagogie-deep:  #A87E1C;
    --fam-edt-deep:        #6C55B8;
    --fam-personnel-deep:  #C06B33;
    --fam-magasin-deep:    #C25555;
    --fam-finances-deep:   #A8821A;
    --fam-compta-deep:     #4A6BB5;
    --fam-comms-deep:      #2E8FC0;
    --fam-outils-deep:     #9C7B43;
    --fam-config-deep:     #5D7286;
    --fam-securite-deep:   #C0524A;
    --fam-saas-deep:       #8E5BA6;
    --fam-compte-deep:     #64748B;

    /* ── Palette data-viz ordonnée (graphiques, sparklines, camemberts).
       À consommer DANS L'ORDRE : une série = --viz-1, deux séries =
       --viz-1 + --viz-2, etc. Calibrée pour rester distinguable en
       impression N&B (luminances échelonnées). Miroir à reprendre en dur
       dans les renderers PDF (QuestPDF ne lit pas le CSS). ── */
    --viz-1: #1E5F8A;   /* bleu primaire */
    --viz-2: #E6A817;   /* ambre accent */
    --viz-3: #16A34A;   /* vert */
    --viz-4: #7C5BC4;   /* violet */
    --viz-5: #DC6B4E;   /* terracotta */
    --viz-6: #0E94A0;   /* sarcelle */
    --viz-7: #C2497D;   /* magenta sourd */
    --viz-8: #64748B;   /* gris (séries résiduelles, "autres") */

    /* ── Échelles formalisées (les pages refondues juin 2026 convergent
       déjà vers ces valeurs — on les grave). ── */
    --radius-sm: 6px;     /* champs compacts, badges carrés */
    --radius-md: 8px;     /* boutons, inputs, selects */
    --radius-lg: 12px;    /* cartes, modales, groupes sidebar */
    --radius-xl: 16px;    /* héros, bandeaux pleine largeur */
    --shadow-rest:  0 2px 6px rgba(15, 23, 42, .04);   /* carte au repos */
    --shadow-hover: 0 4px 14px rgba(15, 23, 42, .08);  /* carte survolée */
    --shadow-modal: 0 24px 48px rgba(15, 23, 42, .18); /* modales, popovers */
    --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
    --space-4: 16px; --space-5: 20px; --space-6: 24px;

    --fam-pilotage:   #8FC9F2;   /* bleu ciel — vision d'ensemble */
    --fam-apprenants: #93D9A3;   /* vert tendre — vie des élèves */
    --fam-admissions: #6FD1C6;   /* turquoise — accueil, entrée */
    --fam-pedagogie:  #F6CE74;   /* or doux — le coeur du métier */
    --fam-edt:        #C3B3F0;   /* lavande — temps et planification */
    --fam-personnel:  #F2AE80;   /* abricot — humain, RH */
    --fam-magasin:    #F09A9A;   /* corail — commerce */
    --fam-finances:   #EDC75A;   /* ambre — argent */
    --fam-compta:     #9FB6E8;   /* bleu acier — rigueur comptable */
    --fam-comms:      #84D2F6;   /* ciel clair — messages */
    --fam-outils:     #E3C699;   /* sable — documents, archivage */
    --fam-config:     #B9C6D2;   /* gris bleuté — réglages, neutre */
    --fam-securite:   #F1948A;   /* rouge doux — vigilance */
    --fam-saas:       #C39BD3;   /* violet — console éditeur */
    --fam-compte:     #AEB6BF;   /* neutre — personnel */
}

/* Application : l'icône du groupe ET celles de ses liens prennent la teinte
   de la famille (les liens utilisent currentColor → on colore le .sb-icon).
   Le libellé reste blanc pour la lisibilité ; seule l'iconographie chante. */
.sidebar nav .nav-group[data-group="pilotage"]   .nav-group-ico,
.sidebar nav .nav-group[data-group="pilotage"]   a .sb-icon { color: var(--fam-pilotage); }
.sidebar nav .nav-group[data-group="apprenants"] .nav-group-ico,
.sidebar nav .nav-group[data-group="apprenants"] a .sb-icon { color: var(--fam-apprenants); }
.sidebar nav .nav-group[data-group="admissions"] .nav-group-ico,
.sidebar nav .nav-group[data-group="admissions"] a .sb-icon { color: var(--fam-admissions); }
.sidebar nav .nav-group[data-group="pedagogie"]  .nav-group-ico,
.sidebar nav .nav-group[data-group="pedagogie"]  a .sb-icon { color: var(--fam-pedagogie); }
.sidebar nav .nav-group[data-group="edt"]        .nav-group-ico,
.sidebar nav .nav-group[data-group="edt"]        a .sb-icon { color: var(--fam-edt); }
.sidebar nav .nav-group[data-group="personnel"]  .nav-group-ico,
.sidebar nav .nav-group[data-group="personnel"]  a .sb-icon { color: var(--fam-personnel); }
.sidebar nav .nav-group[data-group="magasin"]    .nav-group-ico,
.sidebar nav .nav-group[data-group="magasin"]    a .sb-icon { color: var(--fam-magasin); }
.sidebar nav .nav-group[data-group="finances"]   .nav-group-ico,
.sidebar nav .nav-group[data-group="finances"]   a .sb-icon { color: var(--fam-finances); }
.sidebar nav .nav-group[data-group="compta"]     .nav-group-ico,
.sidebar nav .nav-group[data-group="compta"]     a .sb-icon { color: var(--fam-compta); }
.sidebar nav .nav-group[data-group="comms"]      .nav-group-ico,
.sidebar nav .nav-group[data-group="comms"]      a .sb-icon { color: var(--fam-comms); }
.sidebar nav .nav-group[data-group="outils"]     .nav-group-ico,
.sidebar nav .nav-group[data-group="outils"]     a .sb-icon { color: var(--fam-outils); }
.sidebar nav .nav-group[data-group="config"]     .nav-group-ico,
.sidebar nav .nav-group[data-group="config"]     a .sb-icon { color: var(--fam-config); }
.sidebar nav .nav-group[data-group="securite"]   .nav-group-ico,
.sidebar nav .nav-group[data-group="securite"]   a .sb-icon { color: var(--fam-securite); }
.sidebar nav .nav-group[data-group="saas"]       .nav-group-ico,
.sidebar nav .nav-group[data-group="saas"]       a .sb-icon { color: var(--fam-saas); }
.sidebar nav .nav-group[data-group="compte"]     .nav-group-ico,
.sidebar nav .nav-group[data-group="compte"]     a .sb-icon { color: var(--fam-compte); }

/* Lien actif : icône blanche sur fond primaire pour un contraste maximal. */
.sidebar nav .nav-group .nav-group-items a.active .sb-icon { color: #fff; }

/* ───────────────────────────────────────────────────────────────────────
   CHIPS DE STATUT NORMALISÉS (charte docs/60 §4)
   Le motif unique pour tout statut court : 10px / graisse 700 / arrondi 999,
   fond pastel + texte foncé de la même teinte. SEULES ces cinq paires sont
   autorisées — jamais de couleur pleine pour un statut. Les classes locales
   historiques (.status-badge, .badge-*, .status-chip) restent valides mais
   tout nouveau code utilise .chip + variante.
   ─────────────────────────────────────────────────────────────────────── */
.chip {
    display: inline-block;
    font-size: 10px; font-weight: 700; letter-spacing: .3px;
    padding: 2px 9px; border-radius: 999px; white-space: nowrap;
}
.chip-success { background: #EFF8F1; color: #15803D; }  /* OK, publié, actif */
.chip-info    { background: #EFF5FD; color: #1D4ED8; }  /* en cours, soumis */
.chip-warning { background: #FDF8EE; color: #B45309; }  /* attente, brouillon */
.chip-danger  { background: #FCF1F1; color: #B91C1C; }  /* retard, révoqué */
.chip-neutral { background: #F1F5F9; color: #64748B; }  /* archivé, expiré */

/* Mobile : cibles tactiles plus hautes */
@media (max-width: 900px) {
    .sidebar nav .nav-group-head { padding: 11px 8px 11px 10px; }
    .sidebar nav .nav-group-items a { padding: 11px 10px; }
}
