html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ── Account pages – MudBlazor-themed inputs ───────────────────────── */
.account-page-wrap {
    min-height: 70vh;
    display: flex;
    align-items: center;
    justify-content: center;
}

.account-field {
    margin-bottom: 20px;
}

.account-label {
    display: block;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary, rgba(255,255,255,0.6));
    margin-bottom: 6px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.account-input {
    display: block;
    width: 100%;
    padding: 13px 14px;
    font-size: 1rem;
    line-height: 1.5;
    font-family: inherit;
    color: var(--mud-palette-text-primary, rgba(255,255,255,0.87));
    background: transparent;
    border: 1px solid rgba(255,255,255,0.23);
    border-radius: 4px;
    outline: none;
    box-sizing: border-box;
    transition: border-color 0.2s, border-width 0.1s;
}

.account-input:hover {
    border-color: rgba(255,255,255,0.7);
}

.account-input:focus {
    border: 2px solid var(--mud-palette-primary, #e53935);
    padding: 12px 13px;
}

.account-input::placeholder {
    color: rgba(255,255,255,0.3);
}

.account-checkbox-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 20px;
    color: var(--mud-palette-text-secondary, rgba(255,255,255,0.6));
    font-size: 0.875rem;
}

.account-checkbox-row input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--mud-palette-primary, #e53935);
    cursor: pointer;
}

.account-checkbox-row label {
    cursor: pointer;
}

.account-validation-msg {
    display: block;
    color: #ef9a9a;
    font-size: 0.75rem;
    margin-top: 4px;
}

.account-divider {
    border: none;
    border-top: 1px solid rgba(255,255,255,0.09);
    margin: 20px 0;
}

/* ── Page création d'équipe (Rejoindre) ─────────────────────────── */
/* Barre de budget collante : reste en haut au scroll, le fond fait jauge. */
.budget-sticky {
    position: sticky;
    /* Hauteur réelle de la MudAppBar. Elle est en mode Dense : 48px sur
       téléphone, 64px à partir de sm. Le 64px codé en dur laissait un trou
       de 16px sous la barre sur mobile (R9f). */
    top: 64px;
    z-index: 1200;
    margin-bottom: 16px;
    padding: 10px 16px;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,0.12);
    box-shadow: 0 2px 8px rgba(0,0,0,0.35);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    transition: background 0.25s ease;
}

.budget-sticky-label {
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.85);
}

.budget-sticky-value {
    font-size: 1.15rem;
    font-weight: 700;
    color: #fff;
    white-space: nowrap;
}

.budget-sticky-total {
    font-size: 0.75rem;
    font-weight: 400;
    opacity: 0.7;
    margin-left: 4px;
}

/* Cadre regroupant les postes d'un mot-clé limité (couleur fournie en inline). */
.poste-keyword-frame {
    border: 1px solid;
    border-radius: 6px;
    padding: 8px;
    margin-bottom: 12px;
}

.poste-keyword-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 6px;
}

/* Compétence cliquable + overlay de détail (utilisable au doigt). */
.skill-link {
    cursor: pointer;
    border-bottom: 1px dotted currentColor;
    /* Cible tactile : le nom d'une compétence fait ~10px de haut, or l'app est
       utilisée au doigt pendant les tournois. Le padding vertical agrandit la
       zone touchable sans décaler le texte (compensé par la marge négative). */
    padding: 4px 1px;
    margin: -4px -1px;
    touch-action: manipulation;
}

.skill-link:hover,
.skill-link:active {
    opacity: 0.75;
}

.skill-overlay-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.6);
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    /* Le fond apparaît en fondu : sans transition, la fiche « saute » à
       l'écran et on ne sait pas d'où elle vient. */
    animation: skill-overlay-in 120ms ease-out;
}

@keyframes skill-overlay-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.skill-overlay-card {
    width: min(92vw, 460px);
    max-height: 80vh;
    overflow-y: auto;
    padding: 20px 22px 22px;
    border-radius: 12px;
    /* Liseré d'accent : rattache visuellement la fiche au thème de l'app. */
    border-top: 3px solid var(--mud-palette-error);
    animation: skill-card-in 140ms ease-out;
}

@keyframes skill-card-in {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}

.skill-overlay-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 4px;
}

/* Description : interligne aéré, c'est un texte de règle qu'on lit en jouant. */
.skill-overlay-card .skill-overlay-desc {
    line-height: 1.6;
    white-space: pre-line;   /* respecte les paragraphes du livre de règles */
}

/* Rappel discret de la façon de fermer, utile au doigt. */
.skill-overlay-hint {
    display: block;
    margin-top: 14px;
    text-align: right;
    opacity: 0.6;
}
/* ── Rendu du règlement de ligue en markdown (R5) ───────────────────────── */
.reglement-rendu h1,
.reglement-rendu h2,
.reglement-rendu h3 { margin: 1em 0 .4em; line-height: 1.25; }
.reglement-rendu h1 { font-size: 1.6rem; color: var(--mud-palette-error); }
.reglement-rendu h2 { font-size: 1.3rem; }
.reglement-rendu h3 { font-size: 1.1rem; }
.reglement-rendu p  { margin: .5em 0; line-height: 1.6; }
.reglement-rendu ul,
.reglement-rendu ol { margin: .5em 0 .5em 1.4em; }
.reglement-rendu li { margin: .25em 0; }
.reglement-rendu blockquote {
    margin: .8em 0;
    padding: .4em 0 .4em 1em;
    border-left: 3px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
}
.reglement-rendu table { border-collapse: collapse; margin: .8em 0; width: 100%; }
.reglement-rendu th,
.reglement-rendu td {
    border: 1px solid var(--mud-palette-lines-default);
    padding: .4em .6em;
    text-align: left;
}
.reglement-rendu th { background: var(--mud-palette-background-grey); }
.reglement-rendu hr {
    border: none;
    border-top: 1px solid var(--mud-palette-lines-default);
    margin: 1.2em 0;
}
.reglement-rendu code {
    background: var(--mud-palette-background-grey);
    padding: .1em .35em;
    border-radius: 3px;
    font-size: .9em;
}

/* ── Grille du calendrier mensuel d'une ligue (#1) ──────────────────────── */
.calendrier-grille {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 4px;
    overflow: hidden;
}

.calendrier-entete {
    background: rgba(198, 40, 40, 0.18);
    padding: 6px 4px;
    text-align: center;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.calendrier-case {
    background: var(--mud-palette-surface, #1e1e1e);
    min-height: 76px;
    padding: 3px 4px 5px;
}

.calendrier-case.hors-mois { opacity: 0.38; }

.calendrier-case.aujourdhui {
    box-shadow: inset 0 0 0 2px #c62828;
    background: rgba(198, 40, 40, 0.10);
}

.calendrier-numero {
    font-size: 0.72rem;
    color: #9e9e9e;
    text-align: right;
    margin-bottom: 2px;
}

/* Le jour courant porte une pastille pleine : le simple cadre se confondait
   avec les bordures de la grille au premier coup d'œil. */
.calendrier-case.aujourdhui .calendrier-numero {
    color: #fff;
    font-weight: 700;
    background: #c62828;
    border-radius: 999px;
    display: inline-block;
    float: right;
    min-width: 1.35rem;
    line-height: 1.35rem;
    text-align: center;
}

/* Échéance indicative de fin de ronde (format Libre) : volontairement
   distincte d'un match — pas de fond plein, bordure en pointillés. */
.calendrier-echeance {
    border: 1px dashed #5c6bc0;
    color: #9fa8da;
    border-radius: 2px;
    padding: 1px 4px;
    margin-bottom: 2px;
    font-size: 0.64rem;
    line-height: 1.25;
    font-weight: 600;
    clear: both;
}

.calendrier-match {
    background: rgba(198, 40, 40, 0.28);
    border-left: 3px solid #c62828;
    border-radius: 2px;
    padding: 2px 4px;
    margin-bottom: 2px;
    font-size: 0.68rem;
    line-height: 1.25;
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
}

.calendrier-match:hover { background: rgba(198, 40, 40, 0.45); }
.calendrier-match b { display: block; font-size: 0.66rem; color: #ffcdd2; }

/* sur petit écran la grille devient illisible : on la masque au profit
   du tableau « Détail du mois » affiché juste en dessous */
@media (max-width: 700px) {
    .calendrier-grille { display: none; }
}

/* ============================================================
   Responsive mobile — audit R9
   ============================================================ */

/* M1 — l'AppBar débordait horizontalement (368px pour 360 dispo, et 505px
   sur /admin/donnees) : le titre passait sur 2 lignes et poussait les
   boutons d'action hors de l'écran. On empêche tout wrap et on autorise
   le titre à se rétrécir (min-width:0 est indispensable en flex). */
@media (max-width: 599.98px) {
    /* Le <header class="mud-appbar"> lui-même s'élargit au contenu de sa
       toolbar (505px mesurés sur /admin/donnees). C'est LUI qu'il faut
       contraindre : agir seulement sur la toolbar laissait le header
       déborder et le défilement horizontal parasite revenait dès que le
       garde-fou overflow-x était retiré. */
    .mud-appbar {
        max-width: 100vw;
        width: 100%;
        box-sizing: border-box;
    }

    .mud-appbar .mud-toolbar {
        flex-wrap: nowrap;
        overflow: hidden;
        max-width: 100%;
    }

    .mud-appbar .mud-toolbar > .appbar-title {
        min-width: 0;
        flex-shrink: 1;
        overflow: hidden;
    }

    .mud-appbar .mud-toolbar > .appbar-title .mud-typography {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* les icônes de droite (admin / profil / déconnexion) ne doivent
       jamais être comprimées ni rejetées hors champ */
    .mud-appbar .mud-toolbar > .mud-icon-button,
    .mud-appbar .mud-toolbar > form {
        flex-shrink: 0;
    }

    /* garde-fou global : plus aucun défilement horizontal parasite.
       ATTENTION — à poser sur html SEULEMENT, jamais sur body :
       `overflow-x:hidden` sur body calcule `overflow: hidden auto`, ce qui
       fait du body un conteneur de défilement et casse TOUS les
       `position:sticky` de la page (constaté sur la barre de budget de
       /equipes/rejoindre, qui partait à -372px au défilement). */
    html {
        overflow-x: hidden;
    }
}

/* B1 — en mode carte (MudBlazor bascule les MudTable sous 600px), le
   libellé de colonne injecté par td::before depuis DataLabel doit rester
   lisible et bien séparé de la valeur. */
@media (max-width: 599.98px) {
    .mud-table-cell-mobile .mud-table-cell-mobile-title,
    .mud-table-row .mud-table-cell[data-label]::before {
        font-weight: 600;
        opacity: 0.75;
        /* Le libellé ne doit JAMAIS se casser lettre par lettre. MudBlazor
           pose le td en flex : face à une valeur longue (une description de
           règle), le libellé se retrouve comprimé à quelques pixels et
           s'affiche à la verticale, une lettre par ligne. Constaté sur
           « Description » dans les règles spéciales — c'est générique, toute
           table à texte long est concernée. */
        white-space: nowrap;
        flex-shrink: 0;
        margin-right: 12px;
    }

    /* Cellule à contenu long : le libellé passe AU-DESSUS de la valeur.
       Côte à côte, il ne resterait qu'une colonne de 2 mots pour le texte. */
    .mud-table-row .mud-table-cell.cellule-texte-long {
        display: block !important;
    }
    .mud-table-row .mud-table-cell.cellule-texte-long::before {
        display: block;
        margin-bottom: 4px;
    }

    /* les cellules centrées en desktop doivent repasser à gauche en mode
       carte, sinon la valeur flotte loin de son libellé */
    .mud-table-cell-mobile {
        text-align: left !important;
    }
}

/* ------------------------------------------------------------
   m2 — cibles tactiles (audit R9 / carte R9c)
   L'app est utilisée debout, au doigt, pendant les tournois.
   Recommandation Apple/Google : 44px. Mesuré avant correction :
   flèches des champs numériques 20x20, bouton agenda 26x26,
   boutons Size.Small 31px de haut.
   Uniquement sous 600px : le desktop garde sa densité.
   ------------------------------------------------------------ */
@media (max-width: 599.98px) {

    /* flèches ▲▼ des MudNumericField (Gains, Variation fans, XP).
       ATTENTION — piège vérifié sur MATÉRIEL RÉEL (Firefox Android) :
       MudBlazor empile les DEUX flèches dans la hauteur du champ (40px).
       Leur imposer 34px ou 44px de haut chacune donne 68-88px pour 40px
       disponibles : la flèche du bas est rognée et l'utilisateur ne peut
       plus DÉCRÉMENTER. Chromium masquait le défaut (overflow visible),
       seul le test sur téléphone l'a révélé.
       On élargit donc HORIZONTALEMENT sans toucher à la hauteur, qui
       reste la moitié du champ. */
    .mud-input-numeric-spin .mud-button-root {
        min-height: 0 !important;
        height: 50% !important;
        min-width: 44px !important;
        padding: 0 !important;
    }

    .mud-input-numeric-spin {
        height: 100%;
        align-self: stretch;
    }

    /* champ porté à 44px : chaque flèche fait donc 22px de haut sur 44px
       de large — atteignable au pouce sans rien rogner */
    .mud-main-content .mud-input.mud-input-margin-dense {
        min-height: 44px;
    }

    /* autres adornments de champ (icônes en fin de saisie) */
    .mud-input-adornment .mud-button-root,
    .mud-input-adornment .mud-icon-button {
        min-height: 34px !important;
        min-width: 34px !important;
        padding: 4px !important;
    }

    /* boutons icône hors AppBar (agenda, supprimer une ligne, +/- de stats).
       Les flèches de spinner sont EXCLUES : elles sont contraintes par la
       hauteur de leur champ (voir ci-dessus).
       Le socle d'un interrupteur est EXCLU aussi : il porte la classe
       mud-icon-button, mais l'agrandir déplace le curseur hors de sa
       glissière (voir la règle dédiée plus bas). */
    .mud-main-content .mud-icon-button:not(.mud-input-adornment .mud-icon-button):not(.mud-input-numeric-spin .mud-button-root):not(.mud-switch-base) {
        min-height: 44px !important;
        min-width: 44px !important;
    }

    /* boutons texte/contour Size.Small : 31px -> 44px, spinners exclus */
    .mud-main-content .mud-button-root.mud-button:not(.mud-input-numeric-spin .mud-button-root) {
        min-height: 44px !important;
    }

    /* liens de navigation du tiroir : 41px -> 48px, plus confortables
       en liste et évitent les erreurs de sélection au pouce */
    .mud-drawer .mud-nav-link {
        min-height: 48px !important;
    }

    /* liens texte dans les tableaux (nom d'équipe du classement) :
       24px de haut, trop fin pour être touché sans erreur */
    .mud-main-content .mud-table-cell .mud-link,
    .mud-main-content td .mud-link {
        display: inline-block;
        padding: 10px 0;
        line-height: 1.3;
    }

    /* Cases à cocher : le socle est un simple bouton rond, l'agrandir
       recentre l'icône sans rien casser. */
    .mud-main-content .mud-checkbox > .mud-button-root {
        min-height: 44px !important;
        min-width: 44px !important;
    }

    /* ⚠️ Interrupteurs : NE PAS agrandir `.mud-switch-base`.
       MudBlazor le positionne en absolute et déduit la place du curseur de
       sa largeur : le porter de 24 à 44px poussait le curseur hors de sa
       glissière — un petit carré décalé sous la barre (signalé par David
       sur Admin → Utilisateurs).
       La zone tactile passe par le <label> parent, qui englobe déjà
       l'interrupteur ET son texte : toute la ligne est cliquable. */
    .mud-main-content label.mud-switch {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }

    /* ------------------------------------------------------------
       m3 — texte sous 12px (sous-titres de poste sur la fiche
       d'équipe, étiquettes de compétences). Illisible à bout de
       bras dans un gymnase.
       ------------------------------------------------------------ */
    .mud-main-content [style*="font-size:10px"],
    .mud-main-content [style*="font-size: 10px"],
    .mud-main-content [style*="font-size:11px"],
    .mud-main-content [style*="font-size: 11px"] {
        font-size: 12px !important;
    }

    .mud-main-content .mud-typography-caption {
        font-size: 0.78rem;
    }
}

/* ------------------------------------------------------------
   m1 — onglets compacts sous 600px (audit R9 / carte R9d)
   Mesuré avant correction : 800px de contenu d'onglets pour 360px
   d'écran sur /ligues/{id} (Classement / Matchs / Équipes /
   Calendrier / Règlement) — on ne voyait qu'un onglet et demi et
   les onglets Calendrier et Règlement étaient invisibles au
   premier coup d'œil.
   Chaque MudTab a une largeur MINIMALE de 160px imposée par
   MudBlazor : c'est elle qu'il faut lever, sinon rien ne bouge.
   ------------------------------------------------------------ */
@media (max-width: 599.98px) {
    .tabs-compact .mud-tab {
        /* MudBlazor écrit min-width:160px en style INLINE sur chaque onglet
           (5 x 160 = 800px pour 360px d'écran). Un style inline ne peut être
           battu que par !important — sans lui cette règle est ignorée. */
        min-width: 0 !important;
        flex: 1 1 0;
        padding-left: 4px;
        padding-right: 4px;
        font-size: 0.66rem;
        letter-spacing: 0;
        line-height: 1.15;
        /* icône au-dessus du libellé plutôt qu'à côté : deux fois
           moins large, et le libellé reste lisible */
        flex-direction: column;
        gap: 2px;
        min-height: 56px;
    }

    /* l'icône n'a plus besoin de sa marge latérale en mode colonne */
    .tabs-compact .mud-tab .mud-icon-root {
        margin: 0 !important;
        font-size: 1.15rem;
    }

    /* la barre d'onglets occupe toute la largeur, sans flèches de
       défilement puisque tout tient désormais à l'écran */
    .tabs-compact .mud-tabs-tabbar-inner,
    .tabs-compact .mud-tabs-tabbar-wrapper {
        width: 100% !important;
    }

    .tabs-compact .mud-tabs-scroll-button {
        display: none;
    }
}

/* ------------------------------------------------------------
   Barre d'onglets collante (page des données)
   ------------------------------------------------------------
   Les onglets « Réserve / Staff / Équipes… » disparaissaient dès
   qu'on descendait dans une longue liste, obligeant à remonter
   tout en haut pour changer de section. Elle se fige désormais
   sous la barre d'application.

   z-index sous celui des popovers MudBlazor (1300+), sinon un
   menu déroulant ouvert passerait DERRIÈRE les onglets.
   ------------------------------------------------------------ */
.tabs-sticky > .mud-tabs-tabbar {
    position: sticky;
    top: var(--mud-appbar-height, 64px);
    z-index: 100;
    background: var(--mud-palette-surface);
    /* Sans cette ombre, le contenu qui défile dessous se confond
       avec la barre. */
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.35);
}

/* ------------------------------------------------------------
   Règles spéciales des star players (page des données)
   ------------------------------------------------------------
   Les textes vont de 80 à 450 caractères. Affichés en entier et
   en orange, ils noyaient la ligne et on ne voyait plus à quel
   joueur ils appartenaient. Repliés sous le nom, avec un liseré
   discret plutôt qu'une couleur d'alerte.
   ------------------------------------------------------------ */
.regle-star {
    margin-top: 4px;
    border-left: 2px solid var(--mud-palette-divider);
    padding-left: 8px;
}

.regle-star summary {
    cursor: pointer;
    font-size: 0.75rem;
    /* Gris clair : c'est une information, pas une alerte. */
    color: var(--mud-palette-text-secondary);
    list-style: none;
}

.regle-star summary::before {
    content: "▸ ";
    display: inline-block;
    transition: transform 0.15s;
}

.regle-star details[open] summary::before {
    content: "▾ ";
}

.regle-star summary:hover {
    color: var(--mud-palette-text-primary);
}

.regle-star-texte {
    display: block;
    margin-top: 4px;
    color: var(--mud-palette-text-secondary);
    line-height: 1.45;
}

/* Séparation nette entre deux star players : les fiches font
   plusieurs lignes de haut, sans trait on ne sait plus où
   s'arrête un joueur. */
.table-lignes-separees tbody tr:not(:last-child) > td {
    border-bottom: 1px solid var(--mud-palette-divider);
}

.table-lignes-separees tbody tr > td {
    padding-top: 10px;
    padding-bottom: 10px;
    vertical-align: top;
}

/* ------------------------------------------------------------
   Après-match — audit R9e (écran enfin auditable après avoir
   fabriqué un match en ValidationCompetences avec des joueurs
   à 6+ PSP).
   Le popover des MudSelect a exactement la même couleur de fond
   que les MudPaper qu'il recouvre (#1e1e1e) et une ombre très
   faible : le menu de compétences semble transparent et les
   bordures de la carte du joueur suivant le traversent.
   Défaut pré-existant (visible aussi en desktop), mais pénalisant
   surtout sur téléphone où le menu recouvre la carte suivante.
   Corrigé côté mobile uniquement pour rester dans le périmètre R9.
   ------------------------------------------------------------ */
@media (max-width: 599.98px) {
    .mud-popover.mud-popover-open {
        background-color: #2a2a2a !important;
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.7) !important;
        border: 1px solid rgba(255, 255, 255, 0.14);
    }

    /* les items d'une liste longue (58 compétences) doivent rester
       confortables au pouce */
    .mud-popover .mud-list-item {
        min-height: 44px;
    }
}

/* ------------------------------------------------------------
   R9f — bloc de score de /matchs/{id}/detail
   Défaut D'ORIGINE (commit initial 1988cd0, pas une régression
   des commits responsive) : la grille xs=5/2/5 donnait 56px à la
   colonne du score sur un écran de 360px. Le « 2 – 1 » en Typo.h4
   s'y empilait verticalement sur 126px de haut et le pseudo du
   coach se coupait en deux.

   Le markup a été réordonné (domicile / extérieur / score) pour
   que le score passe naturellement sur sa propre ligne en mobile.
   En DESKTOP il doit revenir AU MILIEU : on le remet à sa place
   avec `order`, sans toucher au HTML.
   ------------------------------------------------------------ */
@media (min-width: 600px) {
    .score-grid .score-value { order: 2; }
    .score-grid .score-away  { order: 3; }
}

@media (max-width: 599.98px) {
    /* le score en pleine largeur : plus rien ne l'empile */
    .score-grid .score-value {
        padding-top: 4px;
        border-top: 1px solid rgba(255, 255, 255, 0.09);
        margin-top: 8px;
    }

    /* les noms d'équipe et pseudos de coach ne doivent plus être
       coupés au milieu d'un mot */
    .score-grid .mud-typography {
        overflow-wrap: break-word;
        hyphens: auto;
    }
}

/* ------------------------------------------------------------
   R9f — écrans restés hors périmètre de l'audit R9
   ------------------------------------------------------------ */
@media (max-width: 599.98px) {

    /* Barre de budget collante (/equipes/rejoindre) : la MudAppBar est
       Dense, donc 48px sur téléphone et non 64px. Le décalage codé en dur
       laissait un trou de 16px par lequel le contenu défilait. */
    .budget-sticky {
        top: 48px;
    }

    /* Liens texte (« Retour aux ligues », « S'inscrire », « Mot de passe
       oublié ») : 19-20px de haut, sous le seuil tactile. On élargit la
       zone touchable par le padding vertical.
       PIÈGE — ne PAS utiliser inline-block + line-height ici : sur les
       liens du tiroir et le bouton de titre, cela fait exploser le
       scrollWidth (2520px mesurés) et .mud-layout déborde à 505px, ce qui
       ramenait le défilement horizontal parasite. Le padding seul, sans
       toucher au display, donne la même surface tactile sans effet de
       bord. */
    .mud-main-content .mud-link:not(.mud-table-cell .mud-link),
    .account-page a,
    form[method="post"] a {
        padding-top: 8px;
        padding-bottom: 8px;
    }
}

/* ------------------------------------------------------------
   R9f — MudStack Row sans Wrap (débordement d'/admin/donnees)
   Les barres d'outils d'Admin → Données (sélecteurs Jeu / Saison,
   en-têtes d'onglets avec compteur + boutons) sont des
   `MudStack Row="true"` sans Wrap : sur 360px leur contenu mesure
   408 à 481px et pousse .mud-main-content à 505px.
   C'était la VRAIE cause des 145px de débordement, pas l'AppBar —
   le garde-fou `overflow-x` le masquait seulement.
   Sur téléphone on autorise donc le retour à la ligne.
   ------------------------------------------------------------ */
@media (max-width: 599.98px) {
    /* NB : MudStack Row ne génère PAS `.mud-stack-row` mais les classes
       utilitaires `d-flex flex-row` — vérifié dans le DOM après une
       première tentative infructueuse sur le mauvais sélecteur. */
    .mud-main-content .d-flex.flex-row {
        flex-wrap: wrap;
        min-width: 0;
    }

    /* les enfants d'une barre d'outils ne doivent pas imposer leur
       largeur intrinsèque (un MudSelect de 200px sur 312 disponibles) */
    .mud-main-content .d-flex.flex-row > * {
        min-width: 0;
        max-width: 100%;
    }
}

/* ------------------------------------------------------------
   R9f — bandeau pleine largeur de l'accueil
   Les marges négatives annulent le padding horizontal du
   MudContainer. Ce padding est de 16px à partir de sm mais de 8px
   sur téléphone (MainLayout : Class="px-2 px-sm-4"), d'où un
   débordement de 8px avec un -16px codé en dur.
   ------------------------------------------------------------ */
.home-bandeau {
    --bandeau-gutter: 16px;
    margin: calc(-1 * var(--bandeau-gutter)) calc(-1 * var(--bandeau-gutter)) 24px;
    overflow: hidden;
    border-radius: 0 0 8px 8px;
    max-height: 220px;
}

@media (max-width: 599.98px) {
    .home-bandeau {
        --bandeau-gutter: 8px;
        max-height: 140px;
    }
}

/* ------------------------------------------------------------
   R9f — cases à cocher des pages Account (SSR)
   Ces pages n'utilisent pas MudBlazor (InputText + CSS custom) :
   la case « Se souvenir de moi » est un <input type=checkbox> nu
   de 16x16px, largement sous le seuil tactile.
   ------------------------------------------------------------ */
@media (max-width: 599.98px) {
    /* Le sélecteur doit être AU MOINS aussi spécifique que
       `.account-checkbox-row input[type="checkbox"]` (défini plus haut,
       16x16px) — une règle sur `input[type=checkbox]` seul est battue.
       Vérifié dans le DOM après un premier essai sans effet. */
    .account-checkbox-row input[type="checkbox"] {
        width: 22px;
        height: 22px;
        margin: 11px 0;
    }

    /* la ligne entière devient une cible confortable */
    .account-checkbox-row {
        min-height: 44px;
    }

    .account-checkbox-row label {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }
}

/* ─────────────────────────────────────────────────────────────────────────
   Composition du calendrier (format Libre) — /ligues/{id}/calendrier
   ───────────────────────────────────────────────────────────────────────── */

/* Largeur confortable sur grand écran, mais jamais imposée : sans max-width,
   les deux MudSelect d'une rencontre débordent du conteneur sur mobile. */
.equipe-select {
    flex: 1 1 200px;
    min-width: 0;
}

.calendrier-date {
    flex: 0 1 260px;
    min-width: 0;
}

@media (max-width: 599.98px) {
    /* Une rencontre passe en pile : « Domicile » au-dessus d'« Extérieur ».
       Côte à côte, deux champs + la croix ne tiennent pas dans 360px. */
    .rencontre-ligne .equipe-select {
        flex: 1 1 100%;
    }

    /* Le sélecteur de date prend toute la largeur disponible. */
    .calendrier-date {
        flex: 1 1 100%;
    }

    /* Le calendrier lui-même ne doit jamais dépasser l'écran : MudBlazor lui
       impose une largeur inline (~310px) qui, additionnée aux marges du
       conteneur, provoquait le rognage signalé. */
    .mud-picker-container,
    .mud-picker-inline-paper,
    .mud-picker-paper {
        max-width: calc(100vw - 24px) !important;
    }

    /* ⚠️ Les DERNIERS JOURS DU MOIS étaient invisibles (mois s'arrêtant au 25).
       MudBlazor fixe une hauteur en dur à plusieurs niveaux : 312px sur la
       grille et surtout `height/min-height: 216px` sur
       `.mud-picker-calendar-transition`, alors qu'un mois étalé sur 6 semaines
       demande ~308px. Les deux dernières lignes étaient donc coupées, sans
       barre de défilement (overflow visible). Ce n'est PAS un problème de
       position du popup mais de HAUTEUR.

       ⚠️ Piège : `.mud-picker-calendar` (les semaines) est en
       `position: absolute`. Mettre `height: auto` sur son parent le fait donc
       s'effondrer à 0 et n'affiche plus que 2 semaines — pire que le bug
       d'origine. Il FAUT une hauteur explicite, calée sur 6 semaines. */
    .mud-picker-calendar-content,
    .mud-picker-calendar-container {
        height: auto !important;
        min-height: 0 !important;
        overflow: visible !important;
    }

    .mud-picker-calendar-transition {
        height: 312px !important;      /* 6 semaines : jamais de mois tronqué */
        min-height: 312px !important;
        overflow: visible !important;
    }

    /* Le bandeau rouge du picker ne porte que l'année : 100px pris sur un écran
       de téléphone pour une information déjà lisible dans l'en-tête du mois.
       Masqué en mobile uniquement, ce qui laisse la place aux 6 semaines. */
    .mud-picker-toolbar {
        display: none !important;
    }

    /* Filet de sécurité : si un mois demandait malgré tout plus de place que
       l'écran, on défile dans le calendrier plutôt que de perdre des jours. */
    .mud-picker-paper {
        max-height: calc(100vh - 32px) !important;
        overflow-y: auto !important;
    }
}

/* Libellé « JPV » accolé à l'étoile de la feuille de match : l'icône seule
   n'était pas explicite. Collé à l'étoile (l'IconButton porte déjà ses
   marges) et cliquable, comme l'étoile. */
.mvp-label {
    font-weight: 700;
    letter-spacing: 0.03em;
    margin-left: -6px;
    margin-right: 2px;
    user-select: none;
}

/* ─── Modale de reconnexion du circuit Blazor ────────────────────────────────
   Affichée quand la connexion WebSocket est perdue (typiquement Safari iOS qui
   gèle l'onglet en arrière-plan). Les classes components-reconnect-* sont
   posées par le framework Blazor ; voir wwwroot/reconnect.js. */

#components-reconnect-modal {
    display: none;
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    inset: 0;
    z-index: 10001;
    background: rgba(0, 0, 0, 0.72);
    /* Délai avant apparition : évite un flash sur une micro-coupure. */
    animation: reconnect-fade-in 0.2s ease-out 0.5s backwards;
    padding: 16px;
}

@keyframes reconnect-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

#components-reconnect-modal .reconnect-box {
    background: #2a2a2e;
    color: #f5f5f5;
    border: 1px solid #3f3f46;
    border-radius: 12px;
    padding: 28px 24px;
    text-align: center;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
    max-width: 380px;
    width: 100%;
    box-sizing: border-box;
}

#components-reconnect-modal .reconnect-titre {
    font-size: 1.15rem;
    font-weight: 600;
    margin: 0 0 8px;
}

#components-reconnect-modal .reconnect-detail {
    font-size: 0.9rem;
    color: #b8b8be;
    margin: 0 0 12px;
}

#components-reconnect-modal .reconnect-aide {
    font-size: 0.82rem;
    color: #8e8e96;
    line-height: 1.45;
    margin: 0;
}

#components-reconnect-modal .reconnect-spinner {
    width: 38px;
    height: 38px;
    margin: 0 auto 16px;
    border: 3px solid #4a4a52;
    border-top-color: #b71c1c;
    border-radius: 50%;
    animation: reconnect-spin 0.9s linear infinite;
}

@keyframes reconnect-spin {
    to { transform: rotate(360deg); }
}

/* Le bouton n'a de sens que lorsque les tentatives sont épuisées. */
#components-reconnect-modal #reconnect-retry-button {
    display: none;
    margin: 18px auto 0;
    padding: 11px 26px;
    min-height: 44px;          /* cible tactile confortable (iOS) */
    background: #b71c1c;
    color: #fff;
    border: none;
    border-radius: 8px;
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
}

#components-reconnect-modal #reconnect-retry-button:hover {
    background: #d32f2f;
}

#components-reconnect-modal.components-reconnect-failed #reconnect-retry-button {
    display: block;
}

/* En échec définitif, le compteur et le spinner n'ont plus de sens. */
#components-reconnect-modal.components-reconnect-failed .reconnect-detail,
#components-reconnect-modal.components-reconnect-failed .reconnect-spinner {
    display: none;
}

/* Accessibilité : respecter la préférence système de réduction d'animation. */
@media (prefers-reduced-motion: reduce) {
    #components-reconnect-modal .reconnect-spinner {
        animation: none;
    }
    #components-reconnect-modal.components-reconnect-show,
    #components-reconnect-modal.components-reconnect-failed,
    #components-reconnect-modal.components-reconnect-rejected {
        animation: none;
    }
}

/* Le compteur de tentatives est rempli par Blazor : masqué tant qu'il est vide
   (sinon un « /… » orphelin s'affiche à la première apparition de la modale). */
#components-reconnect-modal .reconnect-compteur {
    display: none;
    white-space: nowrap;
}

#components-reconnect-modal.components-reconnect-show .reconnect-compteur {
    display: inline;
}

/* ─── Description d'un staff dans les tables de réglage ──────────────────────
   En vue mobile MudBlazor empile label/valeur dans chaque cellule : la colonne
   de droite ne fait alors que quelques caractères, et une description s'y
   retrouve écrasée en colonne illisible. On la sort du flux de la cellule pour
   qu'elle occupe toute la largeur, sous le nom du staff. */
.staff-desc {
    font-size: 11px;
    color: #9e9e9e;
    font-style: italic;
    line-height: 1.35;
    margin: 2px 0 0 32px;
}

@media (max-width: 959px) {
    /* La cellule mobile est en flex (label à gauche, valeur à droite) :
       forcer la description sur sa propre ligne, pleine largeur, sinon elle
       se retrouve écrasée dans la colonne de droite et chevauche le nom. */
    .staff-desc {
        flex-basis: 100%;
        width: 100%;
        margin-left: 0;
        margin-top: 6px;
        text-align: left;
        order: 99;
    }

    /* Autorise le retour à la ligne dans la cellule qui porte le nom du staff. */
    .mud-table-cell[data-label="Staff"] {
        flex-wrap: wrap;
    }
}

/* ─── Anti-débordement : chaînes longues sans espace ─────────────────────────
   Un nom saisi sans espace (nom de ligue, d'équipe, pseudo de coach, e-mail)
   ne peut pas être coupé par le navigateur : il pousse alors toute la page en
   largeur. Constaté en QA : une ligue au nom très long faisait passer la page
   de 360 à 1022 px, avec défilement horizontal sur tout le site.
   `overflow-wrap: anywhere` autorise la coupure en dernier recours, sans
   couper les mots normaux (contrairement à `word-break: break-all`). */
.mud-typography,
.mud-card-content,
.mud-list-item-text,
.mud-table-cell,
.mud-chip-content {
    overflow-wrap: anywhere;
}

/* Les cartes et conteneurs ne doivent jamais s'élargir au-delà du viewport. */
.mud-card,
.mud-paper,
.mud-container {
    max-width: 100%;
}

/* ─── Page « Supprimer mon compte » ───────────────────────────────────────────
   Les pages Identity sont rendues en SSR : pas de composant MudBlazor
   interactif pour les champs et le bouton de soumission, d'où ces styles
   alignés sur les .account-* de la page de connexion. */
.account-link {
    color: var(--mud-palette-info);
    text-decoration: underline;
}

.account-danger-btn {
    width: 100%;
    padding: 10px 16px;
    border: none;
    border-radius: 4px;
    background: var(--mud-palette-error);
    color: #fff;
    font-size: 0.875rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: filter 0.15s ease;
    /* 44 px de haut : cible tactile confortable sur mobile. */
    min-height: 44px;
}

.account-danger-btn:hover {
    filter: brightness(1.12);
}

.account-danger-btn:active {
    filter: brightness(0.92);
}

/* Codes de secours 2FA : grille lisible, une colonne sur téléphone. */
.recovery-codes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 8px;
}

.recovery-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.95rem;
    letter-spacing: 0.06em;
    color: var(--mud-palette-text-primary);
    background: rgba(255, 255, 255, 0.06);
    border-radius: 4px;
    padding: 6px 10px;
    display: block;
    text-align: center;
}

/* ------------------------------------------------------------
   MudSelect — le libellé ne doit jamais chevaucher la valeur.

   Signalé par capture téléphone : « Comportement automatique » s'affichait
   PAR-DESSUS « Aucun — règle descriptive ». MudBlazor ne remonte le libellé
   dans l'encoche que s'il juge le champ « rempli », et il considère vide
   toute valeur égale au défaut du type (0 pour un int, "" pour une string).
   Un `Placeholder` ne suffit pas : le calcul est fait côté C#, pas en CSS.

   Or un MudSelect affiche TOUJOURS quelque chose (l'option correspondant à
   la valeur courante) : son libellé doit donc être remonté en permanence,
   comme le fait déjà le variant Outlined dès qu'on choisit une option.
   Générique : vaut pour tous les select de l'app, présents et à venir.
   ------------------------------------------------------------ */
.mud-select .mud-input-label-inputcontrol {
    transform: translate(14px, -8px) scale(0.75) !important;
    transform-origin: top left !important;
    background-color: var(--mud-palette-surface);
    padding: 0 4px;
    pointer-events: none;
}

/* L'encoche de la bordure doit suivre, sinon le trait passe sous le texte. */
.mud-select .mud-input-outlined-border {
    border-top-color: transparent;
}
