.card-custom-style {
    border-radius: 16px !important;
}

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    height: 100%;
    overflow: hidden; /* empêche tout scroll au niveau document */
}

/* MudLayout occupe exactement le viewport, et devient un conteneur flex.

   Le `display: flex` est le maillon MANQUANT de toute la chaîne de défilement.
   Sans lui, MudBlazor laisse `.mud-layout` en bloc ordinaire : le `flex: 1` de
   `.mud-main-content` juste en dessous n'a alors aucun conteneur flex auquel se
   référer et se trouve ignoré, si bien que la hauteur du contenu principal suit
   celle de son contenu. Comme il porte `overflow: hidden` et que `html, body`
   interdisent tout défilement du document, une page plus haute que l'écran
   était simplement ROGNÉE — sans barre de défilement nulle part. Le symptôme
   n'est apparu qu'avec le rapport d'activité, première page vraiment longue.

   Sûr pour la barre supérieure et le tiroir, tous deux en `position: fixed`
   (`.mud-appbar-fixed-top`, `.mud-drawer`) donc hors flux : le seul enfant
   réellement disposé est `.mud-main-content`. Le pied de page l'est aussi.

   `100dvh` plutôt que `100%` : sur mobile, la barre d'outils du navigateur
   apparaît et disparaît, et `vh` ne la suit pas. */
.mud-layout {
    height: 100dvh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Contrepartie OBLIGATOIRE des deux règles ci-dessus, à l'impression.

   Tout ce qui borne l'application à la hauteur de l'écran — `height` fixe et
   `overflow: hidden`, sur `html`, `body` et `.mud-layout` — doit être relâché
   quand la sortie n'est plus un écran mais du papier. Sans cela, le navigateur
   n'imprime que ce qui tient dans une hauteur de fenêtre et coupe net : le
   rapport d'activité, long de plusieurs pages, ne sortait qu'en UNE page.

   Le piège tient à ce que rien ne le signale : à l'écran tout va bien, et le
   défaut ne se voit qu'en ouvrant le PDF produit. Ces trois sélecteurs vivent
   ici, collés aux règles qu'ils annulent, plutôt que dans la feuille de la page
   Rapports — un futur écran imprimable rencontrerait exactement le même mur.

   `display: block` sur le layout : la barre supérieure, le tiroir et le pied de
   page étant masqués à l'impression, le contenu principal est le seul enfant
   restant et n'a plus besoin d'être disposé en flex. */
@media print {
    html, body {
        height: auto !important;
        overflow: visible !important;
    }

    .mud-layout {
        height: auto !important;
        overflow: visible !important;
        display: block !important;
    }
}

/* Le <main> de MudBlazor participe au flex */
.mud-main-content {
    flex: 1 !important;
    min-height: 0 !important;
    display: flex !important;
    flex-direction: column !important;
}

.mud-tabs-panels {
    margin-top: 12px !important;
}

.mud-card-content.mud-card-content-padding {
    padding: 6px 16px 16px 16px;
}

.mud-navmenu.mud-navmenu-margin-normal .mud-nav-link {
    margin: 3px 0;
}

/* Pages dont la grille gère DÉJÀ son propre défilement.

   Le Catalogue et le Journal reposent sur une grille Syncfusion qui pagine et
   fait défiler ses lignes elle-même : le contenu de la page tient donc toujours
   l'écran, à quelques pixels près — ceux des marges de carte et du décalage
   compensant le pied de page. Ces quelques pixels suffisaient à faire naître
   une seconde barre de défilement, verticale et inutile, à côté de celle de la
   grille.

   La règle vise l'ENFANT DIRECT : elle ne s'applique qu'à une page qui se
   déclare telle, et la zone de défilement reste en `auto` pour toutes les
   autres. C'est exactement ce que prévoyait la note ci-dessous, restée sans
   application jusqu'ici.

   `:has()` est disponible dans tous les navigateurs visés (Chrome 105+,
   Firefox 121+, Safari 15.4+) ; support vérifié sur le navigateur cible. */
.body-scroll-area:has(> .lirevia-grille-pleine) {
    overflow-y: hidden;
}

/* ---------------------------------------------------------------------
   Barre de filtres du Catalogue — tout sur le même axe.

   Ce qui décalait les contrôles : le champ de recherche porte un texte
   d'aide (l'astuce des guillemets), affiché seulement à la saisie mais qui
   RÉSERVAIT SA PLACE en permanence. Sa cellule était donc plus haute que
   celles des listes déroulantes, et comme MudGrid étire ses cellules à la
   hauteur de la plus grande, tout ce qui se centrait dedans — l'
   interrupteur « Disponibles », l'icône des colonnes, le bouton
   « Nouvel ouvrage » — se centrait sur une hauteur que le champ de
   recherche était seul à occuper, et tombait donc plus bas que lui.

   Vérifié dans MudBlazor.min.css 9.8.0 plutôt que supposé : `HelperTextOnFocus`
   laisse le texte DANS LE FLUX en permanence et se contente de le masquer
   par `transform: translateY(-100%)`, annulé au `:focus-within`. La place
   est donc bien réservée en tout temps.

   Le texte est ici sorti du flux et ancré sous SON champ. Toutes les
   cellules ont alors la même hauteur, et `align-items: center` suffit.

   ⚠️ Le glissement de MudBlazor doit être REMPLACÉ et pas seulement
   déplacé : hors du flux, `translateY(-100%)` ne cache plus rien, il
   ramène le texte PAR-DESSUS le champ. D'où le fondu d'opacité ci-dessous,
   qui reproduit le comportement voulu sans dépendre de la hauteur.

   ⚠️ Ces règles visent des classes INTERNES à MudBlazor
   (`.mud-input-helper-text`, `.mud-input-helper-onfocus`) : à revérifier
   lors d'une montée de version majeure — d'où la portée limitée à cette
   seule barre. `.mud-input-control` porte déjà `position: relative` dans
   le thème, il sert donc d'ancre sans qu'on ait à la poser.
   --------------------------------------------------------------------- */
.lirevia-barre-filtres {
    align-items: center;
}

.lirevia-barre-filtres .mud-input-helper-text {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 2px;
    white-space: nowrap;
}

.lirevia-barre-filtres .mud-input-helper-text.mud-input-helper-onfocus {
    transform: none;
    opacity: 0;
    pointer-events: none;
    transition: opacity 150ms ease;
}

.lirevia-barre-filtres .mud-input-control:focus-within .mud-input-helper-text.mud-input-helper-onfocus {
    transform: none;
    opacity: 1;
}

/* ---------------------------------------------------------------------
   Tuile de chiffre-clé (écran Visites).

   Fond très léger et bordure fine plutôt qu'une carte en relief : ces
   trois nombres se lisent d'un coup d'œil au-dessus d'une grille, ils
   n'ont pas à rivaliser d'importance avec elle.
   --------------------------------------------------------------------- */
.lirevia-tuile {
    background-color: var(--mud-palette-background-grey);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 6px;
    height: 100%;
}

/* Zone @Body : scroll vertical par défaut.
   Passer overflow-y à hidden si les pages gèrent leur propre scroll
   (grilles pleine hauteur type TinyPM). */
.body-scroll-area {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    padding-top: 0.4rem;
    padding-bottom: 36px; /* compense la hauteur du footer fixe */
}

/* Footer fixé en bas, pleine largeur */
.app-footer {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1200;
    padding: 6px 16px;
    text-align: center;
    color: var(--mud-palette-info-text);
    background-color: var(--mud-palette-appbar-background);
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* Paramétrage identique de tous les grids Syncfusion */
.e-grid {
    font-family: "Roboto", "Montserrat", "Helvetica", "Arial", "sans-serif";
}

    .e-grid .e-altrow {
        background-color: #e3f0fe; /*#e3f1bd;*/
    }

    /* ⚠️ NE PAS ajouter de padding vertical ici. Mesuré le 22/08/2026 :

           hauteur rendue = RowHeight + padding-top + padding-bottom
           42 px          = 32        + 5           + 5

       Syncfusion pose `height` sur la LIGNE, ce qui dimensionne la boîte de
       CONTENU ; le padding s'y ajoute au lieu d'y être compris. Une tentative de
       « resserrer les lignes » en réduisant le padding à 5 px les a donc
       GRANDIES — le thème en mettait moins. La hauteur se règle par
       PaginationAdaptative.HauteurLigne, et par elle seule.

       Le `line-height: 0` du thème confirme le mécanisme : le texte ne
       contribue pas à la hauteur, seuls RowHeight et le padding comptent. */
    /* Texte resserré, en-tête comme lignes : 13 px et une chasse légèrement
       négative gagnent environ 7 % de largeur sans dépendre d'une police
       particulière.

       Une VRAIE police condensée aurait mieux fait, mais aucune n'est
       garantie : l'application ne charge pas de police web, elle se rabat sur
       ce que le poste possède — et « Roboto Condensed » n'est installé
       nulle part par défaut. Une pile du genre « Arial Narrow » rendrait chez
       les uns et pas chez les autres, avec deux grilles d'aspect différent
       selon le poste du bénévole.

       Ce gain est un COMPLÉMENT au masquage de colonnes, pas un substitut :
       aucune taille de police ne fait tenir onze colonnes dans un écran. */
    .e-grid .e-rowcell,
    .e-grid .e-headercelldiv,
    .e-grid .e-headertext {
        font-size: 13px;
        letter-spacing: -0.01em;
    }

    /* Ouvrages que LA BIBLIOTHÈQUE possède, marqués seulement quand elle
       parcourt tout le catalogue partagé (voir Catalogue.MarquerMonFonds).

       Un liseré à gauche plutôt qu'un fond coloré, et c'est délibéré : les
       lignes alternent déjà en vert clair (.e-altrow), un second fond entrerait
       en concurrence avec cette alternance et donnerait quatre nuances à
       distinguer au lieu de deux. Le liseré, lui, se lit identiquement sur les
       deux. C'est le même signal qu'un courriel non lu.

       Posé en ombre INTERNE sur la première cellule : une bordure sur un <tr>
       ne s'affiche pas de façon fiable en table-layout, et un box-shadow sur la
       ligne dépend de border-collapse. */
    .e-grid .e-row.lirevia-mon-fonds .e-rowcell:first-child {
        box-shadow: inset 4px 0 0 var(--mud-palette-primary);
    }

    /* Le titre en demi-gras : le liseré se voit d'un coup d'œil sur la colonne
       de gauche, mais l'œil qui balaie le milieu du tableau a besoin d'un second
       repère. Demi-gras et non gras — il s'agit de distinguer, pas de crier. */
    .e-grid .e-row.lirevia-mon-fonds .e-rowcell:first-child {
        font-weight: 500;
    }

    .e-grid .e-summarycell {
        font-size: 15px;
        padding-top: 6px;
        padding-bottom: 6px;
    }

/* Colonne de navigation des Paramètres : pleine hauteur, comme le menu
   principal. Sans cela, sa hauteur suivrait celle de la section affichée — le
   menu grandirait sur « Cotisations » et rétrécirait sur « Numérotation »,
   donnant l'impression de bouger sous le curseur.

   Le retrait de 170 px correspond à ce qui l'entoure : barre d'application,
   bandeau d'identité de l'association, pied de page et marges. C'est le SEUL
   nombre à ajuster si le menu déborde ou reste court — mesuré ainsi dans la
   console, la valeur juste étant celle qui annule l'écart :

     (() => { const m = document.querySelector('.lirevia-menu-parametres'),
              p = document.querySelector('footer, .mud-main-content > :last-child');
       return Math.round(p.getBoundingClientRect().top - m.getBoundingClientRect().bottom); })()

   dvh et non vh, pour la même raison que dans PaginationAdaptative : c'est
   l'unité dans laquelle .mud-layout borne toute l'application. */
.lirevia-menu-parametres {
    min-height: calc(100dvh - 175px);
}

/* Menu des paramètres REPLIÉ — icônes seules, comme le tiroir principal en
   variante « mini ».

   ⚠️ SOUS md, LA RÈGLE NE S'APPLIQUE PAS, et c'est délibéré : en dessous, la
   colonne du menu occupe déjà toute la largeur et se place AU-DESSUS du
   contenu (MudGrid empile). La replier à 64 px y donnerait une bande d'icônes
   isolée en haut de l'écran, sans rien à sa droite — un gain de place nul pour
   une lisibilité perdue.

   Les largeurs sont posées ici plutôt que par les points de MudGrid parce que
   la grille n'offre que des douzièmes : md="1" vaut encore 100 px sur un écran
   courant, presque le double de ce qu'il faut pour une icône. */
@media (min-width: 960px) {
    .lirevia-menu-replie {
        flex: 0 0 64px;
        max-width: 64px;
    }

    .lirevia-contenu-elargi {
        flex: 1 1 0;
        max-width: none;
    }

    .lirevia-menu-replie .mud-nav-link-text {
        display: none;
    }

    /* L'icône reprend la place du libellé : sans cela elle reste calée à
       gauche et la colonne paraît de travers. */
    .lirevia-menu-replie .mud-nav-link {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    .lirevia-menu-replie .mud-nav-link-icon {
        margin-right: 0;
    }
}

/* Barre de filtres au-dessus des listes */
.filter-group {
    display: flex;
    align-items: center;
    gap: .4rem;
}

.filter-label {
    font-size: .875rem;
    font-weight: 500;
    white-space: nowrap;
}

/* Blazor error UI */
#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 2000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
