html, body {
    font-family: var(--ed-font-family);
    color: var(--ed-text);
}
/*
 * Alias de compatibilite : les feuilles heritees referencent encore --primary-color et
 * consorts. La source de verite reste wwwroot/css/theme.css ; ne rien redefinir ici.
 */
:root {
    --primary-color: var(--ed-primary);
    --primary-light-color: var(--ed-primary-light);
    --primary-dark-color: var(--ed-primary-dark);
    --accent-color: var(--ed-accent);
}

h1:focus {
    outline: none;
}

a, .btn-link {
    color: var(--primary-color);
}

.btn-primary {
    color: var(--ed-primary-contrast);
    background-color: var(--primary-color);
    border-color: var(--primary-color);
}

.rz-body {
    background-color: var(--ed-surface-alt);
}

/*
 * Radzen's theme sets `.rz-layout .rz-body { transform: translateZ(0px); }` as a GPU-compositing
 * hint. A transform makes the element the containing block for any `position: fixed` descendant,
 * which confined our full-screen dialog overlays to the content area instead of the viewport.
 * The transform has no visual purpose, so neutralize it so fixed overlays cover the whole screen.
 * `!important` is required because app.css is loaded before Radzen's standard.css (see index.html),
 * so at equal specificity the vendor rule would otherwise win by source order.
 */
.rz-layout .rz-body {
    transform: none !important;
}

/*
 * Neutralizing the transform above also removed the stacking context `.rz-body` used to create,
 * so body content now competes with the header in the root stacking context. Radzen gives both
 * `.rz-layout .rz-header` and the grid's sticky `.rz-grid-table thead` `z-index: 2`, and at equal
 * z-index DOM order wins — the grid header painted over the header's profile-menu dropdowns.
 * Keep the header above any sticky content in the body. `!important` for the same reason as
 * above: app.css is linked before Radzen's standard.css, so at equal specificity the vendor rule
 * would win on source order.
 */
.rz-layout .rz-header {
    z-index: 10 !important;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem var(--ed-surface), 0 0 0 0.25rem var(--ed-primary);
}

.content {
    padding-top: 1.1rem;
}

.invalid {
    outline: 1px solid var(--ed-danger);
}

.validation-message {
    color: var(--ed-danger);
}

input.invalid,
textarea.invalid,
select.invalid {
    border-color: var(--ed-danger);
}

input.valid.modified,
text.valid.modified,
select.valid.modified {
    border-color: var(--ed-success);
}

#blazor-error-ui {
    background: var(--ed-warning-bg);
    color: var(--ed-warning-text);
    bottom: 0;
    box-shadow: var(--ed-shadow-sm);
}

/* -------------------- */
/* Centralized utilities */
/* -------------------- */
.centered-loading { text-align: center; margin: 2rem 0; justify-content: center; }
.actions-spaced { display: flex; justify-content: space-between; margin-top: 1rem; }
.section-spaced { margin-top: 2rem; }
.mb-2r { margin-bottom: 2rem; }
.icon-lg { font-size: 2rem; }
.icon-xl { font-size: 3rem; }
.h-30vh { height: 30vh; }
.minh-200 { min-height: 200px; }
.dropdown-compact { width: 80px; }
.flex-1 { flex: 1 1 auto; }
.pos-relative { position: relative; }
.text-soft { color: var(--ed-text-muted); }

/* Splash/loading page */
.splash-container { position: absolute; top: 30vh; width: 100%; text-align: center; color: var(--ed-primary); }
.splash-tagline { color: var(--ed-text-muted); letter-spacing: 0.16em; text-transform: uppercase; font-size: 0.8rem; }
.center-row { display: flex; gap: 10px; justify-content: center; align-items: center; }

/* Layout & navigation */
.layout-two-columns { display: grid; grid-template-columns: auto 1fr; }
.sidebar-primary { background-color: var(--ed-sidebar-bg); }
.panelmenu-transparent { background-color: transparent; }
.app-title {
    margin-left: 1rem;
    font-size: clamp(16px, 2.4vw, 26px);
    font-weight: 600;
    letter-spacing: -0.2px;
    color: var(--ed-header-text);
    white-space: nowrap;
}

.app-logo { height: 34px; width: auto; margin-left: 1rem; }
.settings-button { border-radius: var(--ed-radius-pill); color: var(--ed-primary); background-color: var(--ed-surface-alt); }

/* Component-specific helpers */
.current-Tarif-info { padding: 1rem; background-color: var(--ed-surface-alt); border-radius: var(--ed-radius); margin-bottom: 1rem; }
.current-Tarif-info p { margin: 0.5rem 0; font-size: 0.95rem; }

/* Status badges (payments) */
.status-badge { font-size: 12px; padding: 5px 10px; border-radius: var(--ed-radius-pill); margin-right: 5px; }
.status-ok { background-color: var(--ed-success-bg); color: var(--ed-success-text); }
.status-not-ok { background-color: var(--ed-warning-bg); color: var(--ed-warning-text); }

/* Invitation status indicators */
.invitation-status {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-radius: 4px;
    margin-bottom: 8px;
    font-size: 14px;
}

.invitation-status.pending {
    background-color: var(--ed-info-bg);
    color: var(--ed-info-text);
    border-left: 4px solid var(--ed-info);
}

.invitation-status.expired {
    background-color: var(--ed-warning-bg);
    color: var(--ed-warning-text);
    border-left: 4px solid var(--ed-warning);
}

.invitation-status .expiry-info {
    font-size: 12px;
    opacity: 0.8;
}


/* -------------------------------------------------- */
/* Couche responsive partagee du back office */
/* -------------------------------------------------- */

/* Horizontal-scroll wrapper for dense tables, tab strips, wide rows.
   Wrap the element that overflows; the wrapper scrolls, the page does not. */
.ed-scroll-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
}

/* Cap and center content on very wide monitors so it doesn't stretch. */
@media (min-width: 1400px) {
    .rz-body > .container-fluid {
        max-width: 1600px;
        margin-inline: auto;
    }
}

/* Reclaim edge space on phones so content (and long labels) stay inside their zones
   instead of being squeezed by the default page gutters and card padding. */
@media (max-width: 575.98px) {
    .rz-body {
        padding: 6px !important;
    }

    .rz-body .container-fluid {
        padding-inline: 4px !important;
    }

    /* Tighter inner padding on every card gives text more room (e.g. the event title and
       "Du … au …" line fit on one line instead of wrapping). !important because app.css
       loads before Radzen's stylesheet, so at equal specificity source order wins. */
    .rz-card {
        padding: 12px !important;
    }
}

/* -------------------------------------------------- */
/* Sidebar overlay drawer below LG (992px)            */
/* -------------------------------------------------- */
/*
 * Selectors qualify `.rz-layout` (RadzenLayout renders `class="rz-layout layout-two-columns"`)
 * so every rule outranks Radzen's own `.rz-layout` / `.rz-layout .rz-sidebar` base rules by
 * specificity — independent of stylesheet load order (app.css is linked before Radzen's).
 * The sidebar is taken out of flow (`position: fixed`), so the body column fills the row and
 * Radzen's grid areas (which keep the header placed correctly) are left untouched.
 * `--ed-drawer-header` is the measured Radzen header height (57px across the drawer range;
 * MainLayout.razor.css's own header rule is component-scoped and never reaches the child-rendered
 * `.rz-header`), so the drawer/backdrop meet the header bottom with no gap or overlap.
 */
@media (max-width: 991.98px) {
    .rz-layout.layout-two-columns {
        --ed-drawer-header: 57px;
        grid-template-columns: 1fr;
    }

    .rz-layout.layout-two-columns .rz-sidebar {
        position: fixed;
        top: var(--ed-drawer-header);
        left: 0;
        height: calc(100% - var(--ed-drawer-header));
        z-index: 1200;
        transition: transform 0.2s ease;
    }

    /* Off-canvas when the drawer is closed. */
    .rz-layout.layout-two-columns.ed-drawer-closed .rz-sidebar {
        transform: translateX(-100%);
    }

    .ed-drawer-backdrop {
        position: fixed;
        inset: var(--ed-drawer-header) 0 0 0;
        background: var(--ed-overlay);
        z-index: 1150;
    }
}

/* -------------------------------------------------- */
/* Ecrans de change (guichet, devises, caisses, mouvements) */
/* Toutes les couleurs viennent des jetons --ed-* : rien en dur ici. */
/* -------------------------------------------------- */

.ed-change-dialog {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 0.25rem;
}

.ed-change-dialog__footer {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.25rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--ed-border);
}

/* Bandeau explicatif : contexte, pas alerte. */
.ed-change-note {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.65rem 0.85rem;
    border-radius: var(--ed-radius-sm);
    background: var(--ed-info-bg);
    color: var(--ed-info-text);
    border-left: 4px solid var(--ed-info);
}

/* Refus serveur : le message est repris mot pour mot, il porte l'information utile. */
.ed-change-alert {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.65rem 0.85rem;
    border-radius: var(--ed-radius-sm);
    white-space: pre-line;
}

.ed-change-alert--danger {
    background: var(--ed-danger-bg);
    color: var(--ed-danger-text);
    border-left: 4px solid var(--ed-danger);
}

.ed-change-alert--warning {
    background: var(--ed-warning-bg);
    color: var(--ed-warning-text);
    border-left: 4px solid var(--ed-warning);
}

.ed-change-alert--success {
    background: var(--ed-success-bg);
    color: var(--ed-success-text);
    border-left: 4px solid var(--ed-success);
}

/* Bandeau d'amorcage : une caisse neuve est a zero et ne peut rien changer. */
.ed-change-empty-cash {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    margin-bottom: 1rem;
    border-radius: var(--ed-radius);
    background: var(--ed-warning-bg);
    color: var(--ed-warning-text);
    border-left: 4px solid var(--ed-warning);
}

/* Ardoise du guichet : le resultat de la cotation, lisible de loin. */
.ed-change-quote {
    background: var(--ed-surface-sunken);
    border: 1px solid var(--ed-border);
    border-radius: var(--ed-radius);
    padding: 1rem 1.25rem;
}

.ed-change-quote__amount {
    font-size: 2rem;
    font-weight: 700;
    color: var(--ed-primary);
    line-height: 1.2;
}

.ed-change-quote__label {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ed-text-muted);
}

/* Le passage par la monnaie locale, deux etapes face a face. Les deux contreparties sont
   volontairement alignees a droite : c'est leur egalite qui rend le calcul evident. */
.ed-change-passage {
    border-top: 1px solid var(--ed-border);
    padding-top: 0.75rem;
}

.ed-change-passage__etape {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.35rem 0;
}

.ed-change-passage__etape + .ed-change-passage__etape {
    border-top: 1px dashed var(--ed-border);
}

.ed-change-passage__etape strong {
    text-align: right;
    white-space: nowrap;
}

@media (max-width: 640px) {
    /* Sur un telephone, quatre colonnes ecrasent les montants : on repasse en deux lignes. */
    .ed-change-passage__etape {
        grid-template-columns: auto 1fr;
    }
}

.ed-change-quote__value {
    font-weight: 600;
    color: var(--ed-text-strong);
}

.ed-change-quote--stale {
    opacity: 0.55;
}

/* Positions d'une caisse, devise par devise. */
.ed-change-position {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.2rem 0.6rem;
    margin: 0.15rem 0.25rem 0.15rem 0;
    border-radius: var(--ed-radius-pill);
    background: var(--ed-surface-alt);
    border: 1px solid var(--ed-border);
    color: var(--ed-text);
}

.ed-change-position__code {
    font-weight: 700;
    color: var(--ed-primary);
}

.ed-change-position--vide {
    color: var(--ed-text-muted);
    border-style: dashed;
}

/* -------------------------------------------------- */
/* Ecrans de facturation (registre, saisie, parametrage) */
/* Toutes les couleurs viennent des jetons --ed-* : rien en dur ici. */
/* -------------------------------------------------- */

/* Titre de section : structure la saisie longue du parametrage et du formulaire. */
.ed-facture-section__titre {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 1.25rem 0 0.75rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--ed-border);
    color: var(--ed-text-strong);
}

/* Grille des lignes de facture : editable a la saisie, figee au detail. */
.ed-facture-lignes {
    width: 100%;
    min-width: 640px;
    border-collapse: collapse;
    background: var(--ed-surface);
}

.ed-facture-lignes th {
    text-align: left;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ed-text-muted);
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--ed-border-strong);
}

.ed-facture-lignes td {
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid var(--ed-border);
    vertical-align: middle;
    color: var(--ed-text);
}

.ed-facture-lignes__num {
    text-align: right;
}

.ed-facture-lignes__montant {
    font-weight: 600;
    color: var(--ed-text-strong);
}

/* Totaux HT / TVA / TTC, alignes a droite comme sur la piece imprimee. */
.ed-facture-totaux {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.25rem;
    padding: 0.85rem 1rem;
    border-radius: var(--ed-radius);
    background: var(--ed-surface-sunken);
    border: 1px solid var(--ed-border);
}

.ed-facture-totaux__ligne {
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: 1rem;
    min-width: 18rem;
}

.ed-facture-totaux__ligne--ttc {
    margin-top: 0.35rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--ed-border-strong);
}

/* Apercu du prochain numero : ce que la numerotation produira reellement. */
.ed-facture-apercu {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin: 1rem 0 0.75rem;
    padding: 0.85rem 1.25rem;
    border-radius: var(--ed-radius);
    background: var(--ed-surface-sunken);
    border: 1px solid var(--ed-border);
}

/* La sequence est affichee, jamais saisie : le cadre pointille le dit sans texte. */
.ed-facture-apercu__sequence {
    text-align: right;
    padding: 0.35rem 0.85rem;
    border-radius: var(--ed-radius-sm);
    border: 1px dashed var(--ed-border-strong);
    color: var(--ed-text-muted);
}

/* -------------------------------------------------- */
/* Ecran de charte graphique (personnalisation de la marque) */
/* Aucune couleur en dur : la pastille elle-meme affiche le jeton --ed-* courant, */
/* c'est ce qui fait que l'apercu montre la couleur reellement appliquee. */
/* -------------------------------------------------- */

.ed-charte-couleur {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.85rem 1rem;
    border-radius: var(--ed-radius);
    background: var(--ed-surface-alt);
    border: 1px solid var(--ed-border);
    height: 100%;
}

.ed-charte-couleur__saisie {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

/* Pastille de controle : elle lit le jeton, donc la couleur reellement en vigueur. */
.ed-charte-couleur__pastille {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;
    border-radius: var(--ed-radius-sm);
    border: 1px solid var(--ed-border-strong);
    box-shadow: var(--ed-shadow-sm);
}

.ed-charte-media {
    display: flex;
    align-items: center;
    min-height: 5rem;
    margin: 0.35rem 0 0.6rem;
    padding: 0.75rem;
    border-radius: var(--ed-radius);
    background: var(--ed-surface-sunken);
    border: 1px dashed var(--ed-border-strong);
}

.ed-charte-media__apercu {
    max-height: 4rem;
    max-width: 100%;
    object-fit: contain;
}

.ed-charte-media__vide {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--ed-text-muted);
}

/* -------------------------------------------------- */
/* Portail plateforme (parc des bureaux, ouverture d'un bureau) */
/* Toutes les couleurs viennent des jetons --ed-* : rien en dur ici. */
/* -------------------------------------------------- */

/* Bandeau de tete du parc : ce que la plateforme doit voir avant la grille. */
.ed-plateforme-resume {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    padding: 0.9rem 1.1rem;
    margin-bottom: 1rem;
    border-radius: var(--ed-radius);
    background: var(--ed-surface-sunken);
    border: 1px solid var(--ed-border);
}

.ed-plateforme-resume__valeur {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--ed-primary);
}

/* Le compte des bureaux non operationnels se lit comme un avertissement, pas comme un total. */
.ed-plateforme-resume__valeur--alerte {
    color: var(--ed-warning-text);
}

.ed-plateforme-resume__valeur--inconnu {
    color: var(--ed-text-muted);
}

/* Etat de demarrage : la colonne sur laquelle l'oeil doit tomber en premier. */
.ed-plateforme-etat {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.15rem 0.6rem;
    border-radius: var(--ed-radius-pill);
    font-weight: 600;
    white-space: nowrap;
}

.ed-plateforme-etat--pret {
    background: var(--ed-success-bg);
    color: var(--ed-success-text);
}

.ed-plateforme-etat--incomplet {
    background: var(--ed-warning-bg);
    color: var(--ed-warning-text);
}

/* Etat non calculable : neutre et signale comme tel, jamais confondu avec « pret ». */
.ed-plateforme-etat--inconnu {
    background: var(--ed-surface-alt);
    color: var(--ed-text-muted);
    border: 1px dashed var(--ed-border-strong);
}

/* Compteurs d'un bureau (agences, utilisateurs, caisses, devises). */
.ed-plateforme-compteurs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

.ed-plateforme-compteur {
    display: inline-flex;
    align-items: baseline;
    gap: 0.25rem;
    padding: 0.1rem 0.5rem;
    border-radius: var(--ed-radius-pill);
    background: var(--ed-surface-alt);
    border: 1px solid var(--ed-border);
    font-size: 0.8rem;
    color: var(--ed-text);
}

.ed-plateforme-compteur strong {
    color: var(--ed-text-strong);
}

/* Un compteur a zero est une cause de blocage : il se distingue du reste. */
.ed-plateforme-compteur--zero {
    background: var(--ed-warning-bg);
    border-color: var(--ed-warning);
    color: var(--ed-warning-text);
}

/* Etape de checklist, dans le dialogue plateforme comme dans le bandeau bureau. */
.ed-etape {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.55rem 0.7rem;
    border-radius: var(--ed-radius-sm);
    border: 1px solid var(--ed-border);
    background: var(--ed-surface);
}

.ed-etape + .ed-etape {
    margin-top: 0.4rem;
}

.ed-etape--faite {
    background: var(--ed-success-bg);
    border-color: var(--ed-success);
    color: var(--ed-success-text);
}

.ed-etape--restante {
    background: var(--ed-warning-bg);
    border-color: var(--ed-warning);
    color: var(--ed-warning-text);
}

.ed-etape__libelle {
    font-weight: 600;
}

.ed-etape__consequence {
    font-size: 0.83rem;
}

/* Route de l'etape rendue en texte : dans le portail plateforme, elle ne peut pas etre suivie. */
.ed-etape__route {
    font-size: 0.78rem;
    color: var(--ed-text-muted);
    font-family: ui-monospace, "Cascadia Mono", "Consolas", monospace;
}

/* Bandeau de demarrage du bureau : present tant que la checklist n'est pas complete. */
.ed-demarrage {
    border-left: 4px solid var(--ed-warning);
    background: var(--ed-surface);
    margin-bottom: 1rem;
}

.ed-demarrage__entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}

/* Table des devises du formulaire d'ouverture. */
.ed-devises-table {
    width: 100%;
    min-width: 900px;
    border-collapse: collapse;
    background: var(--ed-surface);
}

.ed-devises-table th {
    text-align: left;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ed-text-muted);
    padding: 0.4rem 0.5rem;
    border-bottom: 1px solid var(--ed-border-strong);
}

.ed-devises-table td {
    padding: 0.35rem 0.5rem;
    border-bottom: 1px solid var(--ed-border);
    vertical-align: middle;
}

/* La ligne de reference ne se cote pas contre elle-meme : elle est visuellement a part. */
.ed-devises-table tr.ed-devise--reference td {
    background: var(--ed-info-bg);
}

/* Recapitulatif : ce qui va etre cree, avant le point de non-retour. */
.ed-recap__ligne {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.3rem 0;
    border-bottom: 1px dashed var(--ed-border);
}

.ed-recap__libelle {
    color: var(--ed-text-muted);
}

.ed-recap__valeur {
    font-weight: 600;
    color: var(--ed-text-strong);
    text-align: right;
    word-break: break-word;
}

/* Secret affiche une seule fois : il doit se voir, se lire sans ambiguite et se copier. */
.ed-secret {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.7rem 0.9rem;
    border-radius: var(--ed-radius-sm);
    background: var(--ed-surface-sunken);
    border: 1px solid var(--ed-border-strong);
}

.ed-secret__valeur {
    font-family: ui-monospace, "Cascadia Mono", "Consolas", monospace;
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--ed-text-strong);
    word-break: break-all;
}

/* Actions attachées au champ client du guichet : badge de rattachement ou bouton
   d'enregistrement, selon que le nom saisi corresponde ou non à une fiche du référentiel. */
.ed-guichet-client__actions {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.4rem;
    min-height: 1.75rem;
}

/* --------------------------------------------------------------------------
   Releve d'un compte de tiers.

   L'en-tete reprend le bandeau du carnet tenu a la main : TOTAL RETRAIT,
   TOTAL DEPOT, SOLDE TOTAL, cote a cote et en tete de page. Le bureau lit ses
   comptes ainsi ; deplacer ces trois chiffres l'obligerait a relire chaque
   ligne au lieu de reconnaitre sa feuille.
   -------------------------------------------------------------------------- */
.ed-releve-entete {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--ed-border);
    border-radius: var(--ed-radius-sm);
    background: var(--ed-surface);
}

.ed-releve-total {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 10rem;
    flex: 1 1 10rem;
}

/* Chiffres alignes sur la decimale : une colonne de montants se compare a
   l'oeil, ce que des chasses variables empechent. */
.ed-releve-total strong {
    font-variant-numeric: tabular-nums;
    font-size: 1.05rem;
}

.ed-muted-small {
    display: block;
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    color: var(--ed-text-muted);
}

/* Une aide courte reste disponible exactement a cote du mot qui pose question. Le bouton est
   accessible au clavier et la bulle ne prend aucune place tant qu'elle n'est pas demandee. */
.ed-libelle-aide {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    max-width: 100%;
}

.ed-libelle-aide__bouton {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    padding: 0;
    flex: 0 0 auto;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--ed-text-muted);
    cursor: help;
}

.ed-libelle-aide__bouton .rzi {
    font-size: 1rem;
}

.ed-libelle-aide__bouton:hover,
.ed-libelle-aide__bouton:focus-visible {
    background: var(--ed-surface-sunken);
    color: var(--ed-primary);
    outline: 2px solid var(--ed-primary);
    outline-offset: 2px;
}

.ed-libelle-aide__bouton::after {
    content: attr(data-aide);
    position: absolute;
    z-index: 1200;
    left: 50%;
    bottom: calc(100% + 0.55rem);
    width: max-content;
    max-width: min(18rem, 78vw);
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--ed-border-strong);
    border-radius: var(--ed-radius-sm);
    background: var(--ed-text-strong);
    color: var(--ed-surface);
    box-shadow: var(--ed-shadow);
    font-size: 0.8rem;
    font-weight: 400;
    line-height: 1.35;
    letter-spacing: normal;
    text-align: left;
    text-transform: none;
    white-space: normal;
    transform: translateX(-50%);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.ed-libelle-aide__bouton:hover::after,
.ed-libelle-aide__bouton:focus-visible::after {
    opacity: 1;
    visibility: visible;
}

.ed-aide-metier {
    padding: 0.25rem 0.5rem 0.75rem;
}

.ed-aide-metier section + section {
    margin-top: 1.25rem;
}

.ed-aide-metier h3 {
    margin: 0 0 0.55rem;
    color: var(--ed-primary);
    font-size: 1rem;
}

.ed-aide-metier dl {
    display: grid;
    grid-template-columns: minmax(9rem, 12rem) 1fr;
    gap: 0.45rem 0.85rem;
    margin: 0;
}

.ed-aide-metier dt {
    color: var(--ed-text-strong);
    font-weight: 700;
}

.ed-aide-metier dd {
    margin: 0;
    color: var(--ed-text);
}

@media (max-width: 600px) {
    .ed-aide-metier dl {
        grid-template-columns: 1fr;
        gap: 0.15rem;
    }

    .ed-aide-metier dd + dt {
        margin-top: 0.5rem;
    }
}

/* --------------------------------------------------------------------------
   Etat de journee : la page reprend la disposition du carnet, deux colonnes
   face a face. Sur ecran etroit elles s'empilent — un carnet illisible sur
   telephone ne serait consulte nulle part.
   -------------------------------------------------------------------------- */
.ed-journee-barre {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem;
}

.ed-journee-barre__actions {
    margin-left: auto;
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.ed-journee-colonnes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
    gap: 1rem;
    align-items: start;
}

.ed-journee-colonne__titre {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding-bottom: 0.5rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid var(--ed-border);
}

.ed-journee-colonne__titre strong {
    font-variant-numeric: tabular-nums;
}

.ed-journee-saisie {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--ed-border);
}

/* --------------------------------------------------------------------------
   TABLEAU DE BORD

   La mise en page du poste de controle vit dans TableauDeBord.razor.css. Ne
   restent ici que les deux cadres partages : le cadre commun des graphiques
   (.ed-viz*, reutilise par tous les widgets) et la vue tableau
   (.ed-bord-table*, rendue par TableauDeBordTable.razor).
   -------------------------------------------------------------------------- */

/* ---- Cadre commun des graphiques ---------------------------------------- */
.ed-viz {
    padding: 0.9rem 1rem 1rem;
    border: 1px solid var(--ed-border);
    border-radius: var(--ed-radius);
    background: var(--ed-surface);
    margin-bottom: 1rem;
    /* Un contenu large defile dans son propre cadre : le corps de page ne doit
       jamais defiler horizontalement. */
    overflow-x: auto;
}

.ed-viz__entete {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.ed-viz__toile {
    width: 100%;
    height: auto;
    display: block;
    overflow: visible;
}

.ed-viz__vide {
    margin: 0;
    padding: 1.5rem 0;
    font-size: 0.85rem;
    color: var(--ed-text-muted);
}

/* Le texte ne porte jamais la couleur de la donnee : l'identite vient de la
   marque coloree a cote, jamais de la couleur des caracteres. */
.ed-viz__tick {
    font-size: 0.68rem;
    fill: var(--ed-text-muted);
    font-variant-numeric: tabular-nums;
}

.ed-viz__etiquette {
    font-size: 0.75rem;
    fill: var(--ed-text-muted);
}

.ed-viz__valeur {
    font-size: 0.78rem;
    font-weight: 600;
    fill: var(--ed-text);
    font-variant-numeric: tabular-nums;
}

.ed-viz__signe {
    font-size: 0.95rem;
    fill: var(--ed-text-muted);
}

/* Survol : la cible est plus grande que la marque, et le retour reste sobre. */
.ed-viz__marque {
    cursor: default;
}

.ed-viz__marque:hover path,
.ed-viz__marque:hover circle {
    filter: brightness(0.92);
}

@media (prefers-reduced-motion: reduce) {
    .ed-viz__marque:hover path,
    .ed-viz__marque:hover circle {
        filter: none;
    }
}

/* ---- Vue tableau --------------------------------------------------------- */
.ed-bord-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 1.5rem;
    font-size: 0.85rem;
}

.ed-bord-table caption {
    text-align: left;
    padding-bottom: 0.5rem;
}

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

/* Colonnes de nombres : ici l'alignement vertical prime, donc tabulaire. */
.ed-bord-table td {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.ed-bord-table__total th,
.ed-bord-table__total td {
    border-top: 2px solid var(--ed-border-strong);
    font-weight: 600;
}

/* Visite guidee -----------------------------------------------------------
   Couleurs et rayons viennent des jetons --ed-* : la charte du bureau
   s'applique sans travail supplementaire. */

.ed-tour-masque {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 1400;
    /* Tout le masque laisse passer les clics : l'utilisateur clique reellement
       l'element mis en lumiere, et rien ne peut l'enfermer derriere un voile. */
    pointer-events: none;
}

.ed-tour-bulle {
    position: fixed;
    z-index: 1401;
    max-width: calc(100vw - 24px);
    padding: 1rem;
    background: var(--ed-surface);
    color: var(--ed-text);
    border: 1px solid var(--ed-border-strong);
    border-radius: var(--ed-radius);
    box-shadow: var(--ed-shadow-lg);
}

/* L'ancre n'est pas encore la : la bulle attend, en bas de l'ecran et sans masque.
   Elle reste affichee — sauter serait perdre l'etape — mais ne peut designer un
   element qui n'existe pas, et l'ecran doit rester entierement utilisable pour que
   le geste attendu puisse etre fait. */
.ed-tour-bulle--attente {
    left: 50%;
    bottom: 24px;
    top: auto;
    width: 340px;
    transform: translateX(-50%);
}

.ed-tour-bulle__attente {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.5rem;
    font-size: 0.8rem;
    color: var(--ed-text-muted);
}

.ed-tour-bulle__compteur {
    font-size: 0.75rem;
    color: var(--ed-text-muted);
    margin-bottom: 0.25rem;
}

.ed-tour-bulle__titre {
    font-weight: 600;
    color: var(--ed-text-strong);
    margin-bottom: 0.5rem;
}

.ed-tour-bulle__texte {
    font-size: 0.9rem;
    line-height: 1.45;
}

.ed-tour-bulle__actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1rem;
}

.ed-tour-invitation {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.75rem 1rem;
    margin-bottom: 1rem;
    background: var(--ed-info-bg);
    color: var(--ed-info-text);
    border: 1px solid var(--ed-border);
    border-radius: var(--ed-radius);
}

.ed-tour-invitation__detail {
    font-size: 0.8rem;
    color: var(--ed-text-muted);
}

.ed-tour-lien {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-bottom: 0.75rem;
    font-size: 0.85rem;
    color: var(--ed-info-text);
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
}

.ed-tour-lien:hover {
    text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   Onglets d'un groupe d'ecrans (OngletsGroupe) : des intercalaires de classeur.
   La bande reprend le geste que l'application remplace — le carnet a onglets du
   bureau : une regle fine court sous toute la bande, l'onglet ouvert est le
   seul a la rompre, pose dessus comme l'intercalaire qu'on vient de soulever,
   son bord haut marque de la couleur d'accent du bureau (jetons uniquement :
   la charte du locataire s'applique d'elle-meme). Le nom du groupe ouvre la
   bande en petites capitales. Sur ecran etroit la bande defile, elle ne se
   replie pas : deux rangs d'intercalaires ne se lisent plus.

   La regle est portee par chaque element (et non par le conteneur) : la bande
   defile en overflow-x, un onglet en marge negative y serait rogne.
   -------------------------------------------------------------------------- */
.ed-onglets-groupe {
    display: flex;
    align-items: stretch;
    overflow-x: auto;
    scrollbar-width: none;
}

.ed-onglets-groupe::-webkit-scrollbar {
    display: none;
}

/* Prolonge la regle jusqu'au bord droit, au-dela du dernier onglet. */
.ed-onglets-groupe::after {
    content: "";
    flex: 1 1 0;
    min-width: 1rem;
    border-bottom: 1px solid var(--ed-border-strong);
}

.ed-onglets-groupe__famille {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    padding: 0 1rem 0 0.15rem;
    border-bottom: 1px solid var(--ed-border-strong);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ed-text-muted);
    white-space: nowrap;
}

.ed-onglets-groupe__onglet {
    appearance: none;
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid transparent;
    border-bottom: 1px solid var(--ed-border-strong);
    border-radius: var(--ed-radius-sm) var(--ed-radius-sm) 0 0;
    padding: 0.55rem 1.05rem;
    font: inherit;
    font-size: 0.9rem;
    color: var(--ed-text-muted);
    cursor: pointer;
    white-space: nowrap;
    transition: color 120ms ease, background-color 120ms ease;
}

.ed-onglets-groupe__onglet:hover {
    color: var(--ed-text-strong);
    background: var(--ed-surface-sunken);
}

.ed-onglets-groupe__onglet:focus-visible {
    outline: none;
    /* Anneau interieur : un anneau exterieur serait rogne par l'overflow. */
    box-shadow: inset 0 0 0 2px var(--ed-primary);
}

.ed-onglets-groupe__onglet--actif {
    color: var(--ed-text-strong);
    font-weight: 600;
    background: var(--ed-surface);
    border-color: var(--ed-border-strong);
    border-bottom-color: transparent;
    box-shadow: inset 0 3px 0 var(--ed-accent);
}

.ed-onglets-groupe__onglet--actif:hover {
    background: var(--ed-surface);
}

.ed-onglets-groupe__onglet--actif:focus-visible {
    box-shadow: inset 0 3px 0 var(--ed-accent), inset 0 0 0 2px var(--ed-primary);
}

@media (prefers-reduced-motion: reduce) {
    .ed-onglets-groupe__onglet {
        transition: none;
    }
}

/* --------------------------------------------------------------------------
   JOURNAL D'ACTIVITE — « qui a fait quoi, et quand »

   Le fil se lit comme une liste de phrases, pas comme un tableau : l'heure a
   gauche, la phrase au milieu, l'agence en fin de ligne quand il y en a une.
   Rien n'y est colore par etat — une confirmation n'est pas « bonne » et une
   annulation n'est pas « mauvaise » : ce sont des faits.

   Toutes les valeurs viennent des jetons --ed-*, y compris en theme sombre :
   aucune couleur litterale ici.
   -------------------------------------------------------------------------- */
.ed-activite {
    margin-top: 1.5rem;
    padding: 0.9rem 1rem 1rem;
    border: 1px solid var(--ed-border);
    border-radius: var(--ed-radius-sm);
    background: var(--ed-surface);
}

.ed-activite__entete {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.ed-activite__actions {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.ed-activite__vide {
    margin: 0;
    color: var(--ed-text-muted);
}

.ed-activite__liste {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ed-activite__ligne {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.45rem 0;
    border-top: 1px solid var(--ed-border);
}

.ed-activite__ligne:first-child {
    border-top: 0;
}

.ed-activite__texte {
    flex: 1 1 18rem;
    color: var(--ed-text);
}

.ed-activite__ref {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--ed-text-strong);
}

/* Quand la reference mene quelque part, elle garde sa typographie — chiffres alignes,
   appui du gras — mais prend la couleur d'un lien : sans cela, elle se lirait comme du
   texte mort et personne ne penserait a cliquer. Le soulignement n'apparait qu'a la
   souris ou au clavier, pour ne pas hacher la phrase au repos. */
a.ed-activite__ref {
    color: var(--ed-primary);
    text-decoration: none;
}

a.ed-activite__ref:hover,
a.ed-activite__ref:focus-visible {
    text-decoration: underline;
}

.ed-activite__agence {
    flex: 0 0 auto;
    padding: 0.1rem 0.45rem;
    border-radius: var(--ed-radius-pill);
    background: var(--ed-surface-sunken);
    color: var(--ed-text-muted);
    font-size: 0.75rem;
}

.ed-activite__suite {
    display: flex;
    justify-content: center;
    margin-top: 1rem;
}

/* L'instant exact doit rester atteignable sans souris : d'ou un bouton, focusable
   nativement et nomme par aria-label, plutot qu'un simple `title` que le clavier
   ne decouvre pas. Meme mecanique de bulle que .ed-libelle-aide__bouton. */
.ed-activite__quand {
    position: relative;
    flex: 0 0 auto;
    min-width: 6.5rem;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ed-text-muted);
    font: inherit;
    font-size: 0.8rem;
    text-align: left;
    cursor: help;
}

.ed-activite__quand:hover,
.ed-activite__quand:focus-visible {
    color: var(--ed-primary);
    outline: 2px solid var(--ed-primary);
    outline-offset: 2px;
    border-radius: var(--ed-radius-sm);
}

.ed-activite__quand::after {
    content: attr(data-exact);
    position: absolute;
    z-index: 1200;
    left: 0;
    bottom: calc(100% + 0.4rem);
    width: max-content;
    max-width: min(16rem, 78vw);
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--ed-border-strong);
    border-radius: var(--ed-radius-sm);
    background: var(--ed-text-strong);
    color: var(--ed-surface);
    box-shadow: var(--ed-shadow);
    font-size: 0.8rem;
    font-weight: 400;
    letter-spacing: normal;
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.ed-activite__quand:hover::after,
.ed-activite__quand:focus-visible::after {
    opacity: 1;
    visibility: visible;
}
