@import '_content/Mze.FrontEnd/Mze.FrontEnd.lagwzrsa4q.bundle.scp.css';
@import '_content/Mze.Map/Mze.Map.0zjjzzqdfy.bundle.scp.css';
@import '_content/Mze.Vitrine.FrontEnd/Mze.Vitrine.FrontEnd.2lmm8qzuhr.bundle.scp.css';

/* /Components/Layout/MzeDrawer.razor.rz.scp.css */
/* Tiroir de navigation mobile â€” chrome complet du composant.
   RapatriÃ© de mze-vitrine.css : la famille `.mze-drawer*` n'a que ce composant pour consommateur.
   Valeurs reprises telles quelles, dÃ©placement neutre au rendu ; les espacements en pixels et les
   `rgba` en dur restent Ã  convertir en tokens, changement visuel Ã  arbitrer sÃ©parÃ©ment.

   Visible sous 1280 px, lÃ  oÃ¹ la navigation Ã©ditoriale est repliÃ©e. Panneau latÃ©ral plutÃ´t que
   plein Ã©cran : on garde le repÃ¨re du bord d'Ã©cran, et le geste de fermeture reste Ã©vident.

   `body.mze-noscroll` reste dans mze-vitrine.css : `<body>` n'appartient Ã  aucun composant,
   la rÃ¨gle est posÃ©e par mze-vitrine.js et ne peut donc pas Ãªtre scopÃ©e. */

.mze-drawer[b-sosv4s0s9u] { position: fixed; inset: 0; z-index: 90; }
.mze-drawer[hidden][b-sosv4s0s9u] { display: none; }
.mze-drawer__backdrop[b-sosv4s0s9u] { position: absolute; inset: 0; background: rgba(20, 17, 15, .45); border: 0; width: 100%; cursor: pointer; }

.mze-drawer__panel[b-sosv4s0s9u] {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(86%, 380px); background: var(--mze-bg);
  display: flex; flex-direction: column; overflow-y: auto;
  box-shadow: -8px 0 34px rgba(0, 0, 0, .18);
}

.mze-drawer__head[b-sosv4s0s9u] {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 12px 12px 20px; border-bottom: 1px solid var(--mze-border);
  position: sticky; top: 0; background: var(--mze-bg);
}

.mze-drawer__title[b-sosv4s0s9u] { font-family: var(--mze-font-heading); font-size: 1.15rem; }
.mze-drawer__nav[b-sosv4s0s9u] { padding: 18px 20px; flex: 1; }

.mze-drawer__grp[b-sosv4s0s9u] {
  font-size: .66rem; letter-spacing: .15em; text-transform: uppercase;
  color: var(--mze-text-muted); margin: 22px 0 8px;
}

.mze-drawer__grp:first-child[b-sosv4s0s9u] { margin-top: 0; }
.mze-drawer__nav ul[b-sosv4s0s9u] { list-style: none; margin: 0; padding: 0; }
.mze-drawer__nav li + li[b-sosv4s0s9u] { border-top: 1px solid var(--mze-border); }

.mze-drawer__nav a[b-sosv4s0s9u] {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 0; text-decoration: none; color: var(--mze-text); font-size: .98rem;
}

.mze-drawer__nav a:hover[b-sosv4s0s9u] { color: var(--mze-accent-contrast); }
.mze-drawer__nav a .bi[b-sosv4s0s9u] { color: var(--mze-text-muted); font-size: .8rem; }

.mze-drawer__foot[b-sosv4s0s9u] {
  border-top: 1px solid var(--mze-border); padding: 18px 20px 26px;
  background: var(--mze-bg-alt); display: grid; gap: 12px;
}

.mze-drawer__foot a[b-sosv4s0s9u] { color: var(--mze-text); text-decoration: none; font-size: .9rem; display: flex; align-items: center; gap: 9px; }
.mze-drawer__langs[b-sosv4s0s9u] { display: flex; gap: 8px; }

.mze-drawer__langs a[b-sosv4s0s9u] {
  border: 1px solid var(--mze-border-strong); border-radius: var(--mze-radius-sm);
  padding: 7px 14px; font-weight: 600; font-size: .82rem;
}

.mze-drawer__langs a[aria-current="true"][b-sosv4s0s9u] { background: var(--mze-accent); color: var(--mze-text-on-accent); border-color: transparent; }

/* âš  DÃ‰MO â€” repli mobile du sÃ©lecteur de thÃ¨me (cf. MzeDrawer.razor).
   Au-dessus de 576 px, le dropdown de l'en-tÃªte prend le relais. */

/* Surcharge rapatriÃ©e du bloc @media partagÃ© de mze-vitrine.css, oÃ¹ elle Ã©tait groupÃ©e
   avec `.mze-burger` â€” ce dernier appartient Ã  MzeHeader et y reste. */
@media (min-width: 1280px) {
  .mze-drawer[b-sosv4s0s9u] { display: none; }
}
/* /Components/Layout/MzeFooter.razor.rz.scp.css */
/* Pied de page de la vitrine — chrome complet du composant.
   Le gabarit vivait dans mze-vitrine.css : il est rapatrié ici, `.mze-footer` n'ayant que ce
   composant pour consommateur. Valeurs reprises telles quelles, déplacement neutre au rendu ;
   les espacements en pixels restent à convertir en tokens séparément.
   S'y ajoutent les deux styles en ligne de la maquette (mockup-01-accueil.html). */

/* ---------- Gabarit ---------- */
.mze-footer[b-17gvz7aux0] {
    background: var(--mze-bg-dark);
    color: var(--mze-text-on-dark);
    padding: 40px 0 24px;
}

/* Même exclusion que sur les sections inversées : un bouton porte son propre couple fond/texte,
   la reteinte générale des liens ne doit pas le dissocier (cf. BUG-SITE-001, défaut de contraste). */
.mze-footer a:not(.mze-button)[b-17gvz7aux0] {
    color: var(--mze-text-on-dark);
    text-decoration: none;
    opacity: .82;
}

.mze-footer a:not(.mze-button):hover[b-17gvz7aux0] { opacity: 1; }

/* Titres de colonne : des libellés, pas des titres du document — un <h5> après les <h2> de la page
   sautait trois niveaux dans le plan lu par les robots et les lecteurs d'écran. */
.mze-footer__titre[b-17gvz7aux0] {
    font-size: .74rem;
    letter-spacing: .15em;
    text-transform: uppercase;
    font-family: var(--mze-font-body);
    font-weight: 700;
    margin-bottom: 1em;
}

.mze-footer ul[b-17gvz7aux0] {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 8px;
    font-size: .88rem;
}

.mze-footer__cols[b-17gvz7aux0] {
    display: grid;
    gap: 30px;
    grid-template-columns: 1fr;
}

.mze-footer__bottom[b-17gvz7aux0] {
    border-top: 1px solid color-mix(in srgb, var(--mze-text-on-dark) 22%, transparent);
    margin-top: 30px;
    padding-top: 18px;
    font-size: .78rem;
    opacity: .72;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: space-between;
}

/* Surcharges responsive rapatriées des blocs @media partagés de mze-vitrine.css. */
@media (min-width: 576px) {
    .mze-footer__cols[b-17gvz7aux0] { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 992px) {
    .mze-footer__cols[b-17gvz7aux0] { grid-template-columns: 1.6fr 1fr 1fr 1fr; }

    /* Boutique masquée (FEAT-SITE-014) : la colonne des collections n'est pas rendue ; la grille
       garde les proportions de la maquette sur trois colonnes au lieu d'en laisser une vide. */
    .mze-footer__cols--sans-boutique[b-17gvz7aux0] { grid-template-columns: 1.6fr 1fr 1fr; }
}

/* ---------- Styles en ligne de la maquette ---------- */
.mze-footer__brand[b-17gvz7aux0] {
    color: var(--mze-text-on-dark);
}

.mze-footer__baseline[b-17gvz7aux0] {
    margin-top: 12px;
    max-width: 34ch;
    opacity: .8;
}
/* /Components/Layout/MzeHeader.razor.rz.scp.css */
/* En-tête de la vitrine — chrome complet du composant.
   Rapatrié de mze-vitrine.css : les familles `.mze-header*`, `.mze-lang*`, `.mze-nav`,
   `.mze-collbtn`, `.mze-collmenu*` n'ont que ce composant. `.mze-search*` et `.mze-suggest*`
   ont migré dans MzeChampRecherche.razor.css le 2026-08-24, avec le markup qu'ils habillent
   pour consommateur. Valeurs reprises telles quelles, déplacement neutre au rendu ; les
   espacements en pixels et les `rgba` en dur restent à convertir en tokens, changement visuel
   à arbitrer séparément.

   Restent volontairement dans mze-vitrine.css :
   - `.mze-logo`, partagé avec MzeFooter (`.mze-logo mze-footer__brand`) ;
   - `.mze-iconbtn` et `.mze-cartcount`, primitives partagées ;
   - `.mze-wrap`, gabarit global — seule son occurrence rendue ici est scopée. */

/* ---------- Barre ---------- */
.mze-header[b-h7dy8nidw9] {
  position: sticky; top: 0; z-index: 60;
  background: var(--mze-bg);
  border-bottom: 1px solid var(--mze-border);
}

.mze-header .mze-wrap[b-h7dy8nidw9] { display: flex; align-items: center; gap: 6px; padding-block: 10px; }

/* ---------- Composition de l'en-tête sous 576 px (BUG-SITE-001) ----------
   L'en-tête livré au sprint 1 alignait six éléments incompressibles pour un besoin de 457 px
   là où 310 sont disponibles à 346 px de viewport. Sous 576 px la barre est réduite au logo,
   à la recherche et au hamburger ; langue, thème, compte et panier passent dans le tiroir,
   où ils sont tous atteignables. Aucune fonction n'est supprimée. */
.mze-lang[b-h7dy8nidw9], .mze-account[b-h7dy8nidw9], .mze-cart[b-h7dy8nidw9], .mze-headertheme[b-h7dy8nidw9] { display: none; }
.mze-header__spacer[b-h7dy8nidw9] { flex: 1; }

/* ---------- Sélecteur de langue ---------- */
.mze-lang[b-h7dy8nidw9] { position: relative; flex: none; }

.mze-lang__btn[b-h7dy8nidw9] {
  appearance: none; background: transparent; border: 1px solid transparent; cursor: pointer;
  color: var(--mze-text); font: inherit; font-size: .8rem; font-weight: 600; letter-spacing: .04em;
  height: 44px; padding: 0 8px; border-radius: var(--mze-radius-sm);
  display: inline-flex; align-items: center; gap: 5px;
}

.mze-lang__btn:hover[b-h7dy8nidw9] { background: var(--mze-accent-soft); color: var(--mze-accent-contrast); }
.mze-lang__btn:focus-visible[b-h7dy8nidw9] { outline: 2px solid var(--mze-accent-contrast); outline-offset: 1px; }
.mze-lang__btn .bi-chevron-down[b-h7dy8nidw9] { font-size: .68rem; transition: transform var(--mze-duration); }
.mze-lang[data-open="true"] .mze-lang__btn .bi-chevron-down[b-h7dy8nidw9] { transform: rotate(180deg); }

.mze-lang__menu[b-h7dy8nidw9] {
  display: none; position: absolute; top: calc(100% + 4px); right: 0; z-index: 80;
  min-width: 168px; padding: 5px;
  background: var(--mze-bg); border: 1px solid var(--mze-border-strong);
  border-radius: var(--mze-radius-sm); box-shadow: 0 8px 26px rgba(0,0,0,.11);
}

.mze-lang[data-open="true"] .mze-lang__menu[b-h7dy8nidw9] { display: block; }

.mze-lang__menu a[b-h7dy8nidw9] {
  display: flex; align-items: center; gap: 9px; padding: 9px 11px;
  text-decoration: none; color: var(--mze-text); font-size: .87rem;
  border-radius: var(--mze-radius-sm);
}

.mze-lang__menu a:hover[b-h7dy8nidw9] { background: var(--mze-accent-soft); }
.mze-lang__menu a[aria-current="true"][b-h7dy8nidw9] { font-weight: 700; }
.mze-lang__menu a[aria-current="true"][b-h7dy8nidw9]::after { content: "\F26E"; font-family: bootstrap-icons; margin-left: auto; color: var(--mze-accent-contrast); }
.mze-lang__code[b-h7dy8nidw9] { font-weight: 700; min-width: 22px; }

/* ---------- Navigation ---------- */
.mze-nav[b-h7dy8nidw9] { display: none; flex: none; }
.mze-nav ul[b-h7dy8nidw9] { list-style: none; display: flex; flex-wrap: nowrap; gap: 18px; margin: 0; padding: 0; }
.mze-nav a[b-h7dy8nidw9] { color: var(--mze-text); text-decoration: none; font-size: .88rem; letter-spacing: .02em; white-space: nowrap; }
.mze-nav a:hover[b-h7dy8nidw9] { color: var(--mze-accent-contrast); }

/* ---------- Recherche ----------
   Mobile  : la loupe déploie une barre pleine largeur sous l'en-tête, avec voile.
   Desktop : barre permanente, large, au centre de l'en-tête.
   Le dropdown de suggestions est le MÊME composant dans les deux cas. */
/* Le voile est rendu en frère de <header> par ce composant : le sélecteur `~` reste intra-scope. */
.mze-searchbackdrop[b-h7dy8nidw9] {
  display: none; position: fixed; inset: 0; z-index: 55;
  background: rgba(20,17,15,.34);
}

.mze-header[data-search="open"] ~ .mze-searchbackdrop[b-h7dy8nidw9] { display: block; }

/* ---------- Menu de collections de l'en-tête (FEAT-SITE-003) ----------
   Même patron que le sélecteur de langue : conteneur `data-open`, panneau révélé en CSS, bascule
   par mze-vitrine.js. Aucun second mécanisme de menu n'est introduit. */
.mze-collbtn[b-h7dy8nidw9] {
  display: none; align-items: center; gap: 8px;
  background: var(--mze-accent); color: var(--mze-text-on-accent);
  border: 0; cursor: pointer; font: inherit; font-size: .8rem; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase;
  padding: 12px 17px; border-radius: var(--mze-radius); white-space: nowrap;
}

.mze-collmenu[b-h7dy8nidw9] { position: relative; flex: none; display: none; }

.mze-collmenu__panel[b-h7dy8nidw9] {
  display: none; position: absolute; top: calc(100% + 4px); left: 0; z-index: 80;
  min-width: 260px; max-height: 70vh; overflow-y: auto; padding: 5px;
  background: var(--mze-bg); border: 1px solid var(--mze-border-strong);
  border-radius: var(--mze-radius-sm); box-shadow: var(--mze-shadow-1);
}

.mze-collmenu[data-open="true"] .mze-collmenu__panel[b-h7dy8nidw9] { display: block; }

.mze-collmenu__panel a[b-h7dy8nidw9] {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--mze-space-3);
  padding: 9px 11px; text-decoration: none; color: var(--mze-text);
  font-size: .9rem; border-radius: var(--mze-radius-sm);
}

.mze-collmenu__panel a:hover[b-h7dy8nidw9] { background: var(--mze-accent-soft); color: var(--mze-accent-contrast); }
.mze-collmenu__n[b-h7dy8nidw9] { color: var(--mze-text-muted); font-size: .8rem; }
.mze-collmenu__all[b-h7dy8nidw9] { border-top: 1px solid var(--mze-border); margin-top: var(--mze-space-1); font-weight: 600; }

/* ============================================================
   Surcharges rapatriées des blocs @media partagés de mze-vitrine.css.
   L'ordre mobile-first est conservé.
   ============================================================ */

@media (min-width: 576px) {
  /* L'en-tête retrouve sa composition complète : la largeur disponible le permet à nouveau. */
  .mze-lang[b-h7dy8nidw9] { display: block; }
  /* ⚠ DÉMO — sélecteur de thème, même repli que la langue. */
  .mze-headertheme[b-h7dy8nidw9] { display: block; }
  .mze-account[b-h7dy8nidw9], .mze-cart[b-h7dy8nidw9] { display: inline-grid; }
}

@media (min-width: 992px) {
  .mze-collmenu[b-h7dy8nidw9] { display: block; }
  .mze-collbtn[b-h7dy8nidw9] { display: inline-flex; }
  .mze-searchtoggle[b-h7dy8nidw9] { display: none; }
  /* Le passage de la recherche en élément de flux est porté par MzeChampRecherche.razor.css,
     avec le reste de ses styles (FEAT-SITE-006). */
  .mze-searchbackdrop[b-h7dy8nidw9], .mze-header[data-search="open"] ~ .mze-searchbackdrop[b-h7dy8nidw9] { display: none; }
  .mze-header .mze-wrap[b-h7dy8nidw9] { gap: 10px; }
}

/* La navigation éditoriale n'apparaît qu'à 1280 px : avec cinq entrées, l'en-tête déborde en
   dessous. Entre 992 et 1279 px elle reste dans le menu, au profit de Collections et de la
   recherche, qui mènent à l'achat. `.mze-drawer` était groupé ici — il vit dans MzeDrawer. */
@media (min-width: 1280px) {
  .mze-nav[b-h7dy8nidw9] { display: flex; }
  .mze-burger[b-h7dy8nidw9] { display: none; }
}
/* /Components/Layout/MzeIndicateurBoutique.razor.rz.scp.css */
/* Indicateur d'état de la boutique (FEAT-SITE-014) : bande pleine largeur au-dessus du chrome. Le
   MzeAlert porte un rayon de carte ; en bande d'écran, il le perd. Tokens uniquement. */

.mze-etatboutique[b-q9kmfos9ve]  .mze-alert {
    border-radius: 0;
    justify-content: center;
}

.mze-etatboutique[b-q9kmfos9ve]  a {
    color: inherit;
    font-weight: var(--mze-font-weight-semibold);
    text-decoration: underline;
    margin-left: var(--mze-space-2);
}
/* /Components/Layout/MzeTopbar.razor.rz.scp.css */
/* Bandeau supérieur de la vitrine — chrome complet du composant.
   Rapatrié de mze-vitrine.css : `.mze-topbar` n'a que ce composant pour consommateur.
   Valeurs reprises telles quelles, déplacement neutre au rendu ; les espacements en pixels
   restent à convertir en tokens `--mze-space-*`, changement visuel à arbitrer séparément.

   `.mze-wrap` est rendu par ce composant : le scoping s'applique donc à son occurrence ici,
   sans toucher à la règle globale de la classe. */

.mze-topbar[b-vcp66aujfl] {
  background: var(--mze-bg-alt);
  color: var(--mze-text);
  font-size: .8rem;
  padding: 8px 0;
  border-bottom: 1px solid var(--mze-border);
}

/* Mobile et tablette : message puis logos, centrés ; retour à la ligne si l'écran est trop étroit. */
.mze-topbar .mze-wrap[b-vcp66aujfl] { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; justify-content: center; }
.mze-topbar__info[b-vcp66aujfl] { display: none; gap: 16px; align-items: center; }
.mze-topbar__social[b-vcp66aujfl] { display: flex; gap: 8px; align-items: center; }
.mze-topbar__promo[b-vcp66aujfl] { text-align: center; }
.mze-topbar__promo b[b-vcp66aujfl] { color: var(--mze-accent-contrast); }
.mze-topbar a[b-vcp66aujfl] { color: inherit; }

.mze-topbar__social a[b-vcp66aujfl] {
  display: inline-grid; place-items: center; width: 26px; height: 26px;
  border: 1px solid var(--mze-border-strong); border-radius: var(--mze-radius-sm);
}

/* Ni message ni réseau : rien à montrer sous 992 px (les coordonnées n'y sont pas affichées). */
.mze-topbar--vide-mobile[b-vcp66aujfl] { display: none; }

/* Surcharges rapatriées du bloc @media partagé de mze-vitrine.css. */
@media (min-width: 992px) {
  .mze-topbar--vide-mobile[b-vcp66aujfl] { display: block; }
  .mze-topbar .mze-wrap[b-vcp66aujfl] { justify-content: space-between; flex-wrap: nowrap; }
  .mze-topbar__info[b-vcp66aujfl] { display: flex; }
}
/* /Components/Layout/MzeVitrineLayout.razor.rz.scp.css */
/* Bandeau d'erreur Blazor — seul rescapé du MainLayout.razor.css du template,
réhabillé aux tokens du design system (aucune couleur en dur). */

#blazor-error-ui[b-249bq8simw] {
    background: var(--mze-bg-dark);
    border-top: 1px solid var(--mze-error);
    bottom: 0;
    box-sizing: border-box;
    color: var(--mze-text-on-dark);
    display: none;
    font-family: var(--mze-font-body);
    font-size: .9rem;
    left: 0;
    padding: .6rem 1.25rem .7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui [data-libelle][b-249bq8simw]::after {
    content: attr(data-libelle);
}

#blazor-error-ui .reload[b-249bq8simw] {
    margin-left: .4em;
}

#blazor-error-ui a[b-249bq8simw] {
    color: var(--mze-accent-on-dark);
}

#blazor-error-ui .dismiss[b-249bq8simw] {
    cursor: pointer;
    position: absolute;
    right: .75rem;
    top: .5rem;
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-98d764os9l],
.components-reconnect-repeated-attempt-visible[b-98d764os9l],
.components-reconnect-failed-visible[b-98d764os9l],
.components-pause-visible[b-98d764os9l],
.components-resume-failed-visible[b-98d764os9l],
.components-rejoining-animation[b-98d764os9l] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-98d764os9l],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-98d764os9l],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-98d764os9l],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-98d764os9l],
#components-reconnect-modal.components-reconnect-retrying[b-98d764os9l],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-98d764os9l],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-98d764os9l],
#components-reconnect-modal.components-reconnect-failed[b-98d764os9l],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-98d764os9l] {
    display: block;
}


#components-reconnect-modal[b-98d764os9l] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-98d764os9l 0.5s both;
    &[open]

    {
        animation: components-reconnect-modal-slideUp-b-98d764os9l 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-98d764os9l 0.5s ease-in-out 0.3s;
        animation-fill-mode: both;
    }

}

#components-reconnect-modal[b-98d764os9l]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-98d764os9l 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-98d764os9l {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-98d764os9l {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-98d764os9l {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-98d764os9l] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-98d764os9l] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-98d764os9l] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

#components-reconnect-modal button:hover[b-98d764os9l] {
    background-color: #3b6ea2;
}

#components-reconnect-modal button:active[b-98d764os9l] {
    background-color: #6b9ed2;
}

.components-rejoining-animation[b-98d764os9l] {
    position: relative;
    width: 80px;
    height: 80px;
}

.components-rejoining-animation div[b-98d764os9l] {
    position: absolute;
    border: 3px solid #0087ff;
    opacity: 1;
    border-radius: 50%;
    animation: components-rejoining-animation-b-98d764os9l 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}

.components-rejoining-animation div:nth-child(2)[b-98d764os9l] {
    animation-delay: -0.5s;
}

@keyframes components-rejoining-animation-b-98d764os9l {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/Admin/AdminLayout.razor.rz.scp.css */
/* ================================================================
   AdminLayout.razor.css — chrome du shell d'administration
   ================================================================
   Le chrome lui-même (sidebar, en-tête, card) est intégralement porté par
   MzeAppLayoutWithSidebar : rien n'est réécrit ici. Ce fichier ne fait qu'une
   chose — neutraliser, à l'intérieur de l'administration, les règles
   d'éléments GLOBALES de mze-vitrine.css (body, h1..h6, a, p), qui sont
   dimensionnées pour une vitrine éditoriale. Un h1 à 44px (thème w3) dans un
   écran d'inventaire est illisible.

   Aucune valeur d'axe en dur : tout passe par les tokens --mze-*.
   Mobile-first : la base est le mobile, les surcharges montent en min-width.
   ================================================================ */

.mze-admin[b-8yuhbuarxd] {
    /* Le layout gère sa propre hauteur (100vh, ou auto avec AllowPageScroll).
       Ce conteneur ne fait que porter le périmètre du ::deep. */
    display: contents;

    /* Registre tactile de l'administration — redéfinition de tokens sur le
       conteneur de contexte, pas de jeu de classes parallèle.

       Les valeurs du socle (12 / 18 / 24 px) viennent d'un back-office dense
       piloté à la souris. L'administration est conçue tablette-d'abord
       (FEAT-ADMIN-002, décision 2) et s'utilise à même l'atelier : une case de
       12 px y est plus petite que la case native du navigateur et sous tout
       seuil de cible tactile (WCAG 2.5.8 — 24 px). Le libellé de MzeCheckbox
       reste cliquable et élargit la cible réelle au-delà du carré.

       `display: contents` ne fait pas obstacle : l'héritage des propriétés
       personnalisées suit l'arbre DOM, pas l'arbre de boîtes. */
    --mze-checkbox-size-sm: 16px;
    --mze-checkbox-size-md: 20px;
    --mze-checkbox-size-lg: 24px;

    /* Même raisonnement pour la cible tactile : le socle porte le plancher WCAG
       2.5.8 (24 px), l'administration le relève à la cible confortable du pouce.
       C'est la valeur que la maquette validée de FEAT-ADMIN-023 emploie partout —
       cases de carte, bascules de mode, champs du panneau de filtres. */
    --mze-touch-min: 44px;
}

/* Conteneur de page — le défilement vit ici, pas sur la fenêtre.

   Le shell est cloué à 100vh (`AllowPageScroll="false"`) : sidebar et en-tête ne partent jamais
   au défilement. `flex: 1` + `min-height: 0` donnent à ce conteneur la hauteur restante réelle,
   condition pour qu'un enfant puisse à son tour prendre `flex: 1` et défiler chez lui — sans
   `min-height: 0`, un enfant flex refuse de descendre sous sa taille de contenu et déborde. */
.mze-admin-page[b-8yuhbuarxd] {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* Typographie applicative : échelle de back-office, pas échelle éditoriale. */
.mze-admin[b-8yuhbuarxd]  h1 {
    font-size: var(--mze-text-size-2);
    font-weight: 600;
    letter-spacing: 0;
    margin: 0 0 var(--mze-space-3);
}

.mze-admin[b-8yuhbuarxd]  h2 {
    font-size: var(--mze-text-size-3);
    font-weight: 600;
    letter-spacing: 0;
    margin: 0 0 var(--mze-space-3);
}

.mze-admin[b-8yuhbuarxd]  h3,
.mze-admin[b-8yuhbuarxd]  h4,
.mze-admin[b-8yuhbuarxd]  h5,
.mze-admin[b-8yuhbuarxd]  h6 {
    font-size: var(--mze-text-size-4);
    font-weight: 600;
    letter-spacing: 0;
    margin: 0 0 var(--mze-space-2);
}

.mze-admin[b-8yuhbuarxd]  p {
    margin: 0 0 var(--mze-space-3);
    font-size: var(--mze-text-size-4);
}

/* Focus visible homogène sur tout le shell (exigence d'accessibilité §12). */
.mze-admin[b-8yuhbuarxd]  :focus-visible {
    outline: var(--mze-focus-width) solid var(--mze-focus-color);
    outline-offset: var(--mze-focus-offset);
}

/* Tablette et au-delà : on desserre le rythme vertical, la densité mobile
   n'a plus lieu d'être une fois la sidebar fixe (≥ 992px). */
@media (min-width: 992px) {
    .mze-admin[b-8yuhbuarxd]  h1 {
        margin-bottom: var(--mze-space-4);
    }
}
/* /Components/Pages/Admin/BacResponsive.razor.rz.scp.css */
/* Bac de prévisualisation responsive — outil de développement.

   Ce fichier disparaît avec le composant : rien d'autre n'y renvoie. */

/* Déclencheur : en ligne dans la barre de titre du back-office ; flottant sur la vitrine, hors du flux,
   pour ne rien changer à la composition de l'en-tête qu'il sert à recetter. Au-dessus du contenu,
   au-dessous du bac ouvert. */
.mze-bac-declencheur[b-wqha65ln49] { display: contents; }

.mze-bac-declencheur--flottant[b-wqha65ln49] {
    display: block;
    position: fixed;
    left: var(--mze-space-3);
    bottom: var(--mze-space-3);
    z-index: var(--mze-modal-z);
    box-shadow: var(--mze-modal-shadow);
    border-radius: var(--mze-radius-md);
}

.mze-bac[b-wqha65ln49] {
    position: fixed;
    inset: 0;
    z-index: var(--mze-modal-z);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--mze-space-4);
    background: var(--mze-modal-backdrop);

    /* Le voile laisse passer les clics : on veut pouvoir continuer à piloter l'application derrière
       pendant qu'on observe son rendu mobile. C'est un bac, pas une boîte de dialogue. */
    pointer-events: none;
}

.mze-bac-cadre[b-wqha65ln49] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--mze-space-2);
    padding: var(--mze-space-3);
    border-radius: var(--mze-radius-card);
    background: var(--mze-surface);
    border: 1px solid var(--mze-border);
    box-shadow: var(--mze-modal-shadow);

    /* Le cadre, lui, reste actionnable. */
    pointer-events: auto;

    /* Le viewport demandé prime ; on ne le rétrécit qu'à l'étroit, sinon la mesure ne voudrait plus
       rien dire — un bac qui redimensionne l'appareil qu'il simule ne simule rien. */
    max-width: 100%;
    max-height: 100%;
}

.mze-bac-legende[b-wqha65ln49] {
    font-size: var(--mze-text-size-5);
    color: var(--mze-text-muted);
}

/* Les dimensions viennent du style inline du composant — c'est la donnée de l'appareil, pas une
   valeur de design. Elles ne passent volontairement PAS par des propriétés personnalisées : un
   `var(--mze-*)` sans déclaration globale est précisément ce que l'invariant des tokens interdit
   (BUG-ADMIN-002), et l'exempter pour un outil de développement affaiblirait le garde-fou. */
.mze-bac-ecran[b-wqha65ln49] {
    max-height: 78vh;
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
    background: var(--mze-bg-page);
    display: block;
}

.mze-bac-actions[b-wqha65ln49] {
    display: flex;
    gap: var(--mze-space-2);
}
/* /Components/Pages/Admin/Capture.razor.rz.scp.css */
/* Capture d'atelier (FEAT-ADMIN-022). Une colonne, au pouce ; sur grand écran elle ne s'étale pas —
   un viseur de toute la largeur d'un moniteur ne sert à rien.

   MzeTabs rend sa barre et l'onglet actif directement dans ce conteneur, sans enveloppe : c'est donc
   lui qui porte l'espace entre les deux. */
.mze-capture[b-d9banb1xy0] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    width: 100%;
    max-width: var(--mze-wrap-max);
    margin-inline: auto;
}

@media (min-width: 768px) {
    .mze-capture[b-d9banb1xy0] {
        max-width: calc(var(--mze-wrap-max) / 2);
    }
}
/* /Components/Pages/Admin/CaptureConsultation.razor.rz.scp.css */
/* Onglet « Consultation » de la capture d'atelier (FEAT-ADMIN-022). Mobile-first. */

.mze-capture-consult[b-751adxgyeb] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

.mze-capture-consult-vide[b-751adxgyeb] {
    margin: 0;
    padding: var(--mze-space-5) 0;
    text-align: center;
    color: var(--mze-text-muted);
}

.mze-capture-consult-entete[b-751adxgyeb] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--mze-space-2);
}

.mze-capture-consult-resume[b-751adxgyeb] {
    margin: 0;
    color: var(--mze-text-muted);
}

.mze-capture-consult-aide[b-751adxgyeb] {
    margin: 0;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-capture-consult-articles[b-751adxgyeb] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Cible « Nouvel article » : collée en bas de l'écran pendant un glisser, atteignable où que soit la
   photo dans la liste. */
.mze-capture-consult-nouveau[b-751adxgyeb] {
    position: sticky;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--mze-space-2);
    min-height: var(--mze-input-height-lg);
    padding: var(--mze-space-3);
    border: 2px dashed var(--mze-border);
    border-radius: var(--mze-radius-sm);
    background: var(--mze-surface);
    color: var(--mze-text-muted);
}

.mze-capture-consult-nouveau.est-cible[b-751adxgyeb] {
    border-color: var(--mze-accent);
    color: var(--mze-accent-contrast);
}
/* /Components/Pages/Admin/CapturePriseDeVue.razor.rz.scp.css */
/* Onglet « Prise de vue » de la capture d'atelier (FEAT-ADMIN-022). Mobile-first : une colonne. */

.mze-capture-pdv[b-x6ld8lcu8i] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

/* Viseur plein cadre : le plafond de hauteur du composant est pensé pour une modale de saisie. Ici
   la caméra EST l'écran — on lui laisse la hauteur, en gardant le déclencheur sous le pouce sans
   défiler. */
.mze-capture-pdv[b-x6ld8lcu8i]  .mze-camera-scene {
    max-height: 55vh;
    max-height: 55dvh;
}

.mze-capture-pdv-compteurs[b-x6ld8lcu8i] {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--mze-space-1) var(--mze-space-3);
    margin: 0;
    color: var(--mze-text-muted);
}

.mze-capture-pdv-compteurs strong[b-x6ld8lcu8i] {
    color: var(--mze-text);
}
/* /Components/Pages/Admin/CaptureTraites.razor.rz.scp.css */
/* Onglet « Traités » de la capture d'atelier (FEAT-ADMIN-025). Mobile-first. */

.mze-capture-traites[b-l6au55u78t] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

.mze-capture-traites-vide[b-l6au55u78t] {
    margin: 0;
    padding: var(--mze-space-5) 0;
    text-align: center;
    color: var(--mze-text-muted);
}

.mze-capture-traites-entete[b-l6au55u78t] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--mze-space-2);
}

.mze-capture-traites-resume[b-l6au55u78t] {
    margin: 0;
    color: var(--mze-text-muted);
}

.mze-capture-traites-purge[b-l6au55u78t] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    padding: var(--mze-space-3);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-sm);
}

.mze-capture-traites-purge p[b-l6au55u78t] {
    margin: 0;
    color: var(--mze-error);
}

.mze-capture-traites-actions[b-l6au55u78t] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
}

.mze-capture-traites-articles[b-l6au55u78t] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}
/* /Components/Pages/Admin/CarteArticleCapture.razor.rz.scp.css */
/* Un article de la consultation (FEAT-ADMIN-022). */

.mze-carte-article[b-tsvw5xc4t7] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    padding: var(--mze-space-2);
    border: 1px dashed transparent;
    border-radius: var(--mze-radius-sm);
}

/* Cible du dépôt : un filet d'accent, sans bouger la mise en page (la bordure existe déjà). */
.mze-carte-article.est-cible[b-tsvw5xc4t7] {
    border-color: var(--mze-accent);
    background: var(--mze-surface-alt);
}

.mze-carte-article-entete[b-tsvw5xc4t7] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--mze-space-2);
}

.mze-carte-article-titre[b-tsvw5xc4t7] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-1) var(--mze-space-2);
    margin: 0;
}

.mze-carte-article-titre span[b-tsvw5xc4t7] {
    color: var(--mze-text-muted);
}

.mze-carte-article-edition[b-tsvw5xc4t7] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    /* Remplissage serré : le panneau est déjà dans un volet et une carte, et le compteur doit garder
       ses quatre grands pas sur une ligne à 360 px. */
    padding: var(--mze-space-2);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-sm);
    background: var(--mze-surface-alt);
}

.mze-carte-article-confirmation[b-tsvw5xc4t7] {
    margin: 0;
    color: var(--mze-error);
}

.mze-carte-article-actions[b-tsvw5xc4t7] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
}
/* /Components/Pages/Admin/CarteArticleTraite.razor.rz.scp.css */
/* Un article traité (FEAT-ADMIN-025). */

.mze-carte-traite[b-rht4mgoycw] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
}

.mze-carte-traite-titre[b-rht4mgoycw],
.mze-carte-traite-reference[b-rht4mgoycw] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--mze-space-1) var(--mze-space-2);
    margin: 0;
}

.mze-carte-traite-titre span[b-rht4mgoycw],
.mze-carte-traite-reference span[b-rht4mgoycw] {
    color: var(--mze-text-muted);
}

.mze-carte-traite-nom[b-rht4mgoycw] {
    margin: 0;
    overflow-wrap: anywhere;
}

.mze-carte-traite-alerte[b-rht4mgoycw] {
    margin: 0;
    padding: var(--mze-space-2);
    border-left: 3px solid var(--mze-accent);
    background: var(--mze-surface-alt);
}

.mze-carte-traite-confirmation[b-rht4mgoycw] {
    margin: 0;
    color: var(--mze-error);
}

.mze-carte-traite-actions[b-rht4mgoycw] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
}
/* /Components/Pages/Admin/CollectionsAdmin.razor.rz.scp.css */
/* Arbre des collections (FEAT-ADMIN-026). Tokens uniquement. Mobile d'abord : deux colonnes — la
   collection, qui porte aussi comptes et état, et les actions — puis quatre dès 1024 px, comme
   l'inventaire (`--mze-inv-cols`). Colonne d'actions de largeur FIXE : chaque ligne est sa propre grille, une largeur « auto » la décalerait d'une ligne à l'autre. */

.mze-collections[b-ugn5bkm2am] {
    --mze-collections-cols: minmax(0, 1fr) 132px;
    --mze-collections-ligne: 76px;
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    flex: 1;
    min-height: 0;
}

.mze-collections-outils[b-ugn5bkm2am] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--mze-space-3);
}

/* ::deep obligatoire : en-têtes et cellules appartiennent au markup de MzeGrid. Masquer sous le palier
   (max-width) plutôt que rétablir au-dessus : un « display » rétabli écraserait celui des cellules. */
@media (max-width: 1023.98px) {
    .mze-collections[b-ugn5bkm2am]  .mze-collections-col--large,
    .mze-collections[b-ugn5bkm2am]  .mze-collections-seul-large {
        display: none;
    }
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-nom {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-nom strong,
.mze-collections[b-ugn5bkm2am]  .mze-collections-adresse {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Sous-collection : décalée sous sa parente, avec un filet qui dit la filiation. */
.mze-collections[b-ugn5bkm2am]  .mze-collections-nom--sous {
    margin-left: var(--mze-space-3);
    padding-left: var(--mze-space-2);
    border-left: 2px solid var(--mze-border);
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-adresse,
.mze-collections[b-ugn5bkm2am]  .mze-collections-comptes {
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-meta,
.mze-collections[b-ugn5bkm2am]  .mze-collections-etat,
.mze-collections[b-ugn5bkm2am]  .mze-collections-actions {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mze-space-1) var(--mze-space-2);
}

/* Ligne de méta (mobile) : une seule ligne, coupée à droite — la rangée a une hauteur fixe. */
.mze-collections[b-ugn5bkm2am]  .mze-collections-meta {
    flex-wrap: nowrap;
    overflow: hidden;
    white-space: nowrap;
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-meta .mze-collections-etat {
    flex-wrap: nowrap;
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-actions {
    flex-wrap: nowrap;
    justify-content: flex-end;
    gap: var(--mze-space-1);
    width: 100%;
}

/* « en » suivi d'une coche ou d'une croix : la présence du nom anglais, lisible d'un coup d'œil. */
.mze-collections[b-ugn5bkm2am]  .mze-collections-langue {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    font-size: var(--mze-text-size-6);
    font-weight: var(--mze-font-weight-medium);
    text-transform: lowercase;
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-langue--oui {
    color: var(--mze-color-success-800);
}

.mze-collections[b-ugn5bkm2am]  .mze-collections-langue--non {
    color: var(--mze-color-warning-800);
}

@media (min-width: 1024px) {
    .mze-collections[b-ugn5bkm2am] {
        --mze-collections-cols: minmax(0, 1fr) 140px 200px 236px;
        --mze-collections-ligne: 56px;
    }

    .mze-collections[b-ugn5bkm2am]  .mze-collections-meta,
    .mze-collections[b-ugn5bkm2am]  .mze-collections-seul-compact {
        display: none;
    }
}

.mze-collections-recherche[b-ugn5bkm2am] {
    width: 100%;
    max-width: 420px;
}
/* /Components/Pages/Admin/ContenuPage.razor.rz.scp.css */
/* Édition d'une page du site (FEAT-ADMIN-014). Coque des formulaires : mze-form.css. Tokens uniquement.
   Mobile-first : actions sous le résumé, en ligne au palier tablette. */

.mze-edition[b-7uwkuwk1ux] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    max-width: var(--mze-form-page-max);
}

.mze-edition-tete[b-7uwkuwk1ux] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mze-space-3);
    padding-bottom: var(--mze-space-3);
    border-bottom: 1px solid var(--mze-border);
}

.mze-edition-identite[b-7uwkuwk1ux] {
    flex: 1 1 200px;
    min-width: 0;
}

.mze-edition-identite h1[b-7uwkuwk1ux] {
    margin: 0;
    font-size: var(--mze-text-size-3);
    line-height: 1.2;
}

.mze-edition-identite p[b-7uwkuwk1ux] {
    margin: 0;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-5);
}

.mze-edition-etat[b-7uwkuwk1ux] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mze-space-2);
}

.mze-edition-sections[b-7uwkuwk1ux] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.mze-edition-section[b-7uwkuwk1ux] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    padding: var(--mze-space-3);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
    background: var(--mze-surface);
}

.mze-edition-section--inactive[b-7uwkuwk1ux] {
    background: var(--mze-surface-alt);
    color: var(--mze-text-muted);
}

.mze-edition-section-texte[b-7uwkuwk1ux] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-1);
    min-width: 0;
}

.mze-edition-section-texte strong[b-7uwkuwk1ux] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mze-edition-section-type[b-7uwkuwk1ux] {
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.mze-edition-section-badges[b-7uwkuwk1ux],
.mze-edition-section-actions[b-7uwkuwk1ux] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mze-space-1);
}

.mze-edition-ajout[b-7uwkuwk1ux] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--mze-space-3);
}

@media (min-width: 768px) {
    .mze-edition-section[b-7uwkuwk1ux] {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .mze-edition-section-texte[b-7uwkuwk1ux] {
        flex: 1 1 auto;
    }

    /* Ancre de l'aperçu au survol (MzeHoverPreview) : elle porte désormais la place du texte. */
    .mze-edition-section[b-7uwkuwk1ux]  .mze-edition-section-survol {
        flex: 1 1 auto;
        min-width: 0;
    }
}

.mze-edition-vide[b-7uwkuwk1ux] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--mze-space-3);
    padding: var(--mze-space-6) var(--mze-space-4);
    color: var(--mze-text-muted);
}
/* /Components/Pages/Admin/ContenuSite.razor.rz.scp.css */
/* Liste des pages du site (FEAT-ADMIN-014). Tokens uniquement. */

.mze-contenu[b-wvo0yne35z] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    flex: 1;
    min-height: 0;
}

.mze-contenu-outils[b-wvo0yne35z] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--mze-space-3);
}

.mze-contenu[b-wvo0yne35z]  .mze-contenu-code {
    display: block;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-contenu[b-wvo0yne35z]  .mze-contenu-position,
.mze-contenu[b-wvo0yne35z]  .mze-contenu-actions {
    display: inline-flex;
    align-items: center;
    gap: var(--mze-space-1);
}
/* /Components/Pages/Admin/Contenu/ApercuEcranReduit.razor.rz.scp.css */
/* Un quart de l'écran, dans ses proportions : le cadre fait 25 % de la largeur et 25 % de la hauteur
   de la fenêtre ; son contenu est rendu à la taille de la fenêtre, puis réduit d'autant. */
.mze-apercu-ecran[b-9wqrc6whlw] {
    display: block;
    position: relative;
    width: 25vw;
    height: 25vh;
    overflow: hidden;
    background: var(--mze-surface);
}

.mze-apercu-ecran-cadre[b-9wqrc6whlw] {
    display: block;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    transform: scale(0.25);
    transform-origin: 0 0;
}

.mze-apercu-ecran-attente[b-9wqrc6whlw] {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
}
/* /Components/Pages/Admin/Contenu/ApercuPageContenu.razor.rz.scp.css */
/* Aperçu de la page dans le CMS (FEAT-ADMIN-014). Le conteneur reçoit les tokens du thème du site par
   `data-theme` et le registre de la vitrine par `.mze-vitrine`. */

.mze-apercu-page[b-6h2lccekhe] {
    min-height: 100%;
    background: var(--mze-bg-page);
    color: var(--mze-text);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
    overflow: hidden;
}

/* Section seule : le cadre épouse la section. Étiré à la hauteur de la colonne, il laissait sous elle un
   aplat du fond de page, lu comme une partie de la section, et faisait défiler la colonne pour rien —
   le fond visible autour est celui de la modale. */
.mze-apercu-page--section[b-6h2lccekhe] {
    min-height: 0;
}

.mze-apercu-note[b-6h2lccekhe] {
    margin: 0;
    padding: var(--mze-space-2) var(--mze-space-3);
    background: var(--mze-color-warning-200);
    color: var(--mze-color-warning-800);
    font-size: var(--mze-text-size-5);
}
/* /Components/Pages/Admin/Contenu/ChoixImageContenu.razor.rz.scp.css */
/* Champ image du CMS (FEAT-ADMIN-014). Tokens uniquement. */

.mze-choix-image[b-00nhcpd2xe] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
}

.mze-choix-image-libelle[b-00nhcpd2xe] {
    font-size: var(--mze-text-size-5);
    font-weight: var(--mze-font-weight-medium);
}

.mze-choix-image-corps[b-00nhcpd2xe] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-3);
    align-items: flex-start;
}

.mze-choix-image-vignette[b-00nhcpd2xe] {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 112px;
    height: 112px;
    overflow: hidden;
    border-radius: var(--mze-radius-md);
    background: var(--mze-surface-alt);
}

.mze-choix-image-vignette img[b-00nhcpd2xe] {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* « Sans image » est un état visible, pas un vide. */
.mze-choix-image-vignette--vide[b-00nhcpd2xe] {
    color: var(--mze-text-muted);
    border: 1px dashed var(--mze-border);
    background: transparent;
}

.mze-choix-image-actions[b-00nhcpd2xe] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    flex: 1 1 220px;
    min-width: 0;
}

.mze-choix-image-boutons[b-00nhcpd2xe] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
}

.mze-choix-image-galerie[b-00nhcpd2xe] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
    gap: var(--mze-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.mze-choix-image-option[b-00nhcpd2xe] {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    padding: 0;
    overflow: hidden;
    cursor: pointer;
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
    background: var(--mze-surface-alt);
}

.mze-choix-image-option:hover[b-00nhcpd2xe],
.mze-choix-image-option:focus-visible[b-00nhcpd2xe] {
    outline: var(--mze-focus-width) solid var(--mze-accent);
    outline-offset: 2px;
}

.mze-choix-image-option img[b-00nhcpd2xe] {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* /Components/Pages/Admin/Contenu/EditeurSection.razor.rz.scp.css */
/* Éditeur de section (FEAT-ADMIN-014). Mobile-first : formulaire puis aperçu, empilés ; côte à côte au
   palier bureau, chaque colonne défilant pour elle-même. Tokens uniquement. */

.mze-editeur-section-corps[b-xhazh822qf] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    min-height: 0;
}

.mze-editeur-section-formulaire[b-xhazh822qf] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    min-width: 0;
}

.mze-editeur-section-apercu[b-xhazh822qf] {
    min-width: 0;
}

/* Mode d'aperçu collé en haut de la colonne, sur le fond de la modale. */
.mze-editeur-section-apercu-mode[b-xhazh822qf] {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    justify-content: flex-end;
    padding-bottom: var(--mze-space-2);
    background: var(--mze-modal-bg);
}

.mze-editeur-section-pied[b-xhazh822qf] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--mze-space-2);
    width: 100%;
}

@media (min-width: 1200px) {
    .mze-editeur-section-corps[b-xhazh822qf] {
        display: grid;
        grid-template-columns: minmax(380px, 2fr) 3fr;
        height: 100%;
    }

    .mze-editeur-section-formulaire[b-xhazh822qf],
    .mze-editeur-section-apercu[b-xhazh822qf] {
        overflow-y: auto;
        min-height: 0;
        padding-right: var(--mze-space-2);
    }
}
/* /Components/Pages/Admin/CorbeilleSelection.razor.rz.scp.css */
/* Corbeille de sélection (FEAT-ADMIN-023, phase 6).

   LA GÉOMÉTRIE PORTE LA RÈGLE. La liste des sélectionnés occupe l'espace restant, la zone d'actions
   est bornée à 66 % de la hauteur : agir sur un lot qu'on ne voit plus est exactement ce que la
   corbeille cherche à empêcher. Sans cette borne, six groupes d'actions repoussent la liste hors de
   la vue dès qu'un lot dépasse quelques références — et la corbeille redevient une barre d'outils. */

.mze-corbeille[b-l53zhguqai] {
    display: flex;
    flex-direction: column;
    /* Indispensable : sans elle, les enfants refusent de descendre sous la hauteur de leur contenu
       et c'est le panneau entier qui déborde, pied compris. */
    min-height: 0;
    height: 100%;
    background: var(--mze-surface);
}

/* ===== Liste des références retenues ===== */

.mze-corbeille-liste[b-l53zhguqai] {
    flex: 1 1 auto;
    min-height: 96px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--mze-space-2);
}

.mze-corbeille-vide[b-l53zhguqai] {
    margin: 0;
    padding: var(--mze-space-5) var(--mze-space-3);
    text-align: center;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-5);
    line-height: 1.5;
}

.mze-corbeille-item[b-l53zhguqai] {
    display: grid;
    grid-template-columns: 40px 1fr auto;
    gap: var(--mze-space-2);
    align-items: center;
    padding: var(--mze-space-2);
    border-block-end: 1px solid var(--mze-border);
}

.mze-corbeille-vignette[b-l53zhguqai] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--mze-radius-sm);
    overflow: hidden;
}

.mze-corbeille-vignette--absente[b-l53zhguqai] {
    background: var(--mze-surface-sunken);
    color: var(--mze-text-muted);
}

.mze-corbeille-txt[b-l53zhguqai] {
    min-width: 0;
}

.mze-corbeille-txt strong[b-l53zhguqai] {
    display: block;
    font-size: var(--mze-text-size-5);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mze-corbeille-txt > span[b-l53zhguqai] {
    font-size: var(--mze-text-size-6);
    color: var(--mze-text-muted);
}

/* ===== Zone d'actions ===== */

.mze-corbeille-actions[b-l53zhguqai] {
    flex: 0 1 auto;
    max-height: 66%;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--mze-space-3);
    border-block-start: 1px solid var(--mze-border-strong);
    background: var(--mze-surface-sunken);
}

.mze-corbeille-actions > h3[b-l53zhguqai] {
    margin: 0 0 var(--mze-space-3);
    font-size: var(--mze-text-size-6);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mze-text-muted);
}

.mze-act + .mze-act[b-l53zhguqai] {
    margin-block-start: var(--mze-space-3);
    padding-block-start: var(--mze-space-3);
    border-block-start: 1px solid var(--mze-border);
}

/* Titre d'un groupe sans sélecteur (boutique, étiquettes). Les autres groupes portent leur libellé
   par le Label de MzeSelect, qui le rend accessible au champ ; ce span reprend sa typographie pour
   que les six groupes se lisent d'une seule colonne. */
.mze-act-titre[b-l53zhguqai] {
    display: block;
    margin-block-end: var(--mze-space-1);
    font-size: var(--mze-text-size-5);
    font-weight: 500;
}

.mze-act-ligne[b-l53zhguqai] {
    display: flex;
    flex-wrap: wrap;
    /* flex-end aligne les boutons sur le BAS du sélecteur, qui porte son libellé au-dessus. Un
       align-items par défaut les étirerait sur toute la hauteur, libellé compris. */
    align-items: flex-end;
    gap: var(--mze-space-2);
}

/* Le sélecteur prend la place restante, les boutons gardent la leur. ::deep obligatoire : la racine
   de MzeSelect est rendue par l'enfant et porte SON scope, jamais celui de ce composant. */
.mze-act-ligne[b-l53zhguqai]  .mze-input-field {
    flex: 1 1 96px;
    min-width: 0;
}

.mze-act-ligne[b-l53zhguqai]  .mze-button {
    flex: 0 0 auto;
    min-height: var(--mze-touch-min);
    white-space: nowrap;
}

.mze-corbeille-note[b-l53zhguqai] {
    margin: var(--mze-space-2) 0 0;
    font-size: var(--mze-text-size-6);
    line-height: 1.5;
    color: var(--mze-text-muted);
}

.mze-corbeille-note code[b-l53zhguqai] {
    font-family: var(--mze-font-mono);
}

/* Réserve portée DANS l'écran : sans elle, « Supprimer » se réintroduit par symétrie apparente. */
.mze-corbeille-note--alerte[b-l53zhguqai] {
    margin-block-start: var(--mze-space-3);
    padding: var(--mze-space-2);
    color: var(--mze-error);
    background: color-mix(in srgb, var(--mze-error) 7%, var(--mze-bg));
    border-radius: var(--mze-radius-sm);
}

/* ===== Pied ===== */

.mze-corbeille-pied[b-l53zhguqai] {
    flex: 0 0 auto;
    display: grid;
    padding: var(--mze-space-2) var(--mze-space-3);
    background: var(--mze-surface);
    border-block-start: 1px solid var(--mze-border);
}

/* Vider est une action sur l'ensemble, pas une action de masse de plus : rendue en lien, elle ne se
   confond avec aucun des six groupes ci-dessus. */
.mze-corbeille-vider[b-l53zhguqai] {
    justify-self: start;
    min-height: var(--mze-touch-min);
    padding-inline: 0;
    background: transparent;
    border: 0;
    color: var(--mze-accent-contrast);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.mze-corbeille-vider:disabled[b-l53zhguqai] {
    color: var(--mze-text-muted);
    text-decoration: none;
    cursor: default;
}

/* La cible tactile des boutons de retrait suit le registre de l'administration. ::deep : le <button>
   est rendu par MzeButton. */
.mze-corbeille-item[b-l53zhguqai]  .mze-button {
    min-width: var(--mze-touch-min);
    min-height: var(--mze-touch-min);
}
/* /Components/Pages/Admin/CreationRapideProduit.razor.rz.scp.css */
/* Création rapide d'une référence (FEAT-ADMIN-002 phase 4).

   MOBILE-FIRST, cible tablette : les champs s'empilent, un par ligne, et le formulaire tient dans
   un écran sans défilement horizontal — c'est une exigence de la phase, pas un confort.

   Aucune valeur d'axe en dur : tout passe par les tokens --mze-* (CLAUDE.md § CSS et thèmes). */

/* Conteneur de requête : la disposition des champs suit la largeur DU FORMULAIRE, pas celle de la
   fenêtre. Une fenêtre de 800 px peut n'accorder que 400 px au formulaire — un `@media` aurait
   alors mis trois champs de 130 px côte à côte, illisibles et sous la cible tactile. */
.mze-inv-creation-champs[b-telv4gsk5f] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    container-type: inline-size;
}

/* Type et prix : deux champs courts, empilés sur mobile, côte à côte dès qu'il y a la place.
   Les mettre sur une ligne dès le mobile ferait deux colonnes de 120 px sur une tablette tenue en
   portrait — la cible tactile passerait avant la lisibilité du libellé. */
.mze-inv-creation-ligne[b-telv4gsk5f] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
}

.mze-inv-creation-ligne > *[b-telv4gsk5f] {
    min-width: 0;
}

/* Trois champs sur une ligne seulement quand le formulaire a la place de les porter : à 640 px, ils
   font ~200 px chacun, ce qui reste lisible. En deçà — téléphone, ou fenêtre étroite — ils
   s'empilent, chacun sur toute la largeur. */
@container (min-width: 640px) {
    .mze-inv-creation-ligne[b-telv4gsk5f] {
        flex-direction: row;
    }

    /* ::deep obligatoire : la racine visée appartient au markup de MzeSelect et de MzeInput, pas à
       cette page. Sans lui, la règle exige que l'enfant porte le scope d'ici — ce qu'un composant
       enfant n'a jamais, et elle serait silencieusement inopérante (leçon de BUG-ADMIN-002). */
    .mze-inv-creation-ligne[b-telv4gsk5f] >  * {
        flex: 1 1 0;
        min-width: 0;
    }
}

/* Les photos prises à l'instant sont stylées par PhotosProduit, d'où le bloc a été extrait. */

/* Refus renvoyé par la base plutôt que par un champ : le message porte sur le formulaire entier,
   il ne peut pas s'accrocher sous un contrôle. */
.mze-inv-creation-erreur[b-telv4gsk5f] {
    margin: 0;
    color: var(--mze-error);
    font-size: var(--mze-text-size-3);
}
/* /Components/Pages/Admin/EditeurCollection.razor.rz.scp.css */
/* Éditeur d'une collection (FEAT-ADMIN-026). Tokens uniquement. */

.mze-editeur-collection[b-bq87jxne1e] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

.mze-editeur-collection-filet[b-bq87jxne1e] {
    width: 100%;
    margin: var(--mze-space-1) 0 0;
    border: 0;
    border-top: 1px solid var(--mze-border);
}
/* /Components/Pages/Admin/FicheProduit.razor.rz.scp.css */
/* Fiche produit d'administration (FEAT-ADMIN-002 phase 5).

   Aucune valeur d'axe en dur : couleurs, espacements, rayons et tailles passent tous par un token
   `--mze-*` du socle. Un token absent ne produit RIEN et ne signale rien — c'est le mode de
   défaillance de BUG-ADMIN-002, que l'invariant TokensDesignSystemTests verrouille désormais.

   Mobile-first : la base décrit le téléphone, les surcharges montent aux paliers supérieurs. */

.mze-fiche[b-ovu86l55ei] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    min-height: 0;
}

/* ------------------------------------------------------------------ En-tête d'identité */

.mze-fiche[b-ovu86l55ei]  .mze-fiche-tete {
    display: grid;
    grid-template-columns: auto auto 1fr;
    grid-template-areas:
        "retour vignette identite"
        "etat   etat     etat";
    align-items: center;
    gap: var(--mze-space-3);
    padding-bottom: var(--mze-space-3);
    border-bottom: 1px solid var(--mze-border);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-retour { grid-area: retour; }

.mze-fiche[b-ovu86l55ei]  .mze-fiche-vignette {
    grid-area: vignette;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    overflow: hidden;
    border-radius: var(--mze-radius-md);
    background: var(--mze-surface-alt);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-vignette img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Le motif « sans photo » est un SIGNAL de complétude, pas un vide : une case blanche ne se
   distingue pas d'une image en cours de chargement. */
.mze-fiche[b-ovu86l55ei]  .mze-fiche-vignette--absente {
    color: var(--mze-text-muted);
    border: 1px dashed var(--mze-border);
    background: transparent;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-identite { grid-area: identite; min-width: 0; }

.mze-fiche[b-ovu86l55ei]  .mze-fiche-identite h1 {
    margin: 0;
    font-size: var(--mze-text-size-3);
    line-height: 1.2;

    /* Un nom de catalogue peut être long : il s'ellipse plutôt que de pousser l'état hors écran. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-reference {
    margin: 0;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-5);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-etat {
    grid-area: etat;
    display: flex;
    align-items: center;
    gap: var(--mze-space-2);
}

/* ---------------------------------------------------------------------------- Onglets */

/* La bande d'onglets PASSE À LA LIGNE au lieu de déborder.

   Défaut trouvé à la recette écran du 2026-08-24 : huit onglets font 870 px, et la bande était
   rendue en `flex-wrap: nowrap` dans un conteneur de 306 px sur un Galaxy S25. Le débordement
   n'était pas visible au niveau du document — il était absorbé par le scroller horizontal de
   `.mze-admin-page` —, si bien qu'un contrôle de `scrollWidth` sur la page le déclarait sain.

   Deux conséquences, et la seconde est la pire : cinq onglets sur huit hors du champ, et le
   défilement qui les ramène emporte TOUT le contenu de l'écran, formulaire compris, puisqu'il
   appartient au conteneur de page et non à la bande.

   Même arbitrage que le régime mobile de FEAT-ADMIN-023 pour sa bande de vues : le défilement
   horizontal cache SANS LE DIRE. Le passage à la ligne, lui, montre tout.

   Pas de point de rupture : au-delà de 768 px les huit onglets tiennent sur une ligne, et
   `wrap` n'y change donc rien. Un seuil qui ne fait rien d'un côté est un seuil de trop. */
.mze-fiche[b-ovu86l55ei]  .mze-fiche-onglets {
    /* `flex: 0 0 auto` — la bande ne rétrécit JAMAIS.

       Second temps du même défaut : une fois le passage à la ligne obtenu, la bande occupait trois
       lignes mais gardait une hauteur de 10 px, et ses onglets se peignaient PAR-DESSUS le
       formulaire. La cause était un `min-height: 0` posé ici : le shell d'administration cloue la
       page à la hauteur de la fenêtre, et un élément de colonne flex qui autorise sa propre
       compression se fait écraser sous son contenu. `min-height: 0` a sa place sur un conteneur
       DÉFILANT, pas sur une bande qui doit occuper la place de son contenu. */
    flex: 0 0 auto;

    /* `width: auto` neutralise le `width: max-content` que `mze-pills.css` pose sur la bande. Sans
       lui, `flex-wrap` ne peut RIEN faire : la bande se dimensionne sur son contenu déplié, donc
       elle n'a jamais besoin de passer à la ligne. C'est ce qui a fait croire le correctif inopérant
       au premier essai — la propriété était bien calculée à `wrap`, et la largeur restait à 870 px.

       ⚠ Point de coordination [ADR-002] : le plafond manque au socle, où `.mze-pills` déborde en
       silence dès qu'un consommateur a plus de pilules que de place. Corrigé ici seulement, parce
       qu'un `flex-wrap` posé sur la règle partagée changerait le rendu de ses consommateurs
       existants — ce n'est pas additif. À porter au socle avec eux. */
    width: auto;
    max-width: 100%;
    flex-wrap: wrap;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-onglet {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    padding-top: var(--mze-space-3);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-bloc {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-bloc h2 {
    margin: 0;
    font-size: var(--mze-text-size-5);
    font-weight: var(--mze-font-weight-semibold);
    color: var(--mze-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Empilement en base — c'est un téléphone. La mise en ligne arrive au palier tablette. */
.mze-fiche[b-ovu86l55ei]  .mze-fiche-ligne {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--mze-space-2);
    padding-top: var(--mze-space-3);
    border-top: 1px solid var(--mze-border);
}

/* ------------------------------------------------------------------- Notes et renvois */

.mze-fiche[b-ovu86l55ei]  .mze-fiche-note,
.mze-fiche[b-ovu86l55ei]  .mze-fiche-renvoi-note {
    display: flex;
    align-items: center;
    gap: var(--mze-space-2);
    margin: 0;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-5);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-erreur {
    margin: 0;
    color: var(--mze-error);
    font-size: var(--mze-text-size-5);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-renvoi {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    padding-top: var(--mze-space-3);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-paires {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--mze-space-2) var(--mze-space-4);
    margin: 0;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-paires dt { color: var(--mze-text-muted); }
.mze-fiche[b-ovu86l55ei]  .mze-fiche-paires dd { margin: 0; font-weight: var(--mze-font-weight-medium); }

.mze-fiche[b-ovu86l55ei]  .mze-fiche-chiffre {
    display: flex;
    align-items: baseline;
    gap: var(--mze-space-2);
    margin: 0;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-chiffre strong { font-size: var(--mze-text-size-3); }
.mze-fiche[b-ovu86l55ei]  .mze-fiche-chiffre span { color: var(--mze-text-muted); }

.mze-fiche[b-ovu86l55ei]  .mze-fiche-secondaire {
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

/* -------------------------------------------------------------------------- Tableaux */

/* Le tableau défile DANS son conteneur, jamais la page : un débordement horizontal de page rend
   tout l'écran glissant sur téléphone, y compris les zones qui n'ont rien de large. */
.mze-fiche[b-ovu86l55ei]  .mze-fiche-table {
    display: block;
    width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    font-size: var(--mze-text-size-5);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-table th,
.mze-fiche[b-ovu86l55ei]  .mze-fiche-table td {
    padding: var(--mze-space-2) var(--mze-space-3);
    text-align: left;
    white-space: nowrap;
    border-bottom: 1px solid var(--mze-border);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-table th {
    color: var(--mze-text-muted);
    font-weight: var(--mze-font-weight-semibold);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-col-num { text-align: right; }

/* --------------------------------------------------------------- Images et suggestions */

.mze-fiche[b-ovu86l55ei]  .mze-fiche-images {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-images img {
    width: 88px;
    height: 88px;
    object-fit: cover;
    border-radius: var(--mze-radius-md);
    border: 1px solid var(--mze-border);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-propositions,
.mze-fiche[b-ovu86l55ei]  .mze-fiche-liens {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-propositions li,
.mze-fiche[b-ovu86l55ei]  .mze-fiche-liens li {
    display: flex;
    align-items: center;
    gap: var(--mze-space-3);
    padding: var(--mze-space-2);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-proposition-visuel {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    overflow: hidden;
    border-radius: var(--mze-radius-sm);
    background: var(--mze-surface-alt);
    color: var(--mze-text-muted);
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-proposition-visuel img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-proposition-texte {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.mze-fiche[b-ovu86l55ei]  .mze-fiche-proposition-texte strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ------------------------------------------------------------------------ État vide */

.mze-fiche-vide[b-ovu86l55ei] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--mze-space-3);
    padding: var(--mze-space-6) var(--mze-space-4);
    color: var(--mze-text-muted);
    text-align: center;
}

/* -------------------------------------------------------------------------- Tablette */

@media (min-width: 768px) {
    .mze-fiche[b-ovu86l55ei]  .mze-fiche-tete {
        grid-template-columns: auto auto 1fr auto;
        grid-template-areas: "retour vignette identite etat";
    }

    .mze-fiche[b-ovu86l55ei]  .mze-fiche-ligne {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: flex-start;
    }

    /* Les champs partagent la ligne sans descendre sous une largeur illisible : à l'étroit, ils
       repassent à la ligne d'eux-mêmes plutôt que de se comprimer. */
    .mze-fiche[b-ovu86l55ei]  .mze-fiche-ligne > * {
        flex: 1 1 220px;
        min-width: 0;
    }

    .mze-fiche[b-ovu86l55ei]  .mze-fiche-table { display: table; }
}
/* /Components/Pages/Admin/Inventaire.razor.rz.scp.css */
/* Inventaire — liste du catalogue de gestion (FEAT-ADMIN-002).

   MOBILE-FIRST STRICT, cible tablette (décision 2 de la spec) : la base est l'empilement en
   colonne, les surcharges montent aux breakpoints supérieurs. Cet écran est conçu pour être
   utilisé à même l'atelier, pas au bureau.

   Aucune valeur d'axe en dur : tout passe par les tokens --mze-* (CLAUDE.md § CSS et thèmes).
   Ce bloc n'a qu'un consommateur — cette page — il vit donc dans son .razor.css et pas en global.
   Du CSS global reprenant ces classes écraserait le scope des composants (leçon de SITE-004). */

/* L'écran occupe la hauteur restante et c'est la GRILLE qui défile, pas la page.

   `flex: 1` prend la hauteur laissée par le titre et la barre d'outils dans `.mze-admin-page` ;
   `min-height: 0` est la moitié indispensable — sans elle, un enfant flex refuse de descendre
   sous la hauteur de son contenu et la grille pousserait la page au lieu de défiler chez elle.
   `MzeGrid` fait le reste : sa racine est déjà `flex: 1 1 auto; min-height: 0` et son corps
   porte l'`overflow: auto`. C'est aussi ce qui rend l'auto-pagesize exact — le module JS mesure
   la hauteur réellement disponible, il ne la devine pas. */
.mze-inv[b-4j052pd7gz] {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    gap: var(--mze-space-4);
}

/* ===== Titre et action primaire ===== */

/* En base (mobile), le bouton passe sous le titre et prend toute la largeur : c'est la cible
   tactile la plus généreuse possible, et la saisie est l'action principale de l'écran. */
.mze-inv-titre[b-4j052pd7gz] {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--mze-space-2);
    margin-block-end: var(--mze-space-4);
}

/* ===== Filtres — repliés sur téléphone, déployés au-delà ===== */

/* À partir de la tablette, l'accordéon s'efface : son en-tête disparaît et son panneau reste
   ouvert quoi qu'il arrive. Un seul markup sert les deux régimes, et l'état de repli choisi sur
   téléphone ne peut pas masquer les filtres sur poste fixe.

   ::deep obligatoire : en-tête et panneau appartiennent au markup de MzeAccordionItem, pas à cette
   page (leçon de BUG-ADMIN-002). */
/* Le panneau de l'accordéon ne porte aucun rythme vertical — c'est au consommateur de le donner,
   un conteneur générique n'a pas à imposer une mise en page à ce qu'on lui confie. Sans cette
   règle, les cases de complétude se collent aux sélecteurs : les deux blocs étaient frères dans
   `.mze-inv` et bénéficiaient de son `gap`, ils ne le sont plus. */
.mze-inv[b-4j052pd7gz]  .mze-accordion-panel-inner {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
}

/* ⚠ Le sélecteur part de `.mze-inv`, un élément de CETTE page, et non de `.mze-inv-filtres` qui est
   la racine de MzeAccordion : une classe passée en `CssClass` atterrit sur le markup de l'ENFANT et
   porte donc le scope de l'enfant, jamais celui de la page. La règle ne s'appliquait pas.

   La HAUTEUR compte autant que la largeur : la tablette d'atelier fait 853 × 533 en paysage — assez
   large pour le régime « poste fixe », mais si basse qu'une barre de filtres dépliée y laisserait
   quatre lignes de grille. On ne déplie donc que si l'écran a aussi la hauteur de le porter. */
@media (min-width: 768px) and (min-height: 640px) {
    .mze-inv[b-4j052pd7gz]  .mze-accordion-header {
        display: none;
    }

    .mze-inv[b-4j052pd7gz]  .mze-accordion-panel[hidden] {
        display: block;
    }

    .mze-inv[b-4j052pd7gz]  .mze-accordion-panel-inner {
        padding: 0;
    }

    /* `overflow: visible` est indispensable, pas cosmétique. L'item de l'accordéon rogne son contenu
       pour que son radius coupe proprement ses coins ; ici il n'a plus ni radius, ni bordure, ni
       fond, et le contenu commence PILE à son bord gauche. Résultat : la bordure de la première case
       à cocher était coupée — et son anneau de focus l'aurait été aussi, ce qui rend la tabulation
       invisible sur le premier filtre. */
    .mze-inv[b-4j052pd7gz]  .mze-accordion-item {
        border: none;
        background: transparent;
        overflow: visible;
    }
}

/* ===== Écran bas — la tablette d'atelier en paysage (853 × 533) ===== */

/* Sur un écran de moins de 640 px de haut, chaque pixel du chrome est une fraction de ligne. Les
   espacements de lecture (24 px sous le bouton, 24 px entre les blocs) y coûtaient une ligne de
   grille entière : la liste tombait à 2 lignes en paysage, 7 en portrait — même classe de défaut que
   le point 53 de la vue catalogue (recette de la phase 7, 2026-10-06). Seuil identique à celui de
   l'accordéon des filtres : les deux réglages basculent ensemble. */
@media (max-height: 639.98px) {
    /* 4 px et non 8 : à 8, il manquait 4 px pour la quatrième ligne en paysage (220 disponibles pour
       216 requis, mesuré au bac). */
    .mze-inv-titre[b-4j052pd7gz] {
        margin-block-end: var(--mze-space-1);
    }

    .mze-inv[b-4j052pd7gz] {
        gap: var(--mze-space-1);
    }
}

/* ===== Barre d'outils ===== */

.mze-inv-outils[b-4j052pd7gz] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
}

/* La recherche occupe toute la largeur disponible : c'est le chemin principal vers une
   référence sur un parc de plusieurs milliers d'objets. */
.mze-inv-recherche[b-4j052pd7gz] {
    flex: 1 1 100%;
    min-width: 0;
}

.mze-inv-completude[b-4j052pd7gz] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mze-space-3);
}

/* ===== Actions de masse ===== */

.mze-inv-masse[b-4j052pd7gz] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    padding: var(--mze-space-3);
    border: 1px solid var(--mze-accent);
    border-radius: var(--mze-radius-md);
    background: var(--mze-surface-alt);
}

.mze-inv-masse-compte[b-4j052pd7gz] {
    font-weight: var(--mze-weight-heading);
    color: var(--mze-accent-contrast);
}

/* ===== Cellules ===== */

.mze-inv-vignette[b-4j052pd7gz] {
    width: 40px;
    height: 40px;
    border-radius: var(--mze-radius-sm);
    object-fit: cover;
    display: block;
}

/* Fiche sans photo : cadre neutre plutôt qu'un trou blanc. C'est le repère de complétude de la
   campagne de saisie — il doit se lire d'un coup d'œil sur une colonne de 40 px. */
.mze-inv-vignette--absente[b-4j052pd7gz] {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px dashed var(--mze-border);
    color: var(--mze-text-muted);
    background: var(--mze-surface-alt);
}

/* Les collections d'une ligne tiennent sur une ligne, coupées à l'ellipse. Le titre natif porte
   la liste complète — la cellule fait 140 px au minimum, elle ne peut pas tout montrer. */
.mze-inv-collections[b-4j052pd7gz] {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mze-inv-vide[b-4j052pd7gz] {
    color: var(--mze-text-muted);
}

/* ===== Colonnes — une colonne compacte sous 1024 px, les sept colonnes au-delà ===== */

/* Le gabarit vit ICI, avec ses paliers, et la grille le reçoit verbatim par ColumnsTemplate. Masquer
   des cellules sans retirer leurs pistes laisserait des trous à droite ; et les pistes de service
   (case de sélection) ne sont pas préfixées par la grille, d'où le token en tête.

   Base : case, vignette, colonne compacte. Les sept colonnes larges réclament ~1 000 px — en
   dessous, la grille défilait horizontalement et le prix, le stock et l'état boutique ne
   s'atteignaient qu'en la faisant glisser (recette de la phase 7, 2026-10-06). */
.mze-inv[b-4j052pd7gz] {
    --mze-inv-cols: var(--mze-grid-checkbox-col-width) 64px minmax(0, 1fr);
}

/* ::deep obligatoire : en-têtes et cellules appartiennent au markup de MzeGrid et de MzeGridRow. Une
   classe passée en CssClass porte le scope de l'ENFANT. */
@media (max-width: 1023.98px) {
    .mze-inv[b-4j052pd7gz]  .mze-inv-col--large {
        display: none;
    }
}

@media (min-width: 1024px) {
    .mze-inv[b-4j052pd7gz] {
        --mze-inv-cols: var(--mze-grid-checkbox-col-width) 64px minmax(120px, 0.8fr) minmax(180px, 2fr)
                        110px minmax(140px, 1.4fr) 110px 90px 110px;
    }

    .mze-inv[b-4j052pd7gz]  .mze-inv-col--compact {
        display: none;
    }
}

/* Cellule compacte : le nom porte la ligne, la méta s'efface derrière lui. Même registre que la
   colonne compacte de la vue catalogue. */
.mze-inv-compact[b-4j052pd7gz] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.mze-inv-compact strong[b-4j052pd7gz] {
    font-weight: var(--mze-font-weight-medium);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Une seule ligne, coupée à droite : la rangée a une hauteur fixe (pagination calculée sur elle), une
   méta passée à la ligne déborderait sous la ligne suivante. */
.mze-inv-compact-meta[b-4j052pd7gz] {
    display: flex;
    flex-wrap: nowrap;
    overflow: hidden;
    white-space: nowrap;
    align-items: center;
    gap: var(--mze-space-2);
    font-size: var(--mze-text-size-6);
    color: var(--mze-text-muted);
}

/* ===== Tablette ===== */

@media (min-width: 768px) {
    /* À partir de la tablette, le titre et l'action tiennent sur la même ligne. */
    .mze-inv-titre[b-4j052pd7gz] {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .mze-inv-outils[b-4j052pd7gz] {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
    }

    /* La recherche garde la priorité de largeur, les trois sélecteurs se partagent le reste.

       ::deep est OBLIGATOIRE ici : les trois sélecteurs sont des composants MzeSelect, dont la
       racine appartient à LEUR markup. Blazor pose l'attribut de scope sur le dernier sélecteur
       composé — sans ::deep, la règle exige que l'enfant porte le scope de cette page, ce qu'un
       composant enfant n'a jamais. La règle ne s'appliquait pas et les trois sélecteurs
       s'empilaient en pleine largeur, sur tous les paliers. */
    .mze-inv-recherche[b-4j052pd7gz] {
        flex: 2 1 260px;
    }

    .mze-inv-outils[b-4j052pd7gz] >  :not(.mze-inv-recherche) {
        flex: 1 1 180px;
        min-width: 0;
    }

    .mze-inv-masse[b-4j052pd7gz] {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
    }

    .mze-inv-masse-compte[b-4j052pd7gz] {
        margin-inline-end: auto;
    }
}

/* ===== Desktop ===== */

@media (min-width: 1200px) {
    .mze-inv-recherche[b-4j052pd7gz] {
        flex: 1 1 320px;
    }

    .mze-inv-outils[b-4j052pd7gz] >  :not(.mze-inv-recherche) {
        flex: 0 1 220px;
    }
}
/* /Components/Pages/Admin/InventaireCatalogue.razor.rz.scp.css */
/* Inventaire — vue catalogue en régime établi (FEAT-ADMIN-023).

   MOBILE-FIRST STRICT, cible tablette : la base est le rendu compact, les surcharges montent aux
   breakpoints supérieurs. Aucune valeur d'axe en dur — tout passe par les tokens --mze-*.

   DEUX VARIABLES LOCALES, et leur emplacement n'est pas indifférent :

     --mze-cat-cols      gabarit de colonnes, PARTAGÉ entre l'en-tête unique rendu par la page et
                         les lignes de toutes les grilles (MzeGrid.ColumnsTemplate le reçoit en
                         référence de variable, pas en chaîne littérale). Une seule source de
                         vérité, entièrement responsive, sans un seul conditionnel C#.

     --mze-cat-thead-h   décalage de collage des en-têtes de groupe, posé sur .mze-cat-table et
                         JAMAIS sur :root. Posé globalement, il figerait aussi les en-têtes d'une
                         vue sans en-tête de colonnes 38 px trop bas, et le contenu défilerait dans
                         la bande laissée au-dessus. C'est un défaut relevé en maquette. */

.mze-cat[b-vwet49svwm] {
    display: flex;
    flex-direction: column;
    flex: 1;
    /* min-height: 0 est la moitié indispensable : sans elle, un enfant flex refuse de descendre
       sous la hauteur de son contenu, et la zone de contenu pousserait la page au lieu de
       défiler chez elle. */
    min-height: 0;
}

/* ===== Barre supérieure ===== */

.mze-cat-topbar[b-vwet49svwm] {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mze-space-2);
    padding-block-end: var(--mze-space-3);
    border-block-end: 1px solid var(--mze-border);
}

/* Sur téléphone, la recherche prend sa PROPRE LIGNE. Partagée avec le bouton d'action, elle
   tombait à ~120 px : le geste par défaut de l'écran devenait le plus étroit. */
.mze-cat-recherche[b-vwet49svwm] {
    flex: 1 0 100%;
    min-width: 0;
}

/* Bascule Galerie / Tableau et sélecteur de tri : ils gardent leur largeur, la recherche prend le
   reste. Une bascule qui rétrécit avec la fenêtre finirait par cacher son libellé.

   ⚠ LE ::deep PART DE .mze-cat-topbar, PAS DE .mze-cat-modes. Une classe passée en CssClass
   atterrit sur la racine du composant ENFANT et porte l'attribut de scope de l'enfant : une règle
   `.mze-cat-modes ::deep …` ne matche donc jamais rien, sans que rien ne le signale. Le point de
   départ doit être un élément rendu PAR CETTE PAGE — ici l'en-tête. */
.mze-cat-tri[b-vwet49svwm] {
    flex: 0 0 auto;
}

.mze-cat-topbar[b-vwet49svwm]  .mze-cat-modes {
    flex: 0 0 auto;
}

/* Registre tactile de l'administration : le segmenté de socle est dense par défaut (11 px), ce qui
   convient à une barre d'outils de poste fixe, pas à un écran d'atelier utilisé au doigt. */
.mze-cat-topbar[b-vwet49svwm]  .mze-segmented-control-btn {
    min-height: var(--mze-touch-min);
    padding-inline: var(--mze-space-3);
    font-size: var(--mze-text-size-6);
}

/* Le libellé de mode disparaît sur téléphone, où deux icônes côte à côte suffisent à se distinguer
   et où chaque pixel de la barre est disputé. Il revient dès la tablette, cible déclarée de la
   spec — c'est exactement ce que fait la maquette validée. */
.mze-cat-topbar[b-vwet49svwm]  .mze-segmented-control-libelle {
    display: none;
}

/* ===== Vues nommées ===== */

/* ::deep OBLIGATOIRE. `mze-cat-vues` est passée en CssClass à MzeViewPills : elle atterrit sur le
   markup de L'ENFANT et porte le scope de l'enfant, jamais celui de cette page.

   Ce n'est pas une subtilité cosmétique — c'est ce qui empêchait `flex: 0 0 auto` d'arriver. Sans
   lui, la bande héritait de `flex: 0 1 auto` et se faisait ÉCRASER par la colonne dès que la fenêtre
   manquait de hauteur : 20 px pour un contenu qui en réclame 33, libellés coupés en deux et barre de
   défilement par-dessus. Invisible sur un écran haut, systématique sur une tablette en paysage —
   c'est-à-dire sur la cible déclarée de la spec.

   Troisième occurrence de ce piège dans cette feature (après le bouton d'arbre et la bascule de
   mode) : toute classe passée en CssClass à un composant Mze* se vise par ::deep, sans exception. */
.mze-cat[b-vwet49svwm]  .mze-cat-vues {
    flex: 0 0 auto;
    border-block-end: 1px solid var(--mze-border);
}

/* RÉGIME COMPACT — la bande passe à la ligne au lieu de défiler.

   La classe est posée PAR LE C#, jamais par une media query : le seuil de 768 px ne vit qu'à un
   seul endroit, et le rendu conditionnel des vues et de cette mise en page ne peuvent pas se
   contredire. Une media query ferait un second seuil, qui dirait « compact » pendant que l'état C#
   dit « large » si le module d'observation ne répondait pas.

   overflow-x: clip et non visible : le défilement doit disparaître, mais un `visible` autoriserait
   une puce trop longue à déborder du cadre de la page. */
.mze-cat[b-vwet49svwm]  .mze-cat-vues--compact {
    flex-wrap: wrap;
    overflow-x: clip;
    row-gap: var(--mze-space-2);
}

/* Bouton d'ouverture de la feuille des vues. Le badge est collé au libellé — c'est lui l'alerte,
   il ne doit pas se lire comme un compteur de la puce voisine. */
.mze-cat[b-vwet49svwm]  .mze-cat-vues-btn {
    flex: 0 0 auto;
    min-height: var(--mze-touch-min);
    border-radius: var(--mze-radius-pill);
}

/* Filet entre les vues d'anomalie et le bouton de filtres : ils partagent la bande défilante mais
   pas la nature — les unes désignent un problème, l'autre ouvre une composition. Sans séparation,
   « Filtres détaillés » se lit comme une septième vue. */
.mze-cat-sep[b-vwet49svwm] {
    flex: 0 0 auto;
    align-self: stretch;
    width: 1px;
    margin-inline: var(--mze-space-1);
    background: var(--mze-border);
}

/* ===== Arborescence ===== */

/* Sous 1200 px l'arbre est un TIROIR : il se superpose au contenu et se referme au clic extérieur.
   Fermé, MzeCollapsiblePanel ne rend rien du tout (ReleaseSpaceOnClose) — le piège du panneau rangé
   par translateX, qui élargit le document et décale ensuite les panneaux ouverts hors de la vue,
   n'a donc pas lieu d'être ici. */
.mze-cat-arbre[b-vwet49svwm] {
    width: min(320px, 86vw);
    border-inline-end: 1px solid var(--mze-border);
}

/* ===== Corps ===== */

.mze-cat-corps[b-vwet49svwm] {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    /* Référentiel des panneaux en surimpression (corbeille, filtres — phases 5 et 6), de la
       feuille des vues et de la barre d'action flottante (régime compact). */
    position: relative;

    /* Hauteur réservée à la barre d'action flottante. UNE SEULE déclaration, lue par la barre
       elle-même ET par la réserve du scroller : deux valeurs finiraient par diverger, et la
       dernière ligne de la liste redeviendrait inatteignable sans que rien ne le signale. */
    --mze-cat-barre-h: 68px;
}

/* LE CONTENEUR DE DÉFILEMENT UNIQUE.

   C'est lui, et lui seul, qui défile : c'est ce qui rend le parcours continu à travers les groupes,
   et ce qui donne à <Virtualize> le bon référentiel. Les grilles y renoncent au leur par
   ScrollMode="Host" — sans quoi chaque groupe défilerait de son côté et les en-têtes colleraient
   dans la mauvaise boîte. */
.mze-cat-contenu[b-vwet49svwm] {
    flex: 1 1 auto;
    min-width: 0;
    overflow-y: auto;
    /* Le défilement ne se propage pas au conteneur de page une fois la fin atteinte. */
    overscroll-behavior: contain;
}

/* RÉSERVE DE LA BARRE D'ACTION FLOTTANTE.

   C'est le défaut classique du motif « barre ancrée en bas » : elle recouvre les dernières lignes,
   qui deviennent inatteignables — on ne peut pas défiler « sous » un élément ancré. La réserve est
   posée sur le SCROLLER, pas sur son contenu : un padding sur le contenu serait absorbé par la
   marge du dernier groupe, et la hauteur réservée deviendrait approximative.

   La classe suit exactement la condition de rendu de la barre (BarreDActionRendue) : la réserve
   n'existe jamais sans elle, ni l'inverse. */
.mze-cat-contenu--barre[b-vwet49svwm] {
    padding-block-end: var(--mze-cat-barre-h);
}

.mze-cat-vide[b-vwet49svwm] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    padding: var(--mze-space-6) var(--mze-space-3);
    text-align: center;
    color: var(--mze-text-muted);
}

.mze-cat-vide span[b-vwet49svwm] {
    font-size: var(--mze-text-size-6);
}

/* ===== Tableau ===== */

.mze-cat-table[b-vwet49svwm] {
    /* Rendu compact : case, vignette, et une colonne qui empile nom et méta. Les huit colonnes du
       poste fixe ne tiennent pas sur un téléphone, et les réduire les rendrait toutes illisibles. */
    --mze-cat-cols: var(--mze-grid-checkbox-col-width) 48px 1fr;
    /* Aucun en-tête de colonnes sous 768 px : les en-têtes de groupe collent donc à 0. */
    --mze-cat-thead-h: 0px;

    /* Colonnes de la GALERIE — les paliers de la maquette validée : 2 sur téléphone, puis 3, 4 et 6.
       Ils vivent ici, en CSS, et MzeGrid ne fait que les MESURER pour découper ses tranches. Les
       redéclarer en C# créerait une seconde source de vérité qui dériverait à la première retouche. */
    --mze-grid-cards-cols: repeat(2, minmax(0, 1fr));
}

/* En galerie, il n'y a pas d'en-tête de colonnes : le décalage de collage retombe à 0 à TOUTES les
   largeurs. Sans cette remise à zéro, les en-têtes de groupe se figeraient 38 px trop bas et les
   cartes défileraient dans la bande laissée au-dessus — le défaut relevé en maquette. */
.mze-cat-table.mze-cat-table--cartes[b-vwet49svwm] {
    --mze-cat-thead-h: 0px;
}

/* La mention « sans emplacement » d'une carte : elle prend la couleur d'erreur, comme le motif
   hachuré d'une fiche sans photo. Un trou dans le rangement se signale, il ne se devine pas. */
.mze-cat-sans-emplacement[b-vwet49svwm] {
    color: var(--mze-error);
    font-style: normal;
}

/* En-tête de colonnes UNIQUE, rendu par la page. Masqué en rendu compact. */
.mze-cat-thead[b-vwet49svwm] {
    display: none;
}

.mze-cat-groupe[b-vwet49svwm] {
    /* Boîte de confinement de l'en-tête collant. C'est elle qui fait que l'en-tête du groupe
       suivant POUSSE le précédent au lieu de s'empiler au même offset et de le recouvrir : un
       élément collant ne colle que dans la boîte de son parent. */
    display: block;
}

.mze-cat-groupe-tete[b-vwet49svwm] {
    position: sticky;
    top: var(--mze-cat-thead-h);

    /* z-index 10 — SOUS le panneau en surimpression du socle, qui est à 20.

       Descendu de 20 à 10 le 2026-08-24 (point 54 du sprint). À égalité avec le panneau, c'est
       l'ordre du DOM qui tranchait, et la liste vient après : les en-têtes collants se peignaient
       PAR-DESSUS le tiroir de l'arbre ouvert, et le premier masquait « 95 avec photo (99 %) » —
       c'est-à-dire l'un des deux taux que le régime mobile a précisément déplacés dans cet en-tête.

       Le barème de cette page vit donc désormais SOUS celui du socle (20), en gardant son ordre
       interne : en-tête de groupe 10 < en-tête de colonnes 15. Seule la barre d'action flottante
       reste au-dessus (30), et c'est délibéré — elle s'efface en C# dès qu'un panneau s'ouvre. */
    z-index: 10;
    display: flex;
    align-items: center;
    gap: var(--mze-space-3);
    min-height: 42px;
    padding-inline: var(--mze-space-3);
    /* Fond opaque indispensable en collage : sans lui, les lignes défilent visiblement dessous. */
    background: var(--mze-surface-alt);
    border-block: 1px solid var(--mze-border);
}

.mze-cat-groupe-tete h3[b-vwet49svwm] {
    margin: 0;
    font-size: var(--mze-text-size-5);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mze-cat-groupe-compte[b-vwet49svwm],
.mze-cat-groupe-zone[b-vwet49svwm] {
    flex: 0 0 auto;
    font-size: var(--mze-text-size-6);
    color: var(--mze-text-muted);
    font-variant-numeric: tabular-nums;
}

.mze-cat-groupe-zone[b-vwet49svwm] {
    margin-inline-start: auto;
    display: inline-flex;
    align-items: center;
    gap: var(--mze-space-1);
    white-space: nowrap;
}

/* ===== Cellules ===== */

/* Bascule responsive des colonnes, portée par MzeGridColumn.CssClass.

   Déclarative, et c'est le point : viser les colonnes par leur position (:nth-child) devient faux
   dès qu'une colonne est insérée avant elles, sans que rien ne le signale — la mauvaise colonne
   disparaît et l'écran reste correct à la compilation.

   ::deep obligatoire : ces cellules appartiennent au markup de MzeGridRow, pas à cette page. */
.mze-cat-table[b-vwet49svwm]  .mze-cat-col--large {
    display: none;
}

.mze-cat-compact[b-vwet49svwm] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.mze-cat-compact strong[b-vwet49svwm] {
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mze-cat-compact-meta[b-vwet49svwm] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
    font-size: var(--mze-text-size-6);
    color: var(--mze-text-muted);
}

/* Fiche sans photo : cadre neutre plutôt qu'un trou blanc. C'est le premier repère de complétude
   du catalogue, il doit se lire d'un coup d'œil. */
.mze-cat-vignette-absente[b-vwet49svwm] {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 1px dashed var(--mze-border);
    border-radius: var(--mze-radius-sm);
    color: var(--mze-text-muted);
    background: var(--mze-surface-alt);
}

.mze-cat-manquant[b-vwet49svwm] {
    color: var(--mze-text-muted);
}

/* « Aucune unité » n'est pas une rupture commerciale : c'est une fiche à compléter ou un article
   réformé. La couleur d'erreur signale, le libellé du badge dit quoi. */
.mze-cat-parc-zero[b-vwet49svwm] {
    color: var(--mze-error);
    font-weight: 600;
}

/* L'unité s'efface derrière le nombre : c'est le nombre qui est l'information. Sans elle, un « 33 »
   voisin d'un prix se lirait comme une seconde valeur monétaire. */
.mze-cat-parc-unite[b-vwet49svwm] {
    color: var(--mze-text-muted);
    font-weight: 400;
}

/* ===== Tablette — 768 px. Cible déclarée de la spec. ===== */

@media (min-width: 768px) {

    /* Base réduite de 260 à 180 px le 2026-08-24 (point 53 du sprint).

       Le retour à la ligne d'un conteneur `flex-wrap` se décide sur la BASE des items, pas sur leur
       taille rétrécie : à 851 px — la tablette d'atelier en paysage —, une base de 260 faisait
       déborder la ligne, « Nouvelle référence » passait seule en dessous, et la recherche
       re-grandissait ensuite pour occuper la place laissée libre. La barre coûtait donc 115 px au
       lieu de 58 pour un contenu qui tenait sur une ligne.

       La recherche ne perd rien : `flex-grow: 1` la fait toujours occuper tout le reste. La base ne
       décide que du moment où la barre se casse. */
    .mze-cat-recherche[b-vwet49svwm] {
        order: 0;
        flex: 1 1 180px;
    }

    .mze-cat-table[b-vwet49svwm] {
        /* Le tableau devient un vrai tableau : c'est ici qu'il commence à servir. */
        --mze-cat-cols:
            var(--mze-grid-checkbox-col-width)
            52px
            minmax(120px, 0.9fr)
            minmax(160px, 2fr)
            minmax(110px, 1fr)
            96px
            76px
            116px;
        /* Les en-têtes de groupe viennent se coller JUSTE SOUS l'en-tête de colonnes. */
        --mze-cat-thead-h: var(--mze-grid-head-height);
    }

    .mze-cat-thead[b-vwet49svwm] {
        position: sticky;
        top: 0;
        /* Au-dessus des en-têtes de groupe (10), qui doivent passer dessous — et SOUS le panneau en
           surimpression du socle (20). Descendu de 25 à 15 avec eux le 2026-08-24 : à 25, l'en-tête
           de colonnes traversait lui aussi le tiroir de l'arbre ouvert (point 54 du sprint). */
        z-index: 15;
        display: grid;
        grid-template-columns: var(--mze-cat-cols);
        gap: 0;
        height: var(--mze-grid-head-height);
        align-items: center;
        /* Aligné sur la boîte de contenu d'une ligne de MzeGrid, faute de quoi l'en-tête et les
           lignes partagent le même gabarit mais pas la même origine.

           Trois termes, et le troisième se paie cher si on l'oublie : le halo du conteneur de
           lignes, le padding de la ligne, et la BORDURE de la ligne — que l'en-tête ne porte pas.
           Sans ce 1 px, les pistes `fr` de l'en-tête se calculent sur 2 px de plus que celles des
           lignes : l'écart est nul à gauche, atteint 2 px à droite, et grandit avec le nombre de
           colonnes souples. Il ne casse rien, il désaligne juste tout le tableau, doucement. */
        padding-inline: calc(
            var(--mze-grid-halo-padding) + 1px + var(--mze-grid-row-padding-x));
        background: var(--mze-bg-page);
        border-block-end: 1px solid var(--mze-border-strong);
        font-size: var(--mze-grid-head-font-size);
        font-weight: 600;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--mze-text-muted);
    }

    .mze-cat-th[b-vwet49svwm] {
        display: flex;
        align-items: center;
        gap: var(--mze-space-1);
        min-width: 0;
        padding-inline: var(--mze-grid-cell-padding-x);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .mze-cat-th--num[b-vwet49svwm] {
        justify-content: flex-end;
    }

    .mze-cat-th--triable[b-vwet49svwm] {
        cursor: pointer;
        user-select: none;
    }

    .mze-cat-th--triable:hover[b-vwet49svwm] {
        color: var(--mze-text);
    }

    .mze-cat-th--actif[b-vwet49svwm] {
        color: var(--mze-accent-contrast);
    }

    .mze-cat-th-fleche[b-vwet49svwm] {
        flex: 0 0 auto;
        opacity: 0.6;
    }

    .mze-cat-th--actif .mze-cat-th-fleche[b-vwet49svwm] {
        opacity: 1;
    }

    .mze-cat-table[b-vwet49svwm]  .mze-cat-col--large {
        display: flex;
    }

    .mze-cat-table[b-vwet49svwm]  .mze-cat-col--compact {
        display: none;
    }

    .mze-cat-table[b-vwet49svwm]  .mze-cat-col--num {
        justify-content: flex-end;
        font-variant-numeric: tabular-nums;
    }

    .mze-cat-table[b-vwet49svwm] {
        --mze-grid-cards-cols: repeat(3, minmax(0, 1fr));
    }

    .mze-cat-topbar[b-vwet49svwm]  .mze-segmented-control-libelle {
        display: inline;
    }
}

/* ===== Poste fixe ===== */

@media (min-width: 1200px) {

    .mze-cat-recherche[b-vwet49svwm] {
        flex: 1 1 360px;
    }

    .mze-cat-table[b-vwet49svwm] {
        --mze-grid-cards-cols: repeat(4, minmax(0, 1fr));
    }
}

@media (min-width: 1600px) {

    .mze-cat-table[b-vwet49svwm] {
        --mze-grid-cards-cols: repeat(6, minmax(0, 1fr));
    }
}

/* ===== Rappel de sélection, en barre d'état ===== */

/* ::deep OBLIGATOIRE — quatrième occurrence du piège dans cette feature. `mze-cat-corbeille-btn` est
   passée en CssClass à MzeButton : elle atterrit sur le <button> rendu par L'ENFANT et porte le
   scope de l'enfant. Sans ::deep, la règle ne s'appliquerait jamais, sans erreur ni avertissement —
   le rappel resterait un bouton carré au milieu des compteurs, indiscernable d'un libellé de barre.

   Le point de départ du sélecteur est `.mze-cat`, rendu par cette page : un ::deep partant de la
   classe elle-même ne matcherait rien, puisqu'elle appartient déjà au markup de l'enfant. */
.mze-cat[b-vwet49svwm]  .mze-cat-corbeille-btn {
    flex: 0 0 auto;
    min-height: var(--mze-touch-min);
    border-radius: var(--mze-radius-pill);
    font-weight: 600;
}

/* ===== Régime compact — barre d'action flottante et feuille des vues ===== */

/* LA BARRE D'ACTION FLOTTANTE.

   Ancrée au bas de la zone de contenu, pas de la fenêtre : elle partage le référentiel des
   panneaux, donc elle ne recouvre ni la barre d'état ni la barre supérieure. Rendue SEULEMENT
   quand la sélection existe — zéro hauteur permanente.

   z-index 30 : au-dessus des en-têtes de groupe collants (10) et de l'en-tête de colonnes (15).
   Sans ça, un en-tête collant passerait par-dessus le seul contrôle qui dise combien de références
   sont retenues.

   ⚠ Elle n'est PAS sous les panneaux du socle (20), contrairement à ce que ce commentaire affirmait
   jusqu'au 2026-08-24 : 30 > 20. C'est le RENDU CONDITIONNEL EN C# qui tient cette règle — la barre
   s'efface dès qu'un panneau est déployé (régime mobile, 2026-08-19), sans quoi elle recouvrait le
   pied de la corbeille, c'est-à-dire ses actions de masse. Baisser sa valeur ici ne remplacerait pas
   ce rendu conditionnel : une barre simplement passée dessous resterait visible sur la portion
   d'écran que le panneau ne couvre pas. */
.mze-cat-barre[b-vwet49svwm] {
    position: absolute;
    z-index: 30;
    inset-inline: var(--mze-space-3);
    inset-block-end: var(--mze-space-3);
    display: flex;
    align-items: center;
    gap: var(--mze-space-2);
    padding: var(--mze-space-2);
    background: var(--mze-surface);
    border: 1px solid var(--mze-border-strong);
    border-radius: var(--mze-radius-pill);
    box-shadow: var(--mze-shadow-lg);
}

/* Le rappel prend toute la place restante : c'est lui l'information, le vidage n'est qu'une
   échappatoire. */
.mze-cat-barre[b-vwet49svwm]  .mze-cat-corbeille-btn {
    flex: 1 1 auto;
    justify-content: center;
}

.mze-cat-barre[b-vwet49svwm]  .mze-cat-barre-vider {
    flex: 0 0 auto;
    min-width: var(--mze-touch-min);
    min-height: var(--mze-touch-min);
    border-radius: var(--mze-radius-pill);
}

/* LA FEUILLE DES VUES.

   ::deep obligatoire — `mze-cat-feuille` est passée en CssClass à MzeCollapsiblePanel : elle
   atterrit sur le markup de l'ENFANT et porte le scope de l'enfant. Sans lui, la règle ne
   s'appliquerait jamais, sans erreur ni avertissement. */
.mze-cat-corps[b-vwet49svwm]  .mze-cat-feuille {
    border-start-start-radius: var(--mze-radius-card);
    border-start-end-radius: var(--mze-radius-card);
}

/* Les vues s'empilent en colonne : une feuille n'a pas de raison de reproduire la bande
   horizontale qu'elle remplace, et une puce par ligne rend le compteur lisible d'un coup d'œil. */
.mze-cat-corps[b-vwet49svwm]  .mze-cat-feuille-vues {
    flex-direction: column;
    align-items: stretch;
    overflow-x: visible;
    padding-inline: var(--mze-space-3);
}

/* ===== Taux de complétude, remontés dans l'en-tête de l'arborescence ===== */

/* Le span est rendu par CETTE page (fragment HeaderContent) : il porte donc le scope de la page,
   et se vise sans ::deep — contrairement à une classe passée en CssClass. */
.mze-cat-taux[b-vwet49svwm] {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--mze-space-1) var(--mze-space-2);
    font-size: var(--mze-text-size-6);
    color: var(--mze-text-muted);

    /* Réserve pour le bouton « Fermer » du panneau, qui flotte AU-DESSUS de cet en-tête.

       Défaut trouvé le 2026-08-24, en recettant le point 54 : en tiroir, la croix occupe le coin
       haut-droit du panneau et mordait les 12 derniers pixels du premier taux — « 95 avec photo
       (99 % » sans sa parenthèse fermante. Il n'était pas visible plus tôt parce que les en-têtes
       collants se peignaient par-dessus le tiroir et masquaient la collision.

       La réserve est posée sans condition : arbre épinglé, il n'y a pas de croix, mais l'en-tête a
       de la place et quelques pixels à droite ne se voient pas. Un rendu conditionnel ici aurait
       ajouté un second endroit où le régime se décide, alors qu'il ne vit qu'en C#. */
    padding-inline-end: var(--mze-space-5);
}

.mze-cat-taux-item[b-vwet49svwm] {
    white-space: nowrap;
}

.mze-cat-taux-item b[b-vwet49svwm] {
    color: var(--mze-text);
    font-variant-numeric: tabular-nums;
}
/* /Components/Pages/Admin/Journal.razor.rz.scp.css */
/* Journal d'activité (FEAT-ADMIN-015). L'écran remplit la hauteur du shell et la grille défile en
   elle-même, comme l'inventaire : `flex: 1` ET `min-height: 0` sur toute la chaîne. */

.mze-journal[b-j2lzhd5odm] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    flex: 1;
    min-height: 0;
}

/* Filtres empilés sur téléphone, en ligne au palier tablette. */
.mze-journal-filtres[b-j2lzhd5odm] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

@media (min-width: 768px) {
    .mze-journal-filtres[b-j2lzhd5odm] {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: flex-start;
    }

    .mze-journal-filtres[b-j2lzhd5odm] >  * {
        flex: 1 1 180px;
        min-width: 0;
    }
}
/* /Components/Pages/Admin/Messages.razor.rz.scp.css */
/* Messages de contact (FEAT-SITE-016). La grille remplit la hauteur du shell. Tokens uniquement. */

.mze-messages[b-te5nqoq6xp] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    flex: 1;
    min-height: 0;
}

.mze-messages-detail[b-te5nqoq6xp] {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--mze-space-1) var(--mze-space-4);
    margin: 0 0 var(--mze-space-3);
}

.mze-messages-detail dt[b-te5nqoq6xp] {
    color: var(--mze-text-muted);
}

.mze-messages-detail dd[b-te5nqoq6xp] {
    margin: 0;
}

/* Le message garde ses sauts de ligne, sans jamais être interprété. */
.mze-messages-texte[b-te5nqoq6xp] {
    margin: 0;
    white-space: pre-wrap;
    padding: var(--mze-space-3);
    border-radius: var(--mze-radius-md);
    background: var(--mze-surface-alt);
}
/* /Components/Pages/Admin/OngletApparenceSite.razor.rz.scp.css */
/* Aperçu du thème choisi (FEAT-ADMIN-015). Le conteneur porte `data-theme` : il est rendu avec les
   tokens de CE thème, indépendamment de celui de l'administration. Tokens uniquement. */

.mze-apercu-theme[b-vsusels8px] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
    padding: var(--mze-space-5) var(--mze-space-4);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
    background: var(--mze-bg-page);
    color: var(--mze-text);
    font-family: var(--mze-font-body);
}

.mze-apercu-theme__accroche[b-vsusels8px] {
    margin: 0;
    color: var(--mze-accent-contrast);
    font-family: var(--mze-font-tagline);
    font-size: var(--mze-text-size-6);
    text-transform: uppercase;
    letter-spacing: 0.12em;
}

.mze-apercu-theme__titre[b-vsusels8px] {
    margin: 0;
    font-family: var(--mze-font-heading);
    font-size: var(--mze-text-size-2);
    line-height: 1.2;
}

.mze-apercu-theme__texte[b-vsusels8px] {
    margin: 0;
    color: var(--mze-text-muted);
}

.mze-apercu-theme__actions[b-vsusels8px] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
    padding-top: var(--mze-space-2);
}
/* /Components/Pages/Admin/OrigineVisites.razor.rz.scp.css */
/* Origine géographique des visites (FEAT-INFRA-005). Une teinte pour la grandeur ; texte aux couleurs
   de texte ; légende et infobulle posées sur la carte. */

.mze-geo-entete[b-jw1vg7nux2] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--mze-space-3);
}

.mze-geo-corps[b-jw1vg7nux2] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--mze-space-4);
}

.mze-geo-carte[b-jw1vg7nux2] {
    position: relative;
    align-self: start;
    height: var(--mze-chart-map-height);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
    overflow: hidden;
    background: var(--mze-surface);
}

.mze-geo-tables[b-jw1vg7nux2] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
}

.mze-geo-legende[b-jw1vg7nux2] {
    position: absolute;
    left: var(--mze-space-2);
    bottom: var(--mze-space-2);
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-1);
    padding: var(--mze-space-1) var(--mze-space-2);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-sm);
    background: var(--mze-surface);
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-geo-legende-titre[b-jw1vg7nux2] {
    color: var(--mze-text);
}

.mze-geo-pas[b-jw1vg7nux2],
.mze-geo-ronds[b-jw1vg7nux2] {
    display: flex;
    align-items: flex-end;
    gap: var(--mze-space-2);
}

.mze-geo-pas-item[b-jw1vg7nux2],
.mze-geo-rond-legende[b-jw1vg7nux2] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--mze-chart-gap);
    font-variant-numeric: tabular-nums;
}

/* Pastille de palier : la couleur des aplats, l'opacité de la classe posée en ligne par le code. */
.mze-geo-pas-item i[b-jw1vg7nux2] {
    display: block;
    width: var(--mze-space-5);
    height: var(--mze-chart-magnitude);
    border-radius: var(--mze-chart-gap);
    background: var(--mze-accent-contrast);
}

.mze-geo-rond-legende i[b-jw1vg7nux2] {
    display: block;
    border: 2px solid var(--mze-surface);
    border-radius: 50%;
    background: var(--mze-accent);
    box-shadow: 0 0 0 1px var(--mze-accent-contrast);
}

/* Infobulle de survol, au point du pointeur (posé en ligne). */
.mze-geo-info[b-jw1vg7nux2] {
    position: absolute;
    z-index: 2;
    transform: translate(-50%, calc(-100% - var(--mze-space-2)));
    pointer-events: none;
    white-space: nowrap;
    padding: var(--mze-space-1) var(--mze-space-2);
    border-radius: var(--mze-radius-sm);
    background: var(--mze-bg-dark);
    color: var(--mze-text-on-dark);
    font-size: var(--mze-text-size-6);
}

/* Étiquettes des trois premières villes : éléments créés par MapLibre dans la carte. */
.mze-geo-carte[b-jw1vg7nux2]  .mze-geo-etiquette {
    padding: 0 var(--mze-space-1);
    border-radius: var(--mze-radius-sm);
    background: var(--mze-surface);
    color: var(--mze-text);
    font-size: var(--mze-text-size-6);
    font-weight: var(--mze-font-weight-semibold);
    pointer-events: none;
    /* MapLibre positionne l'élément par transform en ligne : le décalage au-dessus du rond passe par top. */
    top: calc(-1 * var(--mze-space-3));
}

.mze-geo-muet[b-jw1vg7nux2] {
    color: var(--mze-text-muted);
}

.mze-geo .mze-geo-actif td[b-jw1vg7nux2] {
    background: var(--mze-border);
}

@media (min-width: 768px) {
    .mze-geo-carte[b-jw1vg7nux2] {
        height: var(--mze-chart-map-height-md);
    }
}

@media (min-width: 1024px) {
    .mze-geo-corps[b-jw1vg7nux2] {
        grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    }

    .mze-geo-carte[b-jw1vg7nux2] {
        height: var(--mze-chart-map-height-lg);
    }
}
/* /Components/Pages/Admin/PanneauFiltresInventaire.razor.rz.scp.css */
/* Panneau de filtres détaillés (FEAT-ADMIN-023, phase 5).

   Le corps défile, le pied ne défile pas : le compte vivant et « Enregistrer comme vue » doivent
   rester sous les yeux pendant la composition. Un pied qui défile avec les six groupes obligerait à
   descendre pour lire le résultat de ce qu'on vient de cocher — soit exactement la lecture que le
   caractère non modal du panneau cherche à rendre immédiate. */

.mze-fpanel[b-sr1jw8b6ep] {
    display: flex;
    flex-direction: column;
    /* min-height: 0 est la moitié indispensable : sans elle, le corps refuse de descendre sous la
       hauteur de son contenu et c'est le panneau entier qui déborde, pied compris. */
    min-height: 0;
    height: 100%;
    background: var(--mze-surface);
}

.mze-fpanel-corps[b-sr1jw8b6ep] {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Arrivé en bout de course, le défilement ne se propage pas à la liste derrière : le panneau est
       non modal, et emporter la liste au dernier coup de molette serait une surprise. */
    overscroll-behavior: contain;
}

/* ===== Groupes ===== */

.mze-fgroup[b-sr1jw8b6ep] {
    padding: var(--mze-space-3);
    border-block-end: 1px solid var(--mze-border);
}

.mze-fgroup--dernier[b-sr1jw8b6ep] {
    border-block-end: 0;
}

.mze-fgroup > h3[b-sr1jw8b6ep] {
    margin: 0 0 var(--mze-space-2);
    font-size: var(--mze-text-size-6);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mze-text-muted);
}

.mze-fopts[b-sr1jw8b6ep] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
}

/* Registre tactile de l'administration. La pastille de socle est dimensionnée pour un compteur
   inline ; posée en option cliquable dans un écran d'atelier utilisé au doigt, elle doit atteindre
   la cible minimale que .mze-admin déclare.

   ::deep obligatoire : le <button> est rendu par MzeBadge, pas par ce composant. */
.mze-fopts[b-sr1jw8b6ep]  .mze-badge {
    min-height: var(--mze-touch-min);
    height: auto;
}

.mze-frow[b-sr1jw8b6ep] {
    display: flex;
    align-items: flex-start;
    gap: var(--mze-space-2);
    margin-block-start: var(--mze-space-3);
}

.mze-frow > *[b-sr1jw8b6ep] {
    flex: 1 1 0;
    min-width: 0;
}

.mze-fnote[b-sr1jw8b6ep] {
    margin: var(--mze-space-2) 0 0;
    font-size: var(--mze-text-size-6);
    line-height: 1.5;
    color: var(--mze-text-muted);
}

.mze-fnote code[b-sr1jw8b6ep] {
    font-family: var(--mze-font-mono);
}

/* Réserve technique portée DANS l'écran, pas seulement dans un document : filtrer sur le parc coûte
   le même regroupement sur toute la table que le trier, ce que TriInventaire écarte déjà. Sans
   cette note, le groupe manquant se réintroduit par oubli — personne ne retrouve la raison de son
   absence six mois plus tard. */
.mze-fnote--alerte[b-sr1jw8b6ep] {
    margin-block-start: var(--mze-space-3);
    padding: var(--mze-space-2);
    color: var(--mze-error);
    background: color-mix(in srgb, var(--mze-error) 7%, var(--mze-bg));
    border-radius: var(--mze-radius-sm);
}

/* ===== Pied ===== */

.mze-fpanel-pied[b-sr1jw8b6ep] {
    flex: 0 0 auto;
    display: grid;
    gap: var(--mze-space-2);
    padding: var(--mze-space-3);
    background: var(--mze-surface);
    border-block-start: 1px solid var(--mze-border);
}

.mze-fcount[b-sr1jw8b6ep] {
    margin: 0;
    font-size: var(--mze-text-size-3);
}

.mze-fcount b[b-sr1jw8b6ep] {
    font-variant-numeric: tabular-nums;
}

/* Zéro résultat se signale : c'est l'issue qu'on veut voir AVANT de refermer le panneau. */
.mze-fcount--zero b[b-sr1jw8b6ep] {
    color: var(--mze-error);
}

.mze-fcount-neutre[b-sr1jw8b6ep] {
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-fsave[b-sr1jw8b6ep] {
    display: flex;
    align-items: flex-start;
    gap: var(--mze-space-2);
}

.mze-fsave > *:first-child[b-sr1jw8b6ep] {
    flex: 1 1 auto;
    min-width: 0;
}

.mze-fmessage[b-sr1jw8b6ep] {
    margin: 0;
    font-size: var(--mze-text-size-6);
    color: var(--mze-text-muted);
}

.mze-fmessage--erreur[b-sr1jw8b6ep] {
    color: var(--mze-error);
}

/* « Tout effacer » est une action sur l'ensemble, pas un critère de plus : rendu en lien, il ne se
   confond avec aucune option des six groupes. */
.mze-fclear[b-sr1jw8b6ep] {
    justify-self: start;
    min-height: var(--mze-touch-min);
    padding-inline: 0;
    background: transparent;
    border: 0;
    color: var(--mze-accent-contrast);
    font: inherit;
    text-decoration: underline;
    cursor: pointer;
}

.mze-fclear:disabled[b-sr1jw8b6ep] {
    color: var(--mze-text-muted);
    text-decoration: none;
    cursor: default;
}
/* /Components/Pages/Admin/Parametres.razor.rz.scp.css */
/* Écran des paramètres du site (FEAT-ADMIN-015). La coque des formulaires vient de mze-form.css. */

.mze-parametres[b-jw5z3e6c4h] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    max-width: var(--mze-form-page-max);
}

/* Même arbitrage que la fiche produit : la bande d'onglets passe à la ligne plutôt que de déborder
   sur téléphone, et ne rétrécit jamais sous son contenu. */
.mze-parametres[b-jw5z3e6c4h]  .mze-parametres-onglets {
    flex: 0 0 auto;
    width: auto;
    max-width: 100%;
    flex-wrap: wrap;
}
/* /Components/Pages/Admin/PhotosProduit.razor.rz.scp.css */
/* Photos prises à l'instant, en attente de dépôt. Elles sont montrées parce qu'une prise de vue
   qu'on ne voit pas ne se vérifie pas : cadrage manqué, objet coupé, doigt sur l'objectif.
   Repris tels quels de la création rapide, d'où le bloc a été extrait. */
.mze-photos-captures[b-knhi55skrk] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

.mze-photos-capture[b-knhi55skrk] {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--mze-space-1);
    padding: var(--mze-space-1);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-sm);
    background: var(--mze-surface-alt);
}

.mze-photos-capture img[b-knhi55skrk] {
    width: 72px;
    height: 72px;
    object-fit: cover;
    border-radius: var(--mze-radius-sm);
    display: block;
}

.mze-photos-erreur[b-knhi55skrk] {
    margin: 0;
    color: var(--mze-error);
    font-size: var(--mze-text-size-3);
}
/* /Components/Pages/Admin/PlancheCapture.razor.rz.scp.css */
/* Vignettes des photos d'atelier (FEAT-ADMIN-022). */

.mze-planche[b-5a5rvpy9pu] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
    --mze-planche-cote: var(--mze-vignette-md);
}

/* Bandeau : une ligne, la plus récente à droite et en vue (cf. le commentaire du markup). */
.mze-planche--bandeau[b-5a5rvpy9pu] {
    flex-direction: row-reverse;
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: var(--mze-space-1);
    --mze-planche-cote: var(--mze-vignette-sm);
}

/* Peu de photos : on les tasse à gauche. Par une marge automatique sur la plus récente, et non
   par `justify-content: flex-end` — qui, dans un conteneur défilant, pousse le débordement du côté
   où l'on ne peut pas défiler et rend les premières photos inatteignables. Une marge
   automatique, elle, tombe à zéro dès qu'il n'y a plus de place libre. */
.mze-planche--bandeau > .mze-planche-item:first-child[b-5a5rvpy9pu] {
    margin-right: auto;
}

.mze-planche-item[b-5a5rvpy9pu] {
    position: relative;
    flex: 0 0 auto;
}

/* Glissable : le curseur le dit, à la souris. */
.mze-planche-item--deplacable[b-5a5rvpy9pu] {
    cursor: grab;
}

.mze-planche-item--deplacable:active[b-5a5rvpy9pu] {
    cursor: grabbing;
}

/* Le bouton n'est qu'un cadre : pas de remplissage, la vignette occupe toute la cible. */
.mze-planche[b-5a5rvpy9pu]  .mze-planche-ouvrir {
    display: block;
    width: var(--mze-planche-cote);
    height: var(--mze-planche-cote);
    padding: 0;
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-sm);
    overflow: hidden;
    background: var(--mze-surface-sunken);
}

/* Une vignette sans ouverture (articles traités) est un simple cadre — même taille, même bord. */
.mze-planche .mze-planche-ouvrir[b-5a5rvpy9pu] {
    display: block;
    box-sizing: border-box;
    width: var(--mze-planche-cote);
    height: var(--mze-planche-cote);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-sm);
    overflow: hidden;
    background: var(--mze-surface-sunken);
}

.mze-planche .mze-planche-ouvrir img[b-5a5rvpy9pu],
.mze-planche[b-5a5rvpy9pu]  .mze-planche-ouvrir img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Suppression en surimpression, dans le coin : à portée du pouce sans agrandir la vignette. */
.mze-planche[b-5a5rvpy9pu]  .mze-planche-supprimer {
    position: absolute;
    top: var(--mze-space-1);
    right: var(--mze-space-1);
    min-width: var(--mze-touch-min);
    min-height: var(--mze-touch-min);
}
/* /Components/Pages/Admin/QualificationArticle.razor.rz.scp.css */
/* Qualification d'un article d'atelier (FEAT-ADMIN-022) : mode, puis quantité. */
.mze-qualification[b-7v3fyw1fse] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}
/* /Components/Pages/Admin/Statistiques.razor.rz.scp.css */
/* Statistiques de fréquentation (FEAT-INFRA-005). Marques fines (colonnes ≤ 24 px, bout arrondi de
   4 px, socle carré, 2 px d'écart), axe et grille discrets, texte aux couleurs de texte — jamais à la
   couleur de la série. Une seule série : l'accent, en aplat (règle des tokens d'accent). */

/* Largeur de la maquette de l'origine géographique (FEAT-INFRA-005, 2026-11-09) : la carte et son
   tableau côte à côte ne tiennent pas dans la largeur d'un formulaire. */
.mze-stats[b-69e62bqcti] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    max-width: var(--mze-wrap-max);
}

.mze-stats-tuiles[b-69e62bqcti] {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--mze-space-3);
}

.mze-stats-tuile[b-69e62bqcti] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-1);
    padding: var(--mze-space-3) var(--mze-space-4);
    border: 1px solid var(--mze-border);
    border-radius: var(--mze-radius-md);
    background: var(--mze-surface);
}

.mze-stats-tuile span[b-69e62bqcti] {
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-5);
}

.mze-stats-tuile strong[b-69e62bqcti] {
    font-size: var(--mze-text-size-2);
    font-weight: var(--mze-font-weight-semibold);
    font-variant-numeric: tabular-nums;
}

.mze-stats-bloc[b-69e62bqcti] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-2);
}

.mze-stats-bloc h2[b-69e62bqcti],
.mze-stats[b-69e62bqcti]  .mze-stats-bloc h2 {
    margin: 0;
    font-size: var(--mze-text-size-5);
    font-weight: var(--mze-font-weight-semibold);
    color: var(--mze-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Colonnes : un socle commun, chaque colonne grandit depuis lui. */
.mze-stats-colonnes[b-69e62bqcti] {
    display: flex;
    align-items: flex-end;
    gap: var(--mze-chart-gap);
    height: var(--mze-chart-height);
    border-bottom: 1px solid var(--mze-border);
}

.mze-stats-colonne[b-69e62bqcti] {
    position: relative;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    flex: 1 1 0;
    height: 100%;
    min-width: 0;
    outline: none;
}

.mze-stats-barre[b-69e62bqcti] {
    display: block;
    width: 100%;
    max-width: var(--mze-chart-bar-max);
    height: var(--mze-stats-hauteur, 0%);  /* posée en ligne par colonne */
    min-height: 1px;
    border-radius: var(--mze-chart-bar-radius) var(--mze-chart-bar-radius) 0 0;
    background: var(--mze-accent);
}

/* Infobulle : au survol et au focus clavier — la cible est toute la hauteur de la colonne. */
.mze-stats-info[b-69e62bqcti] {
    display: none;
    position: absolute;
    bottom: calc(100% + var(--mze-space-1));
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
    white-space: nowrap;
    padding: var(--mze-space-1) var(--mze-space-2);
    border-radius: var(--mze-radius-sm);
    background: var(--mze-bg-dark);
    color: var(--mze-text-on-dark);
    font-size: var(--mze-text-size-6);
}

.mze-stats-colonne:hover .mze-stats-info[b-69e62bqcti],
.mze-stats-colonne:focus-visible .mze-stats-info[b-69e62bqcti] {
    display: block;
}

.mze-stats-colonne:hover .mze-stats-barre[b-69e62bqcti],
.mze-stats-colonne:focus-visible .mze-stats-barre[b-69e62bqcti] {
    background: var(--mze-accent-contrast);
}

/* Par heure : deux séries côte à côte dans chaque colonne, une teinte chacune, la légende les nomme. */
.mze-stats-colonne--double[b-69e62bqcti] {
    gap: 1px;
}

.mze-stats-colonne--double .mze-stats-barre[b-69e62bqcti] {
    width: 50%;
}

.mze-stats-barre--visites[b-69e62bqcti],
.mze-stats-colonne--double:hover .mze-stats-barre--visites[b-69e62bqcti],
.mze-stats-colonne--double:focus-visible .mze-stats-barre--visites[b-69e62bqcti] {
    background: var(--mze-accent-contrast);
}

.mze-stats-barre--pages[b-69e62bqcti],
.mze-stats-colonne--double:hover .mze-stats-barre--pages[b-69e62bqcti],
.mze-stats-colonne--double:focus-visible .mze-stats-barre--pages[b-69e62bqcti] {
    background: var(--mze-accent);
}

.mze-stats-colonne--double:hover[b-69e62bqcti],
.mze-stats-colonne--double:focus-visible[b-69e62bqcti] {
    background: var(--mze-border);
}

.mze-stats-legende[b-69e62bqcti] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--mze-space-3);
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-stats-legende span[b-69e62bqcti] {
    display: inline-flex;
    align-items: center;
    gap: var(--mze-space-1);
}

.mze-stats-pastille[b-69e62bqcti] {
    display: inline-block;
    width: var(--mze-space-3);
    height: var(--mze-space-3);
    border-radius: var(--mze-chart-gap);
}

.mze-stats-pastille--visites[b-69e62bqcti] {
    background: var(--mze-accent-contrast);
}

.mze-stats-pastille--pages[b-69e62bqcti] {
    background: var(--mze-accent);
}

.mze-stats-axe[b-69e62bqcti] {
    display: flex;
    justify-content: space-between;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-stats-classements[b-69e62bqcti] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--mze-space-4);
}

.mze-stats[b-69e62bqcti]  .mze-stats-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--mze-text-size-5);
}

.mze-stats[b-69e62bqcti]  .mze-stats-table th,
.mze-stats[b-69e62bqcti]  .mze-stats-table td {
    padding: var(--mze-space-1) var(--mze-space-2);
    border-bottom: 1px solid var(--mze-border);
    text-align: left;
}

.mze-stats[b-69e62bqcti]  .mze-stats-table th {
    color: var(--mze-text-muted);
    font-weight: var(--mze-font-weight-medium);
}

.mze-stats[b-69e62bqcti]  .mze-stats-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.mze-stats[b-69e62bqcti]  .mze-stats-libelle {
    display: block;
    overflow-wrap: anywhere;
}

/* Barre de grandeur : fine, une seule teinte, sous le libellé. */
.mze-stats[b-69e62bqcti]  .mze-stats-grandeur {
    display: block;
    width: var(--mze-stats-largeur, 0%);  /* posée en ligne par ligne */
    height: var(--mze-chart-magnitude);
    margin-top: var(--mze-chart-gap);
    border-radius: 0 var(--mze-chart-bar-radius) var(--mze-chart-bar-radius) 0;
    background: var(--mze-accent);
}

@media (min-width: 768px) {
    .mze-stats-tuiles[b-69e62bqcti] {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    .mze-stats-classements[b-69e62bqcti] {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
/* /Components/Pages/Admin/VisionneusePhotos.razor.rz.scp.css */
/* Visionneuse plein écran des photos d'atelier (FEAT-ADMIN-022). */

/* L'image tient dans la fenêtre sans être recadrée : on juge une photo — netteté, cadrage — sur
   l'image entière, pas sur un détail. Sa hauteur laisse place, sous elle, à la navigation ET à la
   confirmation ou au choix de destination : au téléphone, ce qui est sous le pli n'est pas lu. */
.mze-visionneuse-scene[b-psb5zlvtsn] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
    background: var(--mze-surface-sunken);
    border-radius: var(--mze-radius-sm);
    overflow: hidden;
}

.mze-visionneuse-scene img[b-psb5zlvtsn] {
    display: block;
    max-width: 100%;
    max-height: 50vh;
    max-height: 50dvh;
    object-fit: contain;
}

.mze-visionneuse-scene--reduite img[b-psb5zlvtsn] {
    max-height: 30vh;
    max-height: 30dvh;
}

/* Précédente · compteur · suivante, sous l'image. */
.mze-visionneuse-navigation[b-psb5zlvtsn] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--mze-space-2);
    margin-top: var(--mze-space-2);
}

.mze-visionneuse-compte[b-psb5zlvtsn] {
    margin: 0;
    text-align: center;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}

.mze-visionneuse-confirmation[b-psb5zlvtsn] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-1);
    margin: var(--mze-space-2) 0 0;
    color: var(--mze-error);
}

.mze-visionneuse-deplacement[b-psb5zlvtsn] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-1);
    margin-top: var(--mze-space-2);
}

.mze-visionneuse-avertissement[b-psb5zlvtsn] {
    margin: 0;
    color: var(--mze-text-muted);
    font-size: var(--mze-text-size-6);
}
/* /Components/Pages/AtelierVitrine.razor.rz.scp.css */
/* AtelierVitrine — page d'aide au développement (/atelier).

   Les flèches du carrousel vivaient en global dans mze-vitrine.css. Cette page en est
   le SEUL émetteur : la règle suit son unique consommateur (CLAUDE.md § CSS et thèmes).

   Le carrousel lui-même n'est pas concerné — sa piste est en CSS scopé de MzeCarrousel.
   Les flèches sont rendues ici, dans l'en-tête de section, et câblées au composant par
   référence : c'est pourquoi leur style appartient à la page et non au composant.

   Aucune valeur d'axe en dur : tout passe par les tokens --mze-*. */

.mze-carousel__nav[b-tyubkf3eql] {
    display: none;
    gap: var(--mze-space-2);
}

.mze-carousel__nav button[b-tyubkf3eql] {
    width: 44px;
    height: 44px;
    border-radius: var(--mze-radius);
    cursor: pointer;
    background: var(--mze-accent);
    color: var(--mze-text-on-accent);
    border: 0;
    display: grid;
    place-items: center;
    font-size: var(--mze-text-size-3);
    transition: background var(--mze-duration);
}

.mze-carousel__nav button:hover[b-tyubkf3eql] {
    background: color-mix(in srgb, var(--mze-accent) 84%, #000);
}

.mze-carousel__nav button:focus-visible[b-tyubkf3eql] {
    outline: var(--mze-focus-width) solid var(--mze-accent-contrast);
    outline-offset: var(--mze-focus-offset);
}
/* /Components/Pages/FicheProduit.razor.rz.scp.css */
/* Fiche produit — CSS scopé (FEAT-SITE-004, mockup-02-fiche-produit.html).

   Scopé et non global : ces trois blocs n'ont qu'un consommateur, cette page. Les mettre dans
   mze-vitrine.css les aurait chargés sur toutes les pages de la vitrine pour n'en servir qu'une.
   Le fil d'Ariane et la galerie n'y figurent pas : ils appartiennent à MzeFilAriane et MzeGalerie,
   qui portent déjà leur propre CSS scopé.

   Aucune valeur d'axe en dur : tout passe par var(--mze-*). */

/* ---------- Mise en page ---------- */
.mze-pdp[b-4scqdlcay4] {
    display: grid;
    gap: 30px;
    padding-bottom: 40px;
}

.mze-pdp__head[b-4scqdlcay4] {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.mze-pdp__price[b-4scqdlcay4] {
    font-family: var(--mze-font-heading);
    font-size: 1.9rem;
    line-height: 1;
}

.mze-pdp__price small[b-4scqdlcay4] {
    font-family: var(--mze-font-body);
    font-size: .8rem;
    color: var(--mze-text-muted);
}

/* ---------- Tableau de caractéristiques ---------- */
.mze-dl[b-4scqdlcay4] {
    margin: 0;
    font-size: .88rem;
}

.mze-dl div[b-4scqdlcay4] {
    display: flex;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid var(--mze-border);
}

.mze-dl dt[b-4scqdlcay4] {
    color: var(--mze-text-muted);
    min-width: 130px;
    margin: 0;
}

.mze-dl dd[b-4scqdlcay4] {
    margin: 0;
}

/* ---------- Calendrier de disponibilité ----------
   Les jours barrés ne disent jamais POURQUOI ils sont pris : le détail des commandes en conflit
   relève de l'administration (§7.8). */
.mze-avail[b-4scqdlcay4] {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
    margin-top: 10px;
}

/* Jour libre : aplat d'accent doux, chiffre en contraste d'accent. */
.mze-avail span[b-4scqdlcay4] {
    aspect-ratio: 1/1;
    display: grid;
    place-items: center;
    font-size: .7rem;
    border-radius: var(--mze-radius-sm);
    background: var(--mze-accent-soft);
    color: var(--mze-accent-contrast);
}

/* Jour pris. L'écart avec un jour libre doit se voir SANS lire le chiffre : c'est l'information
   principale du calendrier. La version précédente posait un fond clair à 55 % d'opacité, ce qui
   rapprochait les deux états au lieu de les séparer — l'opacité délavait aussi le barré.
   Ici : fond franchement plus sombre, texte assourdi, barré plein. */
.mze-avail span.is-busy[b-4scqdlcay4] {
    background: color-mix(in srgb, var(--mze-text) 26%, var(--mze-bg-alt));
    color: color-mix(in srgb, var(--mze-text) 62%, transparent);
    text-decoration: line-through;
    text-decoration-thickness: 2px;
}

.mze-avail span.is-sel[b-4scqdlcay4] {
    background: var(--mze-accent);
    color: var(--mze-text-on-accent);
    font-weight: 700;
}

/* Cases de remplissage avant le premier jour du mois : pas de fond, pas de bordure. */
.mze-avail span.is-void[b-4scqdlcay4] {
    background: none;
}

.mze-avail__head[b-4scqdlcay4] {
    font-size: .66rem;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--mze-text-muted);
    background: none !important;
}

@media (min-width: 992px) {
    .mze-pdp[b-4scqdlcay4] {
        grid-template-columns: 1.1fr .9fr;
        gap: 52px;
    }
}
/* /Components/Pages/Recherche.razor.rz.scp.css */
/* Page de résultats de recherche (FEAT-SITE-006).

   Reprise de la maquette validée `mockup-06-recherche.html`. Les valeurs d'axe passent toutes par un
   token `--mze-*` : la maquette porte des littéraux parce qu'un navigateur ne sait pas afficher un
   composant Razor, pas parce que ce sont des valeurs à recopier.

   Ces classes n'ont qu'UN consommateur — cette page — donc elles vivent dans son CSS scopé. La seule
   exception est `.mze-hl`, qui est aussi rendue par le panneau de suggestions : elle est déclarée
   dans le CSS de chacun des deux, jamais en global, où elle fuirait sur tout `<mark>` du site. */

/* ===== En-tête de recherche ===== */

.mze-searchhead[b-csxcsf10ja] {
    max-width: 62ch;
}

.mze-searchhead p[b-csxcsf10ja] {
    color: var(--mze-text-muted);
}

/* ===== Groupes de résultats ===== */

.mze-resultgrp[b-csxcsf10ja] {
    padding-bottom: var(--mze-space-6);
}

/* Le titre de groupe est un REPÈRE, pas une accroche : sans cette règle il retombe sur le style de
   titre éditorial de la vitrine — display, très grand — et écrase la hiérarchie de la page, dont le
   vrai titre est le <h1> « Résultats pour … ». */
.mze-resultgrp__title[b-csxcsf10ja] {
    font-family: var(--mze-font-body);
    font-size: var(--mze-text-size-5);
    font-weight: 700;
    letter-spacing: .04em;
    margin: 0 0 var(--mze-space-3);
}

/* ===== Puces de collection et de balise ===== */

.mze-chips[b-csxcsf10ja] {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--mze-space-2);
    margin: 0;
    padding: 0;
}

.mze-chip[b-csxcsf10ja] {
    display: inline-flex;
    align-items: baseline;
    gap: var(--mze-space-2);
    padding: var(--mze-space-2) var(--mze-space-3);
    text-decoration: none;
    color: var(--mze-text);
    border: 1px solid var(--mze-border-strong);
    border-radius: var(--mze-radius);
}

.mze-chip:hover[b-csxcsf10ja] {
    border-color: var(--mze-accent-contrast);
}

/* Le libellé est UN SEUL item flex.

   Sans ce conteneur, le <mark> du surlignage devient un item à part et le `gap` de la puce écarte
   visiblement « Verre » de « rie » — le mot se lit coupé en deux. Le défaut vient du surlignage,
   pas de la maquette : elle n'avait qu'un <mark> par puce et le montrait déjà. */
.mze-chip__l[b-csxcsf10ja] {
    white-space: nowrap;
}

.mze-chip__n[b-csxcsf10ja] {
    color: var(--mze-text-muted);
}

/* Les collections se distinguent des balises par un aplat d'accent — c'est la maquette. L'aplat est
   porté par `--mze-accent`, jamais le texte : sur les thèmes à accent sombre (w5, w6), du texte en
   `--mze-accent` deviendrait illisible. Règle bloquante des tokens d'accent, spec §10.9. */
.mze-chip--coll[b-csxcsf10ja] {
    background: var(--mze-accent-soft);
    border-color: transparent;
    color: var(--mze-accent-contrast);
}

.mze-chip--coll .mze-chip__n[b-csxcsf10ja] {
    color: var(--mze-accent-contrast);
}

/* ===== Surlignage du terme =====

   ::deep OBLIGATOIRE : `<mark>` est rendu par MzeTexteSurligne, un composant ENFANT, et porte donc
   l'attribut de scope de cet enfant. Une règle non préfixée ne matcherait jamais — sans erreur, sans
   avertissement, le terme resterait simplement non surligné. */
.mze-catalog[b-csxcsf10ja]  .mze-hl {
    background: var(--mze-accent-soft);
    color: var(--mze-accent-contrast);
    font-weight: 700;
}
/* /Components/Pages/Sections/FormulaireContact.razor.rz.scp.css */
/* Formulaire de contact (FEAT-SITE-016). Mobile-first : champs empilés, en ligne au palier tablette.
   Tokens uniquement. */

.mze-contact-formulaire[b-nzi3nw2ek7] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
    max-width: var(--mze-form-page-max);
    margin-top: var(--mze-space-4);
    text-align: left;
}

.mze-contact-formulaire[b-nzi3nw2ek7]  form {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-4);
}

.mze-contact-groupe[b-nzi3nw2ek7] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
    margin: 0;
    padding: 0;
    border: 0;
    min-width: 0;
}

.mze-contact-groupe legend[b-nzi3nw2ek7] {
    margin-bottom: var(--mze-space-2);
    padding: 0;
    font-family: var(--mze-font-heading);
    font-size: var(--mze-text-size-4);
}

.mze-contact-ligne[b-nzi3nw2ek7] {
    display: flex;
    flex-direction: column;
    gap: var(--mze-space-3);
}

/* Champ piège : hors écran, sans `display: none` — certains robots ignorent les champs masqués ainsi. */
.mze-contact-piege[b-nzi3nw2ek7] {
    position: absolute;
    left: -10000px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.mze-contact-objet[b-nzi3nw2ek7],
.mze-contact-mention[b-nzi3nw2ek7] {
    margin: 0;
    font-size: var(--mze-text-size-5);
    color: var(--mze-text-muted);
}

@media (min-width: 768px) {
    .mze-contact-ligne[b-nzi3nw2ek7] {
        flex-direction: row;
    }

    .mze-contact-ligne[b-nzi3nw2ek7] >  * {
        flex: 1 1 0;
        min-width: 0;
    }
}
/* /Components/Pages/Sections/SectionGalerie.razor.rz.scp.css */
/* Visionneuse de galerie — FEAT-SITE-010. Plein écran, une photo par diapositive, glissement natif
   (scroll-snap) ; flèches et compteur posés au-dessus. Mobile-first : les flèches n'apparaissent
   qu'à partir de la tablette, le doigt suffit en dessous. */
.mze-visionneuse[b-znmzoos1eb] {
    position: fixed; inset: 0;
    width: 100%; height: 100%; max-width: none; max-height: none;
    margin: 0; padding: 0; border: 0;
    background: var(--mze-scrim-opaque);
    color: var(--mze-text-on-dark);
    overflow: hidden;
}

.mze-visionneuse[b-znmzoos1eb]::backdrop { background: var(--mze-scrim-opaque); }

.mze-visionneuse__piste[b-znmzoos1eb] {
    display: flex; height: 100%;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}

.mze-visionneuse__piste[b-znmzoos1eb]::-webkit-scrollbar { display: none; }

.mze-visionneuse__diapo[b-znmzoos1eb] {
    flex: 0 0 100%; height: 100%; margin: 0;
    scroll-snap-align: center; scroll-snap-stop: always;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: var(--mze-space-2);
    padding: 64px var(--mze-space-2) var(--mze-space-4);
    box-sizing: border-box;
}

.mze-visionneuse__diapo img[b-znmzoos1eb] {
    max-width: 100%; max-height: 100%; min-height: 0;
    object-fit: contain;
    border-radius: var(--mze-radius-sm);
}

.mze-visionneuse__diapo figcaption[b-znmzoos1eb] { font-size: .9rem; text-align: center; }

.mze-visionneuse__barre[b-znmzoos1eb] {
    position: absolute; top: 0; left: 0; right: 0;
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--mze-space-2) var(--mze-space-2) var(--mze-space-2) var(--mze-space-3);
}

.mze-visionneuse__compteur[b-znmzoos1eb] { font-size: .9rem; letter-spacing: .05em; }

.mze-visionneuse .mze-iconbtn[b-znmzoos1eb] { color: var(--mze-text-on-dark); }
.mze-visionneuse .mze-iconbtn:hover[b-znmzoos1eb] { background: var(--mze-scrim-media); color: var(--mze-text-on-dark); }
.mze-visionneuse .mze-iconbtn:focus-visible[b-znmzoos1eb] { outline-color: var(--mze-text-on-dark); }

.mze-visionneuse__nav[b-znmzoos1eb] {
    display: none;
    position: absolute; top: 50%; transform: translateY(-50%);
    font-size: 1.5rem;
}

.mze-visionneuse__nav--prec[b-znmzoos1eb] { left: var(--mze-space-2); }
.mze-visionneuse__nav--suiv[b-znmzoos1eb] { right: var(--mze-space-2); }

@media (min-width: 768px) {
    .mze-visionneuse__nav[b-znmzoos1eb] { display: inline-grid; }
    .mze-visionneuse__diapo[b-znmzoos1eb] { padding: 64px 72px var(--mze-space-5); }
}
/* /Components/Pages/Sections/SectionSignature.razor.rz.scp.css */
/* Signature de la marque. Mobile d'abord : couronne de 190 px, élargie à 230 px dès 576 px. */
.mze-signature[b-ch59ewbxfz] {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.mze-signature__couronne[b-ch59ewbxfz] {
    position: relative;
    width: 190px;
}

.mze-signature__couronne img[b-ch59ewbxfz] {
    display: block;
    width: 100%;
    height: auto;
}

/* Le nom, dans le vide de la couronne : il passe à la ligne de lui-même (« Mademoiselle / Estelle »). */
.mze-signature__nom[b-ch59ewbxfz] {
    position: absolute;
    inset: 22% 20%;
    margin: 0;
    display: grid;
    place-items: center;
    text-align: center;
    font-family: var(--mze-font-tagline);
    font-size: 1.2rem;
    line-height: 1.05;
    color: var(--mze-text);
}

.mze-signature__devise[b-ch59ewbxfz] {
    margin: var(--mze-space-3) 0 0;
    font-family: var(--mze-font-body);
    font-size: .78rem;
    letter-spacing: .32em;
    text-transform: uppercase;
    color: var(--mze-text-muted);
}

.mze-signature__filet[b-ch59ewbxfz] {
    display: block;
    width: 56px;
    height: 1px;
    margin: var(--mze-space-4) auto;
    background: var(--mze-accent);
}

.mze-signature__texte[b-ch59ewbxfz] {
    max-width: 36rem;
    margin: 0;
    font-family: var(--mze-font-heading);
    font-size: 1.15rem;
    line-height: 1.55;
    color: var(--mze-text);
}

@media (min-width: 576px) {
    .mze-signature__couronne[b-ch59ewbxfz] { width: 230px; }
    .mze-signature__nom[b-ch59ewbxfz] { font-size: 1.6rem; }
    .mze-signature__texte[b-ch59ewbxfz] { font-size: 1.35rem; }
}
/* /Components/Pages/Sections/SectionTemoignages.razor.rz.scp.css */
/* Carrousel de témoignages — FEAT-SITE-010. Mobile-first : la piste seule, glissée au doigt ;
   à partir de 768 px, flèches de part et d'autre de la piste. */
.mze-temoignages[b-xwvkcvjqtx] {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: var(--mze-space-2);
}

.mze-temoignages__fleche[b-xwvkcvjqtx] {
    display: none;
    width: 44px;
    height: 44px;
    border: 0;
    border-radius: var(--mze-radius);
    cursor: pointer;
    background: var(--mze-accent);
    color: var(--mze-text-on-accent);
    place-items: center;
    font-size: var(--mze-text-size-3);
    transition: background var(--mze-duration);
}

.mze-temoignages__fleche:hover[b-xwvkcvjqtx] { background: color-mix(in srgb, var(--mze-accent) 84%, #000); }

.mze-temoignages__fleche:focus-visible[b-xwvkcvjqtx] {
    outline: var(--mze-focus-width) solid var(--mze-focus-color);
    outline-offset: var(--mze-focus-offset);
}

@media (min-width: 768px) {
    .mze-temoignages:has(.mze-temoignages__fleche)[b-xwvkcvjqtx] { grid-template-columns: auto minmax(0, 1fr) auto; }
    .mze-temoignages__fleche[b-xwvkcvjqtx] { display: inline-grid; }
}
