/* Jetons de design (direction "SaaS premium" façon Linear/Stripe/Vercel, décidée le 2026-09-01 —
   accent indigo/violet façon Stripe, voir gt-card-accent). Remplace l'accent terracotta du
   2026-08-15 : décision explicitement révisée par l'utilisateur pour cette refonte visuelle. */
:root {
    /* Accent principal (boutons d'action principale, liens, anneau de focus, avatars, en-tête de
       tableau) — bleu marine, décision explicite du 2026-09-08 de reprendre la palette d'une
       maquette de référence (cartes/boutons "Commander" façon LWS). Remplace l'indigo/violet
       #635bff du 2026-09-01 ("SaaS premium" façon Stripe). Approximation visuelle de la maquette
       (pas de code couleur exact fourni) — à ajuster si besoin. */
    --gt-primary: #1a4480;
    --gt-primary-dark: #123363;
    --gt-primary-ring: rgba(26, 68, 128, .35);
    /* Dégradé conservé pour les avatars (voir .gt-avatar) — .btn-primary, lui, passe en aplat plein
       (pas de dégradé) pour coller à la maquette de référence, voir plus bas. */
    --gt-primary-gradient: linear-gradient(135deg, #2c5aa0 0%, #123363 100%);
    --gt-surface: #ffffff;
    --gt-page-bg: #ffffff;
    --gt-border: #e5e7eb;
    /* En-tête sombre des tableaux — bleu marine profond, assez sombre pour porter du texte blanc,
       harmonisé avec le nouvel accent --gt-primary ci-dessus. */
    --gt-header-bg: #0f2a4d;
    --gt-header-color: #ffffff;
    /* Bordure des cartes gt-carnet-card (mobile + grille Carnets) et fond des avatars —
       --gt-primary et --gt-header-bg en sont dérivés/harmonisés. */
    --gt-card-accent: #1a4480;
    /* Accent distinct utilisé uniquement par les barres de classement du tableau de bord et leur
       montant (.gt-ranking-bar-fill/.gt-ranking-amount) — décision explicite du 2026-09-08 de
       s'écarter de l'accent global indigo pour cet élément précis. Même teinte terracotta que
       l'ancien accent de toute l'app (#d97757, 2026-08-15) — ton proche de l'icône Claude Desktop.
       Volontairement identique en mode sombre, comme --gt-primary/--gt-card-accent. */
    --gt-ranking-accent: #d97757;
    /* Pastille "connecté" sur Utilisateurs.razor (voir .gt-online-dot) — bleu ciel demandé
       explicitement le 2026-09-10, distinct de --gt-primary (bleu marine) pour bien se détacher de
       l'avatar. Volontairement identique en mode sombre (assez clair pour rester lisible sur fond
       sombre, même principe que --gt-primary/--gt-ranking-accent ci-dessus/dessous). */
    --gt-online: #38bdf8;
    /* Boutons "Télécharger X" par table (Administration, voir CLAUDE.md) — même teinte que
       --gt-ranking-accent (#d97757, proche du logo Claude Desktop), demandée explicitement le
       2026-09-11 pour distinguer visuellement ces boutons du rouge d'alerte --gt-danger-text déjà
       utilisé pour les actions destructrices/alertes ailleurs dans l'app. Jeton dédié plutôt que
       réutiliser --gt-ranking-accent tel quel : ce dernier est documenté comme réservé aux barres de
       classement du tableau de bord uniquement. Volontairement identique en mode sombre, même
       principe que --gt-primary/--gt-ranking-accent. */
    --gt-corail-accent: #d97757;
    --gt-row-hover-bg: #eef3f9;
    --gt-text-muted: #6b7280;
    /* Texte principal / titres — variabilisés (2026-08-21) pour que le mode sombre puisse les
       éclaircir ; avant ça c'était des #1f2937/#111827 codés en dur un peu partout. */
    --gt-text: #1f2937;
    --gt-heading: #111827;
    /* Piste de la barre de classement (Tableau de bord) — dérivée de --gt-card-accent, trop
       claire pour rester lisible telle quelle en sombre. */
    --gt-track-bg: #ece9fc;
    /* Pied de carte carnet (frais payé / non payé), voir .gt-carnet-card-footer. */
    --gt-success-bg: #ecfdf5;
    --gt-success-text: #15803d;
    --gt-neutral-bg: #f3f4f6;
    --gt-neutral-text: #4b5563;
    /* Couleur de statut "à vérifier" (Tableau de bord) — réservée aux alertes, distincte de
       l'accent indigo pour ne pas se confondre avec une simple donnée métier. */
    --gt-warning-bg: #fff7ed;
    --gt-warning-border: #fdba74;
    --gt-warning-text: #9a3412;
    /* Variante "plus grave" de l'alerte ci-dessus (Tableau de bord, frais non payés) — distincte de
       l'ambre réservé aux écarts de niveau, pour ne pas confondre les deux natures d'alerte. */
    --gt-danger-bg: #fef2f2;
    --gt-danger-border: #fca5a5;
    --gt-danger-text: #b91c1c;
    --gt-radius: .75rem;
    --gt-radius-sm: .5rem;
    /* Ombres teintées (bleu marine très désaturé plutôt que gris neutre, harmonisées avec
       --gt-header-bg ci-dessus) et une variante -lg pour les éléments élevés au survol (cartes,
       modals) — plus "premium" que l'ombre plate d'origine. */
    --gt-shadow-sm: 0 1px 2px rgba(15, 42, 77, .06), 0 1px 1px rgba(15, 42, 77, .04);
    --gt-shadow: 0 8px 24px -8px rgba(15, 42, 77, .16), 0 2px 8px -2px rgba(15, 42, 77, .08);
    --gt-shadow-lg: 0 24px 48px -16px rgba(15, 42, 77, .28), 0 8px 16px -8px rgba(15, 42, 77, .16);

    /* Coins arrondis un peu plus doux pour tous les composants Bootstrap (boutons, champs, cartes, modals). */
    --bs-border-radius: var(--gt-radius-sm);
    --bs-border-radius-sm: .375rem;
    --bs-border-radius-lg: var(--gt-radius);
}

/* Mode sombre (2026-08-21) — piloté par [data-bs-theme] plutôt qu'un attribut maison : un seul
   attribut sur <html> déclenche à la fois le dark mode natif de Bootstrap 5.3 (formulaires,
   modals, badges...) et ces jetons --gt-*. Appliqué avant le premier rendu par le script bloquant
   de App.razor (localStorage 'gt-theme', ou prefers-color-scheme si rien n'est stocké) ; basculé
   par le bouton ThemeToggle (wwwroot/js/theme.js). --gt-primary/--gt-card-accent/--gt-header-bg ne
   sont volontairement pas redéfinis : l'accent bleu marine et l'en-tête bleu marine profond
   restent lisibles tels quels sur fond sombre. */
:root[data-bs-theme="dark"] {
    --gt-surface: #1c1f26;
    --gt-page-bg: #14161b;
    --gt-border: #2e323c;
    --gt-row-hover-bg: #182a3d;
    --gt-text-muted: #9aa1ac;
    --gt-text: #e5e7eb;
    --gt-heading: #f3f4f6;
    --gt-track-bg: #2f2b57;
    --gt-success-bg: #103322;
    --gt-success-text: #4ade80;
    --gt-neutral-bg: #262a32;
    --gt-neutral-text: #b0b6c0;
    --gt-warning-bg: #2b2116;
    --gt-warning-border: #7c4a1d;
    --gt-warning-text: #fb923c;
    --gt-danger-bg: #2b1616;
    --gt-danger-border: #7c2d2d;
    --gt-danger-text: #f87171;
    --gt-shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
    --gt-shadow: 0 8px 24px -8px rgba(0, 0, 0, .5), 0 2px 8px -2px rgba(0, 0, 0, .35);
    --gt-shadow-lg: 0 24px 48px -16px rgba(0, 0, 0, .6), 0 8px 16px -8px rgba(0, 0, 0, .4);
}

/* Roboto Condensé — exception ponctuelle à la règle "pas de police custom" ci-dessous, demandée
   explicitement le 2026-09-11 pour les boutons de filtre "Écart de niveau"/"Frais non payés" de
   Carnets.razor (voir .gt-carnets-filtres-boutons .btn dans Carnets.razor.css) uniquement — pas
   utilisée ailleurs dans l'app. Hébergée localement dans wwwroot/fonts/ (licence SIL Open Font
   License, voir wwwroot/fonts/OFL.txt), jamais via un CDN — cohérent avec la convention du projet
   (Bootstrap déjà vendorisé) et avec font-src 'self' dans la Content-Security-Policy (voir plus
   bas dans ce fichier et App.razor) : un chargement via fonts.googleapis.com aurait exigé
   d'assouplir cette CSP. Fichier variable (un seul .woff2 couvrant tout l'axe de graisse 100-900,
   d'où `font-weight: 400 700` plutôt que deux @font-face distincts) — sous-ensemble "latin"
   uniquement (assez pour le français, tous les caractères accentués courants sont dans Latin-1
   Supplement, U+0000-00FF). */
@font-face {
    font-family: 'Roboto Condensed';
    src: url('fonts/RobotoCondensed-VariableFont_wght.woff2') format('woff2-variations'),
         url('fonts/RobotoCondensed-VariableFont_wght.woff2') format('woff2');
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}

html, body {
    /* Pas de police custom chargée (le projet évite les CDN, voir Bootstrap déjà vendorisé) — pile
       système qui se rapproche du rendu Inter/SF utilisé par Linear/Stripe/Vercel. Exception :
       Roboto Condensé, voir @font-face plus haut, réservée à 2 boutons précis de Carnets.razor. */
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
    background-color: var(--gt-page-bg);
}

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

a:not(.btn) {
    transition: color .12s ease;
}

.btn-primary {
    color: #fff;
    /* Aplat plein (pas de dégradé) — décision explicite du 2026-09-08 pour coller à la maquette de
       référence (bouton "Commander"), contrairement à .gt-avatar qui garde --gt-primary-gradient. */
    background-color: var(--gt-primary);
    border-color: var(--gt-primary-dark);
    box-shadow: 0 2px 8px -2px rgba(26, 68, 128, .45);
    transition: transform .12s ease, box-shadow .12s ease, filter .12s ease;
}

    .btn-primary:hover, .btn-primary:active, .btn-primary:focus {
        background-color: var(--gt-primary-dark) !important;
        border-color: var(--gt-primary-dark) !important;
    }

    .btn-primary:hover {
        filter: brightness(1.06);
        box-shadow: 0 4px 14px -2px rgba(26, 68, 128, .55);
    }

    .btn-primary:active {
        transform: translateY(1px);
    }

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

.content {
    padding-top: 1.1rem;
}

h1 {
    font-weight: 700;
    font-size: 1.8rem;
    letter-spacing: 0;
    text-transform: none;
    color: var(--gt-heading);
    margin-bottom: 1.25rem;
}

/* Sous 992px (mobile + tablette confondus), titre réduit — un seul palier plutôt que deux
   (mobile normal / tablette réduite) : décision explicite du 2026-09-10, la taille du titre doit
   diminuer progressivement à mesure que l'écran rétrécit, pas seulement sur la plage tablette où
   le menu latéral de nav prend déjà de la place à partir de 641px (voir NavMenu.razor.css, jamais
   replié au-delà). Appliqué à tous les titres de page (généralisé depuis Home.razor, qui avait
   cette règle en premier pour cette seule plage tablette, voir .gt-dashboard-heading plus bas). */
@media (max-width: 991.98px) {
    h1 {
        font-size: 1.25rem;
    }
}

h1:focus {
    outline: none;
}

/* Bouton "Ajouter" des pages liste : toujours sur la même ligne que le titre, aligné à droite,
   quelle que soit la largeur d'écran (décidé le 2026-09-10, convention pour toutes les pages
   liste avec un bouton d'ajout — Clients/Utilisateurs/Mises/Prêts/Livraisons ; Carnets n'en a pas,
   les carnets se créent depuis Clients). Sous 768px (même seuil que la bascule tableau
   desktop/cartes mobile déjà utilisée sur ces pages), le bouton perd son texte et devient un
   cercle plein icône "+" — bien visible sans empiéter sur le titre. */
.gt-page-heading {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: .75rem;
}

.gt-page-heading h1 {
    margin-bottom: 0;
    min-width: 0;
}

.gt-btn-ajouter {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    flex-shrink: 0;
    white-space: nowrap;
}

.gt-btn-ajouter-icone {
    display: none;
}

@media (max-width: 767.98px) {
    .gt-btn-ajouter {
        width: 2.75rem;
        height: 2.75rem;
        padding: 0;
        border-radius: 50%;
        justify-content: center;
    }

    .gt-btn-ajouter-icone {
        display: inline-block;
    }

    .gt-btn-ajouter-texte {
        display: none;
    }
}

/* Bouton "Télécharger X" par table (Administration) — variante colorée de .btn-outline-*, même
   principe que .btn-outline-danger de Bootstrap mais avec --gt-corail-accent (voir plus haut)
   plutôt que le rouge d'alerte de l'app. flex-shrink: 0 pour ne jamais se faire écraser par un
   titre de table long, à côté duquel il est positionné (voir Administration.razor). */
.gt-btn-telecharger {
    flex-shrink: 0;
    color: var(--gt-corail-accent);
    border-color: var(--gt-corail-accent);
    background-color: transparent;
}

.gt-btn-telecharger:hover:not(:disabled),
.gt-btn-telecharger:focus-visible:not(:disabled) {
    color: #fff;
    background-color: var(--gt-corail-accent);
    border-color: var(--gt-corail-accent);
}

.gt-btn-telecharger:disabled {
    color: var(--gt-corail-accent);
    border-color: var(--gt-corail-accent);
    opacity: .55;
}

.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;
}

/* Convention tableau standard (toutes les pages) : lignes de 48-56px, alignement vertical centré. */
.table-standard > :not(caption) > * > th,
.table-standard > :not(caption) > * > td {
    padding: 14px 16px;
    vertical-align: middle;
}

.table-standard td.actions {
    text-align: end;
    white-space: nowrap;
}

.table-standard td.actions .btn {
    padding: 0.25rem 0.5rem;
    line-height: 1;
}

/* Look "SaaS" du tableau desktop : carte blanche, bordure fine, ombre légère, en-tête discret,
   survol de ligne. Remplace le zèbre Bootstrap classique par un style plus épuré. */
.table-responsive.table-scroll-desktop {
    background-color: var(--gt-surface);
    border: 1px solid var(--gt-border);
    border-radius: var(--gt-radius);
    box-shadow: var(--gt-shadow-sm);
}

.table-standard {
    margin-bottom: 0;
}

.table-standard thead th {
    background-color: var(--gt-header-bg);
    color: var(--gt-header-color);
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    border-bottom: 1px solid var(--gt-header-bg);
}

.table-standard tbody td {
    border-color: var(--gt-border);
    color: var(--gt-text);
}

.table-standard tbody tr td {
    transition: background-color .12s ease;
}

.table-standard tbody tr:hover td {
    background-color: var(--gt-row-hover-bg);
}

.table-standard tbody tr:last-child td {
    border-bottom: none;
}

/* État vide (aucune donnée) : carte discrète à bordure pointillée plutôt qu'un simple texte italique. */
.gt-empty-state {
    background-color: var(--gt-surface);
    border: 1px dashed var(--gt-border);
    border-radius: var(--gt-radius);
    padding: 3rem 1.5rem;
    text-align: center;
    color: var(--gt-text-muted);
}

/* Champ mot de passe avec bouton œil (afficher/masquer) — voir PasswordToggleButton.razor
   (pages InteractiveServer) et js/password-toggle.js (pages SSR statiques : Login,
   MotDePasseOublie, ReinitialiserMotDePasse). Login.razor a sa propre version en couleurs
   fixes dans LoginLayout.razor.css, indépendante de ces jetons adaptatifs. */
.gt-password-field {
    position: relative;
}

.gt-password-field .form-control {
    padding-right: 2.75rem;
}

.gt-password-toggle {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    padding: 0;
    color: var(--gt-text-muted);
    cursor: pointer;
}

.gt-password-toggle:hover {
    color: var(--gt-text);
}

/* Pastille avatar (initiales) devant un nom, dans un tableau ou une carte mobile. */
.gt-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    /* Même dégradé que les boutons primaires — cohérence entre tableau et carte. */
    background-image: var(--gt-primary-gradient);
    background-color: var(--gt-card-accent);
    color: #fff;
    font-size: .7rem;
    font-weight: 700;
    flex-shrink: 0;
    box-shadow: 0 2px 6px -1px rgba(26, 68, 128, .4);
}

/* Pastille "connecté" sur l'avatar d'un utilisateur (Utilisateurs.razor uniquement, décidé le
   2026-09-10, façon Facebook) — n'apparaît que si connecté, rien du tout sinon (voir
   Utilisateurs.razor.EstConnecte). Enveloppe séparée de .gt-avatar plutôt qu'une modification de
   .gt-avatar lui-même : cette classe est partagée par toutes les pages liste, la modifier
   affecterait les avatars partout, pas seulement ici. */
.gt-avatar-wrapper {
    position: relative;
    display: inline-flex;
    flex-shrink: 0;
}

.gt-online-dot {
    position: absolute;
    right: -1px;
    bottom: -1px;
    width: .65rem;
    height: .65rem;
    border-radius: 50%;
    background-color: var(--gt-online);
    border: 2px solid var(--gt-surface);
}

/* Pastille signalant l'utilisateur connecté dans la barre du haut (même accent que le reste). */
.gt-status-dot {
    display: inline-block;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background-color: var(--gt-primary);
    box-shadow: 0 0 0 2px rgba(26, 68, 128, .25);
    flex-shrink: 0;
}

/* Formulaires (popups Ajouter/Modifier) : libellés en gras, champs plus spacieux,
   titre de popup plus marqué — convention par défaut pour tous les formulaires. */
.form-label {
    font-weight: 600;
    color: var(--gt-text);
    margin-bottom: .4rem;
}

.form-control, .form-select {
    padding: .55rem .85rem;
}

.modal-title {
    font-weight: 700;
    font-size: 1.35rem;
}

:root {
    --bs-modal-padding: 1.5rem;
}

/* Modal flottant plus "premium" : ombre marquée plutôt que la bordure/ombre plate de Bootstrap. */
.modal-content {
    border: none;
    box-shadow: var(--gt-shadow-lg);
}

/* Cartes gt-carnet-card (grille Carnets + vue mobile de toutes les pages liste). Pas de bandeau
   de couleur en en-tête (retiré le 2026-08-15) : la distinction entre cartes vient uniquement de
   l'ombre portée et de cette bordure colorée, pas d'un fond plein sur l'identité de la ligne. */
.gt-carnet-card {
    border: 1.5px solid var(--gt-card-accent);
    /* Ombre plus marquée qu'un simple shadow-sm Bootstrap, pour bien séparer les cartes entre
       elles maintenant que l'en-tête n'a plus de fond de couleur propre. */
    box-shadow: 6px 6px 16px -6px rgba(15, 42, 77, .22);
    transition: transform .15s ease, box-shadow .15s ease;
}

/* Léger effet de survol (souris uniquement — @media (hover:hover) évite l'état "collé" sur un
   simple tap tactile) : cohérent avec la demande de micro-interactions "SaaS premium". */
@media (hover: hover) and (pointer: fine) {
    .gt-carnet-card:hover {
        transform: translateY(-3px);
        box-shadow: 0 14px 28px -10px rgba(15, 42, 77, .3);
    }
}

/* Modificateur "bord à bord" (décidé le 2026-09-10) : sur les vues carte mobile des pages liste
   (Clients/Utilisateurs/Mises/Prêts/Livraisons — pas Carnets.razor, qui garde son .gt-carnet-card
   normal, affiché à toutes les tailles d'écran et pas seulement en mobile), la carte perd ses
   bordures gauche/droite et s'étire jusqu'aux bords de l'écran. Une simple bordure à 0 ne suffit
   pas à atteindre le bord de l'écran : il faut aussi annuler par une marge négative le padding
   horizontal du conteneur ancêtre (`article.content.px-4` dans MainLayout.razor) — padding qui
   change de valeur à 641px (sidebar qui passe d'un panneau superposé à une vraie colonne fixe,
   voir le piège "sidebar fixe dès 641px" déjà documenté dans CLAUDE.md), d'où les deux marges
   différentes ci-dessous plutôt qu'une seule valeur fixe. Coins non arrondis sur ce modificateur :
   un rayon conservé donnerait l'impression que la carte n'atteint pas vraiment le bord de l'écran.
   Au-delà de 768px, la vue carte est de toute façon masquée (`d-md-none`) au profit du tableau. */
@media (max-width: 767.98px) {
    .gt-carnet-card-bord-a-bord {
        margin-left: -1.5rem;
        margin-right: -1.5rem;
        border-left: 0;
        border-right: 0;
        border-radius: 0;
    }
}

@media (min-width: 641px) and (max-width: 767.98px) {
    .gt-carnet-card-bord-a-bord {
        margin-left: -2rem;
        margin-right: -1.5rem;
    }
}

/* Signale un écart entre le niveau saisi par le commercial (CarnetNiveau) et le niveau calculé
   (Niveau2, "1/0" par défaut tant qu'aucune mise n'est enregistrée — même valeur par défaut que
   CarnetNiveau à la création, donc pas de fausse alerte sur un carnet neuf). Le cadre + le fond de
   la carte passent en rouge ; le pied de carte (déjà coloré pour son propre usage : frais payé)
   reste inchangé au-dessus de ce fond. */
.gt-carnet-card-alerte {
    border-color: #dc2626;
    background-color: #dc2626;
    box-shadow: 6px 4px 14px -6px rgba(220, 38, 38, .45);
}

.gt-carnet-card-alerte .card-body,
.gt-carnet-card-alerte .card-body .text-muted,
.gt-carnet-card-alerte .card-body .fw-semibold,
.gt-carnet-card-alerte .gt-carnet-details dt,
.gt-carnet-card-alerte .gt-carnet-details dd,
.gt-carnet-card-alerte .gt-field-icon,
.gt-carnet-card-alerte .gt-amount-primary,
.gt-carnet-card-alerte .gt-carnet-card-header,
.gt-carnet-card-alerte .gt-carnet-num,
.gt-carnet-card-alerte .text-success,
.gt-carnet-card-alerte .text-dark,
.gt-carnet-card-alerte .gt-carnet-stat-label,
.gt-carnet-card-alerte .gt-carnet-stat-value {
    color: #fff !important;
}

.gt-carnet-card-alerte .gt-carnet-card-header {
    border-bottom-color: rgba(255, 255, 255, .3);
}

/* Le bloc de mise en avant (.gt-carnet-stats) a son propre fond clair (--gt-row-hover-bg) —
   invisible/mal contrasté une fois la carte passée en rouge, remplacé par un voile blanc
   translucide, même principe que .gt-action-chip pour les boutons d'action sur cette même carte. */
.gt-carnet-card-alerte .gt-carnet-stats {
    background-color: rgba(255, 255, 255, .18);
}

/* Les boutons d'action (outline-*) deviennent illisibles sur le fond rouge de l'alerte : chaque
   bouton reçoit son propre fond blanc individuel (un peu plus grand que le bouton, avec une ombre
   légère pour bien le détacher), plutôt qu'un bandeau plein largeur commun. Actif en permanence
   (pas seulement en alerte) — sans effet visible sur une carte normale déjà à fond blanc. */
.gt-action-chip {
    display: inline-flex;
    background-color: #fff;
    border-radius: calc(var(--bs-border-radius, .5rem) + 3px);
    padding: 3px;
    box-shadow: var(--gt-shadow-sm);
}

/* Boutons d'action (icônes) : léger effet de levée au survol, cohérent avec le reste des
   micro-interactions de la refonte "SaaS premium". */
.table-standard td.actions .btn,
.gt-action-chip .btn {
    transition: transform .12s ease, box-shadow .12s ease;
}

@media (hover: hover) and (pointer: fine) {
    .table-standard td.actions .btn:hover:not(:disabled),
    .gt-action-chip .btn:hover:not(:disabled) {
        transform: translateY(-1px);
    }
}

.gt-carnet-card-header {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .75rem 1rem .5rem;
    border-bottom: 1px solid var(--gt-border);
    color: var(--gt-text);
}

/* flex: 1 1 auto + min-width: 0 (décidé le 2026-09-10, avec .gt-carnet-num-texte ci-dessous) :
   le nom occupe tout l'espace restant et pousse le badge/les actions éventuels vers la droite
   (remplace l'ancien justify-content: space-between sur .gt-carnet-card-header, qui écartait les
   éléments plutôt que de les regrouper à droite dès qu'il y en avait plus d'un) — et surtout
   permet au nom de se tronquer (voir .gt-carnet-num-texte) au lieu de pousser les boutons d'action
   hors de la carte sur un nom long et un petit écran. */
.gt-carnet-num {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-weight: 700;
    letter-spacing: .03em;
    flex: 1 1 auto;
    min-width: 0;
}

/* Texte du nom/identifiant dans l'en-tête de carte (pas l'avatar, qui garde sa taille fixe) :
   se tronque avec une ellipse plutôt que de repousser le badge/les boutons d'action hors de la
   carte sur un nom long et un petit écran (décidé le 2026-09-10, voir "Colonne Actions" dans
   CLAUDE.md pour le contexte de ce déplacement). */
.gt-carnet-num-texte {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Boutons d'action déplacés dans l'en-tête de carte, à droite du nom (et du badge de statut s'il y
   en a un) — décidé le 2026-09-10, pour que la carte ne s'étire plus verticalement à cause d'une
   rangée de boutons en bas du corps. flex-shrink: 0 : les boutons gardent toujours leur taille,
   c'est le nom (.gt-carnet-num-texte ci-dessus) qui cède la place en se tronquant. */
.gt-carnet-card-actions {
    display: flex;
    align-items: center;
    gap: .375rem;
    flex-shrink: 0;
}

.gt-carnet-details dt {
    display: flex;
    align-items: center;
    gap: .4rem;
    color: var(--gt-text-muted);
    font-weight: 400;
}

/* Petit texte discret pour le compteur à côté du titre "Liste des carnets" (décidé le 2026-09-10,
   revue visuelle) — remplace le "(N)" collé directement au titre, plus proche du traitement
   "N élément(s)" déjà utilisé à côté de la recherche sur Clients.razor. */
.gt-carnets-compteur {
    font-size: 1.05rem;
    font-weight: 400;
    color: var(--gt-text-muted);
}

/* Bloc de mise en avant (Cotisé / Prêt accordé / Solde restant) en tête de carte carnet — décidé
   le 2026-09-10 (revue visuelle de Carnets.razor) : ces 3 montants sont les plus consultés d'un
   coup d'œil, ils sortent donc de la liste dt/dl uniforme ci-dessous (qui leur donnait le même
   poids visuel qu'aux 7 autres champs) pour un traitement à part — même esprit que .gt-stat-tile
   du tableau de bord (chiffre en gras + libellé discret), mais sans bordure/ombre propres pour ne
   pas créer une "carte dans la carte" une fois niché dans .gt-carnet-card. */
.gt-carnet-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .25rem;
    background-color: var(--gt-row-hover-bg);
    border-radius: var(--gt-radius-sm);
    padding: .6rem .35rem;
    margin-bottom: .9rem;
}

.gt-carnet-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .15rem;
    min-width: 0;
}

.gt-carnet-stat-label {
    font-size: .66rem;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--gt-text-muted);
    font-weight: 600;
    white-space: nowrap;
}

.gt-carnet-stat-value {
    font-size: .92rem;
    font-weight: 700;
    color: var(--gt-text);
}

/* Met en avant "Solde restant" (le montant le plus consulté d'un coup d'œil) par la taille — la
   couleur (toujours verte) vient de l'utilitaire générique .gt-text-success (voir plus haut dans
   ce fichier), appliqué directement dans le Razor avec .gt-text-danger sur "Prêt accordé"
   (toujours rouge) — décidé le 2026-09-10, sur demande explicite, couleurs fixes plutôt que
   conditionnelles au montant. Taille découplée de la couleur ici pour rester composable. */
.gt-carnet-stat-highlight .gt-carnet-stat-value {
    font-size: 1.02rem;
}

/* Icône décorative devant un champ de la carte carnet (SVG à la main, pas de librairie d'icônes). */
.gt-field-icon {
    flex-shrink: 0;
    color: var(--gt-text-muted);
}

.gt-amount-primary {
    color: var(--gt-primary);
}

/* Utilitaires de couleur génériques pour un montant, dans l'esprit de .gt-amount-primary
   ci-dessus mais rouge/vert — ajoutés le 2026-09-10 pour "Prêt accordé"/"Solde restant"
   (toujours rouge/toujours vert, décidé explicitement), réutilisés tels quels partout où ces
   champs apparaissent (Carnets.razor, Livraisons.razor) plutôt que dupliqués par page. S'appuient
   sur --gt-danger-text/--gt-success-text (déjà utilisés par le pied de carte "Frais non payé"
   ci-dessous), donc déjà adaptés au mode sombre. */
.gt-text-danger {
    color: var(--gt-danger-text);
}

.gt-text-success {
    color: var(--gt-success-text);
}

/* Pied de carte carnet : bandeau plein largeur (remplace le badge) signalant l'état des frais. */
.gt-carnet-card-footer {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    padding: .65rem 1rem;
    font-weight: 600;
    font-size: .85rem;
    border-top: none;
}

.gt-carnet-footer-paye {
    background-color: var(--gt-success-bg);
    color: var(--gt-success-text);
}

.gt-carnet-footer-non-paye {
    background-color: var(--gt-neutral-bg);
    color: var(--gt-neutral-text);
}

/* Tableau de bord (Home.razor). */

/* Sur mobile (<576px), le titre et l'icône loupe restent seuls sur la première ligne (le bouton
   "Rechercher" texte de .gt-dashboard-filter est caché, remplacé par l'icône) ; Date Début/Date
   Fin (sans bouton) passent à la ligne juste en dessous, toujours sans libellé visible — décision
   du 2026-09-09 : les dates restent modifiables sur mobile, seul l'emplacement du bouton change.
   flex-wrap + order pilotent ce passage à la ligne (voir règles ci-dessous), pas une media query
   séparée : à partir de 576px, tout repasse sur une seule ligne (voir media query plus bas). */
.gt-dashboard-heading {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .6rem;
    margin-bottom: 1.1rem;
}

.gt-dashboard-heading h1 {
    order: 1;
    flex-shrink: 0;
    white-space: nowrap;
}

/* Bouton icône loupe — doublon du bouton "Rechercher" texte de .gt-dashboard-filter, affiché
   uniquement sur mobile (<576px) à côté du titre — les deux déclenchent la même méthode
   Rechercher(). margin-left:auto le pousse à l'extrémité droite de la première ligne (titre +
   icône), même quand .gt-dashboard-filter est passé à la ligne suivante juste en dessous. */
.gt-dashboard-search-icon {
    order: 2;
    margin-left: auto;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    padding: 0;
}

/* Date Début/Date Fin + bouton "Rechercher" (masqué sur mobile, voir .btn ci-dessous). Pas de
   <label> visible sur les champs (voir aria-label dans le Razor) : ni la ligne du titre (dès
   576px) ni la ligne dédiée sous le titre (mobile) n'ont la place de les garder. */
.gt-dashboard-filter {
    order: 3;
    flex-basis: 100%;
    display: flex;
    align-items: center;
    gap: .4rem;
}

.gt-dashboard-filter .form-control {
    min-height: 2.3rem;
    width: 8.75rem;
    padding: .25rem .5rem;
    background-color: var(--gt-surface);
}

.gt-dashboard-filter .btn {
    display: none;
    min-height: 2.3rem;
    padding: .25rem .75rem;
    white-space: nowrap;
    flex-shrink: 0;
}

@media (min-width: 576px) {
    .gt-dashboard-heading {
        flex-wrap: nowrap;
    }

    .gt-dashboard-search-icon {
        display: none;
    }

    .gt-dashboard-filter {
        order: 2;
        flex-basis: auto;
        margin-left: auto;
    }

    .gt-dashboard-filter .btn {
        display: inline-block;
    }
}

/* Entre 576px et 991.98px, le sidebar de nav prend déjà de la place à partir de 641px (voir
   NavMenu.razor.css, jamais replié au-delà) : les champs de filtre sont resserrés pour que titre +
   Date Début + Date Fin + Rechercher tiennent sans passer à la ligne (le titre lui-même est réduit
   par la règle globale sur h1, voir plus haut — généralisée à toutes les pages le 2026-09-10,
   à l'origine spécifique à cette page). Testé sans débordement horizontal à
   576/640/700/768/900/991px (voir aussi la marge prise par le sidebar). Au-delà de 992px, assez de
   place pour repasser à la taille normale. */
@media (min-width: 576px) and (max-width: 991.98px) {
    .gt-dashboard-filter .form-control {
        width: 7rem;
    }
}

.gt-dashboard-statistics {
    border: 1px solid #aeb6c0;
    border-radius: 1rem;
    padding: 1.25rem 1rem 1.15rem;
    background-color: var(--gt-surface);
}

/* Titre "Statistiques" retiré visuellement (2026-09-09, le titre "Tableau de bord" suffit) —
   visually-hidden (classe Bootstrap) plutôt que supprimé, pour rester lisible par un lecteur
   d'écran (voir aria-labelledby de la section). */
.gt-dashboard-section-title {
    margin: 0;
    color: var(--gt-heading);
    font-size: 1.05rem;
    font-weight: 700;
}

.gt-dashboard-statistics .gt-hero-figure {
    min-height: 6.1rem;
    padding: .85rem 1rem;
    border-width: 1px;
    border-radius: .65rem;
    box-shadow: 0 2px 5px rgba(31, 41, 55, .16);
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.gt-dashboard-statistics .gt-hero-label {
    display: flex;
    align-items: center;
    gap: .55rem;
    color: #111827;
    font-size: .9rem;
    font-weight: 700;
}

.gt-dashboard-statistics .gt-hero-label svg {
    flex-shrink: 0;
    width: 1.75rem;
    height: 1.75rem;
    padding: .35rem;
    border-radius: 50%;
    stroke: currentColor;
}

.gt-dashboard-statistics .gt-hero-value {
    margin: .2rem 0 0 3.05rem;
    color: #111827;
    font-size: 1.55rem;
    font-weight: 800;
}

.gt-dashboard-statistics .col:nth-child(1) .gt-hero-figure {
    background-color: #fce7fb;
    border-color: #e9a7e5;
}

.gt-dashboard-statistics .col:nth-child(1) .gt-hero-label svg {
    background-color: #a000bd;
    color: #fff;
}

.gt-dashboard-statistics .col:nth-child(2) .gt-hero-figure {
    background-color: #e8f0ff;
    border-color: #9bbcff;
}

.gt-dashboard-statistics .col:nth-child(2) .gt-hero-label svg {
    background-color: #2563eb;
    color: #fff;
}

.gt-dashboard-statistics .col:nth-child(3) .gt-hero-figure {
    background-color: #fff1e7;
    border-color: #ffc38f;
}

.gt-dashboard-statistics .col:nth-child(3) .gt-hero-label svg {
    background-color: #ed760c;
    color: #111827;
}

@media (max-width: 575.98px) {
    .gt-dashboard-statistics {
        padding: 1rem .75rem .85rem;
    }
}

/* Popup "Aide" d'Administration.razor — étapes de l'ordre d'import recommandé. */
.gt-aide-import-etapes li {
    margin-bottom: .85rem;
}

.gt-aide-import-etapes li:last-child {
    margin-bottom: 0;
}

/* Le chiffre que la page met en avant (montant collecté aujourd'hui) — un seul par page. */
.gt-hero-figure {
    background-color: var(--gt-surface);
    border: 1px solid var(--gt-border);
    border-radius: var(--gt-radius);
    box-shadow: var(--gt-shadow);
    padding: 1.75rem 2rem;
    /* Sans ça, les 3 cartes n'ont pas la même hauteur dès qu'un libellé passe sur deux lignes
       (période affichée plus longue que "Carnets créés") — .col Bootstrap s'étire déjà à la
       hauteur de la ligne, mais son contenu direct doit explicitement suivre pour en profiter.
       Même correctif que .gt-stat-tile/.gt-activity-panel un peu plus bas dans ce fichier. */
    height: 100%;
}

.gt-hero-label {
    color: var(--gt-text-muted);
    font-size: .95rem;
    font-weight: 600;
}

.gt-hero-value {
    font-size: clamp(2.25rem, 5vw, 3rem);
    font-weight: 700;
    line-height: 1.1;
    color: var(--gt-primary);
    margin-top: .25rem;
}

/* Tuile KPI (compteur/montant secondaire) — plus discrète que le hero figure. */
.gt-stat-tile {
    background-color: var(--gt-surface);
    border: 1px solid var(--gt-border);
    border-radius: var(--gt-radius);
    box-shadow: var(--gt-shadow-sm);
    padding: 1.1rem 1.25rem;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: .35rem;
}

.gt-stat-tile-header {
    display: flex;
    align-items: center;
    gap: .5rem;
    color: var(--gt-text-muted);
}

.gt-stat-tile-icon {
    flex-shrink: 0;
    color: var(--gt-card-accent);
}

.gt-stat-tile-label {
    font-size: .85rem;
    font-weight: 600;
}

.gt-stat-tile-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--gt-text);
}

.gt-stat-tile-value.gt-amount-primary {
    color: var(--gt-primary);
}

/* Tuiles KPI du tableau de bord (Carnets en cours/livrés, Montant total cotisé, Prêts en cours) —
   reprennent le même traitement que les 3 tuiles "hero" juste au-dessus (badge d'icône en cercle
   coloré + fond pastel assorti), pour unifier les deux blocs de la page plutôt que de retomber sur
   un style neutre. Couleurs non variabilisées et non adaptées au mode sombre, par cohérence
   volontaire avec .gt-dashboard-statistics .gt-hero-figure (même limitation assumée là-bas). */
.gt-dashboard-kpis .gt-stat-tile-header {
    color: #111827;
}

.gt-dashboard-kpis .gt-stat-tile-icon {
    width: 1.75rem;
    height: 1.75rem;
    padding: .35rem;
    border-radius: 50%;
    stroke: currentColor;
}

.gt-dashboard-kpis .gt-stat-tile-value,
.gt-dashboard-kpis .gt-stat-tile-value.gt-amount-primary {
    color: #111827;
}

.gt-dashboard-kpis .col:nth-child(1) .gt-stat-tile {
    background-color: #e8f0ff;
    border-color: #9bbcff;
}

.gt-dashboard-kpis .col:nth-child(1) .gt-stat-tile-icon {
    background-color: #2563eb;
    color: #fff;
}

.gt-dashboard-kpis .col:nth-child(2) .gt-stat-tile {
    background-color: #e6f9ef;
    border-color: #86efac;
}

.gt-dashboard-kpis .col:nth-child(2) .gt-stat-tile-icon {
    background-color: #15803d;
    color: #fff;
}

.gt-dashboard-kpis .col:nth-child(3) .gt-stat-tile {
    background-color: #fce7fb;
    border-color: #e9a7e5;
}

.gt-dashboard-kpis .col:nth-child(3) .gt-stat-tile-icon {
    background-color: #a000bd;
    color: #fff;
}

.gt-dashboard-kpis .col:nth-child(4) .gt-stat-tile {
    background-color: #fff1e7;
    border-color: #ffc38f;
}

.gt-dashboard-kpis .col:nth-child(4) .gt-stat-tile-icon {
    background-color: #ed760c;
    color: #111827;
}

/* Tuile "point de vigilance" — statut réservé, jamais utilisé pour une donnée métier neutre. */
.gt-alert-tile {
    background-color: var(--gt-warning-bg);
    border: 1px solid var(--gt-warning-border);
    border-radius: var(--gt-radius);
    padding: 1rem 1.25rem;
    height: 100%;
    display: flex;
    align-items: center;
    gap: .85rem;
}

.gt-alert-tile-icon {
    flex-shrink: 0;
    color: var(--gt-warning-text);
}

.gt-alert-tile-value {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--gt-warning-text);
    line-height: 1.15;
}

.gt-alert-tile-label {
    font-size: .82rem;
    color: var(--gt-warning-text);
    opacity: .85;
}

.gt-alert-tile-link {
    margin-left: auto;
    flex-shrink: 0;
    font-size: .8rem;
    font-weight: 600;
    color: var(--gt-warning-text);
    white-space: nowrap;
}

/* Variante "frais non payés" — plus grave qu'un simple écart de niveau, voir --gt-danger-*. */
.gt-alert-tile-danger {
    background-color: var(--gt-danger-bg);
    border-color: var(--gt-danger-border);
}

.gt-alert-tile-danger .gt-alert-tile-icon,
.gt-alert-tile-danger .gt-alert-tile-value,
.gt-alert-tile-danger .gt-alert-tile-label,
.gt-alert-tile-danger .gt-alert-tile-link {
    color: var(--gt-danger-text);
}

/* Classement des commerciaux (Administrateur/Super Administrateur uniquement). */
.gt-ranking-row {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .6rem 0;
    border-bottom: 1px solid var(--gt-border);
}

.gt-ranking-row:last-child {
    border-bottom: none;
}

.gt-ranking-position {
    flex-shrink: 0;
    width: 1.5rem;
    text-align: center;
    font-weight: 700;
    color: var(--gt-text-muted);
    font-size: .9rem;
}

.gt-ranking-info {
    flex: 1;
    min-width: 0;
}

.gt-ranking-name {
    font-weight: 600;
    color: var(--gt-text);
    margin-bottom: .25rem;
}

.gt-ranking-bar-track {
    background-color: var(--gt-track-bg);
    border-radius: 999px;
    height: .4rem;
    overflow: hidden;
}

.gt-ranking-bar-fill {
    background-color: var(--gt-ranking-accent);
    height: 100%;
    border-radius: 999px;
}

.gt-ranking-amount {
    flex-shrink: 0;
    font-weight: 700;
    color: var(--gt-ranking-accent);
    white-space: nowrap;
}

/* Listes de détail (mises / carnets créés / frais encaissés) sous les tuiles KPI. */
.gt-activity-panel {
    background-color: var(--gt-surface);
    border: 1px solid var(--gt-border);
    border-radius: var(--gt-radius);
    box-shadow: var(--gt-shadow-sm);
    height: 100%;
    display: flex;
    flex-direction: column;
}

.gt-activity-panel-title {
    padding: .85rem 1rem;
    border-bottom: 1px solid var(--gt-border);
    font-size: .85rem;
    font-weight: 600;
    color: var(--gt-text-muted);
}

.gt-activity-panel-list {
    max-height: 280px;
    overflow-y: auto;
}

/* Montants dont la taille de police s'ajuste (gtFitAmounts, wwwroot/js/dashboard.js) pour ne
   jamais déborder de leur conteneur, quelle que soit la longueur du chiffre affiché — la mesure
   se fait sur le conteneur parent direct (carte/ligne), pas sur l'élément lui-même, pour rester
   compatible avec les lignes flex (classement, listes d'activité) sans casser leur mise en page. */
.gt-fit-text {
    white-space: nowrap;
}

/* Bouton clair/sombre (ThemeToggle.razor), présent dans MainLayout et LoginLayout. */
.gt-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    border: 1px solid var(--gt-border);
    background-color: var(--gt-surface);
    color: var(--gt-text-muted);
    cursor: pointer;
    flex-shrink: 0;
    padding: 0;
}

.gt-theme-toggle:hover {
    border-color: var(--gt-primary);
    color: var(--gt-primary);
}

.gt-theme-icon {
    width: 1.1rem;
    height: 1.1rem;
}

.gt-theme-icon-moon {
    display: none;
}

:root[data-bs-theme="dark"] .gt-theme-icon-sun {
    display: none;
}

:root[data-bs-theme="dark"] .gt-theme-icon-moon {
    display: block;
}

