﻿/* ==========================================================================
   Alif Back-office — design system (modern, light, professional, épuré)
   Font: Inter · Components: Syncfusion fluent2 · calm restful palette
   ========================================================================== */

@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('fonts/InterVariable.woff2') format('woff2');
}

:root {
    /* Brand (harmonised with Syncfusion fluent2 blue) */
    --brand: #0f6cbd;
    --brand-hover: #115ea3;
    --brand-active: #0c3b5e;
    --brand-tint: #eef5fc;
    --brand-tint-strong: #dcebf9;

    /* Neutrals — calm cool grays */
    --bg: #f3f6f9;
    --surface: #ffffff;
    --surface-2: #f8fafc;
    --border: #e6ebf1;
    --border-strong: #d4dce6;

    /* Text */
    --text: #1f2b3d;
    --text-soft: #46556b;
    --text-muted: #7c8aa0;

    /* Feedback */
    --success: #0f8b5f;
    --success-tint: #e7f6ef;
    --warning: #b5730b;
    --warning-tint: #fbf1e0;
    --danger: #c8342e;
    --danger-tint: #fbeceb;

    /* Shape & depth */
    --radius-sm: 8px;
    --radius: 12px;
    --radius-lg: 16px;
    --shadow-xs: 0 1px 2px rgba(16, 33, 60, .05);
    --shadow-sm: 0 1px 3px rgba(16, 33, 60, .07), 0 1px 2px rgba(16, 33, 60, .04);
    --shadow-md: 0 6px 18px rgba(16, 33, 60, .08), 0 2px 6px rgba(16, 33, 60, .05);

    /* Layout */
    /* LA BARRE EST DIMENSIONNEE SUR LE LIBELLE LE PLUS LONG, ET MESUREE, PAS ESTIMEE.
       A 268 px, « Rapprochement des versements » et « Rapprochement des remboursements »
       sortaient tous deux coupes — « Rapprochement des versem… », « Rapprochement des
       rembou… » — donc identiques a l'oeil, sur les deux entrees qu'on venait justement de
       separer pour qu'on les distingue.

       Mesure au canvas, dans la police reelle du menu, sur les trois langues, sur un poste dont
       la racine est a 14,5 px :
         francais  229 px  « Rapprochement des remboursements »   <- le pire cas
         anglais   213 px  « Management of training categories »
         arabe     126 px
       Hors texte : 52 px de retraits et d'ecarts (en rem, donc a l'echelle du texte) plus
       18 px d'icone et 10 px d'ascenseur (fixes). Soit 309 px a cette echelle.

       EN REM, ET NON EN PIXELS. C'est le point qui compte : les libelles sont dimensionnes en
       rem, donc ils grandissent avec la taille de police du poste. Une largeur figee en pixels
       aurait convenu a la machine sur laquelle la mesure a ete faite et aurait retronque les
       memes libelles sur un poste regle a 16 px — le defaut serait revenu chez quelqu'un
       d'autre, sans qu'on le voie. 22rem laisse de la marge aux deux echelles : 319 px pour
       309 requis a 14,5 px de racine, 352 px pour 338 requis a 16 px.

       AVANT D'ALLONGER UN LIBELLE DE MENU, REMESURER. L'ellipse posee sur .nav-text est le
       filet : si elle reapparait, c'est que cette valeur a pris du retard. */
    --sidebar-w: 22rem;
    --header-h: 64px;

    --font-sans: 'Inter', 'Segoe UI Variable', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
}

/* ---------- Base ---------- */
html, body {
    font-family: var(--font-sans);
    font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    background-color: var(--bg);
    color: var(--text);
    font-size: 14.5px;
    line-height: 1.6;
    letter-spacing: -0.005em;
}

h1, h2, h3, h4, h5 {
    color: var(--text);
    font-weight: 650;
    letter-spacing: -0.02em;
    line-height: 1.25;
    margin: 0 0 .35em;
}

h1 { font-size: 1.6rem; }
h2 { font-size: 1.3rem; }
h3 { font-size: 1.075rem; font-weight: 620; }

p { color: var(--text-soft); }

a, .btn-link { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-hover); }

::selection { background: var(--brand-tint-strong); }

/* Slim, calm scrollbars */
* { scrollbar-width: thin; scrollbar-color: #cdd6e2 transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: #cdd6e2; border-radius: 8px; border: 2px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: #b6c2d2; }

h1:focus { outline: none; }

/* ---------- Page header (title band above content) ---------- */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.5rem;
}
.page-header h1 { margin-bottom: .25rem; }
.page-header p { margin: 0; color: var(--text-muted); font-size: .95rem; }

/* ---------- Buttons (Syncfusion) — softer, roomier ---------- */
.e-btn, .e-css.e-btn {
    border-radius: var(--radius-sm);
    font-weight: 550;
    letter-spacing: -0.01em;
    padding: 8px 16px;
    transition: background-color .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.e-btn.e-primary {
    background: var(--brand);
    border-color: var(--brand);
    box-shadow: var(--shadow-xs);
}
.e-btn.e-primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); }
.e-btn.e-success { background: var(--success); border-color: var(--success); }
.e-btn.e-danger  { background: var(--danger);  border-color: var(--danger); }
.e-btn.e-warning { background: var(--warning); border-color: var(--warning); }
.e-btn.e-small { padding: 5px 11px; font-size: .82rem; border-radius: 7px; }
.e-btn.e-flat { box-shadow: none; }
.e-grid td .e-btn.e-small { margin: 0 3px; }

/* ---------- Inputs (Syncfusion) — aligned & calm ---------- */
.e-input-group, .e-ddl.e-input-group, .e-float-input {
    border-radius: var(--radius-sm) !important;
}
/* LA BORDURE DU BAS N'EST PAS PLUS EPAISSE : ELLE EST PLUS SOMBRE.

   MESURE DU 01/09/2026 sur le theme Fluent 2 : les quatre cotes font bien 1 px, mais le haut et
   les cotes sont en #d1d1d1 quand le bas est en #616161. C'est l'« accent du bas » herite du
   Material Design, ou un champ se signalait par un soulignement. A l'oeil, une ligne deux fois
   plus sombre se lit comme une ligne plus grasse — d'ou l'impression signalee, et elle vaut pour
   TOUS les champs du back-office.

   ON REDEFINIT LA VARIABLE, ON NE SE BAT PAS SUR LA SPECIFICITE. La regle du theme qui pose cette
   couleur porte quatre :not() et pese 0,5,0 ; toute regle ecrite ici pour la contrer devrait
   etre plus lourde qu'elle, et le resterait jusqu'a la prochaine version du theme. En reposant
   « --color-sf-border-alt » SUR LES CHAMPS EUX-MEMES, on laisse la regle du theme s'appliquer —
   elle resout simplement une autre valeur. C'est le mecanisme prevu par le theme.

   PORTEE VOLONTAIREMENT ETROITE : la variable sert a 37 endroits dans le theme, dont tous ne sont
   pas des champs de saisie. La redefinir sur :root les toucherait tous ; posee sur les groupes
   d'entree, elle ne descend que la ou on la veut. */
.e-input-group,
.e-input-group.e-control-wrapper,
.e-float-input,
.e-float-input.e-control-wrapper {
    --color-sf-border-alt: var(--border-strong);
    /* ET LA COULEUR DES TROIS AUTRES COTES PAR LA MEME PORTE. Sans elle, le bas passait a
       #d4dce6 pendant que le haut restait au #d1d1d1 du theme : deux gris voisins, mais deux
       gris. Un cadre se lit d'un seul tenant ou pas du tout. */
    --color-sf-border: var(--border-strong);
}

.e-input-group.e-control-wrapper { border-color: var(--border-strong); }
.e-input-group.e-input-focus, .e-ddl.e-input-focus {
    box-shadow: 0 0 0 3px var(--brand-tint) !important;
    border-color: var(--brand) !important;
    /* Repete pour le bas : la regle du theme le vise separement et gagnait meme sur !important
       de la forme raccourcie, faute d'etre aussi specifique. */
    border-bottom-color: var(--brand) !important;
}
input.form-control, select.form-control, .e-input {
    border-radius: var(--radius-sm);
    border-color: var(--border-strong);
    color: var(--text);
    font-family: var(--font-sans);
}
input.form-control:focus, select.form-control:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-tint);
}

/* ---------- Grids (Syncfusion) — airy, professional ---------- */
.e-grid {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    background: var(--surface);
    font-family: var(--font-sans);
}
.e-grid .e-gridheader { border-top: 0; background: var(--surface-2); }
.e-grid .e-headercell, .e-grid .e-columnheader { background: var(--surface-2); }
.e-grid .e-headercelldiv {
    color: var(--text-muted);
    font-weight: 600;
    font-size: .74rem;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.e-grid .e-row .e-rowcell {
    color: var(--text-soft);
    border-color: var(--border);
    padding-top: 11px;
    padding-bottom: 11px;
}
.e-grid .e-row:hover .e-rowcell,
.e-grid .e-row:hover td.e-rowcell { background: var(--brand-tint) !important; }
.e-grid .e-altrow .e-rowcell { background: #fbfcfe; }
.e-grid .e-row.e-selectionbackground .e-rowcell,
.e-grid td.e-selectionbackground { background: var(--brand-tint-strong) !important; }

/* ---------- Dialogs (Syncfusion) — refined modal ---------- */
.e-dialog {
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    border: 1px solid var(--border);
    overflow: hidden;
}
.e-dialog .e-dlg-header { font-weight: 650; letter-spacing: -0.01em; color: var(--text); }
.e-dialog .e-dlg-header-content { border-bottom: 1px solid var(--border); padding: 18px 22px; }
.e-dialog .e-dlg-content { padding: 20px 22px; color: var(--text-soft); }
.e-dlg-overlay { background: rgba(23, 37, 58, .38); backdrop-filter: blur(2px); }

/* ---------- Forms inside dialogs — perfectly aligned ---------- */
.e-dialog .e-dlg-content .mb-2 { margin-bottom: 1rem !important; }
.e-dialog .e-dlg-content label,
.form-field label {
    display: block;
    font-size: .8rem;
    font-weight: 600;
    color: var(--text-soft);
    margin-bottom: .4rem;
    letter-spacing: -0.005em;
}
.e-dialog .e-dlg-content .e-input-group,
.e-dialog .e-dlg-content input.form-control,
.e-dialog .e-dlg-content .e-richtexteditor { width: 100%; }
.e-dialog .e-dlg-content .mt-3 {
    display: flex; gap: .5rem; padding-top: .5rem;
    border-top: 1px solid var(--border); margin-top: 1.25rem !important;
}

/* checkbox rows */
label > input[type=checkbox] { margin-right: .5rem; transform: translateY(1px); }
input[type=checkbox], input[type=radio] { accent-color: var(--brand); }

/* ---------- Alerts ---------- */
.alert { border-radius: var(--radius-sm); border: 1px solid transparent; padding: .7rem 1rem; font-size: .9rem; }
.alert-danger  { background: var(--danger-tint);  color: #8f221d; border-color: #f2cecb; }
.alert-success { background: var(--success-tint); color: #0a6344; border-color: #c7ecdb; }
.alert-info    { background: var(--brand-tint);   color: var(--brand-active); border-color: var(--brand-tint-strong); }
.alert-warning { background: var(--warning-tint); color: #8a5709; border-color: #f0dcb8; }

/* ---------- Images in grids (logos / photos) ---------- */
.e-grid img { border-radius: 6px; }

/* ---------- Validation ---------- */
.valid.modified:not([type=checkbox]) { outline: none; }
.invalid { outline: 1px solid var(--danger); border-radius: var(--radius-sm); }
.validation-message { color: var(--danger); font-size: .85rem; }

/* ==========================================================================
   Login page (split screen) — modern, professional
   ========================================================================== */
.auth { min-height: 100vh; display: flex; background: var(--surface); }

/* Brand panel */
.auth-brand {
    position: relative;
    flex: 0 0 46%;
    max-width: 660px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 3rem 3.25rem;
    overflow: hidden;
    color: #fff;
    background: linear-gradient(150deg, #1b8ae0 0%, #0f6cbd 42%, #0a487e 100%);
}
.auth-brand-top { display: flex; align-items: center; gap: .7rem; position: relative; z-index: 2; }
.auth-logo-mark {
    width: 42px; height: 42px; border-radius: 12px;
    display: grid; place-items: center;
    font-weight: 800; font-size: 1.25rem; letter-spacing: -.02em;
    color: #0f6cbd; background: #fff;
    box-shadow: 0 8px 20px rgba(0, 0, 0, .18);
}
.auth-logo-text { font-weight: 750; font-size: 1.35rem; letter-spacing: -.02em; }

.auth-brand-content { position: relative; z-index: 2; max-width: 31rem; }
.auth-headline { color: #fff; font-size: 2.2rem; line-height: 1.2; font-weight: 700; letter-spacing: -.025em; margin-bottom: 1.1rem; }
.auth-tag { color: rgba(255, 255, 255, .86); font-size: 1.02rem; line-height: 1.65; margin-bottom: 2rem; }
.auth-points { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .95rem; }
.auth-points li { display: flex; align-items: center; gap: .75rem; color: rgba(255, 255, 255, .95); font-size: .96rem; font-weight: 500; }
.auth-check { flex: 0 0 auto; color: #fff; background: rgba(255, 255, 255, .2); border-radius: 50%; padding: 4px; box-sizing: content-box; }
.auth-brand-foot { position: relative; z-index: 2; color: rgba(255, 255, 255, .7); font-size: .8rem; }

/* decorative layers */
.auth-blob { position: absolute; border-radius: 50%; z-index: 1; }
.auth-blob-1 { width: 460px; height: 460px; right: -150px; top: -140px; background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, .35), rgba(255, 255, 255, 0) 70%); }
.auth-blob-2 { width: 380px; height: 380px; left: -130px; bottom: -150px; background: radial-gradient(circle at 40% 40%, rgba(140, 205, 255, .5), rgba(255, 255, 255, 0) 70%); }
.auth-grid-overlay {
    position: absolute; inset: 0; z-index: 1; opacity: .14;
    background-image: linear-gradient(rgba(255, 255, 255, .3) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, .3) 1px, transparent 1px);
    background-size: 44px 44px;
    -webkit-mask-image: radial-gradient(circle at 72% 18%, #000 0%, transparent 62%);
    mask-image: radial-gradient(circle at 72% 18%, #000 0%, transparent 62%);
}

/* Form panel */
.auth-form-wrap { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; padding: 2rem; background: var(--surface); }
.auth-card { width: 100%; max-width: 400px; }
.auth-mobile-logo { display: none; align-items: center; gap: .6rem; margin-bottom: 2rem; }
.auth-mobile-name { font-weight: 600; color: var(--text); font-size: 1.05rem; }
.auth-mobile-name b { color: var(--brand); font-weight: 750; }

.auth-title { font-size: 1.85rem; font-weight: 700; letter-spacing: -.025em; margin-bottom: .35rem; color: var(--text); }
.auth-subtitle { color: var(--text-muted); font-size: .98rem; margin-bottom: 2rem; }

/* ---------- Boîtes de dialogue redimensionnables ---------- */
/* Portée par une classe et non par « .e-dlg-content » tout court : le back-office compte une
   quarantaine de boîtes, dont la plupart sont des formulaires courts qui n'ont rien à gagner à
   devenir des colonnes flex — et beaucoup à perdre si leurs champs se mettaient à s'étirer. */
.bo-dlg-flex .e-dlg-content { display: flex; flex-direction: column; }

/* min-height:0 est la ligne qui fait réellement le travail. Sans elle, un enfant flex refuse de
   descendre sous sa taille de contenu : la grille déborderait de la boîte au lieu de rétrécir
   avec elle, et la réduire n'aurait aucun effet visible. */
.bo-dlg-flex .e-dlg-content > .e-grid,
.bo-dlg-flex .e-dlg-content > .bo-dlg-corps { flex: 1 1 auto; min-height: 0; }

/* Le corps qui défile quand le contenu n'est pas une grille mais du texte de longueur inconnue. */
.bo-dlg-flex .e-dlg-content > .bo-dlg-corps { overflow-y: auto; }

/* Un enfant de colonne flex s'étire sur toute la LARGEUR par défaut : le bouton « Ajouter un
   droit » est devenu une bande pleine largeur à la seconde où la boîte est passée en flex.
   Constaté à l'essai, pas prévu. Les boutons reprennent leur largeur naturelle ; la grille, elle,
   doit bien s'étirer — d'où la règle ciblée plutôt qu'un align-items sur le conteneur. */
.bo-dlg-flex .e-dlg-content > .e-btn { align-self: flex-start; }

/* ---------- Sélecteur de langue de l'écran de connexion ---------- */
/* Les boutons portent la même classe .bo-lang-opt que ceux de la barre latérale, mais PAS les
   mêmes règles : celles du menu vivent dans NavMenu.razor.css, isolées par le CSS scopé de
   Blazor, et ne franchissent donc pas la frontière du composant. D'où cette reprise ici — ce
   n'est pas une duplication par négligence, c'est la conséquence de l'isolation. */
.auth-lang { display: flex; gap: .3rem; margin-bottom: 1.6rem; }
.auth-lang .bo-lang-opt {
    padding: .3rem .75rem; font-size: .75rem; font-weight: 600; letter-spacing: .03em;
    color: var(--text-muted); background: transparent; cursor: pointer;
    border: 1px solid rgba(0,0,0,.12); border-radius: var(--radius-sm, 6px);
}
.auth-lang .bo-lang-opt:hover { background: rgba(0,0,0,.04); }
/* La langue courante se lit à la COULEUR et à aria-pressed : le contraste seul ne dit rien à un
   lecteur d'écran. */
.auth-lang .bo-lang-opt.is-active { color: #fff; background: var(--brand); border-color: var(--brand); }

/* ---------- Écran de connexion en arabe ---------- */
/* dir="rtl" retourne le texte mais PAS les décalages écrits en dur : l'icône du champ est
   positionnée à gauche et la saisie réserve sa place par un padding gauche. Sans ces deux
   règles, l'icône se superposerait au texte arabe, qui commence à droite. */
.auth[dir="rtl"] .auth-input-ico { left: auto; right: .95rem; }
.auth[dir="rtl"] .auth-input .form-control { padding: 0 2.75rem 0 1rem; }

.auth-form { display: flex; flex-direction: column; }
.auth-field { margin-bottom: 1.15rem; }
.auth-field label { display: block; font-size: .82rem; font-weight: 600; color: var(--text-soft); margin-bottom: .45rem; }
.auth-input { position: relative; }
.auth-input-ico { position: absolute; left: .95rem; top: 50%; transform: translateY(-50%); color: var(--text-muted); pointer-events: none; }
.auth-input .form-control {
    width: 100%; height: 48px;
    padding: 0 1rem 0 2.75rem;
    border-radius: 11px;
    border: 1px solid var(--border-strong);
    font-size: .96rem;
    color: var(--text);
    background: var(--surface);
    transition: border-color .14s ease, box-shadow .14s ease;
}
.auth-input .form-control:focus { border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-tint); outline: none; }
.auth-input .form-control::placeholder { color: #aab4c4; }
[dir="rtl"] .auth-input-ico { left: auto; right: .95rem; }
[dir="rtl"] .auth-input .form-control { padding: 0 2.75rem 0 1rem; }

.auth-alert { display: flex; align-items: center; gap: .55rem; margin-bottom: 1.25rem; }

.auth-submit {
    margin-top: .5rem; height: 50px;
    display: flex; align-items: center; justify-content: center; gap: .5rem;
    border: none; border-radius: 12px;
    color: #fff; font-size: 1rem; font-weight: 600; letter-spacing: -.01em; cursor: pointer;
    background: linear-gradient(135deg, #1b8ae0, #0f6cbd);
    box-shadow: 0 8px 18px rgba(15, 108, 189, .32);
    transition: transform .12s ease, box-shadow .14s ease, filter .14s ease;
}
.auth-submit:hover { filter: brightness(1.03); box-shadow: 0 10px 22px rgba(15, 108, 189, .42); transform: translateY(-1px); }
.auth-submit:active { transform: translateY(0); }
.auth-submit svg { transition: transform .16s ease; }
.auth-submit:hover svg { transform: translateX(3px); }

.auth-foot { display: flex; align-items: center; justify-content: center; gap: .4rem; margin-top: 2rem; color: var(--text-muted); font-size: .8rem; }
.auth-form .validation-message { margin-top: .35rem; font-size: .82rem; }

@media (max-width: 860px) {
    .auth-brand { display: none; }
    .auth-mobile-logo { display: flex; }
    .auth-form-wrap { background: var(--bg); }
    .auth-card { background: var(--surface); border: 1px solid var(--border); border-radius: 18px; padding: 2rem 1.75rem; box-shadow: var(--shadow-md); }
}

/* ---------- Grid action icons (Actions columns) ---------- */
.grid-action {
    display: inline-grid;
    place-items: center;
    width: 30px;
    height: 30px;
    margin: 0 2px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    text-decoration: none;
    vertical-align: middle;
    transition: background-color .13s ease, color .13s ease, border-color .13s ease;
}
.grid-action:hover { background: var(--surface-2); color: var(--text); border-color: var(--border); }
.grid-action:active { transform: translateY(.5px); }
.grid-action-brand:hover   { color: var(--brand);   background: var(--brand-tint);   border-color: var(--brand-tint-strong); }
.grid-action-danger:hover  { color: var(--danger);  background: var(--danger-tint);  border-color: #f2cecb; }
.grid-action-success:hover { color: var(--success); background: var(--success-tint); border-color: #c7ecdb; }
.grid-action-warning:hover { color: var(--warning); background: var(--warning-tint); border-color: #f0dcb8; }

/* Une action fermee reste VISIBLE et grise, elle ne disparait pas : sur l'offre d'un projet en
   ligne, l'operateur doit voir que « modifier » et « supprimer » existent et sont interdits,
   sinon il cherche une commande absente. Le :hover est neutralise pour ne rien promettre. */
.grid-action:disabled { opacity: .38; cursor: not-allowed; }
.grid-action:disabled:hover { background: transparent; color: var(--text-muted); border-color: transparent; }

/* ==========================================================================
   Collapsible sidebar (checkbox #sb-toggle in MainLayout) + smooth animation
   ========================================================================== */
.sb-toggle { display: none; }

@media (min-width: 901px) {
    /* collapse the sidebar to an icon rail by shrinking its width variable */
    .sb-toggle:checked ~ .page { --sidebar-w: 76px; }

    .sb-toggle:checked ~ .page .brand { justify-content: center; padding-left: .5rem; padding-right: .5rem; gap: 0; }
    .sb-toggle:checked ~ .page .brand-text,
    .sb-toggle:checked ~ .page .brand-mark { display: none; }

    .sb-toggle:checked ~ .page .nav-scroll { padding-left: .55rem; padding-right: .55rem; }
    .sb-toggle:checked ~ .page .nav-group-label { display: none; }
    .sb-toggle:checked ~ .page .nav-group + .nav-group {
        border-top: 1px solid var(--border);
        margin-top: .45rem;
        padding-top: .45rem;
    }
    .sb-toggle:checked ~ .page .nav-text { display: none; }
    .sb-toggle:checked ~ .page .nav-link { justify-content: center; padding: .55rem; gap: 0; }

    .sb-toggle:checked ~ .page .nav-footer { justify-content: center; padding: .75rem 0; }
    .sb-toggle:checked ~ .page .nav-user-name,
    .sb-toggle:checked ~ .page .nav-logout-form { display: none; }
}

/* ---------- Error UI ---------- */
.blazor-error-boundary {
    background: #b32121; padding: 1rem 1rem 1rem 3.7rem; color: white; border-radius: var(--radius-sm);
}
.blazor-error-boundary::after { content: "Une erreur s'est produite."; }

/* ---------- KYC document review (Users console) ---------- */
.kyc-doc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: .75rem; max-width: 900px; }
.kyc-doc-item { display: flex; align-items: center; gap: .6rem; padding: .75rem .9rem; border: 1px solid var(--border, #e6ebf1); border-radius: 10px; background: var(--surface, #fff); text-decoration: none; color: var(--text, #1f2b3d); transition: border-color .13s ease, box-shadow .13s ease; }
.kyc-doc-item:hover { border-color: var(--brand, #0f6cbd); box-shadow: 0 2px 8px rgba(16,33,60,.08); }
.kyc-doc-badge { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: .18rem .5rem; border-radius: 999px; background: var(--brand-tint, #eef5fc); color: var(--brand, #0f6cbd); flex: 0 0 auto; }
.kyc-doc-label { flex: 1 1 auto; font-size: .88rem; }
.kyc-doc-open { font-size: .8rem; font-weight: 600; color: var(--brand, #0f6cbd); flex: 0 0 auto; }

/* ---------- Project detail / validation workflow (Projects console) ---------- */
/* L'EN-TETE PORTE MAINTENANT UNE ACTION A SA DROITE. Le titre et la pastille restent en flux
   normal a gauche ; l'action est sortie du flux par un flottement a droite plutot que par une
   grille, parce que le titre et la pastille sont des elements en ligne dont l'alignement sur la
   ligne de base tient a ce flux. La position relative sert d'ancre a la boite de dialogue. */
.proj-head { margin-bottom: 1rem; }
.proj-head-actions { float: inline-end; }
.proj-head::after { content: ""; display: block; clear: both; }
.proj-head h1 { display: inline-flex; align-items: baseline; gap: .5rem; font-size: 1.5rem; margin: 0 .6rem 0 0; }
.proj-head h1 small { font-size: .85rem; font-weight: 500; color: var(--text-muted); }
.proj-owner { color: var(--text-soft); font-size: .9rem; margin-top: .25rem; }

/* LE DECLENCHEUR DU PASSE-PARTOUT est en contour et non plein : il ouvre un formulaire, il
   n'engage rien. Un bouton plein en haut a droite se lirait comme l'action principale de la
   fiche, alors que l'action principale est de trancher les dossiers. */
.pp-declencheur { font-size: .85rem; }

.status-badge { display: inline-block; font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; padding: .22rem .6rem; border-radius: 999px; background: var(--brand-tint); color: var(--brand); vertical-align: middle; }
.status-badge.online, .status-badge.cloture, .status-badge.valide { background: var(--success-tint); color: var(--success); }
.status-badge.blocked, .status-badge.non_cloture, .status-badge.refuse { background: var(--danger-tint); color: var(--danger); }
.status-badge.en_attente_de_cloture, .status-badge.prevalidation, .status-badge.ready, .status-badge.encours { background: var(--warning-tint); color: var(--warning); }
.status-badge.draft { background: var(--brand-tint); color: var(--text-muted); }

.action-bar { display: flex; flex-wrap: wrap; gap: .5rem; margin: .75rem 0 1.25rem; }

.val-section { margin-bottom: 1.5rem; }
.val-section h3 { font-size: 1.05rem; margin-bottom: .6rem; color: var(--text); }

.val-item { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: .75rem; padding: .7rem .9rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); margin-bottom: .5rem; }
.val-item-main { display: flex; align-items: flex-start; gap: .6rem; flex: 1 1 260px; min-width: 0; }
.val-dot { flex: 0 0 auto; width: .6rem; height: .6rem; margin-top: .35rem; border-radius: 50%; background: var(--text-muted); }
.val-item.ok .val-dot { background: var(--success); }
.val-item.ko .val-dot { background: var(--danger); }
.val-item.ok { border-color: var(--success-tint); background: var(--success-tint); }
.val-item.ko { border-color: var(--danger-tint); background: var(--danger-tint); }
.val-label { font-weight: 600; color: var(--text); font-size: .9rem; }
.val-value { color: var(--text-soft); font-size: .85rem; word-break: break-word; }
.val-actions { display: flex; flex: 0 0 auto; gap: .4rem; }
/* MODIFICATION D'UN CHAMP DU DOSSIER. Meme gabarit que le bloc de refus juste dessous : les
   deux s'ouvrent sous la ligne, occupent toute la largeur et rendent la main par un bouton.
   Une troisieme mise en forme pour un troisieme geste rendrait l'ecran illisible. */
.val-edit { flex: 1 1 100%; margin-top: .5rem; }
.val-edit textarea, .val-edit input, .val-edit select { width: 100%; }
.val-edit-note { font-size: .78rem; color: var(--text-muted, #666); margin: .4rem 0 .5rem; }
.val-edit-actions { display: flex; gap: .5rem; }
.val-motif { flex: 1 1 100%; display: flex; gap: .5rem; align-items: flex-start; margin-top: .4rem; }
.val-motif textarea { min-height: 2.2rem; flex: 1 1 auto; }
.val-motif-shown { flex: 1 1 100%; font-size: .82rem; color: var(--danger); margin-top: .3rem; }

.modal-backdrop-custom { position: fixed; inset: 0; background: rgba(16, 33, 60, .45); display: flex; align-items: center; justify-content: center; z-index: 1050; }
.modal-card { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-md); padding: 1.25rem 1.5rem; width: 100%; max-width: 420px; }
.modal-card h3 { margin-top: 0; margin-bottom: .75rem; }
.modal-card .hint { color: var(--text-muted); font-size: .85rem; }
.modal-actions { display: flex; justify-content: flex-end; gap: .5rem; margin-top: 1rem; }

/* Onglets de validation projet (SfTab) */
.proj-val-tabs { margin-top: 1rem; }
.val-tab-count { font-size: .72em; opacity: .6; margin-left: .35rem; font-weight: 600; }

/* Temoin d'onglet : ce qui MANQUE, la ou le compteur dit ce qui est fait. Meme place et meme
   taille que le compteur, mais plein et colore — il signale, il ne renseigne pas. La couleur ne
   porte jamais seule l'information : le point d'exclamation et la phrase complete (visually-hidden
   + infobulle) disent la meme chose sans elle. */
.val-tab-warn {
    display: inline-grid;
    place-items: center;
    width: 1.15em;
    height: 1.15em;
    margin-left: .35rem;
    border-radius: 50%;
    background: var(--warning);
    color: #fff;
    font-size: .72em;
    font-weight: 700;
    line-height: 1;
    vertical-align: 1px;
}
.proj-val-tabs .val-section { padding: .25rem 0; }

/* ---------- Carte de section ----------
   Reprise du cadre de .wf (le bloc « Statut du projet »), qui servait de modele : les sections
   de la fiche projet s'enchainaient auparavant sans separation, titres colles au bloc precedent.
   Une carte par section rend la coupure visible sans avoir a espacer au jugé. */
.bo-card {
    margin: 0 0 1.25rem;
    padding: 1rem 1.1rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
}
.bo-card > h3 { font-size: 1.05rem; font-weight: 600; margin: 0 0 .85rem; color: var(--text); }
.bo-card > :last-child { margin-bottom: 0; }

/* ---------- Onglet « Offre & tranches » ----------
   BORNER LES CHAMPS. Un SfDropDownList ou un SfNumericTextBox sans largeur prend TOUTE celle de
   la page : sur un ecran de bureau, la liste « Type d'offre » faisait plus de 1 400 px pour trois
   valeurs. Les champs sont donc poses en grille de colonnes bornees, et non plus empiles pleine
   largeur. Les zones de saisie libre (objectifs, utilisation des fonds) gardent une largeur plus
   confortable — elles recoivent des phrases, pas un nombre. */
.offer-grid { display: flex; flex-wrap: wrap; gap: .9rem 1.25rem; margin-bottom: 1rem; }
.offer-field { flex: 1 1 260px; max-width: 320px; min-width: 0; }
.offer-field-wide { flex: 1 1 100%; max-width: 620px; }
.offer-field > label { display: block; font-size: .9rem; font-weight: 600; margin-bottom: .25rem; }
.offer-field .form-text { font-size: .8rem; }
.bo-card .e-input-group, .bo-card .e-ddl { width: 100%; }

/* ---------- Onglet « Documents » de la fiche projet ----------
   AUCUNE de ces classes n'existait dans la feuille : le balisage posait .doc-row, .doc-label,
   .doc-status et .doc-actions sur du vide. L'ecran rendait donc du texte empile et une file de
   boutons colles les uns aux autres. Une carte par piece, un etat lisible d'un coup d'oeil, et
   des actions qui se distinguent. */
.doc-count {
    font-size: .72em; font-weight: 600; opacity: .6; margin-left: .5rem;
    text-transform: none; letter-spacing: 0;
}

.doc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; }

.doc-card {
    padding: .8rem .95rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
}

/* Une piece EXIGEE A CE STADE et ABSENTE est ce qui bloque le dossier : elle se voit sans etre
   lue, par un liseré, et non par la seule couleur d'une pastille. « A ce stade » compte : une
   piece du second palier, sur un dossier en pre-validation, est obligatoire mais pas encore due. */
.doc-card-manquant { border-left: 3px solid var(--warning); background: var(--warning-tint); }

/* LE STATUT SUIT LE NOM, il n'est pas renvoye au bord droit de l'ecran. Sur un onglet large de
   1 200 px, un `space-between` eloignait la pastille de la piece qu'elle qualifie au point qu'il
   fallait suivre la ligne des yeux pour les rapprocher. */
.doc-head {
    display: flex; flex-wrap: wrap; align-items: baseline;
    justify-content: flex-start; gap: .5rem;
}
.doc-name { font-weight: 600; font-size: .92rem; color: var(--text); }

.doc-req {
    display: inline-block; margin-left: .4rem; padding: .05rem .4rem;
    border-radius: 999px; background: var(--warning-tint); color: var(--warning);
    font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .02em;
    vertical-align: 1px;
}

/* La pastille d'etat. La couleur ne porte jamais seule l'information : le mot est ecrit. */
.doc-pill {
    flex: 0 0 auto; padding: .12rem .55rem; border-radius: 999px;
    font-size: .74rem; font-weight: 700; white-space: nowrap;
}
.doc-pill-vide    { background: var(--surface-2);   color: var(--text-muted); }
.doc-pill-attente { background: var(--warning-tint); color: var(--warning); }
.doc-pill-ok      { background: var(--success-tint); color: var(--success); }
.doc-pill-ko      { background: var(--danger-tint);  color: var(--danger); }

/* Le motif d'un refus est une phrase ecrite par un operateur : sa propre ligne, pas un suffixe
   de pastille. */
.doc-motif {
    margin: .45rem 0 0; padding-left: .6rem;
    border-left: 2px solid var(--danger-tint);
    font-size: .84rem; color: var(--danger);
}

/* Le meme champ « motif » accompagne aussi une VALIDATION (livrables) : la teinte de refus y
   serait un contresens. */
.doc-motif-ok { border-left-color: var(--success-tint); color: var(--text-soft); }

.doc-actions { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .65rem; }

/* Les actions sont des boutons SOBRES et de meme taille — c'est leur alignement qui les rend
   lisibles, pas cinq couleurs differentes. Seules « valider » et les actions destructrices se
   teintent, et seulement au survol. */
.doc-btn {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .3rem .6rem; border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text-soft);
    font-size: .82rem; font-weight: 600; line-height: 1.3;
    cursor: pointer; text-decoration: none;
    transition: background-color .13s ease, color .13s ease, border-color .13s ease;
}
.doc-btn:hover        { background: var(--surface-2); color: var(--text); }
.doc-btn-ok:hover     { background: var(--success-tint); color: var(--success); border-color: #c7ecdb; }
.doc-btn-ko:hover     { background: var(--danger-tint);  color: var(--danger);  border-color: #f2cecb; }
.doc-btn-primaire     { background: var(--brand); color: #fff; border-color: var(--brand); }
.doc-btn-primaire:hover { background: var(--brand); color: #fff; filter: brightness(1.06); }

.doc-reject {
    display: flex; flex-wrap: wrap; gap: .45rem; align-items: center;
    margin-top: .65rem; padding-top: .65rem; border-top: 1px dashed var(--border);
}
.doc-reject .form-control { flex: 1 1 260px; max-width: 460px; }

/* ---------- Onglet « Livrables » ----------
   Il souffrait exactement du meme mal que Documents : aucune de ses classes (.liv-list, .liv-row,
   .liv-status, .liv-detail) n'existait dans cette feuille, et l'onglet rendait un en-tete de
   tableau nu flottant sous un bouton. Il reprend donc le vocabulaire de Documents — .doc-card,
   .doc-pill, .doc-btn — pour que les deux onglets de la meme fiche se lisent pareil, et n'ajoute
   ici que ce qui lui est propre. */

/* La carte selectionnee, dont le detail s'affiche en dessous. */
.doc-card-actif { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.doc-card-actif .doc-name a { color: var(--brand); }

/* Echeance et compteur de pieces : des precisions, pas des titres. */
.liv-meta { font-size: .8rem; color: var(--text-muted); }

.liv-texte {
    margin: 0 0 1rem; padding-left: .7rem;
    border-left: 2px solid var(--border);
    font-size: .88rem; color: var(--text-soft); white-space: pre-wrap;
}

.liv-sous-titre { font-size: .92rem; font-weight: 600; margin: 0 0 .7rem; color: var(--text); }

.liv-doc-desc { margin: .4rem 0 0; font-size: .84rem; color: var(--text-soft); }

/* Panneau compte (page détail membre) */
.acct-panel { margin-bottom: 1.25rem; padding: .9rem 1rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface); }
.acct-panel h3 { margin: 0 0 .25rem; font-size: 1rem; }
.acct-panel .action-bar { margin: .5rem 0 0; }

.val-doc-link { display: inline-block; margin-top: .25rem; font-size: .85rem; font-weight: 600; color: var(--brand); }

/* ---------- Grille principale d'une page : elle occupe le reste de la fenetre ---------- */
/* La hauteur des SfGrid etait figee en pixels — 600 px pour vingt-quatre d'entre elles — et le
   bas de l'ecran restait vide : 258 px mesures sur /projects le 02/08/2026, sur une fenetre de
   888 px. La chaine de hauteur posee dans MainLayout.razor.css rend enfin possible de demander
   « le reste », et ces deux lignes le demandent.

   LE SELECTEUR EST VOLONTAIREMENT STRICT : « > », donc uniquement une grille placee DIRECTEMENT
   dans la zone de contenu, c'est-a-dire la grille qui EST la page. Celles des boites de dialogue,
   des volets et des panneaux imbriques gardent la taille qu'on leur a donnee — elles n'ont aucune
   raison de s'etirer, et plusieurs partagent leur ecran avec autre chose.

   flex-basis: auto conserve la hauteur declaree comme point de depart, si bien qu'aucune page
   n'a a etre modifiee : la grille part de sa taille actuelle et grandit. Le min-height empeche
   l'effet inverse sur une petite fenetre, ou la grille se comprimerait jusqu'a l'illisible. */
.content > .e-grid {
    flex: 1 1 auto;
    min-height: 320px;
    /* La grille devient elle-meme une colonne, sans quoi elle grandirait en laissant ses lignes
       a leur taille d'origine — un cadre etire autour d'un tableau qui ne bouge pas. */
    display: flex;
    flex-direction: column;
}

/* L'EN-TETE ET LA PAGINATION NE CEDENT PAS. Un element flex est compressible par defaut :
   sans cette ligne, l'en-tete se fait ecraser pour laisser la place aux lignes — mesure sur
   /projects, 77 px de contenu reduits a 55 px — et comme il est en overflow: hidden, la barre
   de filtres se retrouve coupee en deux sans le moindre signe. */
.content > .e-grid > .e-gridheader,
.content > .e-grid > .e-gridpager {
    flex: 0 0 auto;
}

/* Seule la zone des lignes absorbe la place restante. */
.content > .e-grid > .e-gridcontent {
    flex: 1 1 auto;
    min-height: 0;
}

/* LE !important EST ICI NECESSAIRE, ET C'EST LE SEUL ENDROIT. Syncfusion calcule la hauteur de
   sa zone defilante en JavaScript au moment du rendu et la POSE EN STYLE EN LIGNE (height: 360px
   mesure sur /users). Une feuille de style ne peut pas passer devant un style en ligne autrement.
   Sans cette ligne, la grille occupe bien toute la page mais s'arrete de remplir a la hauteur
   d'origine, et le vide se retrouve A L'INTERIEUR du cadre au lieu d'etre en dessous.

   Sans danger ici : aucune grille du back-office n'active la virtualisation, laquelle deduit du
   nombre de lignes visibles une hauteur exacte et se briserait a la voir changer sous elle. */
.content > .e-grid > .e-gridcontent > .e-content {
    height: 100% !important;
}

/* Logo des ecrans d'authentification. Meme regle que sur le site public : les deux pages de
   connexion doivent presenter la marque a l'identique. */
.auth-logo-img { height: 40px; width: auto; display: block; }

/* ------------------------------------------------------------------ évaluation ESG d'un projet
   Neuf critères par pilier, chacun avec ses quatre options. La densité compte : un opérateur qui
   note vingt-sept critères doit voir le libellé du niveau qu'il choisit, pas seulement sa valeur,
   sinon il coche au jugé. C'est pour cela que chaque option porte le texte du guide en entier. */
.esg-eval { padding: .5rem 0; }
.esg-eval-secteur { margin-bottom: 1.25rem; }

.esg-eval-scores { display: flex; flex-wrap: wrap; gap: 1rem; margin-bottom: 1.5rem; }
.esg-eval-score { background: #f4f6f9; border-radius: .5rem; padding: .6rem 1rem; min-width: 9rem; }
.esg-eval-score span { display: block; font-size: .8rem; color: #5a5a5a; }
.esg-eval-score strong { font-size: 1.4rem; }
/* La tuile du score global porte en plus la pastille du niveau : sans place reservee, elle
   depassait du cadre. Constate en deroulant l'ecran le 12/08/2026. */
.esg-eval-score-global { background: #e8edf3; display: flex; flex-direction: column;
                         align-items: flex-start; gap: .25rem; }
.esg-eval-score-global .badge { margin: 0 !important; white-space: nowrap; }

.esg-eval-pilier { margin-bottom: 2rem; }
.esg-eval-pilier > h5 { border-bottom: 2px solid #1f3a5f; padding-bottom: .35rem; }

.esg-eval-critere { border: 1px solid #e3e6ea; border-radius: .5rem; padding: .75rem 1rem;
                    margin-bottom: .75rem; }
.esg-eval-critere-tete { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.esg-eval-code { font-family: ui-monospace, monospace; font-weight: 700; color: #1f3a5f;
                 background: #e8edf3; border-radius: .3rem; padding: .1rem .45rem; }
.esg-eval-desc { color: #444; margin-top: .3rem; }
.esg-eval-preuves { color: #5a5a5a; font-size: .85rem; margin-top: .2rem; font-style: italic; }

/* Les quatre options côte à côte tant que la place le permet, empilées ensuite : les libellés du
   guide font parfois une ligne entière, et les tronquer ferait perdre ce qui distingue 0,5 de 1. */
.esg-eval-options { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
                    gap: .5rem; margin-top: .6rem; }
.esg-eval-option { display: flex; align-items: flex-start; gap: .45rem; cursor: pointer;
                   border: 1px solid #e3e6ea; border-radius: .4rem; padding: .45rem .6rem;
                   font-size: .88rem; }
.esg-eval-option:hover { background: #f7f9fb; }
.esg-eval-option.retenue { border-color: #1f3a5f; background: #eef3f9; }
.esg-eval-note { font-weight: 700; color: #1f3a5f; min-width: 1.8rem; }
.esg-eval-libelle { flex: 1; }

.esg-eval-justif { margin-top: .6rem; }

/* RAPPROCHEMENT DES VERSEMENTS : la ligne est le seul chemin vers les actions.
   Confirmer, detacher et refuser vivent dans la boite de detail qu'ouvre un clic sur la ligne ;
   la grille elle-meme ne porte aucune colonne d'action. Le curseur le dit, la phrase au-dessus
   de la grille l'ecrit. Sans l'un ni l'autre, un confirmateur cherche un bouton qui n'existe
   pas et repart en croyant qu'il n'a pas le droit d'agir. */
.rv-astuce { margin: .25rem 0 .75rem; font-size: .9rem; }
.rv-grille-cliquable .e-row { cursor: pointer; }

/* LA GRILLE PREND LA HAUTEUR RESTANTE ET DEFILE TOUTE SEULE.

   .content (la mise en page) est deja une colonne flex haute de 100vh, et cette enveloppe en est
   un enfant direct : lui donner flex:1 suffit a lui donner exactement la place qui reste sous le
   titre, le compte et les onglets — sans aucune constante de hauteur, qui se serait dementie au
   premier libelle ajoute au-dessus.

   LA BASE EST A ZERO (flex: 1 1 0) ET NON « auto ». Avec « auto », un element flex ne descend
   pas sous la hauteur de son contenu : une grille de trois cents lignes aurait pousse la page
   entiere au lieu de defiler dans son propre cadre. La base a zero fait l'inverse — la hauteur
   vient de la place disponible, et le contenu s'y plie.

   LE PLANCHER DE 240 PX la garde utilisable sur un ecran court : sur une fenetre basse, la place
   restante peut tomber a rien, et une grille haute de 40 px ne se lit pas. En dessous de ce
   plancher, c'est la page qui defile — .content est deja en overflow auto. */
.grille-pleine-hauteur { flex: 1 1 0; min-height: 240px; }

/* LE DETAIL D'UNE LIGNE : haut comme son contenu, jamais plus haut que la fenetre.

   La boite portait une hauteur fixe de 560 px, ou le detail d'une ligne ordinaire flottait au
   milieu du vide. Sans hauteur, elle epouse son contenu — mais une ligne heritee porte deux
   pavés d'explication, et rien ne l'empecherait alors de deborder par le bas. Ce plafond lui
   rend son cadre, et c'est le corps qui defile, pas la fenetre. */
/* LE SELECTEUR PORTE « .e-dialog », ET CE N'EST PAS UN ORNEMENT : Syncfusion recopie CssClass
   sur TROIS elements — la boite, le voile qui la centre (.e-dlg-container, fixe et plein ecran)
   et jusqu'au bouton de fermeture. Mesure faite en ligne : « .rv-detail » seul plafonnait le
   voile a 756 px de haut, ce qui n'etait pas le but et deplacait le centrage.

   ET « !important » PARCE QUE SYNCFUSION ECRIT SON PROPRE PLAFOND EN STYLE EN LIGNE :
   max-height: 925px, mesure en ligne, soit la fenetre moins 20 px. Une regle de feuille de
   style ne passe pas devant un style en ligne autrement. Sans ce mot, la boite touchait
   presque les deux bords de l'ecran — ce qui n'est pas faux, mais pas un cadre. */
.e-dialog.rv-detail { max-height: 80vh !important; }
.e-dialog.rv-detail .e-dlg-content { overflow-y: auto; }

/* ---------------------------------------------------------------------------------------------
   LE TABLEAU DE BORD.
   Chaque compteur est un LIEN vers l'ecran qui permet d'agir : un chiffre sur lequel on ne peut
   rien faire n'est pas une information, c'est une inquietude. La couleur du filet superieur
   distingue les familles au premier coup d'oeil, sans qu'il faille lire les libelles.
   --------------------------------------------------------------------------------------------- */
.tdb-entete { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
              flex-wrap: wrap; margin-bottom: 1.2rem; }
.tdb-entete h1 { margin: 0 0 .25rem; }

.tdb-cartes { display: grid; gap: .9rem; margin-bottom: 1.2rem;
              grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.tdb-carte { display: flex; flex-direction: column; gap: .35rem;
             padding: 1.1rem 1rem; border: 1px solid #e6ebf1; border-radius: .6rem;
             border-top: 4px solid #94a3b8; background: #fff;
             text-decoration: none; color: inherit; transition: box-shadow .15s, transform .15s; }
.tdb-carte:hover { box-shadow: 0 4px 14px rgba(12,42,82,.12); transform: translateY(-1px); }
.tdb-nombre { font-size: 2rem; font-weight: 700; line-height: 1; color: #0c2a52; }
.tdb-libelle { font-size: .84rem; color: #555b63; }
.tdb-carte.attente   { border-top-color: #eab308; }
.tdb-carte.enligne   { border-top-color: #16a34a; }
.tdb-carte.cloture   { border-top-color: #f97316; }
.tdb-carte.profils   { border-top-color: #1d5ba6; }
.tdb-carte.documents { border-top-color: #dc2626; }
.tdb-carte.comptes   { border-top-color: #7c3aed; }
.tdb-carte.promesses { border-top-color: #0891b2; }

/* L'alerte n'apparait que s'il y a lieu : un bandeau permanent annoncant « 0 » apprend a ne plus
   regarder cet endroit, et c'est le jour ou il compte qu'on ne le verra pas. */
.tdb-alerte { display: flex; flex-wrap: wrap; gap: .4rem; align-items: baseline;
              padding: .85rem 1rem; margin-bottom: 1.2rem;
              border: 1px solid #f3b0b0; border-radius: .6rem; background: #fff5f5; color: #8a1c1c; }

.tdb-colonnes { display: grid; gap: 1rem; grid-template-columns: 1.4fr 1fr; align-items: start; }
@media (max-width: 900px) { .tdb-colonnes { grid-template-columns: 1fr; } }
.tdb-bloc { padding: 1.1rem 1.2rem; border: 1px solid #e6ebf1; border-radius: .6rem; background: #fff; }
.tdb-bloc h2 { font-size: 1.05rem; margin: 0 0 .8rem; }

.tdb-dossier { display: grid; grid-template-columns: 1fr auto auto; gap: .8rem; align-items: center;
               padding: .7rem 0; border-bottom: 1px solid #eef2f6; }
.tdb-dossier:last-child { border-bottom: 0; }
.tdb-dossier.retard .tdb-age { color: #b91c1c; font-weight: 700; }
.tdb-ref { font-weight: 600; color: #1d5ba6; text-decoration: none; }
.tdb-nom { font-size: .84rem; color: #555b63; }
.tdb-statut { font-size: .76rem; padding: .2rem .55rem; border-radius: 999px;
              background: #eef4fb; color: #1d5ba6; white-space: nowrap; }
.tdb-age { font-size: .84rem; color: #555b63; min-width: 3rem; text-align: right; }

.tdb-evenement { padding: .55rem 0 .55rem .7rem; border-left: 3px solid #e6ebf1; margin-bottom: .3rem; }
.tdb-evenement-tete { display: flex; flex-wrap: wrap; gap: .4rem; align-items: baseline; }
.tdb-cle { font-size: .84rem; color: #555b63; }
.tdb-date { font-size: .76rem; color: #8b93a0; }
/* LE NOM DU MEMBRE EST UN LIEN, ET IL DOIT RESTER UN NOM. Il prend la couleur des references
   de la colonne voisine (.tdb-ref) et garde la graisse qu'il avait en <strong> : sans cela, un
   <a> nu ressortait en bleu souligne et cassait la lecture du bloc. */
.tdb-membre { font-weight: 700; color: #1d5ba6; text-decoration: none; }
.tdb-membre:hover { text-decoration: underline; }
/* Le projet, quand la notification en porte un : une ligne secondaire, sous l'evenement. */
.tdb-evenement-projet { font-size: .8rem; margin-top: .1rem; }
.tdb-evenement-projet a { color: #1d5ba6; text-decoration: none; }
.tdb-evenement-projet a:hover { text-decoration: underline; }
/* La famille de l'evenement se lit au filet de gauche : compte, dossier, argent. Trois couleurs,
   pas seize — au-dela, une couleur n'informe plus, elle decore. */
.tdb-evenement.compte  { border-left-color: #7c3aed; }
.tdb-evenement.dossier { border-left-color: #1d5ba6; }
.tdb-evenement.argent  { border-left-color: #16a34a; }

/* LES INSCRIPTIONS RECENTES. Le resume est en tete parce que c'est lui qui se lit en une seconde
   et dit si quelque chose cloche ; noye sous deux cents lignes, il ne serait jamais lu. */
.ins-filtres { display: flex; gap: 1.2rem; align-items: flex-end; flex-wrap: wrap; margin-bottom: 1rem; }
.ins-filtres label { display: flex; flex-direction: column; gap: .25rem; font-size: .85rem; }
/* LA CASE PREND LA HAUTEUR D'UNE LISTE, SINON ELLE SE POSE TROP BAS. La barre aligne ses
   colonnes par le bas ; une liste fait 35 px, une case et son texte 20. Sans hauteur imposee,
   le bas de la case rejoint le bas de la liste et le texte se retrouve sur le bord inferieur au
   lieu du milieu. En lui donnant la meme hauteur, le bas coincide toujours et le contenu se
   centre sur le milieu des listes. */
.ins-case { flex-direction: row !important; align-items: center; gap: .45rem !important;
            min-height: 35px; }
/* LES CHIFFRES S'ALIGNENT SUR LEUR LIGNE DE BASE, PAS SUR LE HAUT DE LEUR BOITE. Les nombres
   sont ecrits plus gros que leur legende ; sans consigne, la barre etirait chaque bloc sur toute
   sa hauteur et les chiffres flottaient a des hauteurs differentes selon la taille de leur
   propre texte. La ligne de base est la seule reference qui tienne quand deux textes n'ont pas
   le meme corps. Le bouton, lui, est recentre a part : sa ligne de base est celle de son
   libelle, ce qui le ferait remonter au-dessus des chiffres. */
.ins-resume { display: flex; gap: 1.6rem; flex-wrap: wrap; align-items: baseline;
              padding: .8rem 1rem; margin-bottom: 1rem;
              border: 1px solid #e6ebf1; border-radius: .6rem; background: #f8fafc; font-size: .9rem; }
.ins-resume > button { align-self: center; }
.ins-resume strong { font-size: 1.15rem; color: #0c2a52; }
.ins-table .inactif { background: #fcfcfd; color: #6b7280; }
.ins-email { font-size: .78rem; color: #8b93a0; }
.ins-pastille { font-size: .74rem; padding: .15rem .5rem; border-radius: 999px; white-space: nowrap; }
.ins-pastille.oui { background: #e7f6ec; color: #166534; }
.ins-pastille.non { background: #f3f4f6; color: #6b7280; }
/* La barre d'actions ne se montre qu'avec une selection : une barre toujours visible, aux boutons
   grises, invite a chercher ce qui manque. */
.ins-actions { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap;
               padding: .7rem 1rem; margin-bottom: 1rem;
               border: 1px solid #dbe4ef; border-radius: .6rem; background: #eef4fb; }
.ins-coche { width: 2.2rem; text-align: center; }
/* LE BOUTON DE RAFRAICHISSEMENT PREND LA HAUTEUR D'UNE LISTE, pour la meme raison que la case a
   cocher : la barre aligne par le bas et un bouton plus court se poserait de travers. */
.ins-rafraichir { min-height: 35px; display: inline-flex; align-items: center; gap: .4rem;
                  font-size: .85rem; }
.act-icone-refresh { display: inline-block; width: 14px; height: 14px; background: currentColor;
                     -webkit-mask: var(--act-refresh) center / contain no-repeat;
                     mask: var(--act-refresh) center / contain no-repeat; }
:root { --act-refresh: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M21 12a9 9 0 1 1-2.64-6.36'/><path d='M21 3v6h-6'/></svg>"); }
.ins-message { padding: .7rem 1rem; margin-bottom: 1rem; border-radius: .6rem; font-size: .9rem; }
.ins-message.ok { background: #e7f6ec; color: #166534; border: 1px solid #b7e2c6; }
.ins-message.ko { background: #fff5f5; color: #8a1c1c; border: 1px solid #f3b0b0; }

/* LA BOITE DE RECEPTION. Une ligne traitee s'efface visuellement sans disparaitre : la faire
   disparaitre empecherait de revenir sur une decision prise trop vite. */
/* LES LARGEURS SONT PORTEES PAR LA GRILLE, plus par la feuille de style : elles etaient posees
   ici du temps du tableau maison, que la grille Syncfusion a remplace pour rendre le tri et le
   filtrage. Seul reste l'effacement des lignes deja traitees. */
.act-table .lue, .e-grid .lue { color: #9aa3b0; }
.act-pastille { display: inline-block; width: .55rem; height: .55rem; border-radius: 50%;
                margin-inline-end: .5rem; vertical-align: middle; background: #94a3b8; }
.act-pastille.compte  { background: #7c3aed; }
.act-pastille.dossier { background: #1d5ba6; }
.act-pastille.argent  { background: #16a34a; }
.act-cle { font-size: .72rem; color: #b45309; background: #fffbeb; padding: .1rem .35rem;
           border-radius: .25rem; margin-inline-start: .4rem; }

/* LE FIL D'UN MEMBRE, VU DU BACK-OFFICE. Les deux cotes sont distingues par l'alignement autant
   que par la couleur : imprime en noir et blanc, le fil reste lisible. */
.chat-fil-bo { max-height: 22rem; overflow-y: auto; display: flex; flex-direction: column;
               gap: .6rem; padding: .2rem; margin-bottom: .8rem; }
.chat-message-bo { max-width: 80%; padding: .5rem .7rem; border-radius: .6rem; font-size: .87rem; }
.chat-message-bo.membre { align-self: flex-start; background: #f1f5f9; color: #0c2a52; }
.chat-message-bo.alif   { align-self: flex-end;   background: #e7f0fb; color: #0c2a52; }
.chat-auteur-bo { display: block; font-size: .72rem; font-weight: 700; margin-bottom: .15rem;
                  color: #4b5563; }
/* Trois regles reprises telles quelles de app.css du site public (.chat-corps, .chat-heure,
   .chat-saisie textarea), pour que les deux cotes du fil se ressemblent. .chat-corps est la plus
   importante des trois : sans white-space: pre-wrap, les retours a la ligne ecrits par le membre
   etaient ecrases cote agent, alors qu'ils restaient conserves cote membre. */
.chat-corps { white-space: pre-wrap; word-break: break-word; }
.chat-heure { margin-top: .2rem; font-size: .68rem; opacity: .7; }
.chat-saisie textarea { width: 100%; resize: none; font-size: .87rem; }

/* LE BLOC DES SOUSCRIPTIONS SUR LA FICHE D'UN MEMBRE.
   Le resume se lit avant la grille : c'est lui qui porte le chiffre qu'on vient chercher. */
.sous-bloc { margin-bottom: 1rem; }
.sous-resume { margin: 0 0 .7rem; font-size: .92rem; color: #0c2a52; }
.sous-resume strong { font-weight: 700; }

/* LES PROMESSES EN ATTENTE. Le resume porte le chiffre qu'on vient chercher ; les trois colonnes
   d'argent s'alignent a droite, seule facon de comparer des montants d'un coup d'oeil. */
.prom-resume { margin: 0 0 .5rem; font-size: .95rem; color: #0c2a52; font-weight: 600; }
.prom-note { margin: 0 0 .9rem; font-size: .84rem; color: #8a6100; }
/* .prom-table et .prom-num ont disparu avec le tableau brut que la grille remplace : elle
   aligne ses colonnes de nombres par TextAlign, et gere elle-meme l'alignement vertical. */

/* LE RETOUR APRES UN POINTAGE DANS « ACTIVITE DES MEMBRES ».
   Il reprend l'encadre d'alerte existant mais en ton neutre : ce n'est pas un incident, c'est un
   accuse de reception. Le bouton d'annulation est a l'oppose du texte, la ou l'oeil finit sa
   lecture. */
.act-retour { justify-content: space-between; align-items: center;
              border-color: #cfe0f5; background: #f3f7fc; color: #0c2a52; }

/* LE CHAMP DATE : NOTRE FORMAT DANS LE CHAMP, LE CALENDRIER DU NAVIGATEUR A COTE.

   Meme regle que sur le site public, et meme mesure (01/09/2026) : un input[type=date] affiche ses
   trois nombres dans l'ordre de la langue de CHROME. Le 1er septembre 2026 s'y ecrivait
   « 09/01/2026 », et ni lang="fr" sur le document ni sur le champ n'y changeaient rien.

   Ce qu'on lit et ce qu'on tape est donc un champ TEXTE dont nous ecrivons le format. Le champ
   date reel est conserve, reduit a son seul bouton calendrier : il ne sert plus qu'a ouvrir le
   calendrier natif et a rendre une valeur — invariable, elle — que le composant reecrit ensuite
   en jour / mois / annee. */
.date-champ { position: relative; display: block; }

/* La place du bouton, prise sur le champ texte pour que la saisie ne passe jamais dessous. */
.date-champ input.form-control { padding-inline-end: 2.6rem; }

.date-champ .date-natif {
    position: absolute; inset-inline-end: .3rem; top: 50%; transform: translateY(-50%);
    width: 26px; height: 26px; padding: 0; border: 0; background: none;
    color: var(--text-muted); cursor: pointer;
}
.date-champ .date-natif:disabled { cursor: default; opacity: .4; }

/* Tout le champ natif disparait SAUF son bouton calendrier. Les selecteurs -webkit- couvrent
   Chrome, Edge et Safari ; Firefox n'a pas ce bouton et le champ y reste simplement invisible,
   le champ texte suffisant a saisir la date. */
.date-champ .date-natif::-webkit-datetime-edit,
.date-champ .date-natif::-webkit-inner-spin-button,
.date-champ .date-natif::-webkit-clear-button { display: none; }
.date-champ .date-natif::-webkit-calendar-picker-indicator {
    width: 26px; height: 26px; margin: 0; padding: 0; cursor: pointer; opacity: .55;
}
.date-champ .date-natif::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* La ligne sous le champ : la date en toutes lettres, ou le motif du refus. Sans couleur, un
   « date incomprise » se lirait comme le rappel de format qu'il remplace. */
.date-champ + .field-hint { display: block; font-size: .78rem; color: var(--text-muted);
                            margin-top: .25rem; }
.date-champ + .field-hint-erreur { color: var(--danger, #b3261e); }

/* UN PALIER DE CONTREPARTIE EST UNE CARTE, PAS SIX CHAMPS EN VRAC. La classe existait dans le
   balisage depuis l'origine mais n'avait AUCUNE regle : deux paliers a la suite formaient un bloc
   continu de douze champs, sans qu'on voie ou l'un finissait. Signale le 01/09/2026. */
.contrepartie-row { border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
                    padding: .85rem .9rem .9rem; margin-bottom: .9rem;
                    background: var(--surface, #fff); }

/* Le numero, en tete de carte : c'est lui qui rend le decoupage lisible d'un coup d'oeil. */
.contrepartie-rang { font-size: .78rem; font-weight: 700; letter-spacing: .04em;
                     text-transform: uppercase; color: var(--text-muted);
                     margin-bottom: .55rem; }

/* LES DOSSIERS BLOQUES DE LA FILE D'ATTENTE. Ils se lisent, ils ne s'apparient pas : le tableau
   est volontairement en retrait de celui des candidats proposes juste au-dessus, pour qu'un
   operateur ne confonde pas ce qu'il peut faire avec ce qu'il ne peut que constater. */
.table-ecartes { background: #fafbfc; }
.table-ecartes tbody td { color: #555b63; }
.table-ecartes tbody td:first-child { font-variant-numeric: tabular-nums; }

/* L'ANNONCE DE VIREMENT SE LIT AVANT LA DATE DE RELANCE : c'est elle qui dit s'il faut relancer.
   Verte parce qu'elle est une bonne nouvelle, mais SANS pastille ni gras : annonce n'est pas recu,
   et un marqueur trop appuye ferait lire « paye ». */
.prom-annonce { font-size: .8rem; color: #15803d; }


/* LE RESUME DE L'OFFRE, pose au-dessus de la ligne « Type d'offre » de l'onglet de validation
   (10/09/2026). Il se lit comme une fiche, pas comme un formulaire : aucune case de saisie,
   aucun bouton. La bordure pointillee le distingue des lignes a juger qui l'entourent. */
.offre-resume { border: 1px dashed var(--border); border-radius: var(--radius-sm); background: var(--surface); padding: .8rem .95rem; margin-bottom: .5rem; }
.offre-resume-tete { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .75rem; margin-bottom: .6rem; }
.offre-resume-tete .text-muted { font-size: .8rem; }
.offre-resume-grille { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: .5rem 1.25rem; margin: 0; }
.offre-resume-grille dt { font-size: .75rem; font-weight: 600; color: var(--text-muted); margin: 0; }
.offre-resume-grille dd { font-size: .9rem; color: var(--text); margin: 0; word-break: break-word; }
.offre-resume-sous { font-size: .8rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text-muted); margin: .9rem 0 .35rem; }
.offre-resume-texte { font-size: .85rem; margin: .6rem 0 0; white-space: pre-line; }
.offre-resume-vide, .offre-resume-manque { font-size: .85rem; margin: 0; color: var(--text-soft); }
.offre-resume-manque { color: var(--danger); }
.offre-resume-liste { margin: 0; padding-inline-start: 1.1rem; font-size: .85rem; }
.offre-resume-table { overflow-x: auto; }
.offre-resume-table table { border-collapse: collapse; font-size: .85rem; min-width: 420px; }
.offre-resume-table th, .offre-resume-table td { text-align: start; padding: .25rem .9rem .25rem 0; border-bottom: 1px solid var(--border); }
.offre-resume-table th { font-size: .75rem; color: var(--text-muted); font-weight: 600; }

/* Fenêtre « Tranche » : le mode de remboursement, et le nombre d'échéances qui en résulte. */
.tranche-remb { display: flex; flex-wrap: wrap; gap: .4rem 1.25rem; margin-top: .25rem; }
.tranche-remb label { display: inline-flex; align-items: center; gap: .4rem; font-weight: 400; cursor: pointer; }
.tranche-echeances { font-size: .85rem; font-weight: 600; color: var(--text, #222); }

/* Fiche projet : ce qui manque se lit. Champ vide, facultatif vide, complément du dossier. */
.val-value-vide { color: var(--text-muted, #777); font-style: italic; }
.val-item.facultatif { background: var(--surface-2, #f5f6f8); }
.complement-dossier { margin-top: 1rem; padding: .9rem 1rem; border: 1px solid var(--border, #e3e6ea); border-radius: 8px; }
.complement-dossier h4 { font-size: .95rem; margin: 0 0 .6rem; }
.complement-dossier dl { display: grid; grid-template-columns: 11rem 1fr; gap: .45rem 1rem; margin: 0; }
.complement-dossier dt { font-weight: 600; font-size: .85rem; }
.complement-dossier dd { margin: 0; font-size: .85rem; white-space: pre-line; }
.complement-vide { color: var(--danger, #b42318); font-style: italic; }
.complement-visuels { display: flex; flex-wrap: wrap; gap: .5rem; }
.complement-visuels img { height: 64px; border-radius: 4px; border: 2px solid transparent; }
.complement-visuels img.banniere { border-color: var(--primary, #1d4ed8); }
.complement-resultats td { padding: .1rem .8rem .1rem 0; }
