/*
 * Tokens DS — ce que la PaletteLight de MudBlazor ne couvre pas.
 * Source : Charte_Graphique_EXTRANETSDO.html (projet WebDev gelé).
 *
 * ⚠️ Aucune couleur en dur dans les composants : on passe par ces variables ou par
 * les tokens du thème (DsTheme.cs). C'est ce qui laisse le mode sombre ajoutable
 * en configuration plus tard — ne pas court-circuiter.
 */
:root {
    /* Accent orange : hors slots standard MudBlazor, d'où cette variable. */
    --ds-accent: #FF9900;

    /* Navy — décliné (--mud-palette-primary vaut le navy de base). */
    --ds-navy-deep: #002245;
    --ds-navy-menu: #1C497F;
    --ds-steel: #436891;
    --ds-link: #054173;

    /* Bandeau d'environnement (TEST/DEMO) — masqué en production. */
    --ds-bandeau-fond: var(--ds-accent);
    --ds-bandeau-texte: #002245;

    /*
     * Repères de PVP (écran Bons Plans / lignes de commande). Décodage des entiers
     * RGB WLangage (SDO Constantes.wl) : kCoulBlanc, kCoulVertCata, kCoulVertPvpE.
     * Le rouge « vente à perte » (kCoulRouge) n'était pas exposé en constante socle :
     * token défini ici, appliqué par la page quand le contrôle SRP le signale.
     */
    --ds-pvp-blanc: #FFFFFF;      /* kCoulBlanc  — origine « PVP » (marché / saisi) */
    --ds-pvp-vert-cata: #C0FFC0;  /* kCoulVertCata — PVP catalogue */

    /* En-cours planifiés (Page_CdeEncoursPlan) : fonds du legacy, RVB(255,204,0) pour un bloc
       (expédition / préparation / semaine), RVB(255,255,204) pour un groupe Famille > Support > Flux. */
    --ds-enc-bloc-fond: #FFCC00;
    --ds-enc-groupe-fond: #FFFFCC;
    --ds-pvp-vert-ens: #6FA877;   /* kCoulVertPvpE — PVP enseigne */
    --ds-pvp-perte: #F8C4C4;      /* vente à perte */
}

/*
 * Cellule PVP colorée selon l'origine du prix (badge + fond). Le fond est un repère
 * d'aide à la vente, non bloquant. Enveloppe le champ de saisie ou la valeur.
 */
.ds-pvp {
    display: inline-block;
    border-radius: 4px;
    padding: 0 .25rem;
}
/* PVP « libre » : pas de fond propre -> hérite de la ligne (fond normal ET survol). */
.ds-pvp-blanc { background: transparent; }
.ds-pvp-vert-cata { background: var(--ds-pvp-vert-cata); }
.ds-pvp-vert-ens { background: var(--ds-pvp-vert-ens); }
.ds-pvp-perte { background: var(--ds-pvp-perte); }

/*
 * Bons Plans — mise en page PLEINE HAUTEUR : la page occupe la zone disponible
 * (titre + filtres fixes en haut, récap en bas), et SEULE LA LISTE défile. Un seul
 * ascenseur, en-tête de colonnes figé. Repli gracieux : si la hauteur ne se borne
 * pas, la page défile normalement (en-tête non figé) — jamais deux ascenseurs.
 */
/* Sur Bons Plans UNIQUEMENT, le pied suit le contenu au lieu d'être épinglé en bas
   (le gabarit met le corps en flex-grow) : évite un grand vide quand la liste est
   courte. Scopé via :has(.ds-bp-plein), sans impact sur les autres pages. */
.mud-main-content:has(.ds-bp-plein) .mud-container.flex-grow-1 { flex-grow: 0; }

/* La liste (articles + récap) : dimensionnée au contenu, PLAFONNÉE — elle ne défile
   que si elle dépasse. ~17rem = barre bleue + titre + filtres + pied + marges. Ajustable. */
.ds-bp-liste-scroll {
    max-height: calc(100vh - 17rem);
    overflow: auto;
}
/* On neutralise le défilement interne de MudTable pour ne pas créer un 2ᵉ ascenseur :
   c'est .ds-bp-liste-scroll qui défile, et l'en-tête colle en haut de CE conteneur. */
.ds-bp-liste-scroll .mud-table-container { overflow: visible; }

/* Commande Nouveautés — mise en page pleine hauteur en FLEX : le corps remplit la
   fenêtre, SEULE la zone défilante scrolle. Robuste à tout retour à la ligne de la barre
   de filtres et à toute taille d'écran (aucune valeur en dur -> jamais 2 ascenseurs).
   Scopé par :has(.ds-cn-plein) -> n'affecte QUE cette page. */
.mud-main-content:has(.ds-cn-plein) { height: 100vh; overflow: hidden; }
.mud-main-content:has(.ds-cn-plein) .mud-container.flex-grow-1 {
    flex-grow: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.ds-cn-plein {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
#ds-cn-scroll {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;   /* annule le calc hérité de .ds-bp-liste-scroll */
    overflow: auto;
    scrollbar-gutter: stable;   /* réserve TOUJOURS la gouttière d'ascenseur */
}
/* Les zones HORS zone défilante (barre de filtres, réglette) sont insérées de la même
   largeur d'ascenseur -> même largeur utile que les tuiles, avec ou sans ascenseur. */
.ds-cn-hors-scroll { margin-right: var(--ds-sb, 0px); }
.ds-bp-liste-scroll thead th {
    position: sticky;
    top: 0;
    background: var(--mud-palette-surface);
    z-index: 2;
}

/* Commande Nouveautés — en-tête de FAMILLE : sépare visuellement les blocs de produits
   d'une même famille (non collant, pour ne pas entrer en conflit avec l'en-tête de
   colonnes de la vue liste, lui aussi épinglé en haut de la zone défilante). */
.ds-cn-fam {
    background: var(--mud-palette-surface);
    border-bottom: 2px solid var(--ds-accent);
    padding: .35rem .25rem;
    font-weight: 600;
}

/* Réservations de commande — entrée SÉLECTIONNÉE de la liste de gauche.
   Le legacy peignait le fond en RVB(181,203,240) (kCoulBleuEntListe) ; ici on passe par
   les tokens du thème, comme partout ailleurs (décision 020 §11 : aucune couleur en dur). */
.ds-rcde-selection {
    background: color-mix(in srgb, var(--ds-steel) 18%, transparent);
    border-inline-start: 3px solid var(--ds-accent);
    font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Réservations — COLONNE DE GAUCHE en « cartes-réponse » (patron A : BKB/OPE/CAT).

   Une carte répond à trois questions dans l'ordre où le client se les pose : de quoi
   s'agit-il (titre + éditeur), jusqu'à quand (MEV + J-n), où j'en suis (pastille de
   statut + case de refus). Le libellé est REPLACÉ par LibelleReservation, jamais
   réécrit — l'original reste en infobulle.

   ⚠️ Aucune couleur en dur : le filet de famille et les pastilles sont des déclinaisons
   des tokens de la charte (bleus DS, vert « valider », rouge « annuler »).
   --------------------------------------------------------------------------- */

/* Filets de famille — trois profondeurs du bleu DS + le gris des filets pour « Autres ».
   Repère SECONDAIRE : le nom de la famille reste écrit en tête de groupe. */
:root {
    --ds-rcde-fam-jv: var(--mud-palette-secondary);
    --ds-rcde-fam-vi: var(--ds-steel);
    --ds-rcde-fam-au: var(--ds-navy-menu);
    --ds-rcde-fam-autres: var(--mud-palette-lines-default);

    /* Hauteur de l'en-tête de famille et gouttière entre cartes : c'est le couple qui
       aligne le bandeau de détail sur la première carte. Ne pas figer l'un sans l'autre. */
    --ds-rcde-entete-h: 1.75rem;
    --ds-rcde-gouttiere: .5rem;
}

/* Corps de l'écran : la zone qui DÉFILE. La page étant en pleine hauteur (ds-cn-plein),
   sans cela le bas des deux colonnes serait purement inatteignable.
   - petit écran : les colonnes s'empilent, un SEUL ascenseur pour l'ensemble ;
   - grand écran : chaque colonne défile pour son compte, et l'en-tête de famille collant
     s'accroche en haut de la colonne de gauche. */
.ds-rcde-corps {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-wrap: wrap;
    gap: .75rem;
    align-items: stretch;
    overflow: auto;
    scrollbar-gutter: stable;
}
@media (min-width: 60rem) {
    .ds-rcde-corps { flex-wrap: nowrap; overflow: hidden; }
    .ds-rcde-corps > * {
        overflow-y: auto;
        max-height: 100%;
        scrollbar-gutter: stable;
    }
    /* La colonne défilante colle ses cartes à l'ascenseur : on écarte les deux.
       ⚠️ padding, pas margin — la gouttière d'ascenseur appartient au conteneur de
       défilement, une marge sur les cartes ne la franchirait pas. */
    .ds-rcde-corps > .ds-rcde-colonne { padding-right: .5rem; }
}

.ds-rcde-colonne {
    flex: 0 0 20rem;
    max-width: 22rem;
    min-width: 16rem;
    display: flex;
    flex-direction: column;
    gap: var(--ds-rcde-gouttiere);
}

/* Colonne de DÉTAIL. Son bandeau s'aligne sur la première CARTE de gauche (et non sur le
   haut de la colonne) : il descend de la hauteur de l'en-tête de famille, gouttière
   comprise. Les deux valeurs sont des variables — les changer d'un côté les change des deux.
   Sur petit écran les colonnes s'empilent : le décalage n'a plus de sens et disparaît. */
.ds-rcde-detail {
    flex: 1 1 40rem;
    min-width: 22rem;
}
@media (min-width: 60rem) {
    .ds-rcde-detail {
        padding-top: calc(var(--ds-rcde-entete-h) + var(--ds-rcde-gouttiere));
    }
}

/* En-tête de famille COLLANT : la colonne peut défiler sans qu'on perde le groupe.
   Fond opaque obligatoire — les cartes passent dessous. */
.ds-rcde-fam {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: baseline;
    gap: .5rem;
    background: var(--mud-palette-background);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    box-sizing: border-box;
    min-height: var(--ds-rcde-entete-h);
    padding: .4rem .15rem .3rem;
    margin-top: .25rem;
    text-transform: uppercase;
    letter-spacing: .09em;
    font-size: .72rem;
    font-weight: 700;
    color: var(--ds-link);
}
.ds-rcde-fam:first-child { margin-top: 0; }
.ds-rcde-fam-cpt {
    font-weight: 400;
    letter-spacing: 0;
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Arbre famille ▸ support de BKB : les en-têtes sont des BOUTONS (repli au clic et au
   clavier). Placé après .ds-rcde-fam, dont il neutralise l'habillage natif du bouton. */
.ds-rcde-noeud {
    width: 100%;
    align-items: center;
    justify-content: flex-start;   /* un bouton centre son contenu par défaut */
    text-align: start;
    font-family: inherit;
    border-width: 0 0 1px;
    border-style: solid;
    border-color: var(--mud-palette-lines-default);
    cursor: pointer;
}
.ds-rcde-noeud:hover { background: var(--mud-palette-action-default-hover); }
.ds-rcde-noeud:focus-visible { outline: 3px solid var(--ds-accent); outline-offset: -3px; }
.ds-rcde-chevron { flex: 0 0 auto; margin-inline-start: -.2rem; }

/* Sous-niveau « support » : ni collant (seule la famille s'accroche), ni en capitales
   espacées — il se lit comme une subdivision de la famille, pas comme un pair. */
.ds-rcde-sup {
    display: flex;
    gap: .4rem;
    background: transparent;
    padding: .3rem .15rem .25rem .6rem;
    font-size: .78rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    border-color: transparent;
}
.ds-rcde-branche {
    display: flex;
    flex-direction: column;
    gap: var(--ds-rcde-gouttiere);
    padding-inline-start: 1rem;
}

.ds-rcde-carte {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: .5rem .6rem .3rem;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-inline-start: 4px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    cursor: pointer;
}
.ds-rcde-carte:hover { background: var(--mud-palette-action-default-hover); }
.ds-rcde-carte:focus-visible { outline: 3px solid var(--ds-accent); outline-offset: 2px; }

.ds-rcde-carte-jv { border-inline-start-color: var(--ds-rcde-fam-jv); }
.ds-rcde-carte-vi { border-inline-start-color: var(--ds-rcde-fam-vi); }
.ds-rcde-carte-au { border-inline-start-color: var(--ds-rcde-fam-au); }
.ds-rcde-carte-autres { border-inline-start-color: var(--ds-rcde-fam-autres); }

/* Carte OUVERTE : le filet passe à l'accent DS, comme l'ancienne entrée sélectionnée. */
.ds-rcde-carte-active {
    border-inline-start-color: var(--ds-accent);
    background: color-mix(in srgb, var(--ds-steel) 12%, var(--mud-palette-surface));
}

/* Refusée : la carte s'éteint et le titre est barré — le refus est une RÉPONSE, il se
   voit, au lieu de ressembler à une réservation qu'on aurait oubliée. */
.ds-rcde-carte-refusee { opacity: .72; }
.ds-rcde-carte-refusee .ds-rcde-titre { text-decoration: line-through; }

/* Titre : deux lignes au plus, l'original en infobulle (title=""). */
.ds-rcde-titre {
    font-size: .875rem;
    font-weight: 500;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}

.ds-rcde-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .3rem .5rem;
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}
.ds-rcde-editeur {
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--ds-link);
}

/* Échéance : un badge, pas une mention grise. Rouge sous le seuil d'urgence. */
.ds-rcde-jours {
    padding: 0 .3rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 3px;
    font-weight: 500;
    white-space: nowrap;
}
.ds-rcde-jours-urgent {
    color: var(--mud-palette-error);
    border-color: transparent;
    background: color-mix(in srgb, var(--mud-palette-error) 14%, transparent);
    font-weight: 700;
}

/* Boutons d'action du bandeau (Imprimer en contour, Confirmer en plein) : même hauteur
   imposée, le style de chacun reste. Le bouton plein porte DropShadow="false" : son ombre
   portée le faisait paraître 1 à 2 px plus haut que le contour, à hauteur pourtant égale. */
.ds-rcde-action.mud-button-root {
    height: 36px;
    box-sizing: border-box;
}

/* En-tête des colonnes TOUJOURS VISIBLE quand les articles défilent (Cyril, 05/10/2026).
   Un élément collant s'accroche au conteneur défilant le plus proche : MudBlazor enveloppe le
   tableau dans .mud-table-container, qui a son propre débordement et ne défile jamais —
   on le lui retire, pour que l'en-tête s'accroche à la colonne de détail (qui, elle, défile).
   Fond plein : les lignes ne transparaissent pas dessous. Libellés d'en-tête non coupés
   (la colonne de bout, à 100 %, comprimait « PU brut » sur deux lignes). */
.ds-rcde-articles .mud-table-container { overflow: visible; }
.ds-rcde-articles thead th.mud-table-cell {
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--mud-palette-surface);
    white-space: nowrap;
}
/* Grand écran : la colonne de détail a une marge HAUTE (alignement sur la première carte, voir
   .ds-rcde-detail) et l'élément collant s'arrête SOUS elle — les lignes défilaient dans cette
   bande, au-dessus de l'en-tête. On le remonte d'autant, jusqu'au vrai bord. */
@media (min-width: 60rem) {
    .ds-rcde-detail .ds-rcde-articles thead th.mud-table-cell {
        top: calc(-1 * (var(--ds-rcde-entete-h) + var(--ds-rcde-gouttiere)));
    }
}

/* Liste des articles d'une réservation : un article = DEUX lignes de tableau, le titre
   (toute la largeur) puis les chiffres. Les deux doivent se lire comme UN bloc : pas de filet
   entre elles, et le survol éclaire les deux à la fois. */
.ds-rcde-articles .ds-rcde-art-titre > td.mud-table-cell {
    border-bottom: none;
    padding-bottom: 0;
}
/* Jaquette sur les DEUX lignes de l'article (rowspan), à gauche : elle garde la bordure du bas
   (celle de la ligne de titre est retirée juste au-dessus) et son espacement. */
.ds-rcde-articles .ds-rcde-art-titre > td.mud-table-cell.ds-rcde-art-jaq {
    border-bottom: 1px solid var(--mud-palette-table-lines);
    padding-bottom: 6px;
    width: 1%;
    vertical-align: middle;
}
/* Case carrée à la LARGEUR des petites jaquettes (75 px) : un CD la remplit, un DVD y tient en hauteur. */
.ds-jaq.ds-jaq-2lignes { height: 4.5rem; aspect-ratio: 1; }
/* Téléphone : le tableau s'empile en fiches, la jaquette passe au-dessus du titre, centrée.
   ⚠️ SOUS LA REQUÊTE MÉDIA de MudBlazor (9.7 : max-width 960px). La classe mud-sm-table est
   posée À TOUTE LARGEUR par Breakpoint.Sm ; sans la requête, ces règles valaient aussi sur
   grand écran — la case de la jaquette perdait sa largeur et son trait, et s'étalait. */
@media (max-width: 960px) {
    .ds-rcde-articles.mud-xs-table .ds-rcde-art-titre > td.mud-table-cell.ds-rcde-art-jaq,
    .ds-rcde-articles.mud-sm-table .ds-rcde-art-titre > td.mud-table-cell.ds-rcde-art-jaq {
        width: auto;
        border-bottom: none;
        justify-content: center;
        text-align: center;
    }
}
.ds-rcde-articles.mud-table-hover .ds-rcde-art-titre:hover + .ds-rcde-art-chiffres,
.ds-rcde-articles.mud-table-hover .ds-rcde-art-titre:has(+ .ds-rcde-art-chiffres:hover) {
    background-color: var(--mud-palette-table-hover);
}
/* Cases PVP / marge gardées VIDES hors BKB (même mise en page que BKB) : inutiles, et
   visibles comme deux lignes blanches, quand le tableau passe en fiches empilées.
   Même requête média que ci-dessus : hors d'elle, les masquer amputait la ligne de ses deux
   dernières cases (traits de séparation arrêtés avant le bord). */
@media (max-width: 960px) {
    .mud-xs-table .ds-rcde-vide,
    .mud-sm-table .ds-rcde-vide {
        display: none;
    }
}

/* Statut : trois états, et trois seulement. */
.ds-rcde-pastille {
    display: inline-flex;
    align-items: center;
    padding: 0 .45rem;
    border-radius: 999px;
    font-size: .7rem;
    font-weight: 600;
    letter-spacing: .03em;
    text-transform: uppercase;
    white-space: nowrap;
}
.ds-rcde-pastille-attente {
    background: color-mix(in srgb, var(--mud-palette-warning) 18%, transparent);
    color: var(--mud-palette-warning-darken);
}
.ds-rcde-pastille-repondu {
    background: color-mix(in srgb, var(--mud-palette-success) 18%, transparent);
    color: var(--mud-palette-success-darken);
}
.ds-rcde-pastille-refus {
    background: color-mix(in srgb, var(--mud-palette-error) 16%, transparent);
    color: var(--mud-palette-error-darken);
}
.ds-rcde-pastille-neutre {
    background: color-mix(in srgb, var(--ds-steel) 14%, transparent);
    color: var(--mud-palette-text-secondary);
}

/* Case « je ne veux pas », en pied de carte : séparée par un filet pointillé pour qu'on
   ne la coche pas en visant le titre. Le libellé du profil est long -> il s'enroule. */
.ds-rcde-refus {
    border-top: 1px dashed var(--mud-palette-lines-default);
    padding-top: .15rem;
    margin-top: .05rem;
}
.ds-rcde-refus .mud-checkbox { margin-left: -.35rem; }
.ds-rcde-refus .mud-button-root.mud-icon-button { padding: .25rem; }
.ds-rcde-refus .mud-typography {
    font-size: .72rem;
    line-height: 1.25;
    color: var(--mud-palette-text-secondary);
}
.ds-rcde-carte-refusee .ds-rcde-refus .mud-typography {
    color: var(--mud-palette-error);
    font-weight: 500;
}

/* Vue TUILES : grille de cartes responsive (vue par défaut, façon legacy). */
.ds-bp-tuiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    grid-auto-rows: 1fr;      /* toutes les lignes à la même hauteur */
    gap: .75rem;
    align-items: stretch;
}
.ds-bp-tuile { cursor: pointer; height: 100%; position: relative; }   /* remplit sa cellule ; relative pour le glyphe en coin */
/* Catalogue de commande : la tuile n'est PAS cliquable (seul le glyphe loupe l'est). */
.ds-cn-plein .ds-bp-tuile { cursor: default; }
/* Panier de commande : même grille, tuile non cliquable (seuls la quantité et le retrait le sont). */
.ds-panier-tuiles .ds-bp-tuile { cursor: default; }
/* Glyphe « fiche produit » : loupe blanche sur fond rouge, plein coin haut-droit. */
.ds-cat-fiche {
    position: absolute;
    top: 0;
    right: 0;
    width: 2.25rem;
    height: 2.25rem;
    background: var(--mud-palette-error);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border-top-right-radius: inherit;   /* épouse le coin arrondi de la tuile */
    border-bottom-left-radius: .6rem;
}
.ds-cat-fiche:hover { filter: brightness(1.12); }
.ds-cat-fiche .mud-icon-root { color: #fff; }
/* Valeur de remise mise en avant (accent DS orange). */
.ds-remise { color: var(--ds-accent); }
/* Saisie de la quantité : en avant (gras + accent DS orange). !important pour
   battre la couleur/graisse par défaut de l'input MudBlazor. */
.ds-qte input { font-weight: 700 !important; color: var(--ds-accent) !important; }

/* Écran Import — contrôle (CdeUploadValid).
   1) Colonnes ALIGNÉES entre les tableaux par famille : table-layout fixe (les largeurs des
      <th> font foi, identiques d'un tableau à l'autre).
   2) Champs Quantité / PVP collés à DROITE : le champ MudBlazor est un bloc large=100 % que ni
      text-align ni flex ne déplacent -> margin-left:auto le pousse à droite ; text-align:right
      cadre la valeur dans le champ. */
.ds-cde-table .mud-table-root { table-layout: fixed; }
.ds-num-droite.mud-input-control { margin-left: auto; }
.ds-num-droite input { text-align: right; }
/* Libellé produit : toujours sur une ligne, tronqué avec « … » si trop long. */
/* Titre d'une tuile : il s'affiche EN ENTIER, sur autant de lignes qu'il faut (29/09/2026).
   Il était coupé par des points de suspension — or le titre complet d'un article fait jusqu'à
   64 caractères. Deux lignes réservées : les tuiles d'un même rang restent alignées dans le
   cas courant ; la grille égalise les hauteurs dans les autres. */
.ds-bp-titre {
    white-space: normal;
    overflow-wrap: anywhere;
    max-width: 100%;
    min-height: calc(2 * 1.57em);
}

/*
 * Bons Plans — seules les DONNÉES MODIFIABLES sont sélectionnables : la liste entière
 * est non-sélectionnable, on ré-autorise la sélection dans les seuls champs de saisie.
 */
.ds-liste-bp { user-select: none; }
/* Champs de saisie : sélectionnables, alignés à droite, MÊME POLICE que la ligne. */
.ds-liste-bp input { user-select: text; text-align: right; font-size: inherit; }


/*
 * Titre de page dans la barre bleue (Lib_ChemiNav remonté dans l'AppBar).
 * Tronqué plutôt que de pousser la zone compte hors de la barre sur petit écran.
 */
.ds-titre-page {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Le séparateur est décoratif : atténué, et retiré de la vocalisation. */
.ds-titre-sep {
    opacity: .45;
    margin-inline-end: .25rem;
}

/*
 * Notifications (snackbar) CENTRÉES DANS L'ÉCRAN.
 * Par défaut MudBlazor les pose dans un coin ; les messages de contrôle de saisie y
 * passaient inaperçus alors qu'ils bloquent la progression de l'assistant.
 */
.ds-snackbar-centre {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .5rem;
    z-index: 2000;
    max-width: min(90vw, 480px);
}

/*
 * Le CHROME du gabarit (barre bleue, menu, pied de page) n'est pas du contenu :
 * un double-clic dans le vide ne doit pas venir le sélectionner.
 * ⚠️ Volontairement limité au chrome : les DONNÉES des pages (listes, champs,
 * n° de SAV) restent sélectionnables et copiables — c'est le geste de l'utilisateur
 * qui relève un numéro pour le coller ailleurs.
 */
.mud-appbar,
.mud-drawer,
.ds-pied {
    -webkit-user-select: none;
    user-select: none;
}

/* Anneau de focus accent (charte §10 « Focus »). */
.ds-focus-accent:focus-visible {
    outline: 3px solid var(--ds-accent);
    outline-offset: 2px;
}

/*
 * Bandeau d'environnement (Lib_Base : TEST / DEMO, + « (L) » si compte lecture seule).
 * Sur l'AppBar navy, il doit SAUTER AUX YEUX : il dit à l'utilisateur qu'il n'est pas
 * en production. Par défaut le chip MudBlazor sortait sombre sur sombre — illisible,
 * donc inutile. D'où l'accent.
 */
.ds-bandeau {
    background-color: var(--ds-bandeau-fond) !important;
    color: var(--ds-bandeau-texte) !important;
    font-weight: 700;
    letter-spacing: .04em;
}

/*
 * Entrée de menu ACTIVE dans le tiroir.
 *
 * Par défaut MudBlazor colore le lien actif en --mud-palette-primary : le navy DS
 * (#0D416B) sur le fond de tiroir navy foncé (#102D46). Résultat : l'entrée de la page
 * courante devenait la SEULE illisible du menu. On la passe à l'accent orange, qui est
 * précisément le rôle que la charte lui donne (§10, mise en évidence).
 */
.mud-drawer .mud-nav-link.active {
    color: var(--ds-accent) !important;
    background-color: rgba(255, 153, 0, .12);
    border-inline-start: 3px solid var(--ds-accent);
}

.mud-drawer .mud-nav-link.active .mud-icon-root {
    color: var(--ds-accent) !important;
}

/*
 * Le contenu du tiroir est un conteneur flex en colonne : un <hr> y hérite
 * « flex: 1 0 auto » et s'ÉTIRE — le séparateur sous la zone compte occupait 266 px
 * de vide, repoussant le menu en bas de l'écran sur mobile. Un séparateur ne pousse pas.
 */
.mud-drawer .mud-drawer-content > .mud-divider {
    flex: 0 0 auto;
}

/*
 * Texte secondaire DANS le tiroir (l'identifiant sous le code client).
 * --mud-palette-text-secondary vaut le bleu #054173, pensé pour du texte sur fond
 * clair : sur le navy du tiroir il devient illisible. On le rend au fond sombre.
 */
.mud-drawer .mud-text-secondary {
    color: rgba(255, 255, 255, .7) !important;
}

/*
 * Compte en lecture seule (gpbCptLect → Gr_Valider inactif, spec §5.5).
 * Traitement visuel DISTINCT de la rétrogradation Light des pages RCde (étage 4) :
 * la charte §10 insiste — l'utilisateur doit comprendre POURQUOI c'est bloqué.
 */
.ds-cpt-lecture {
    background: #FBFBFB;
    border: 1px dashed var(--mud-palette-lines-default);
}

/*
 * Aide de saisie DISCRÈTE (Page_MonCompte champ Courriel, Page_MotDePasse règle de
 * complexité). Deux corrections au rendu par défaut :
 *
 *  • TAILLE — « Plusieurs adresses possibles, séparées par « ; ». » passe à la ligne
 *    dès que le champ se rétrécit, et une aide sur deux lignes décale tout ce qui la
 *    suit à chaque redimensionnement.
 *  • COULEUR — MudBlazor colore l'aide en --mud-palette-text-secondary, qui vaut ici
 *    le BLEU de la charte (#054173) : une aide facultative s'y affiche aussi
 *    fortement qu'une valeur saisie. Un gris clair la remet à son rang.
 *
 * Elle est secondaire : elle ne dispute la place ni au libellé ni à la valeur.
 */
.ds-aide-compacte .mud-input-helper-text {
    font-size: .7rem;
    line-height: 1.3;
    color: #8A8A8A;
}

/* Dialogue Conditionnements (RCde, lot E) — matrice articles × colis.
   1) Le tableau prend la largeur de son contenu (pas 100 %) : le dialogue est ouvert « au
      contenu », 2 à 5 colonnes ne doivent pas s'étirer sur tout l'écran.
   2) Colonnes de quantité à LARGEUR FIXE et centrées : en-tête, pièces par article, total et
      champ de saisie tombent ainsi sur le même axe.
   3) Le champ MudBlazor est un bloc : margin auto le centre, text-align centre la valeur. */
.ds-cdt-matrice .mud-table-root { width: auto; }
.ds-cdt-article { min-width: 18rem; max-width: 32rem; }
.ds-cdt-qte { width: 6.5rem; min-width: 6.5rem; text-align: center !important; white-space: nowrap; }
.ds-cdt-qte .mud-input-control { width: 5rem; }
.ds-num-centre.mud-input-control { margin-left: auto; margin-right: auto; }
.ds-num-centre input { text-align: center; }
.ds-cdt-colis { font-size: .7rem; font-weight: 400; text-transform: uppercase; letter-spacing: .04em; opacity: .7; }
.ds-cdt-explication { max-width: 32rem; }
/* Bloc d'aide « Comment ça marche ? » des écrans RCde. */
.ds-rcde-aide { margin: .25rem 0 0 1.1rem; padding: 0; max-width: 60rem; }
.ds-rcde-aide li { margin: .3rem 0; }
.ds-rcde-aide ul { margin: .2rem 0 0 1.1rem; padding: 0; }

/* Choix du client (décision 028, demande de Cyril du 30/09/2026) : la liste occupe la hauteur
   de la FENÊTRE, ses lignes défilent à l'intérieur (en-tête de colonnes fixe), la pagination
   reste en bas. Même mécanique que ds-cn-plein, scopée par :has(.ds-choix-plein). */
.mud-main-content:has(.ds-choix-plein) { height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
.ds-choix-plein { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ds-choix-plein .ds-choix-table { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ds-choix-plein .ds-choix-table .mud-table-container { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* Documents en cours (décision 029) : dans une page pleine hauteur (ds-cn-plein), le tableau prend
   la place restante et ses lignes défilent sous un en-tête fixe ; la pagination reste en bas. */
.ds-cn-plein .ds-table-pleine { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ds-cn-plein .ds-table-pleine .mud-table-container { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* Jaquettes article (composant Jaquette). Taille par défaut = petite jaquette à sa taille
   d'origine (75 x 116) ; ds-jaq-tuile l'élargit dans les tuiles ; ds-jaq-liste la réduit dans une ligne de tableau ;
   ds-jaq-grande pour la fiche produit. Le visuel de remplacement prend la même place, pour
   que les tuiles gardent toutes la même hauteur. */
.ds-jaq { display: inline-flex; align-items: center; justify-content: center; flex: none; height: 7.25rem; aspect-ratio: 75 / 116; }
.ds-jaq img { width: 100%; height: 100%; object-fit: contain; display: block; }
.ds-jaq .ds-jaq-repli { width: 70%; height: 70%; color: var(--mud-palette-text-disabled); }
.ds-jaq-liste { height: 3rem; }
/* Tuile : MÊME hauteur que la petite jaquette (la tuile ne grandit pas), mais toute la largeur
   de la tuile. Les petites font toutes 75 px de LARGE (75x75 un CD, 75x94 un Blu-ray) : dans
   une case taillée pour 75x116, un CD n'occupait que 75x75. On prend la GRANDE (425 de large),
   pour qu'une pochette carrée remplisse les 116 px sans flou. */
.ds-jaq.ds-jaq-tuile { aspect-ratio: auto; width: 100%; height: var(--ds-jaq-tuile-h, 7.25rem); }
/* Tuile compacte (Cyril, 30/09/2026) : lignes resserrées, chiffres POUSSÉS EN BAS (mt-auto dans
   une colonne flexible), et la place gagnée rendue à la jaquette — la tuile garde sa taille. */
.ds-bp-tuile.ds-tuile-jaq { display: flex; flex-direction: column; --ds-jaq-tuile-h: 9.25rem; }
.ds-jaq.ds-jaq-tuile .ds-jaq-repli { width: auto; aspect-ratio: 1; }
.ds-jaq-grande { height: auto; width: min(100%, 16rem); }

/* En-cours réalisés (spec Encours §3) : en-tête de chaque commande, au-dessus de ses lignes. */
.ds-enc-table .ds-enc-commande { background: var(--mud-palette-background-gray); color: var(--mud-palette-primary); }

/* En-cours planifiés (spec Encours §2) : la liste défile sous la barre de filtres ; ruptures de
   bloc et de groupe aux couleurs du legacy (tokens ci-dessus). */
.ds-enc-corps { flex: 1 1 auto; min-height: 0; overflow: auto; }
.ds-enc-plan thead th { position: sticky; top: 0; z-index: 1; background: var(--mud-palette-surface); }
.ds-enc-plan tr.ds-enc-bloc td { background: var(--ds-enc-bloc-fond); color: var(--ds-navy-deep); font-weight: 700; }
.ds-enc-plan tr.ds-enc-groupe td { background: var(--ds-enc-groupe-fond); color: var(--ds-navy-deep); font-weight: 500; }

/* En-cours, vue vignettes : mêmes ruptures que la liste, en bandeaux au-dessus des grilles. */
.ds-enc-bloc-titre { background: var(--ds-enc-bloc-fond); color: var(--ds-navy-deep); font-weight: 700; border-radius: 4px; }
.ds-enc-groupe-titre { background: var(--ds-enc-groupe-fond); color: var(--ds-navy-deep); font-weight: 500; border-radius: 4px; }
.ds-enc-commande-titre { background: var(--mud-palette-background-gray); color: var(--mud-palette-primary); border-radius: 4px; }

/* En-cours : ligne / vignette cliquable (fiche commande, origine d'une quantité) + sa loupe en liste. */
.ds-enc-cliquable, .ds-cn-plein .ds-bp-tuile.ds-enc-cliquable { cursor: pointer; }
.ds-enc-loupe { display: inline-flex; color: var(--mud-palette-primary); }

/* En-cours réalisés : en-tête d'une commande — numéro et date de passation en avant, puis origine / référence. */
.ds-enc-num { font-weight: 700; color: var(--mud-palette-primary); margin-right: .75rem; }
.ds-enc-date { font-weight: 700; color: var(--ds-navy-deep); margin-right: .75rem; }
.ds-enc-origine { color: var(--mud-palette-text-secondary); }

/* Écran OPA (patron B) : un tableau par conditionnement. Largeurs FIGÉES (table-layout fixed)
   pour que les colonnes de chiffres tombent au même endroit d'un bloc à l'autre — sinon chaque
   tableau dimensionne ses colonnes selon son contenu. Grand écran seulement : sur téléphone le
   tableau s'empile en fiches (même requête média que MudBlazor, cf. plus haut). */
@media (min-width: 961px) {
    .ds-opa-lignes table { table-layout: fixed; }
}
.ds-opa-lignes tfoot td.mud-table-cell { border-bottom: none; }
.ds-opa-saisie { max-width: 6rem; margin-inline: auto; }
.ds-opa-saisie input { text-align: center; }
