/* Thème « IDeal Evolution 01 » (premier thème produit, fidèle à une référence de style réelle ; valeurs
   exactes dans design-refs/ideal-evolution-01/_mapping.md) : typographie system-ui (échelle remontée
   prompt 95 : corps 15 px, menu 14 px), accent bleu #1f6bff, fond app #ebeef4 (clair) / #212837 (sombre),
   surfaces #FFFFFF / #2a374f, rayons 6 px, barre 54 px, tiroir 239/65 px. Le détail des couleurs/typo vit
   dans le thème MudBlazor centralisé
   (IdealeThemes.cs) ; cette feuille porte les variables globales (dégradés, ombres, rayons) et les réglages
   de shell non couverts par le thème. Architecture multi-thèmes : pour ajouter un thème, on peut scoper des
   variables sous [data-theme-ui="<cle>"] (le défaut « IDeal Evolution 01 » est porté par :root). */

/* Police web embarquée (issue de la référence) : FontAwesome (icônes). La référence n'embarque AUCUNE
   police de texte propriétaire — le corps reste en system-ui (cf. famille principale ci-dessous). Cette
   déclaration rend la police d'icônes disponible localement (aucune dépendance distante, aucune marque
   tierce dans l'UI). */
@font-face {
    font-family: 'Ideale Icons';
    font-style: normal;
    font-weight: 900;
    font-display: block;
    src: url('fonts/fa-solid-900.woff2') format('woff2');
}

/* === Variables CSS globales « IDeal Evolution 01 » (consommées partout — rien en dur dans les composants) =
   Dégradés KPI, ombres, rayons, surfaces secondaires, et ombre de la barre supérieure (clair/sombre). */
:root {
    /* Dégradés d'accent KPI (accent #1f6bff de la référence). */
    --g-blue: linear-gradient(135deg, #4f8bff, #1f6bff);
    --g-amber: linear-gradient(135deg, #F59E0B, #F97316);
    --g-green: linear-gradient(135deg, #22C55E, #16A34A);
    /* Ombres (clair). */
    --sh-sm: 0 1px 2px rgba(33, 40, 55, .06);
    --sh: 0 4px 14px rgba(33, 40, 55, .07);
    --sh-lg: 0 12px 34px rgba(33, 40, 55, .14);
    /* Ombre de la barre supérieure (référence : halo bleu très léger en clair). */
    --sh-topbar: 0 6px 6px rgba(31, 107, 255, .1);
    /* Rayons (référence : sm 3 / défaut 6 / lg 9). */
    --r-sm: 6px;
    --r: 6px;
    --r-lg: 9px;
    --r-pill: 999px;
    /* Surface secondaire (fond intermédiaire / champ de recherche clair = gris 100 de la référence). */
    --s-2: #ebeef4;
    /* Survol d'item de menu (référence : gris 300 à 50 %). */
    --ideale-nav-hover: rgba(201, 210, 227, .5);
}

/* Mode sombre : surfaces secondaires et ombres plus profondes. La règle s'accroche à l'attribut posé
   par MudBlazor (data-theme="dark") et à la classe utilitaire éventuelle. */
[data-theme="dark"], .mud-theme-dark {
    --sh-sm: 0 1px 2px rgba(0, 0, 0, .40);
    --sh: 0 4px 14px rgba(0, 0, 0, .45);
    --sh-lg: 0 12px 34px rgba(0, 0, 0, .55);
    /* Ombre de barre en sombre (référence). */
    --sh-topbar: 0 2px 16px rgba(0, 0, 0, .35);
    /* Champ de recherche / fond intermédiaire sombre (référence). */
    --s-2: #364767;
    /* Survol d'item de menu sombre (référence : gris 800 à 50 %). */
    --ideale-nav-hover: rgba(60, 78, 113, .5);
}

html, body {
    /* Famille principale « IDeal Evolution 01 » = system-ui (fidèle à la référence ; aucune police de texte
       propriétaire). 'Ideale Icons' (FontAwesome) reste disponible pour d'éventuelles icônes. */
    font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', 'Liberation Sans', Arial, sans-serif;
    /* Corps « IDeal Evolution 01 » — échelle remontée (prompt 95) : 15 px / interligne 1.45. Base coordonnée
       avec la typographie du thème MudBlazor (IdealeThemes.BuildTypography → Default 15 px). */
    font-size: 15px;
    line-height: 1.45;
    /* BUG ascenseur horizontal permanent (prompt 78) : le tiroir de l'assistant IA (Persistent, ancré à
       droite) est en position fixed ; FERMÉ, il reste hors-champ à droite et créait un ascenseur horizontal
       permanent — même en plein écran — qui tronquait les bulles d'aide de bord. On clippe le débordement
       HORIZONTAL au niveau du conteneur de défilement (le défilement vertical reste intact, et aucun contenu
       utile n'est masqué : le tiroir reste pleinement visible quand il s'ouvre, en superposition/dock). */
    overflow-x: hidden;
}

/* Liens et boutons Bootstrap résiduels : alignés sur l'accent du thème courant (plus de bleu Fluent figé). */
a, .btn-link {
    color: var(--mud-palette-primary);
}

.btn-primary {
    color: #fff;
    background-color: var(--mud-palette-primary);
    border-color: var(--mud-palette-primary);
}

.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.2rem var(--mud-palette-primary);
}

/* Classes utilitaires KPI : tuiles/indicateurs à fond dégradé (consomment les variables ci-dessus). */
.ideale-kpi-blue { background: var(--g-blue); color: #fff; }
.ideale-kpi-amber { background: var(--g-amber); color: #fff; }
.ideale-kpi-green { background: var(--g-green); color: #fff; }

.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: "Une erreur est survenue."
    }

/* Conteneur de l'aide contextuelle : ancre la bulle MAISON (positionnée par rapport à l'icône). inline-flex
   pour ne pas casser les mises en page « champ + ? » alignées. */
.ideale-aide {
    position: relative;
    display: inline-flex;
    align-items: center;
}

/* Icône d'aide contextuelle (composant AideContextuelle) : discrète, légèrement estompée au repos,
   pleinement visible au survol/focus pour rester accessible. */
.ideale-aide-icone {
    opacity: 0.6;
    padding: 4px;
}

    .ideale-aide-icone:hover,
    .ideale-aide-icone:focus-visible {
        opacity: 1;
    }

/* === Bulle d'aide MAISON (prompt 60) ===============================================================
   Remplace le tooltip MudBlazor (popover dont la largeur restait incontrôlable). Bulle = simple <span>
   positionné SOUS l'icône, largeur PLAFONNÉE à 300px et retour à la ligne GARANTIS (white-space:normal +
   coupure de mots), hauteur auto → texte sur 2-3 lignes. Masquée au repos, révélée au survol/focus du « ? ».
   Couleurs reprises du tooltip MudBlazor (gris foncé + texte clair) → identique en clair ET sombre. */
.ideale-aide-bulle {
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    /* Repositionnement « shift » (prompt 79) : la bulle est centrée par défaut, mais un décalage horizontal
       (--decalage, calculé en JS au survol) la ramène DANS le viewport quand elle déborderait d'un bord →
       texte complet, jamais tronqué (y compris l'aide « comment obtenir la clé API » au bord droit). */
    transform: translateX(calc(-50% + var(--decalage, 0px)));
    z-index: 1400;
    max-width: 300px;
    width: max-content;
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
    text-align: center;
    padding: 8px 12px;
    border-radius: var(--r-sm);
    background-color: var(--mud-palette-gray-darker);
    color: var(--mud-palette-dark-text);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.45;
    box-shadow: var(--sh-lg);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 120ms ease;
}

/* Flèche pointant vers le « ? » (au-dessus de la bulle). Quand la bulle est décalée (--decalage) pour rester
   dans le viewport, la flèche est décalée en SENS INVERSE afin de continuer à pointer vers l'icône « ? ». */
.ideale-aide-bulle::after {
    content: "";
    position: absolute;
    bottom: 100%;
    left: calc(50% - var(--decalage, 0px));
    transform: translateX(-50%);
    border: 6px solid transparent;
    border-bottom-color: var(--mud-palette-gray-darker);
}

/* Révélation au survol de l'icône (ou focus clavier dans le conteneur). */
.ideale-aide:hover .ideale-aide-bulle,
.ideale-aide:focus-within .ideale-aide-bulle {
    opacity: 1;
    visibility: visible;
}

/* Bulle d'aide contextuelle (MudTooltip) : compacte et lisible. Sans contrainte, une aide longue
   s'étire sur toute la largeur en une seule ligne ; on borne la largeur, on autorise le retour à la
   ligne, on arrondit les coins et on aère le contenu. */
.mud-tooltip {
    max-width: 300px;
    white-space: normal;
    overflow-wrap: anywhere;
    border-radius: var(--r-sm);
    padding: 8px 12px;
    line-height: 1.45;
    text-align: left;
}

/* Texte d'aide réservé aux lecteurs d'écran : visuellement masqué mais présent dans le DOM, pour
   être annoncé via aria-describedby quand le champ associé reçoit le focus (cf. AideContextuelle). */
.ideale-aide-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Champs de formulaire HTML natif (pages de connexion : POST réel vers /auth/login et
   /auth/plateforme/login — impossible d'utiliser MudTextField puisqu'il faut un vrai POST pour
   poser le cookie). On les style donc à la main pour suivre le thème MudBlazor (clair/sombre) via
   les variables de palette : couleurs de texte, surface et bordures issues du thème courant. */
.ideale-form-label {
    display: block;
    margin: 14px 0 5px;
    font-weight: 600;
    font-size: 0.75rem;
    color: var(--mud-palette-text-primary);
}

.ideale-form-field {
    display: block;
    width: 100%;
    /* Hauteur compacte ~32 px (densité Fluent). */
    padding: 6px 12px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--mud-default-borderradius);
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--mud-palette-text-primary);
    background-color: var(--mud-palette-surface);
    box-sizing: border-box;
    /* color-scheme aligne les éléments natifs (caret, remplissage auto) sur le thème. */
    color-scheme: light dark;
    transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}

    .ideale-form-field::placeholder {
        color: var(--mud-palette-text-disabled);
    }

    .ideale-form-field:hover {
        border-color: var(--mud-palette-text-secondary);
    }

    .ideale-form-field:focus {
        outline: none;
        border-color: var(--mud-palette-primary);
        box-shadow: 0 0 0 2px rgba(var(--mud-palette-primary-rgb), 0.25);
    }

.mud-width-full {
    width: 100%;
}

.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;
}

/* === Pied de page « collé en bas » (sticky footer) ===========================
   Le pied de page est unique (dans les layouts) et toujours ancré tout en bas :
   la zone de contenu prend la hauteur disponible et pousse le pied en bas de la
   fenêtre quand la page est courte ; sur une page longue, il apparaît à la fin
   après défilement. Jamais collé juste sous le contenu.

   Layouts MudBlazor (MainLayout, PlatformLayout, BackOfficeLayout). */
.mud-layout {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.mud-main-content {
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
}

/* Layout épuré (SetupLayout : connexion, launcher, assistant). Fond professionnel sobre façon
   Microsoft 365 : léger halo d'accent en haut au-dessus du fond thématisé (clair/sombre), sans
   dégradé criard ni image. */
.setup-shell {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background:
        radial-gradient(900px 480px at 50% -5%, rgba(var(--mud-palette-primary-rgb), 0.10), transparent 70%),
        var(--mud-palette-background);
}

/* Zone enveloppant le pied : poussée tout en bas de l'espace disponible. */
.ideale-pied-zone {
    margin-top: auto;
}

/* === Page de connexion plateforme (esprit IONOS, prompt 101) =================
   Barre supérieure pleine largeur (logo IDeal + accroche en italique léger + sélecteur de langue) au-dessus
   d'un fond neutre, avec la box de connexion centrée, arrondie et descendue. */

/* Barre supérieure : surface du thème + ombre de la barre applicative (cohérence visuelle). */
.ideale-connexion-barre {
    display: flex;
    align-items: center;
    gap: 14px;
    height: 60px;
    padding: 0 24px;
    background-color: var(--mud-palette-surface);
    box-shadow: var(--sh-topbar);
    flex: 0 0 auto;
}

/* Logo IDeal dans la barre : large et homogène avec la barre (occupe l'essentiel de la hauteur de 60 px,
   avec une marge verticale propre), largeur auto (ratio 600×123 préservé), rendu net. */
.ideale-connexion-logo {
    height: 44px;
    width: auto;
    display: block;
    flex: 0 0 auto;
    object-fit: contain;
}

/* Séparateur vertical discret entre le logo et l'accroche : fin filet du thème (divider), hauteur calée sur
   l'optique de la barre, centré verticalement par le flex parent (align-items:center). Décoratif. */
.ideale-connexion-separateur {
    flex: 0 0 auto;
    width: 1px;
    height: 30px;
    background-color: var(--mud-palette-divider);
    opacity: 0.8;
}

/* Accroche produit juste à côté du logo : texte fin, léger italique, couleur discrète. Un cran plus grande
   (~0.9375rem) pour plus de présence ; line-height:1 + alignement flex → même centre optique que le logo. */
.ideale-connexion-accroche {
    font-size: 0.9375rem;
    font-weight: 400;
    font-style: italic;
    color: var(--mud-palette-text-secondary);
    letter-spacing: 0.01em;
    line-height: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Sélecteur de langue : poussé vers la droite, sans être collé au bord (le padding de la barre l'en éloigne). */
.ideale-connexion-barre-fin {
    margin-left: auto;
    flex: 0 0 auto;
}

/* Corps : box centrée horizontalement et DESCENDUE (davantage d'air au-dessus). */
.ideale-connexion-corps {
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: clamp(48px, 12vh, 140px) 1rem 2rem;
}

/* Box de connexion façon IONOS : coins BIEN arrondis (rayon dédié, plus marqué que le token --r-lg du thème
   actif pour l'élégance IONOS), ombre douce, largeur IMPOSANTE (650 px) tout en restant responsive
   (width:100% → 100% de la largeur disponible, avec marges, sur petit écran). */
.ideale-connexion-carte {
    width: 100%;
    max-width: 650px;
    border-radius: 18px;
    box-shadow: var(--sh-lg);
}

/* Champs E-mail / Mot de passe SCOPÉS à la box de connexion plateforme (n'affecte pas l'écran d'instance qui
   partage .ideale-form-field) : police plus lisible (~15px) et hauteur augmentée (champs plus confortables). */
.ideale-connexion-carte .ideale-form-field {
    font-size: 15px;
    padding: 11px 14px;
}

/* Libellés un cran plus lisibles, cohérents avec les champs agrandis (scopés à la box de connexion). */
.ideale-connexion-carte .ideale-form-label {
    font-size: 0.8125rem;
    margin: 18px 0 6px;
}

/* Bouton « Se connecter » plus GÉNÉREUX (plus haut via le padding vertical) et nettement DÉCOLLÉ du champ
   mot de passe (marge au-dessus). Pleine largeur de la box conservée (mud-width-full). Le bleu du Design
   System reste inchangé (mud-button-filled-primary non touché). */
.ideale-connexion-carte .ideale-connexion-bouton {
    margin-top: 24px;
    padding-top: 13px;
    padding-bottom: 13px;
    height: auto;
    font-size: 0.95rem;
}

/* Avatar rond du titre, cohérent avec « Connexion ». */
.ideale-connexion-avatar {
    height: 40px;
    width: 40px;
}

.ideale-connexion-titre {
    font-weight: 700;
    letter-spacing: 0.01em;
}

/* Bloc identité du client à côté de son avatar (prompt 160) : nom + « Connexion » empilés. min-width:0 pour
   autoriser la troncature du nom long sans déborder de la carte. */
.ideale-connexion-identite {
    min-width: 0;
}

/* Responsive : sur petit écran, l'accroche ET son séparateur se masquent pour ne pas encombrer (logo +
   langue conservés). */
@media (max-width: 760px) {
    .ideale-connexion-accroche,
    .ideale-connexion-separateur {
        display: none;
    }

    .ideale-connexion-barre {
        padding: 0 14px;
    }
}

/* Pied de page centré (variante utilisée par SetupLayout : connexion / launcher / assistant). */
.ideale-pied-centre {
    text-align: center;
}

/* Logo produit dans la barre supérieure (à côté du burger) : présent et imposant (38 px) tout en restant
   adapté à la hauteur de contenu de la barre (54 px), ratio préservé (fichier carré 64×64), net. Léger
   espace avant le wordmark ; centré verticalement par la toolbar (align-items:center). */
.ideale-appbar-logo {
    height: 38px;
    width: auto;
    display: block;
    object-fit: contain;
    flex: 0 0 auto;
    margin-right: 6px;
}

/* Initiales de repli dans une pastille d'habillage (AvatarHabille, prompt 160) : quand le client n'a pas de
   logo, on affiche ses initiales — texte gras et lisible sur le dégradé (blanc via la couleur de l'avatar). */
.ideale-avatar-initiales {
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

/* Brand (zone logo en haut à gauche de la barre, fidèle à .brand de la référence) : burger + logo texte,
   calé à gauche. Largeur souple (le header ne commence pas par un grand vide). */
.ideale-brand {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-right: 8px;
    min-width: 0;
}

/* Marque (texte « IDeal Evolution Studio ») : 16 px / 600, couleur encre du header. */
.ideale-brand-texte {
    font-size: 16px;
    font-weight: 600;
}

/* Le nom de l'appli est un LIEN vers le tableau de bord : curseur main, léger éclaircissement au survol
   (couleur primaire), AUCUN effet de glissement/translation. */
.ideale-brand-lien {
    cursor: pointer;
    transition: color 150ms ease;
}

    .ideale-brand-lien:hover {
        color: var(--mud-palette-primary);
    }

/* Zone de droite de la barre : toujours ancrée à l'EXTRÊME DROITE (margin-left:auto) — elle ne se décale pas
   vers le centre quand la fenêtre s'agrandit (la recherche, plafonnée, laisse l'espace à la marge auto). */
.ideale-appbar-droite {
    display: flex;
    align-items: center;
    /* Espacement HOMOGÈNE entre les 4 utilitaires (bascule thème · assistant IA · cloche · avatar) — gap
       uniforme de 12 px (prompt 78 : barre aérée, cloche un peu plus éloignée de l'avatar qu'auparavant). */
    gap: 12px;
    margin-left: auto;
    flex-shrink: 0;
}

/* Alignement vertical (recette interface 24/06/2026) : lune (bascule clair/sombre), cloche et avatar sur le
   MÊME axe horizontal. Chaque utilitaire devient une boîte de hauteur commune (40 px) qui CENTRE son contenu →
   la lune (MudIconButton), la cloche (MudIcon + badge) et l'avatar partagent exactement le même centre vertical
   dans la barre de 54 px. `!important` sur display/align : sans ça, le conteneur d'info-bulle de la lune reste
   en `inline-block` (réglage MudBlazor) → le bouton, plus haut que 40 px, se cale en HAUT au lieu d'être centré
   (lune ~2 px trop bas). On force donc le centrage flex. */
.ideale-appbar-droite > * {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center;
    height: 40px;
}

/* La cloche est un MudIcon (plus petit que sa boîte) enveloppé d'un badge : on centre explicitement l'icône
   DANS le badge (sinon elle se cale en haut → cloche ~2,4 px trop haute). L'activateur et le badge prennent la
   hauteur commune et centrent leur contenu → l'icône de cloche retombe sur le même axe que la lune et l'avatar. */
.ideale-cloche-activateur,
.ideale-cloche-activateur .mud-badge-root {
    display: inline-flex;
    align-items: center;
    height: 40px;
}

/* Espacement uniforme désormais porté par le `gap` du conteneur (.ideale-appbar-droite) : on ne fixe plus de
   marges asymétriques entre les éléments (prompt 78 : écart identique entre les 4 utilitaires). */

/* Bouton BURGER (≡) : au survol, PAS de rond/cercle derrière l'icône — on neutralise le fond de survol et la
   vague (ripple) de MudBlazor. Le seul retour visuel = l'icône qui grise légèrement (couleur secondaire). */
.ideale-brand .mud-icon-button {
    --mud-ripple-opacity: 0;
    --mud-ripple-opacity-secondary: 0;
}

.ideale-brand .mud-icon-button:hover,
.ideale-brand .mud-icon-button:focus-visible,
.ideale-brand .mud-icon-button:active {
    background-color: transparent !important;
}

.ideale-brand .mud-icon-button:hover .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* Activateur du menu avatar : photo ronde + nom, cliquable d'un bloc. */
.ideale-avatar-activateur {
    cursor: pointer;
}

/* Avatar = rond strict 30 × 30 px (conforme ASPStudio), aligné avec l'e-mail à côté. !important pour battre
   les tailles MudBlazor (.mud-avatar-medium = 40 px) quelle que soit la spécificité. */
.ideale-avatar-activateur .mud-avatar {
    width: 30px !important;
    height: 30px !important;
    min-width: 30px !important;
    max-width: 30px !important;
    font-size: 12px;
    border-radius: 50%;
}

.ideale-avatar-nom {
    font-weight: 500;
    max-width: 180px;
}

/* Activateur de la cloche : zone cliquable compacte autour de l'icône + pastille. */
.ideale-cloche-activateur {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
}

/* Sidebar : fond identique au contenu (référence) → un filet droit la sépare du contenu. */
.ideale-drawer.mud-drawer {
    border-right: 1px solid var(--mud-palette-divider);
}

/* Recherche globale (centre de la barre), conforme ASPStudio. On cible la BOÎTE de saisie outlined de
   MudAutocomplete (`.mud-input.mud-input-outlined`, qui sinon fait ~61 px) et l'input qu'elle contient :
   hauteur 40 px FORCÉE, fond gris #EBEEF4 (--s-2), coins arrondis, AUCUNE bordure au repos, liseré bleu
   UNIQUEMENT au focus. `!important` pour battre les styles internes de MudBlazor (hauteur dense, fond, outline). */
.ideale-recherche-globale {
    flex: 1 1 auto;
    max-width: 760px;
    margin: 0 16px;
}

    /* La boîte outlined = le RECTANGLE GRIS VISIBLE : hauteur TOTALE 40 px (box-sizing border-box pour que
       padding/bordure n'ajoutent rien), fond gris, contenu (loupe + input) centré verticalement. C'est CET
       élément qui dessine le fond #EBEEF4 ; sa hauteur mesurée = la hauteur visible du champ. */
    .ideale-recherche-globale .mud-input.mud-input-outlined {
        box-sizing: border-box !important;
        height: 40px !important;
        min-height: 40px !important;
        max-height: 40px !important;
        border-radius: var(--r-sm);
        /* --s-2 = #EBEEF4 en clair (réf. ASPStudio), surface sombre adaptée en mode sombre. */
        background-color: var(--s-2) !important;
        align-items: center;
    }

    /* Pile MudBlazor compactée : ni le conteneur de saisie ni le contrôle n'ajoutent de hauteur (label
       flottant non utilisé ici — placeholder seul). */
    .ideale-recherche-globale .mud-input-control-input-container,
    .ideale-recherche-globale .mud-input-control {
        margin: 0 !important;
        padding: 0 !important;
    }

    /* L'input lui-même (le slot EST l'input) : 40 px TOTAL grâce à box-sizing:border-box (sans ça, le
       padding vertical s'AJOUTAIT à la hauteur → input à 52 px). Padding-left FAIBLE (4 px) : la loupe est un
       adornement flex AVANT l'input, donc c'est lui qui fournit l'espace gauche — un grand padding-left
       s'AJOUTERAIT à la largeur de la loupe (double vide). Le texte démarre donc juste après la loupe. */
    .ideale-recherche-globale .mud-input-slot {
        box-sizing: border-box !important;
        height: 40px !important;
        min-height: 40px !important;
        background-color: transparent !important;
        padding: 6px 12px 6px 4px !important;
        /* Texte saisi + placeholder à 14 px, centrés verticalement dans les 40 px (line-height adapté) → le
           champ ne paraît plus « gros ». !important pour battre la typo MudBlazor (subtitle1 ≈ 16 px). */
        font-size: 14px !important;
        line-height: 1.4 !important;
    }

    /* Loupe COMPACTE et près du bord gauche : on neutralise la marge à droite de l'adornement et on resserre
       le bouton-icône, pour que le texte commence juste à droite de la loupe (sans grand vide). */
    .ideale-recherche-globale .mud-input-adornment-start {
        margin-right: 0 !important;
    }

    .ideale-recherche-globale .mud-input-adornment-start .mud-icon-button {
        padding: 6px !important;
    }

    /* Bordure de l'outline (le <fieldset>) : AUCUNE au repos (ni au survol). */
    .ideale-recherche-globale .mud-input-outlined-border {
        border-color: transparent !important;
    }

    /* AU FOCUS uniquement : liseré bleu (le focus est sur l'input dans la boîte → :focus-within). */
    .ideale-recherche-globale .mud-input.mud-input-outlined:focus-within .mud-input-outlined-border {
        border-color: var(--mud-palette-primary) !important;
        border-width: 2px !important;
    }

    /* Placeholder gris et loupe grise (au repos). */
    .ideale-recherche-globale .mud-input-slot::placeholder {
        color: var(--mud-palette-text-secondary);
        opacity: 1;
    }

    .ideale-recherche-globale .mud-input-adornment .mud-icon-root {
        color: var(--mud-palette-text-secondary);
    }

/* Zone de contenu (toutes les pages) : largeur PLEINE (MaxWidth.False) avec un espacement horizontal CONSTANT
   d'environ 40 px. Combiné à la marge gauche du contenu qui suit le tiroir (MudBlazor : 226 px déployé / 65 px
   replié), le contenu se cale toujours à ~40 px du bord et s'élargit quand le menu se ferme — sans grand vide. */
.ideale-contenu {
    padding-left: 40px;
    padding-right: 40px;
}

/* Pied de page de copyright (cf. PiedDePageCopyright) : discret, séparé du contenu par un fin filet. La
   couleur secondaire et le filet (divider) MudBlazor s'adaptent au thème clair/sombre. Le logo et la ligne
   copyright forment UNE UNITÉ CENTRÉE horizontalement (logo juste à gauche du texte, même axe optique) —
   identique sur la plateforme ET la page de connexion (prompt 122). */
.ideale-pied-copyright {
    width: 100%;
    padding: 0.6rem 0.25rem 0.5rem;
    border-top: 1px solid var(--mud-palette-divider);
    opacity: 0.85;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

    /* Texte du copyright : marges annulées pour un centrage vertical net avec le logo (align-items:center). */
    .ideale-pied-copyright .mud-typography {
        letter-spacing: 0.01em;
        margin: 0;
    }

/* Petit logo discret du pied, JUSTE À GAUCHE du texte (et non collé au bord), ratio carré préservé (48×48),
   net, centré verticalement sur la même ligne optique que le texte. */
.ideale-pied-logo {
    height: 20px;
    width: auto;
    display: block;
    object-fit: contain;
    flex: 0 0 auto;
    align-self: center;
}

/* === « IDeal Evolution 01 » : surfaces, formes et densité globales ==================================
   Complète le thème MudBlazor centralisé. Objectif : interface fidèle à la référence — angles 6 px,
   bordures fines, ombres douces, mode sombre pleinement stylé. */

/* Cartes & grandes surfaces de contenu : angles à 6 px (référence) avec ombre douce. */
.mud-card,
.mud-table,
.mud-paper-outlined,
.mud-expansion-panels {
    border-radius: var(--r);
}

/* Ombre très douce (référence : 0 1px 2px rgba(33,40,55,.06)) pour les cartes élevées ;
   les papiers « outlined » restent plats (bordure seule). */
.mud-card.mud-elevation-1,
.mud-card.mud-elevation-2 {
    box-shadow: var(--sh-sm);
}

.mud-paper-outlined {
    box-shadow: none;
}

/* Contrôles (boutons, champs) : angles à 6 px (rayon de la référence). */
.mud-button-root.mud-button,
.mud-input-control .mud-input-slot,
.mud-input-outlined .mud-input-slot {
    border-radius: var(--r-sm);
}

/* Barre supérieure « IDeal Evolution 01 » (54 px) : on aligne le décalage du contenu principal sur cette
   hauteur via la variable MudBlazor (sinon un espace resterait sous la barre). Les éléments de la barre
   (brand, recherche, icônes, avatar) sont centrés verticalement dans ces 54 px (toolbar en align-items:center). */
.mud-layout {
    --mud-appbar-height: 54px !important;
}

/* Hauteur effective de la barre = 54 px, contenu centré verticalement, sans débordement. */
.ideale-appbar .mud-toolbar {
    height: 54px;
    min-height: 54px;
    align-items: center;
}

/* Barre supérieure : surface claire/sombre du thème, séparée du contenu par l'ombre de la référence
   (halo bleu très léger en clair, ombre plus marquée en sombre — variable --sh-topbar). */
.ideale-appbar.mud-appbar {
    box-shadow: var(--sh-topbar);
}

/* Icônes utilitaires de la barre (burger, notifications, IA, thème, etc.) : fines (20 px). */
.ideale-appbar .mud-icon-button .mud-icon-root {
    font-size: 20px;
}

/* Les éléments de la barre ne se compriment PAS (flex-shrink:0) — sauf la recherche qui occupe l'espace.
   Sans cela, sur une barre serrée, la cloche et l'avatar pouvaient être réduits à 0 (invisibles / non
   cliquables). La recherche, elle, peut rétrécir (min-width:0) au lieu de pousser les icônes hors champ. */
.ideale-appbar .mud-toolbar > * {
    flex-shrink: 0;
}

.ideale-appbar .ideale-recherche-globale {
    flex: 1 1 auto;
    min-width: 0;
}

/* Densité « IDeal Evolution 01 » : tous les éléments du menu latéral à la MÊME hauteur, coins arrondis 6 px.
   Liste plus DENSE : hauteur de ligne resserrée (30 px), padding vertical réduit (3 px) et marge verticale
   nulle → l'espace vertical entre groupes est resserré et homogène. */
.mud-nav-link,
.mud-nav-group .mud-nav-link {
    min-height: 30px;
    padding-top: 3px;
    padding-bottom: 3px;
    padding-left: 10px;
    padding-right: 10px;
    border-radius: var(--r-sm);
    margin: 0 8px;
    /* Police du menu = 14 px (prompt 95 : valeur d'origine de la référence ASPStudio), taille UNIQUE pour tout
       le menu (groupes ET sous-entrées partagent ce sélecteur) → homogène sur l'ensemble de la sidebar.
       Line-height 20 px : aéré et cohérent avec la remontée d'échelle. */
    font-size: 14px;
    font-weight: 400;
    line-height: 20px;
}

/* Sous-entrées d'un groupe (ex. Pilotage → Tableau de bord / Santé…) : MudBlazor impose `padding:8px 16px`
   (sélecteur plus spécifique que la densité ci-dessus) → lignes trop hautes. On REssERRE le padding vertical
   et la hauteur mini pour une liste compacte, en CONSERVANT l'indentation gauche (padding-left de MudBlazor). */
.ideale-drawer .mud-nav-item .mud-nav-link {
    padding-top: 2px !important;
    padding-bottom: 2px !important;
    min-height: 26px;
}

/* Icône d'item : 16 px (référence 1rem). Seuls les GROUPES portent encore une icône (les sous-entrées sont
   en texte seul) : espace icône ↔ libellé ENCORE resserré (compact, 2 px), identique pour tous les groupes. */
.mud-nav-link .mud-nav-link-icon {
    margin-right: 2px;
    min-width: 0;
}

.mud-nav-link .mud-nav-link-icon .mud-icon-root,
.mud-nav-link .mud-nav-link-icon.mud-icon-root {
    font-size: 16px;
}

/* Libellé d'item : ne pas déborder horizontalement (renfort anti-ascenseur horizontal). Un libellé trop long
   est tronqué proprement (…) plutôt que de pousser la largeur de la colonne. Le flyout réaffiche le texte entier. */
.mud-nav-link .mud-nav-link-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Chevrons de groupe (MudNavGroup) : petits et fins. */
.mud-nav-group > .mud-nav-link .mud-nav-link-expand-icon {
    font-size: 16px;
}

/* Survol (référence) : fond gris translucide (sauf item actif). */
.mud-nav-link:hover:not(.active) {
    background-color: var(--ideale-nav-hover);
}

/* État actif « IDeal Evolution 01 » (fidèle à la référence) : FOND TRANSPARENT, texte et icône en couleur
   primaire (#1f6bff), graisse 600. Pas de pavé plein ni de barre latérale. */
.mud-nav-link.active {
    background-color: transparent;
    color: var(--mud-palette-primary);
    font-weight: 600;
}

.mud-nav-link.active .mud-nav-link-icon .mud-icon-root,
.mud-nav-link.active .mud-nav-link-icon.mud-icon-root {
    color: var(--mud-palette-primary);
}

/* Boutons compacts (~34 px) sans capitales forcées (la casse normale vient du thème). */
.mud-button-root.mud-button {
    min-height: 34px;
}

/* Lignes de tableau compactes (~38–40 px) : on resserre le rembourrage vertical des cellules. */
.mud-table-cell {
    padding-top: 8px;
    padding-bottom: 8px;
}

/* === Tiroir de navigation mini-variant (v0.6) ======================================================
   Le contenu du tiroir est une colonne flex : la navigation occupe l'espace, le bouton utilitaire est
   ancré tout en bas. */
.ideale-drawer-flux {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.ideale-drawer-nav {
    flex: 1 1 auto;
    overflow-y: auto;
    /* Aucun défilement horizontal : on masque tout débordement latéral (libellé long, padding) → plus de barre
       de défilement horizontale en bas de la sidebar. Le défilement vertical reste possible. En mode replié,
       l'override plus bas repasse en overflow:visible pour laisser sortir la bulle (flyout). */
    overflow-x: hidden;
}

/* En mode replié : le menu (icônes) est court → on laisse DÉBORDER (overflow visible) pour que la bulle
   de sous-menu (flyout) sorte à droite sans être rognée. overflow:visible ne masque jamais de contenu. */
.mud-drawer--closed.mud-drawer-mini.ideale-drawer,
.mud-drawer--closed.mud-drawer-mini .ideale-drawer-nav {
    overflow: visible;
}

/* Bouton utilitaire ancré en bas du tiroir (préférences / aide), séparé par un filet. */
.ideale-drawer-bas {
    margin-top: auto;
    border-top: 1px solid var(--mud-palette-divider);
    padding-bottom: 4px;
}

/* Libellés de section (Navigation / SOLUTION / ADMINISTRATION) — densité « IDeal Evolution 01 » : petits et
   HOMOGÈNES (même taille/graisse/couleur pour les trois), gris atténué, MAJUSCULES, marge régulière au-dessus
   de chaque bloc. Taille réduite (12 → 11 px) pour un rendu plus discret. */
.ideale-nav-section {
    padding: 10px 20px 4px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* Par défaut (mode déployé) : on montre le libellé long, on masque le micro-repère court. */
.ideale-nav-section-court {
    display: none;
}

/* En-tête de la 1re section (« Navigation ») : titre + boutons « tout dérouler / tout enrouler » alignés à
   droite (prompt 79). Porté par .ideale-nav-section-long → automatiquement MASQUÉ en mode replié (mini). */
.ideale-nav-section-entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4px;
}

.ideale-nav-actions {
    display: inline-flex;
    align-items: center;
    gap: 2px;
}

.ideale-nav-action-btn {
    padding: 2px;
    opacity: 0.65;
}

    .ideale-nav-action-btn:hover,
    .ideale-nav-action-btn:focus-visible {
        opacity: 1;
    }

    .ideale-nav-action-btn .mud-icon-root {
        font-size: 1.15rem;
    }

/* === Mode replié (mini) PROPRE ====================================================================
   Notre MudNavMenu est enveloppé dans .ideale-drawer-flux ; le sélecteur natif de MudBlazor qui masque le
   texte en mini exige un MudNavMenu enfant DIRECT de .mud-drawer-content → il ne s'applique donc pas chez
   nous (d'où les libellés tronqués « P », « M »…). On masque donc explicitement le texte d'item et le chevron
   en mode replié ; le titre de section, lui, n'est PAS masqué : on y montre son micro-repère court (B2).
   Seules les icônes d'item restent (centrées). */
.mud-drawer--closed.mud-drawer-mini .mud-nav-link-text,
.mud-drawer--closed.mud-drawer-mini .mud-nav-link-expand-icon {
    display: none;
}

/* Mode replié : titre de section réduit à son micro-repère court (« Nav » / « Sol » / « Adm »), centré et
   discret → on conserve la séparation Navigation / Solution / Administration sans casser l'alignement des
   icônes. Le libellé long est masqué, le court est affiché. */
.mud-drawer--closed.mud-drawer-mini .ideale-nav-section {
    padding: 8px 0 4px;
    text-align: center;
    font-size: 10px;
    letter-spacing: 0.03em;
}

.mud-drawer--closed.mud-drawer-mini .ideale-nav-section-long {
    display: none;
}

.mud-drawer--closed.mud-drawer-mini .ideale-nav-section-court {
    display: inline;
}

/* En mode replié : chaque item devient un petit CARRÉ compact (32×32) CENTRÉ horizontalement dans la colonne
   (margin auto) → icône parfaitement centrée et alignée avec les micro-libellés de section (NAV/SOL/ADM, eux
   aussi centrés). Padding nul : le survol (fond gris) reste à la taille du carré, sans déborder. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-link {
    justify-content: center;
    width: 32px;
    height: 32px;
    min-height: 32px;
    padding: 0;
    margin: 2px auto;
    border-radius: var(--r-sm);
}

.mud-drawer--closed.mud-drawer-mini .mud-nav-link .mud-nav-link-icon {
    margin-right: 0;
}

/* Verrou anti-mouvement (recette interface 24/06/2026) : on RÉAFFIRME explicitement la même boîte au repos,
   au survol ET au focus clavier → AUCUNE variation de taille/marge/padding/bordure/line-height entre les états.
   Seule la couleur de l'icône change (cf. règles de survol plus bas). L'anneau de focus reste un `outline`
   (hors flux, ne décale rien). Résultat : icônes strictement immobiles quand on passe de l'une à l'autre. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-link,
.mud-drawer--closed.mud-drawer-mini .mud-nav-link:hover,
.mud-drawer--closed.mud-drawer-mini .mud-nav-link:focus,
.mud-drawer--closed.mud-drawer-mini .mud-nav-link:focus-visible {
    width: 32px;
    height: 32px;
    min-height: 32px;
    padding: 0;
    margin: 2px auto;
    border: 0;
    line-height: 18px;
}

/* Chevron « sous-menu » en mode replié : SEULS les en-têtes de GROUPE (`.mud-nav-group > .mud-nav-link`, qui
   ouvrent une bulle) reçoivent un petit triangle discret à droite de l'icône → repère visuel qu'un menu
   déroulant existe. Les items sans sous-menu (Préférences/Aide, hors groupe) n'en ont pas. Pseudo-élément
   (pointer-events:none) → n'interfère ni avec le survol ni avec la bulle. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-group > .mud-nav-link {
    position: relative;
    overflow: visible;
}

.mud-drawer--closed.mud-drawer-mini .mud-nav-group > .mud-nav-link::after {
    content: "";
    position: absolute;
    top: 50%;
    right: -7px;
    transform: translateY(-50%);
    width: 0;
    height: 0;
    border-top: 3px solid transparent;
    border-bottom: 3px solid transparent;
    border-left: 4px solid var(--mud-palette-text-secondary);
    opacity: 0.75;
    pointer-events: none;
}

/* Survol en mode replié : AUCUN fond gris/carré derrière l'icône. On neutralise le fond de survol (hérité de
   la règle générale) ; à la place, l'ICÔNE passe en BLEU (accent du thème), comme un lien survolé. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-link:hover:not(.active) {
    background-color: transparent;
}

/* Transition de couleur propre pour l'icône et le chevron au survol. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-link .mud-nav-link-icon .mud-icon-root,
.mud-drawer--closed.mud-drawer-mini .mud-nav-group > .mud-nav-link::after {
    transition: color 150ms ease, border-color 150ms ease;
}

/* Au survol : icône en bleu primaire (sans fond). */
.mud-drawer--closed.mud-drawer-mini .mud-nav-link:hover .mud-nav-link-icon .mud-icon-root,
.mud-drawer--closed.mud-drawer-mini .mud-nav-link:hover .mud-nav-link-icon.mud-icon-root {
    color: var(--mud-palette-primary);
}

/* Le chevron des icônes à sous-menu passe aussi en bleu au survol, pour rester cohérent avec l'icône. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-group > .mud-nav-link:hover::after {
    border-left-color: var(--mud-palette-primary);
}

/* Atténuer l'effet de vague (ripple) du menu SANS masquer les éléments : la classe `.mud-ripple` est posée
   par MudBlazor sur le lien interactif LUI-MÊME (et non sur un calque enfant) — un `display:none` sur
   `.mud-ripple` masquerait donc tous les liens. On désactive proprement l'animation via la propriété dédiée. */
.ideale-drawer .mud-nav-link {
    --mud-ripple-opacity: 0;
    --mud-ripple-opacity-secondary: 0;
}

/* === Flyout (bulle de sous-menu) en mode replié ====================================================
   MudBlazor n'a pas de flyout au survol : on le construit en CSS, UNIQUEMENT au survol (on ne touche PAS
   l'état par défaut → impossible de vider la sidebar). Au survol d'une icône de groupe, son sous-menu
   sort en bulle flottante à droite, avec ses libellés, sans redéployer la sidebar. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-group {
    position: relative;
}

/* En mode replié et HORS survol : on REPLIE de force le conteneur de sous-entrées de CHAQUE groupe (même le
   groupe actif, déplié par défaut) → les sous-entrées ne « fuient » pas dans le rail, les icônes restent
   contiguës et parfaitement alignées. !important pour battre le style inline `grid-template-rows:1fr`
   posé par MudBlazor sur un groupe déplié. Le survol (règle ci-dessous, plus spécifique) rouvre en bulle.

   CORRECTION DU CLIGNOTEMENT (point clé) : on COUPE la transition `grid-template-rows` du collapse en mode
   replié. Sans ça, l'ouverture CSS au survol déclenche un `transitionend` que le JS de MudCollapse intercepte
   pour réconcilier ses classes selon l'état `Expanded` (faux pour un groupe non déplié) → il ré-applique
   `mud-collapse-hidden`, qui entre en conflit avec notre affichage de bulle → la bulle vibre/clignote. En
   supprimant la transition, aucun `transitionend` n'est émis : la bulle apparaît/disparaît instantanément et
   reste STABLE. L'accordéon animé ne joue donc plus du tout en mode replié (il reste normal en déployé). */
.mud-drawer--closed.mud-drawer-mini .mud-nav-group > .mud-collapse-container,
.mud-drawer--closed.mud-drawer-mini .mud-nav-group > .mud-collapse-container .mud-collapse-wrapper {
    grid-template-rows: 0 !important;
    /* AUCUNE animation d'apparition : on coupe la transition ET toute animation du collapse en mode replié
       (conteneur + wrapper interne). La bulle apparaît/disparaît NETTEMENT, sans scale/zoom/contraction. Cela
       évite aussi le `transitionend` qui faisait clignoter la bulle (cf. correction du prompt précédent). */
    transition: none !important;
    animation: none !important;
}

/* STABILITÉ DES ICÔNES AU SURVOL (recette interface 24/06/2026) : le conteneur de sous-entrées est sorti du
   FLUX en PERMANENCE (position absolue + masqué hors survol), et plus seulement au survol. Sans ça, l'ouverture
   d'un flyout faisait passer ce conteneur de « en flux » à « absolu » → les icônes voisines, encore en flux, se
   décalaient légèrement (petit saut vertical au passage d'une icône à l'autre). Désormais il ne réserve JAMAIS
   d'espace : zéro décalage. La règle de survol ci-dessous ne fait que le RÉVÉLER (visibility) — la position est
   déjà posée ici. visibility:hidden suffit à le rendre non cliquable et invisible hors survol. */
.mud-drawer--closed.mud-drawer-mini .mud-nav-group > .mud-collapse-container {
    position: absolute;
    inset-inline-start: 100%;
    top: 0;
    visibility: hidden;
}

.mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container {
    grid-template-rows: 1fr !important;
    /* Les groupes NON dépliés portent la classe MudBlazor `.mud-collapse-hidden` (visibility:hidden) → sans
       ça, leur bulle resterait invisible au survol. On rétablit la visibilité pour TOUS les groupes. */
    visibility: visible !important;
    position: absolute;
    inset-inline-start: 100%;
    top: 0;
    min-width: 220px;
    background-color: var(--mud-palette-surface);
    /* Bulle NEUTRE : pas de liseré/bordure ; seule une ombre douce la détache du fond (clair comme sombre). */
    border: none;
    border-radius: var(--r);
    box-shadow: var(--sh-lg);
    z-index: 1300;
}

    /* Dans le flyout : conteneur interne non rogné. */
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-collapse-wrapper {
        overflow: visible;
    }

    /* Dans le flyout : sous-items en PLEINE LARGEUR (on annule le carré 32×32 du rail), alignés à gauche,
       libellés réaffichés. Espacement vertical RÉDUIT (liste compacte) : padding vertical 3 px, marge nulle. */
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link {
        justify-content: flex-start;
        width: auto;
        height: auto;
        padding: 3px 16px 3px 14px;
        margin: 0;
        min-height: 0;
        transition: color 150ms ease;
    }

    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link-text {
        display: inline !important;
    }

    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link .mud-nav-link-icon {
        margin-right: 10px;
    }

    /* Dans la bulle : AUCUN fond/surbrillance gris — ni au repos, ni au survol, ni sur l'entrée active. On
       neutralise tout fond (la règle générale de survol et le fond d'actif de MudBlazor) avec !important. */
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link,
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link:hover,
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link.active {
        background-color: transparent !important;
    }

    /* Seul marqueur d'état dans la bulle = le TEXTE en BLEU (accent), au survol ET sur l'entrée active. */
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link:hover,
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link:hover .mud-nav-link-text,
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link.active,
    .mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .mud-nav-link.active .mud-nav-link-text {
        color: var(--mud-palette-primary) !important;
    }

/* Titre du groupe en tête de la bulle (flyout). Masqué partout par défaut (en mode déployé, l'en-tête du
   groupe porte déjà le libellé → pas de doublon), affiché UNIQUEMENT en tête de la bulle au survol en replié :
   gras, séparé des sous-entrées par un filet. */
.ideale-flyout-titre {
    display: none;
}

.mud-drawer--closed.mud-drawer-mini .mud-nav-group:hover > .mud-collapse-container .ideale-flyout-titre {
    display: block;
    /* Titre de bulle PLUS PETIT et discret, cohérent avec les titres de section (11 px / 600). */
    padding: 6px 16px 5px 14px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    border-bottom: 1px solid var(--mud-palette-divider);
    margin-bottom: 3px;
}

/* Anneau de focus visible et contrasté (accessibilité AA) pour les éléments interactifs au
   clavier : on s'appuie sur l'accent du thème courant (clair comme sombre). */
.mud-button-root:focus-visible,
.mud-icon-button:focus-visible,
.mud-nav-link:focus-visible,
a:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* === Compte à rebours de déconnexion (recette interface 24/06/2026) ================================
   Barre de progression « qui se vide » (de 100 % à 0 %) avec le compteur (10 → 0) centré À L'INTÉRIEUR.
   On donne assez de hauteur à la barre pour loger le chiffre, et un halo léger au texte pour qu'il reste
   lisible aussi bien sur la portion remplie (bleu) que sur la portion vide (piste claire/sombre). */
.ideale-deconnexion-rebours.mud-progress-linear {
    height: 24px;
    border-radius: var(--r-sm);
}

.ideale-deconnexion-compteur {
    font-weight: 700;
    color: var(--mud-palette-text-primary);
    /* Halo = couleur de surface (blanc en clair, sombre en mode sombre) → contraste sur les deux fonds. */
    text-shadow: 0 0 2px var(--mud-palette-surface), 0 0 2px var(--mud-palette-surface);
}

/* === Bulles d'aide (tooltips) — réglage TRANSVERSE (prompts 58 & 59) ===============================
   La bulle MudBlazor est le POPOVER lui-même : div `.mud-popover.mud-tooltip` (avec `d-flex`), dans lequel le
   texte est injecté à l'ouverture. C'est CET élément qui doit plafonner sa largeur et autoriser le retour à la
   ligne. On cible donc `.mud-popover.mud-tooltip` (spécificité supérieure à `.mud-tooltip` seul et au `d-flex`
   utilitaire), on force `display:block` (évite toute ambiguïté de calcul de largeur du conteneur flex à un seul
   item), `white-space:normal !important` (annule tout `nowrap` hérité), et la coupure des mots. Mesuré : un
   texte d'aide long s'affiche sur plusieurs lignes dans une bulle ≤ 300 px. Transverse (toutes les bulles). */
.mud-popover.mud-tooltip {
    display: block !important;
    max-width: 300px;
    white-space: normal !important;
    overflow-wrap: anywhere;
    word-break: break-word;
    text-align: center;
    line-height: 1.4;
    height: auto !important;
}

/* Sécurité : si une bulle héberge un contenu enfant (ChildContent au lieu de Text), il wrappe aussi. */
.mud-popover.mud-tooltip > * {
    white-space: normal !important;
    max-width: 100%;
}

/* === Toasts (snackbars) — placement GLOBAL (prompt 58) ============================================
   Configurés « top-center » côté code (Program.cs). On les décale sous la barre du haut (54 px) pour
   qu'ils apparaissent CENTRÉS, juste sous la barre, dans la zone de contenu (clair comme sombre). */
.mud-snackbar-location-top-center {
    top: 66px;
}

/* === Zone basse FIXE : dock chatbot AU-DESSUS du pied de page copyright (prompts 96 & 97) ==========
   Conteneur fixe en bas, pleine largeur, empilant le DOCK puis le COPYRIGHT (dernière ligne tout en bas).
   Le dock s'ouvre VERS LE HAUT (sa hauteur croît) ; le copyright, dernier enfant, reste collé en bas et ne
   bouge pas. z-index sous les dialogues/popovers MudBlazor mais au-dessus du contenu. */
.ideale-bas-fixe {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1300;
    display: flex;
    flex-direction: column;
}

/* Dock chatbot : bloc pleine largeur DANS le conteneur fixe (donc plus position:fixed lui-même). */
.ideale-chatbot-dock {
    display: flex;
    flex-direction: column;
    background-color: var(--mud-palette-surface);
    border-top: 1px solid var(--mud-palette-divider);
    box-shadow: var(--sh-lg);
}

.ideale-chatbot-dock--reduit {
    height: 44px;
}

.ideale-chatbot-dock--ouvert {
    height: min(60vh, 640px);
}

/* Barre d'en-tête UNIQUE et cliquable (TOGGLE ouvrir/fermer — prompt 97) : pleine largeur, ~44 px, curseur
   main, léger survol cohérent avec la sidebar. Div natif (pas de .mud-ripple). Anneau de focus au clavier. */
.ideale-chatbot-barre {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    height: 44px;
    padding: 0 8px 0 16px;
    cursor: pointer;
    color: var(--mud-palette-text-primary);
    user-select: none;
}

.ideale-chatbot-barre:hover {
    background-color: var(--ideale-nav-hover);
}

.ideale-chatbot-barre:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.ideale-chatbot-barre-texte {
    font-weight: 600;
}

.ideale-chatbot-barre-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-left: auto;
}

.ideale-chatbot-chevron {
    color: var(--mud-palette-text-secondary);
}

/* Corps (panneau de conversation) : occupe tout l'espace restant du dock ouvert ; le panneau réutilisé
   (AssistantIaPanneau, classe .ideale-ia-panneau) prend toute la largeur. */
.ideale-chatbot-corps {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
}

    .ideale-chatbot-corps > .ideale-ia-panneau {
        width: 100%;
    }

/* Pied de page (copyright) DANS la zone basse fixe : DERNIÈRE LIGNE, fond opaque (couvre le contenu qui
   défile dessous) et fin filet de séparation. Padding vertical discret. */
.ideale-bas-pied {
    background-color: var(--mud-palette-background);
    border-top: 1px solid var(--mud-palette-divider);
    padding: 2px 0;
}

/* On réserve l'espace bas du contenu pour ne pas le masquer sous la zone fixe (UNIQUEMENT le layout qui la
   porte, via :has → n'affecte pas les autres layouts). Deux cas : pied SEUL (IA désactivée) vs dock + pied
   (la règle plus bas, même spécificité, l'emporte par l'ordre source quand le dock est présent). Quand le
   dock est OUVERT, il recouvre volontairement le bas (conversation au premier plan). */
.mud-layout:has(.ideale-bas-fixe) .mud-main-content {
    padding-bottom: 44px;
}

.mud-layout:has(.ideale-chatbot-dock) .mud-main-content {
    padding-bottom: 88px;
}

/* CORRECTIF « grand vide en haut » (prompt 70) : dans la colonne flex du panneau, MudDivider porte
   « flex: 1 0 auto » (utile pour un divider horizontal en LIGNE) — en COLONNE il grandit verticalement
   (~80px) et vole l'espace de la conversation. On le fige à sa hauteur intrinsèque (1px). */
.ideale-ia-panneau > .mud-divider {
    flex: 0 0 auto;
}

/* Conversation VIDE : on centre verticalement le message d'accueil + les suggestions (plutôt qu'un texte
   collé en haut surmontant un grand vide). Dès qu'un message arrive, la classe disparaît (alignement haut). */
.ideale-ia-panneau .ideale-ia-accueil {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.ideale-ia-panneau {
    /* Plus d'ascenseur horizontal PROPRE au panneau IA (prompt 79) : on clippe tout débordement latéral
       résiduel (tout passe à la ligne). Conservé dans le dock pleine largeur. */
    overflow-x: hidden;
}

/* Cause racine de l'overflow flex : un enfant flex (ex. le champ de saisie « Votre question… ») ne peut pas
   rétrécir sous sa largeur de contenu sans min-width:0 → il poussait le panneau au-delà de sa largeur. On
   autorise la réduction des éléments extensibles et on borne le champ de saisie à la largeur du panneau. */
.ideale-ia-panneau .flex-grow-1 {
    min-width: 0;
}

.ideale-ia-panneau .mud-input-control {
    max-width: 100%;
}

/* Messages : les mots/URL longs passent à la ligne (jamais de débordement horizontal de la bulle). */
.ideale-ia-panneau .mud-paper {
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* Champ « masqué » (clé API, prompt 79) : on n'utilise PAS type=password (qui déclenche la proposition de
   login/mot de passe enregistré du navigateur). Le champ reste un type=text, mais sa saisie est masquée
   visuellement par -webkit-text-security (puces) — la valeur n'est donc jamais lisible à l'écran. */
.ideale-champ-masque input {
    -webkit-text-security: disc;
    text-security: disc;
}

/* Dictée vocale (prompt 73) : pulsation discrète du bouton/icône pendant l'écoute, pour un repère visuel
   clair que le micro est actif. N'affecte que l'élément en écoute (pas les liens → jamais via .mud-ripple). */
/* Pulsation en OPACITÉ uniquement (pas de transform) : la boîte de l'élément ne bouge pas → le bouton micro
   reste « stable » et cliquable (sinon une animation de mise à l'échelle bloquerait clics et tests Playwright). */
@keyframes ideale-dictee-pulse {
    0% { opacity: 1; }
    50% { opacity: 0.5; }
    100% { opacity: 1; }
}

.ideale-dictee-active {
    animation: ideale-dictee-pulse 1.1s ease-in-out infinite;
}

/* ====================================================================================================
   AIDE CONTEXTUELLE DE PAGE (prompt 108) — icône d'aide en en-tête → popover (aide statique + « Demander à
   l'IA »). Largeur bornée + défilement interne ; 100 % thématisé (clair/sombre via variables MudBlazor).
   ==================================================================================================== */
.ideale-aidepage {
    display: inline-flex;
    align-items: center;
}

/* Carte du panneau d'aide : largeur lisible bornée, hauteur plafonnée avec ascenseur interne (réponses IA longues). */
.ideale-aidepage-carte {
    width: min(92vw, 380px);
    max-height: min(70vh, 560px);
    overflow-y: auto;
    overflow-x: hidden;
}

/* Les mots/URL longs de la réponse IA passent à la ligne (jamais de débordement horizontal). */
.ideale-aidepage-reponse {
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* ====================================================================================================
   ORBE VOCAL — REFONTE VISUELLE haut de gamme (prompt 105-bis) : sphère de PLASMA bleue à cœur étoilé.
   Couches superposées (halo + sphère/filaments + flare + cœur) en SVG ; filaments organiques via un filtre
   feTurbulence+feDisplacementMap (dans le composant) ; animations CSS fluides. 4 états : repos / écoute /
   réflexion / parole. « isolation: isolate » confine les fusions « screen » → rendu identique clair/sombre.
   ==================================================================================================== */

/* Conteneur : remplit la boîte du parent (déclencheur ~60px, scène ~min(60vw,280px)). */
.ideale-orbe {
    display: block;
    width: 100%;
    height: 100%;
    line-height: 0;
    isolation: isolate; /* les fusions screen ne débordent pas sur la page (clair comme sombre) */
}

.ideale-orbe-svg {
    width: 100%;
    height: 100%;
    overflow: visible; /* le halo et les rais de lumière débordent volontairement de la viewBox */
}

/* Centrage des transformations animées sur le centre de chaque élément SVG. */
.ideale-orbe-halo,
.ideale-orbe-filaments,
.ideale-orbe-flare,
.orbe-ray,
.ideale-orbe-core,
.ideale-orbe-core-point {
    transform-box: fill-box;
    transform-origin: center;
}

/* Filaments : fusion lumineuse additive (screen) + rotation lente. Le filtre plasma (composant) les ondule. */
.ideale-orbe-filaments {
    mix-blend-mode: screen;
    animation: orbe-rotation 34s linear infinite;
}

/* Flare (rais de lumière) : fusion screen, rais fins. Rotation propre de chaque rai (croix + diagonales). */
.ideale-orbe-flare {
    mix-blend-mode: screen;
    animation: orbe-flare-repos 4.4s ease-in-out infinite;
}
.orbe-ray-h { transform: rotate(90deg); }
.orbe-ray-d1 { transform: rotate(45deg); }
.orbe-ray-d2 { transform: rotate(135deg); }

/* Cœur : bloom doux + pulsation lente. Le point central scintille légèrement. */
.ideale-orbe-core {
    filter: drop-shadow(0 0 8px #6cb6ff) drop-shadow(0 0 18px #2f8bff);
    animation: orbe-core-repos 3.6s ease-in-out infinite;
}
.ideale-orbe-core-point {
    filter: drop-shadow(0 0 5px #ffffff);
    animation: orbe-point-repos 3.6s ease-in-out infinite;
}

/* Halo : respiration douce. */
.ideale-orbe-halo {
    animation: orbe-halo-repos 4.6s ease-in-out infinite;
}

/* --- ÉTAT : ÉCOUTE — cœur vif et réactif, rais qui scintillent, filaments plus agités ------------- */
.ideale-orbe--ecoute .ideale-orbe-core { animation: orbe-core-ecoute 1.15s ease-in-out infinite; }
.ideale-orbe--ecoute .ideale-orbe-core-point { animation: orbe-point-actif 0.5s ease-in-out infinite; }
.ideale-orbe--ecoute .ideale-orbe-flare { animation: orbe-flare-ecoute 0.9s ease-in-out infinite; }
.ideale-orbe--ecoute .ideale-orbe-halo { animation: orbe-halo-actif 1.15s ease-in-out infinite; }
.ideale-orbe--ecoute .ideale-orbe-filaments { animation: orbe-rotation 16s linear infinite; }

/* --- ÉTAT : RÉFLEXION — filaments qui tournent / se réorganisent, cœur qui scintille --------------- */
.ideale-orbe--reflexion .ideale-orbe-filaments { animation: orbe-rotation 7s linear infinite; }
.ideale-orbe--reflexion .ideale-orbe-core { animation: orbe-core-reflexion 1.5s ease-in-out infinite; }
.ideale-orbe--reflexion .ideale-orbe-flare { animation: orbe-flare-reflexion 2.2s linear infinite; }
.ideale-orbe--reflexion .ideale-orbe-halo { animation: orbe-halo-repos 2.4s ease-in-out infinite; }

/* --- ÉTAT : PAROLE — le cœur pulse en rythme, les rais battent (signal onboundary côté logique) ---- */
.ideale-orbe--parole .ideale-orbe-core { animation: orbe-core-parole 0.62s ease-in-out infinite; }
.ideale-orbe--parole .ideale-orbe-core-point { animation: orbe-point-actif 0.31s ease-in-out infinite; }
.ideale-orbe--parole .ideale-orbe-flare { animation: orbe-flare-parole 0.62s ease-in-out infinite; }
.ideale-orbe--parole .ideale-orbe-halo { animation: orbe-halo-actif 0.62s ease-in-out infinite; }
.ideale-orbe--parole .ideale-orbe-filaments { animation: orbe-rotation 12s linear infinite; }

/* Keyframes — rotation des filaments, respiration du halo, battement du flare, pulsation du cœur. */
@keyframes orbe-rotation { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

@keyframes orbe-halo-repos { 0%,100% { opacity: 0.72; transform: scale(1); } 50% { opacity: 0.95; transform: scale(1.04); } }
@keyframes orbe-halo-actif { 0%,100% { opacity: 0.85; transform: scale(1.02); } 50% { opacity: 1; transform: scale(1.1); } }

@keyframes orbe-core-repos { 0%,100% { transform: scale(1); opacity: 0.95; } 50% { transform: scale(1.07); opacity: 1; } }
@keyframes orbe-core-ecoute { 0%,100% { transform: scale(0.94); opacity: 0.9; } 50% { transform: scale(1.2); opacity: 1; } }
@keyframes orbe-core-reflexion { 0%,100% { transform: scale(1); opacity: 0.8; } 25% { transform: scale(1.08); opacity: 1; } 50% { transform: scale(0.96); opacity: 0.85; } 75% { transform: scale(1.05); opacity: 1; } }
@keyframes orbe-core-parole { 0% { transform: scale(1); } 35% { transform: scale(1.22); } 65% { transform: scale(0.97); } 100% { transform: scale(1); } }

@keyframes orbe-point-repos { 0%,100% { opacity: 0.9; } 50% { opacity: 1; } }
@keyframes orbe-point-actif { 0%,100% { opacity: 0.7; } 50% { opacity: 1; } }

@keyframes orbe-flare-repos { 0%,100% { transform: scale(0.92); opacity: 0.7; } 50% { transform: scale(1.02); opacity: 0.92; } }
@keyframes orbe-flare-ecoute { 0%,100% { transform: scale(0.9) rotate(0deg); opacity: 0.7; } 50% { transform: scale(1.12) rotate(3deg); opacity: 1; } }
@keyframes orbe-flare-reflexion { from { transform: scale(0.96) rotate(0deg); opacity: 0.8; } to { transform: scale(0.96) rotate(360deg); opacity: 0.8; } }
@keyframes orbe-flare-parole { 0% { transform: scale(0.95); opacity: 0.75; } 40% { transform: scale(1.18); opacity: 1; } 100% { transform: scale(0.95); opacity: 0.75; } }

/* Accessibilité : version apaisée si l'utilisateur réduit les animations (on garde une respiration très douce). */
@media (prefers-reduced-motion: reduce) {
    .ideale-orbe-halo, .ideale-orbe-filaments, .ideale-orbe-flare,
    .ideale-orbe-core, .ideale-orbe-core-point {
        animation-duration: 8s !important;
        animation-timing-function: ease-in-out !important;
    }
    .ideale-orbe--reflexion .ideale-orbe-flare { animation: none !important; }
}

/* --- DÉCLENCHEUR : bouton flottant rond (bas-droite, au-dessus de la barre du dock, sans la masquer) --- */
.ideale-orbe-declencheur {
    position: fixed;
    right: 22px;
    bottom: 58px; /* au-dessus de la barre du dock (44px) + marge */
    width: 60px;
    height: 60px;
    padding: 5px;
    border: 1px solid rgba(120, 170, 255, 0.35);
    border-radius: var(--r-pill, 999px);
    /* « Puits » sombre (toujours, clair ET sombre) : le plasma bleu lumineux ressort dans les deux thèmes. */
    background: radial-gradient(circle at 50% 45%, #11244e 0%, #0a132b 70%, #060c1d 100%);
    box-shadow: var(--sh-lg), 0 0 14px rgba(47, 124, 255, 0.45);
    cursor: pointer;
    z-index: 1310;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.ideale-orbe-declencheur:hover {
    transform: scale(1.06);
    box-shadow: var(--sh-lg), 0 0 20px rgba(74, 150, 255, 0.7);
}
.ideale-orbe-declencheur:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.ideale-orbe-declencheur-mini {
    display: block;
    width: 100%;
    height: 100%;
}

/* --- OVERLAY « mode vocal » : plein écran, fond sombre à halo (toujours sombre, clair ET sombre) ------- */
.ideale-orbe-overlay {
    position: fixed;
    inset: 0;
    /* Sous le z-index des dialogues MudBlazor (1400) pour que le dialogue de confirmation d'action s'affiche
       AU-DESSUS du mode vocal ; au-dessus du dock (1300) et du déclencheur (1310). */
    z-index: 1390;
    display: flex;
    flex-direction: column;
    background:
        radial-gradient(circle at 50% 42%, rgba(47, 111, 237, 0.28), rgba(10, 16, 28, 0.94) 60%),
        rgba(8, 12, 22, 0.96);
    color: #eaf1ff;
    backdrop-filter: blur(6px);
}

.ideale-orbe-overlay-barre {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    color: #eaf1ff;
}

.ideale-orbe-overlay-titre { font-weight: 700; font-size: 1rem; }

.ideale-orbe-overlay-barre .mud-icon-button { color: #eaf1ff; }

.ideale-orbe-scene {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 16px 20px 32px;
    text-align: center;
}

/* Bouton invisible autour de l'orbe (geste central) : pas de fond/bordure, juste la zone cliquable. */
.ideale-orbe-zone {
    width: min(60vw, 260px);
    height: min(60vw, 260px);
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    border-radius: var(--r-pill, 999px);
}
.ideale-orbe-zone:disabled { cursor: default; }
.ideale-orbe-zone:focus-visible {
    outline: 2px solid var(--orbe-c1, #8fc0ff);
    outline-offset: 6px;
}

.ideale-orbe-etat { font-size: 1.05rem; font-weight: 600; color: #eaf1ff; }

.ideale-orbe-transcription {
    max-width: 640px;
    font-size: 1rem;
    color: #cfe0ff;
    opacity: 0.95;
}
.ideale-orbe-transcription-libelle { font-weight: 700; color: #9fbfff; }

.ideale-orbe-reponse {
    max-width: 640px;
    width: 100%;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(143, 192, 255, 0.35);
    border-radius: var(--r-lg, 16px);
    padding: 14px 16px;
    text-align: left;
}
.ideale-orbe-reponse-texte { white-space: pre-wrap; line-height: 1.5; color: #f1f6ff; }
.ideale-orbe-reponse-meta { font-size: 0.78rem; color: #9fbfff; }

.ideale-orbe-message {
    max-width: 640px;
    color: #ffd9a8;
    font-size: 0.9rem;
}

.ideale-orbe-controles {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
}
.ideale-orbe-indice { font-size: 0.78rem; color: #8aa0c8; }

/* Zone de l'indicateur IA à GAUCHE, juste à côté de la recherche (prompt 76) : un petit espace les sépare,
   et la zone ne se comprime pas. L'espace « auto » de la barre la sépare nettement du groupe avatar à droite. */
.ideale-ia-indicateur-zone {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    margin-left: 4px;
}

/* === Indicateur d'IA active dans la barre (prompt 72) ============================================
   Petite pastille cliquable : icône + modèle/fournisseur + repère de budget (jetons). Cohérente avec la
   barre (couleur héritée, survol BLEU sans fond gris, pas d'animation parasite), stable au redimensionnement. */
.ideale-ia-indicateur {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 10px;
    border-radius: var(--r-pill, 999px);
    cursor: pointer;
    color: inherit;
    white-space: nowrap;
    transition: color 0.15s ease;
}

/* Survol : l'icône et le texte passent en bleu primaire, SANS fond gris (cohérent burger/icônes de la barre). */
.ideale-ia-indicateur:hover {
    color: var(--mud-palette-primary);
}

.ideale-ia-indicateur-modele {
    font-size: 13px;
    font-weight: 600;
}

.ideale-ia-indicateur-budget {
    font-size: 12px;
    opacity: 0.75;
}

/* Badge d'origine de la config IA active (spécifique utilisateur vs globale héritée) : pastille discrète. */
.ideale-ia-indicateur-origine {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    padding: 1px 6px;
    border-radius: var(--r-pill, 999px);
    background: color-mix(in srgb, var(--mud-palette-primary) 16%, transparent);
    color: var(--mud-palette-primary);
}

/* Panneau de détail (popover) : largeur confortable et bornée. */
.ideale-ia-indicateur-detail {
    min-width: 280px;
    max-width: 340px;
}

/* Responsive : sur écran moyen on masque le budget compact ; sur petit écran, il ne reste que l'icône
   (le détail complet reste accessible au clic). */
@media (max-width: 960px) {
    .ideale-ia-indicateur-budget {
        display: none;
    }
}

@media (max-width: 740px) {
    .ideale-ia-indicateur-modele {
        display: none;
    }
}
/* ── Calendrier (espace personnel — menu avatar) ─────────────────────────────────────────────
   Grille mensuelle simple : 7 colonnes (lundi → dimanche). Le jour courant est mis en évidence,
   les jours des mois adjacents sont atténués. Thème clair/sombre via les variables MudBlazor. */
.ideale-calendrier-grille {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
}

.ideale-calendrier-entetes {
    margin-bottom: 4px;
}

.ideale-calendrier-entete {
    text-align: center;
    font-size: 12px;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    padding: 4px 0;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.ideale-calendrier-grille + .ideale-calendrier-grille {
    margin-top: 4px;
}

.ideale-calendrier-jour {
    min-height: 84px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--r-sm, 8px);
    padding: 6px;
    background: var(--mud-palette-surface);
}

.ideale-calendrier-numero {
    font-size: 13px;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.ideale-calendrier-hors-mois {
    background: transparent;
    opacity: 0.45;
}

.ideale-calendrier-aujourdhui {
    border-color: var(--mud-palette-primary);
    box-shadow: inset 0 0 0 1px var(--mud-palette-primary);
}

.ideale-calendrier-aujourdhui .ideale-calendrier-numero {
    color: var(--mud-palette-primary);
}

/* === Menu : entrée « grisée + cadenas » (prompts 126 locataire & 136 Exploitant) ===================== */
/* Visibilité à deux/trois niveaux : une entrée que l'on peut voir mais pas piloter (locataire : droit
   manquant ; Exploitant : aucun locataire courant) est rendue par un MudNavLink désactivé. On renforce
   l'affordance « non cliquable » : curseur interdit, opacité réduite et cadenas (icône principale) en couleur
   secondaire — clair ET sombre via les variables du thème. La règle cible « .ideale-drawer-nav » → s'applique
   au menu plateforme ET au menu locataire (qui porte aussi « .ideale-locataire-nav »). La distinction
   grisé/invisible reste gouvernée par les sources uniques NavigationPlateforme / NavigationLocataire. */
.ideale-drawer-nav .ideale-nav-verrou.mud-nav-link.mud-nav-link-disabled {
    cursor: not-allowed;
    opacity: 0.55;
}

.ideale-drawer-nav .ideale-nav-verrou.mud-nav-link.mud-nav-link-disabled .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* E-mail de l'utilisateur connecté dans la barre du shell locataire : discret, tronqué si trop long. */
.ideale-locataire-utilisateur {
    max-width: 220px;
    color: var(--mud-palette-text-secondary);
}

/* Le formulaire de déconnexion (POST natif) ne doit pas perturber l'alignement des icônes de la barre. */
.ideale-locataire-deconnexion-form {
    display: inline-flex;
    align-items: center;
    margin: 0;
}

/* === Landing humaine du locataire (prompt 127) : cartes par entité + responsables empilés ============ */
/* Carte d'entité : hauteur homogène dans la grille (les actions s'alignent en bas). */
.ideale-carte-entite {
    height: 100%;
    display: flex;
    flex-direction: column;
}

.ideale-carte-entite .mud-card-actions {
    margin-top: auto;
}

/* Carte « grisée » (vue mais non pilotée) : estompée et non interactive, cohérent avec la visibilité 3 états. */
.ideale-carte-grisee {
    opacity: 0.6;
}

/* Description tronquée à quelques lignes pour garder des cartes régulières. */
.ideale-carte-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Avatars de responsables EMPILÉS (chevauchement léger) ; le premier sans décalage. */
.ideale-resp-avatars {
    display: flex;
    align-items: center;
}

.ideale-resp-avatar {
    display: inline-flex;
    margin-left: -8px;
    border: 2px solid var(--mud-palette-surface);
    border-radius: 50%;
}

.ideale-resp-avatar:first-child {
    margin-left: 0;
}

/* Bloc nom/rôle du responsable principal : ne déborde pas la carte. */
.ideale-resp-principal {
    min-width: 0;
}

/* Mini-fiche (au survol d'un avatar) : alignée à gauche, lignes lisibles. */
.ideale-resp-fiche {
    text-align: left;
    line-height: 1.4;
}

/* === Sélecteur d'habillage (prompt 130) ============================================================= */
/* Nuancier : pastilles cliquables ; la pastille choisie est entourée. */
.ideale-habillage-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.ideale-swatch {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

.ideale-swatch:disabled {
    cursor: default;
}

.ideale-swatch-sel {
    border-color: var(--mud-palette-text-primary);
    transform: scale(1.12);
}

/* Color picker natif : taille raisonnable, coins arrondis. */
.ideale-color-input {
    width: 42px;
    height: 28px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--r-sm);
    background: transparent;
    cursor: pointer;
    padding: 0;
}

.ideale-degrade-slider {
    min-width: 220px;
}

/* Grille d'icônes (recherche) : enveloppe, hauteur bornée avec défilement. */
.ideale-habillage-icones {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    max-height: 96px;
    overflow-y: auto;
    border: 1px solid var(--mud-palette-divider);
    border-radius: var(--r-sm);
    padding: 4px;
}

/* Aperçu : tuile avec bandeau dégradé + corps. Surfaces CLAIRE et SOMBRE fixées (indépendantes du thème). */
.ideale-habillage-apercu {
    width: 150px;
    border-radius: var(--r);
    overflow: hidden;
    box-shadow: var(--sh-sm);
}

.ideale-apercu-clair {
    background: #ffffff;
    color: #1f2430;
}

.ideale-apercu-sombre {
    background: #171b24;
    color: #e6e9ef;
}

.ideale-apercu-bandeau {
    height: 46px;
    display: flex;
    align-items: center;
    padding: 0 12px;
}

.ideale-apercu-corps {
    padding: 8px 12px;
    display: flex;
    flex-direction: column;
}

.ideale-apercu-titre {
    font-weight: 600;
    font-size: 0.85rem;
    line-height: 1.2;
}

.ideale-apercu-soustitre {
    font-size: 0.72rem;
    opacity: 0.7;
}

.ideale-habillage-logo-apercu {
    height: 28px;
    width: auto;
    border-radius: 4px;
}

/* === Rendu de l'habillage PARTOUT (prompt 131) : bandeau réutilisable ================================ */
/* Bandeau au dégradé effectif de l'entité : texte/icône blancs (contraste garanti, fond saturé hors thème). */
.ideale-habillage-bandeau {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    color: #fff;
    border-radius: var(--r) var(--r) 0 0;
}

/* Variante compacte : en-tête de carte (plus fin que l'en-tête de page de détail). */
.ideale-habillage-bandeau-compact {
    padding: 10px 14px;
    gap: 10px;
}

/* Teinte « sourde » : entité vue mais non pilotée (grisée) — désaturée, reconnaissable sans être vive. */
.ideale-habillage-sourd {
    filter: saturate(0.35);
}

/* Média (logo ou icône) : pastille translucide pour détacher l'icône du dégradé. */
.ideale-habillage-bandeau-media {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: var(--r-sm);
    background: rgba(255, 255, 255, 0.18);
}

.ideale-habillage-bandeau-logo {
    max-width: 36px;
    max-height: 36px;
    border-radius: 4px;
}

/* Bloc texte : titre + sous-titre, tronqués pour ne pas déborder. */
.ideale-habillage-bandeau-texte {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

.ideale-habillage-bandeau-titre {
    font-weight: 700;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ideale-habillage-bandeau-soustitre {
    font-size: 0.78rem;
    opacity: 0.85;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Zone d'actions/badges ancrée à droite du bandeau. */
.ideale-habillage-bandeau-actions {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* === Tableau de bord coloré (prompt 132, H3) : cartes KPI à dégradés ================================= */
/* Carte KPI : fond dégradé (fourni en style inline, issu du design system), texte blanc, icône en filigrane.
   Le dégradé saturé garantit le contraste du texte en clair ET sombre (indépendant des surfaces du thème). */
.ideale-tuile-kpi {
    position: relative;
    overflow: hidden;
    height: 100%;
    min-height: 104px;
    padding: 16px 18px;
    border-radius: var(--r-lg);
    box-shadow: var(--sh);
    color: #fff;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* Variante cliquable (lien « voir ») : curseur main + léger lift au survol. */
.ideale-tuile-kpi-lien {
    cursor: pointer;
    transition: box-shadow .15s ease, transform .15s ease;
}

.ideale-tuile-kpi-lien:hover {
    box-shadow: var(--sh-lg);
    transform: translateY(-2px);
}

/* Icône décorative en filigrane (grande, translucide, ancrée en haut à droite). */
.ideale-tuile-kpi .ideale-kpi-filigrane {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 72px;
    height: 72px;
    font-size: 72px;
    opacity: 0.22;
    pointer-events: none;
}

/* Ligne haute : titre (+ éventuel badge démo). */
.ideale-kpi-haut {
    display: flex;
    align-items: center;
    gap: 8px;
    z-index: 1;
}

.ideale-kpi-titre {
    font-size: 0.82rem;
    font-weight: 600;
    opacity: 0.95;
}

/* Grand chiffre mis en avant. */
.ideale-kpi-valeur {
    font-size: 2rem;
    font-weight: 800;
    line-height: 1.1;
    z-index: 1;
}

.ideale-kpi-tendance {
    font-size: 0.76rem;
    opacity: 0.9;
    z-index: 1;
}

/* Invite « voir » (lien), ancrée en bas. */
.ideale-kpi-voir {
    margin-top: auto;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.78rem;
    font-weight: 600;
    opacity: 0.95;
    z-index: 1;
}

/* Carte de SOLUTION habillée sur le tableau de bord : bandeau (BandeauHabille) + corps cliquable. */
.ideale-carte-solution {
    height: 100%;
    cursor: pointer;
    transition: box-shadow .15s ease, transform .15s ease;
}

.ideale-carte-solution:hover {
    box-shadow: var(--sh-lg);
    transform: translateY(-2px);
}
