/**
 * Moteur V4 — pages.css
 *
 * EXTRAIT de medson-clinical, prive de ses regles .med-* : ce fichier habille
 * la MECANIQUE des blocs et du chrome, jamais une identite.
 *
 * ═══════════════════════════════════════════════════════════════════════════
 * 🔴 CE FICHIER EST UN SIGNAL, PAS SEULEMENT UNE FEUILLE DE STYLE
 * ═══════════════════════════════════════════════════════════════════════════
 * `V4BlockSchema::themeDressesBlocks()` teste la SEULE présence de
 * `assets/css/pages.css` pour décider si un thème habille ses blocs. Tant que
 * ce fichier existe, `feature_grid`, `category_grid` et `product_pick`
 * CESSENT d'émettre leurs styles en ligne de repli et s'en remettent aux
 * classes stylées ici.
 *
 * Conséquence directe : **supprimer ce fichier ne « retire » pas du style, il
 * en rend le repli au socle** ; le VIDER, en revanche, laisse les blocs nus.
 * Les trois familles de classes ci-dessous sont donc OBLIGATOIRES :
 *
 *   .mnx-perks*        ← feature_grid, density=bar   (bande de réassurance)
 *   .mnx-dept-band     ← category_grid, tiles        (« Nos univers »)
 *   .mnx-product-grid  ← product_pick                (grilles de produits)
 *
 * Un style en ligne l'emporte sur toute feuille : c'est pourquoi le socle les
 * retire ici plutôt que de les additionner (incident documenté — bande de
 * rayons compacte devenue tuiles hautes, grille de 4 rendue en 5).
 */

/* ═══════════════════════════════════════════════════════════════════════════
   HERO SPLIT — proportions de la maquette
   ═══════════════════════════════════════════════════════════════════════════
   Le socle rend `grid-template-columns:1fr 1fr` EN LIGNE sur le div interne.
   Un style en ligne l'emporte sur une feuille : on le reprend donc avec
   `!important`, seul moyen de changer la proportion sans toucher au moteur.
   C'est l'exception assumée du thème — ailleurs, on ne surcharge jamais un
   style en ligne du socle.

   Pourquoi : à 50/50, la colonne de texte fait ~373px une fois retirés ses
   `padding:clamp(2rem,5vw,3.5rem)`, et le titre de la maquette y tombe sur
   4 lignes au lieu de 3. 55/45 lui rend sa respiration sans écraser le visuel.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (min-width: 721px) {
  .sws-v4-hero--split > div {
    grid-template-columns: 55fr 45fr !important;
  }
}

/* 🔴 LE CTA S'ÉTIRAIT SUR TOUTE LA COLONNE.
   `.sws-v4-hero__inner` est un `display:flex; flex-direction:column` posé EN
   LIGNE par le socle, SANS `align-items` : la valeur initiale `stretch`
   s'applique donc, et le bouton — pourtant `display:inline-block` — occupait
   toute la largeur (constaté au rendu réel, accueil chez-km : un bouton
   « Découvrir nos produits » de 770px).

   `align-self` sur l'enfant suffit et évite de surcharger le conteneur. */
.sws-v4-hero__inner > .sws-v4-hero__cta { align-self: flex-start; }
.sws-v4-hero--split[style*="center"] .sws-v4-hero__cta,
.sws-v4-hero__inner[style*="align-items:center"] > .sws-v4-hero__cta { align-self: center; }

/* Même défaut sur le bandeau `text_media` (colonne de texte en flex). */
.sws-v4-text-media__text > a,
.sws-v4-text-media__text > .sws-v4-text-media__cta { align-self: flex-start; }

/* ═══════════════════════════════════════════════════════════════════════════
   BANDE DE RÉASSURANCE — feature_grid, density = bar
   ═══════════════════════════════════════════════════════════════════════════
   La bande claire de la maquette, sous le hero : fond bleu très pâle, texte
   bleu profond, icônes cerclées. Le socle ne pose plus AUCUN style en ligne
   ici (ni fond, ni marges) : tout vient de ces règles.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 🔴 BANDE SOMBRE — CE N'EST PAS UN CHOIX ESTHÉTIQUE LIBRE.
   `V4BlockFeatureGrid` écrit ses libellés EN LIGNE en `color:#fff` (l.444) et
   ses sous-titres en `rgba(255,255,255,.62)` (l.462), codés EN DUR, sans
   variable. Un style en ligne l'emporte sur toute feuille : aucune règle CSS
   d'ici ne peut les repeindre (vérifié au rendu réel — la surcharge restait
   sans effet).

   Sur un fond clair, ce blanc est INVISIBLE : mesuré `rgb(255,255,255)` sur
   `rgb(243,248,252)` à la page catégorie de la boutique 1000056. La bande est
   donc SOMBRE, pour que le blanc du socle redevienne lisible.

   Écart assumé avec la maquette (bande claire). Le corriger proprement
   demanderait de remplacer ces `#fff` par une variable CSS dans le moteur —
   ce qui profiterait à TOUT thème à bande claire, et relève d'un lot dédié. */
.mnx-perks {
  background: var(--color-primary-dark);
  border-block: 1px solid var(--color-primary-dark);
  padding-block: 18px;
  color: #fff;
}

.mnx-perks__inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px 28px;
}

.mnx-perks__item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-width: 0;
  text-align: start;
  /* `px` et non `rem` : un theme peut poser `html{font-size:62.5%}`
     (1rem=10px, convention sws-listing) et le texte tombait a 9.4px —
     mesure au navigateur le 2026-09-27. */
  font-size: 15px;
}

/* ── Bande : icone AU-DESSUS ───────────────────────────────────────────
   `presentation: empile` — chaque point porte alors son titre ET sa
   description sur deux lignes. Cote a cote, il ne reste quune ligne :
   mesure, items de 57px contre 133 a la source.
   Opt-in par la classe : un bloc qui ne demande rien garde sa rangee. */
.mnx-perks__item.sws-v4-feature-grid__item--empile {
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 12px;
}

/* Icône cerclée de la maquette. Le socle rend `<i class="fa fa-…">` quand
   l'icône est un mot-clé, un caractère brut sinon : les deux sont habillés. */
.mnx-perks__item i,
.mnx-perks__item .sws-v4-feature-grid__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* `--band-icon-size` : la taille de pastille appartient a lidentite.
     Repli 36px — la valeur ecrite ici jusquici, donc aucun preset ne bouge.
     Mesure : la source pose 44px, le socle 36. */
  width: var(--band-icon-size, 36px);
  height: var(--band-icon-size, 36px);
  flex: 0 0 var(--band-icon-size, 36px);
  /* Pastille PLEINE : un cercle borde se perd sur un aplat sombre, et son
     glyphe en `--color-primary` y devient INVISIBLE — mesure, brun sur brun.
     `--color-accent` est la couleur prevue pour ressortir, et le texte suit. */
  background: var(--color-accent);
  border: 0;
  border-radius: 999px;
  color: var(--color-on-accent, #fff);
  font-size: 16px;
  font-style: normal;
}

.mnx-perks__item strong,
.mnx-perks__item .sws-v4-feature-grid__title {
  font-weight: 600;
  /* `inherit` : la bande porte deja sa couleur de texte, et
     `--color-primary-dark` n est declare que par 5 themes sur 20. */
  color: inherit;
}

/* La bande étant sombre, on ne touche PAS aux couleurs (le blanc en ligne du
   socle est correct ici). Seuls les éléments que le socle ne colore pas en
   ligne — les liens du partial de réassurance — sont repris. */
.mnx-perks__item a { color: #fff; }
.mnx-perks__item a:hover { color: var(--color-accent); }

/* Les tailles en ligne du bloc (`.82rem` / `.72rem`) sont désormais correctes :
   `base.css` remet `html` à 16px, annulant le `font-size:10px` de Bootstrap 3
   qui les rendait à 8.2px / 7.2px. Voir le commentaire détaillé dans base.css —
   aucun `!important` par règle n'est nécessaire. */

@media (max-width: 720px) {
  .mnx-perks__inner { grid-template-columns: 1fr; gap: 12px; }
  .mnx-perks__item { justify-content: flex-start; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   NOS UNIVERS — category_grid, presentation = tiles
   ═══════════════════════════════════════════════════════════════════════════
   🔴 `.mnx-dept-band` est PLEINE LARGEUR et sans marge : le socle compte
   là-dessus (il retire son `padding-inline` et son conteneur quand le thème
   habille). La maquette, elle, montre des tuiles BORNÉES à la largeur de
   lecture — on rétablit donc la borne ICI, sur la grille, pas sur la bande.
   ═══════════════════════════════════════════════════════════════════════════ */

.mnx-dept-band {
  padding-block: calc(var(--section-spacing, 80px) / 2);
  background: var(--color-background);
}

/* `auto-fit` + `minmax` plutôt que 4 colonnes FIXES.
   Mesuré : avec `repeat(4,…)` et 5 rubriques, la 5ᵉ tuile se retrouvait SEULE
   sur une seconde rangée (bande de 400px au lieu de 190) — un trou béant à
   droite. Le socle rend AU PLUS 6 rubriques, et une boutique en a un nombre
   quelconque : la grille doit donc s'adapter au nombre réel, pas l'inverse. */
.mnx-dept-tiles,
.mnx-dept-grid {
  display: grid;
  /* 200px et pas 240 : à 1240px de conteneur (1200 utiles), 240px ne laisse
     tenir que 4 colonnes et la 5ᵉ rubrique se retrouvait SEULE sur une rangée
     (mesuré : bande de 400px au lieu de 190). 200px tient les 5, et jusqu'aux
     6 rubriques que le socle rend au maximum. En dessous, `auto-fit` réduit
     le nombre de colonnes tout seul — aucun point de rupture à maintenir. */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
  max-width: var(--container-max-width, 1240px);
  margin-inline: auto;
  padding-inline: 20px;
}

/* 🔴 LE BALISAGE D'UNE TUILE N'EST PAS CELUI QU'ON CROIT.
   Le socle NE rend PAS `<img>` + `<h3>` + `<p>`. Il rend :

     <a class="mnx-dept-tile mnx-hero__promo [--blue|--peach] [--bg]"
        style="background-image:url(…)">
       <span class="mnx-hero__promo-label">Catégorie</span>
       <span class="mnx-hero__promo-title">Gourmandises</span>
       <span class="mnx-hero__promo-cta">Voir la sélection →</span>
     </a>

   L'image est un `background-image` EN LIGNE, pas un élément. Styler `img`/`h3`
   laissait donc les trois `<span>` nus, en texte sombre PAR-DESSUS la photo —
   illisible (constaté au rendu réel, accueil chez-km).

   D'où : hauteur fixe, texte en bas, et un VOILE sur les tuiles à image. */
.mnx-dept-tile,
.mnx-dept-tiles > a,
.mnx-dept-grid > a {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 5px;
  min-width: 0;
  /* Hauteur commune : sans elle, une tuile sans image s'écrase et la rangée
     part en escalier (constaté — 4 tuiles de 3 hauteurs différentes). */
  min-height: 190px;
  padding: 22px 20px;
  background: var(--color-surface);
  background-size: cover;
  background-position: center;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
  color: var(--color-text);
  text-decoration: none;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.mnx-dept-tile:hover,
.mnx-dept-tiles > a:hover,
.mnx-dept-grid > a:hover {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  color: var(--color-text);
}

/* Variantes de fond du socle : ramenées à la palette clinique (le beige et le
   pêche de `modern-luxe` n'ont rien à faire ici). */
.mnx-hero__promo--blue  { background-color: var(--color-surface-blue, #E8F2FA); }
.mnx-hero__promo--peach { background-color: var(--color-surface); }

/* ── Tuile AVEC image : voile + texte blanc ─────────────────────────────── */
.mnx-hero__promo--bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
              rgba(10, 44, 77, .82) 0%,
              rgba(10, 44, 77, .38) 55%,
              rgba(10, 44, 77, .10) 100%);
  z-index: 0;
}
.mnx-hero__promo--bg > * { position: relative; z-index: 1; }
.mnx-hero__promo--bg .mnx-hero__promo-label { color: var(--color-accent); }
.mnx-hero__promo--bg .mnx-hero__promo-title,
.mnx-hero__promo--bg .mnx-hero__promo-cta   { color: #fff; }

/* ── Textes ─────────────────────────────────────────────────────────────── */
.mnx-hero__promo-label {
  font-size: .625rem;
  font-weight: 700;
  letter-spacing: var(--letter-spacing-label, .10em);
  text-transform: uppercase;
  color: var(--color-primary);
}

.mnx-hero__promo-title {
  font-family: var(--font-family-heading);
  font-size: 1.125rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--color-primary-dark);
}

.mnx-hero__promo-cta {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: .75rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

@media (max-width: 1024px) {
  .mnx-dept-tiles,
  .mnx-dept-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .mnx-dept-tiles,
  .mnx-dept-grid { grid-template-columns: 1fr; gap: 16px; padding-inline: 16px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   BANDEAU PROFESSIONNELS DE SANTÉ — text_media
   ═══════════════════════════════════════════════════════════════════════════
   Dans la maquette c'est une BANDE identifiable (fond teinté, filet, coins
   arrondis), pas du texte posé sur le fond de page. `text_media` pose en ligne
   ses `padding` et sa `color`, mais NI fond NI bordure : on peut donc l'habiller
   sans surcharger quoi que ce soit.

   Le sélecteur vise la dernière section de la page (l'emplacement `below` du
   layout `clinique`) : sur la fiche produit, `text_media` n'est pas en dernier
   et garde son rendu neutre.
   ═══════════════════════════════════════════════════════════════════════════ */

/* `margin-block` RÉDUITE : le socle pose déjà `padding-block:40px` EN LIGNE sur
   cette section. Une marge d'une demi-section par-dessus creusait 80px de vide
   entre les tuiles et le bandeau (mesuré au rendu réel). Les deux s'additionnent
   — on ne garde donc ici que le petit écart qui manque. */
.sws-v4-text-media:last-of-type {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  max-width: var(--container-max-width, 1240px);
  margin-inline: auto;
  margin-block: 8px calc(var(--section-spacing, 80px) / 2);
}

/* Le CTA du bandeau : plein, comme dans la maquette. */
.sws-v4-text-media:last-of-type .sws-v4-text-media__cta,
.sws-v4-text-media:last-of-type a[class*="cta"] {
  background: var(--color-primary);
  color: #fff;
  border-color: var(--color-primary);
}

@media (max-width: 640px) {
  .sws-v4-text-media:last-of-type {
    margin-inline: 16px;
    border-radius: var(--radius);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   GRILLES DE PRODUITS — product_pick
   ═══════════════════════════════════════════════════════════════════════════
   4 colonnes en desktop comme la maquette. Le socle ne pose son repli
   `auto-fit` que si le thème n'habille pas : ici, c'est cette grille qui fait
   foi, y compris pour ses variantes de présentation.
   ═══════════════════════════════════════════════════════════════════════════ */

.mnx-product-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 22px;
}

/* 🔴 DANS LA COLONNE DE RÉSULTATS, 4 COLONNES NE TIENNENT PAS.
   La grille n'y dispose que de ~942px (1240 − sidebar 220 − gouttière 30) :
   `repeat(4,…)` y donnait des cartes de 220px, trop étroites pour le titre et
   le prix. `auto-fit` en rend 3 confortables, et remonte à 4 dès que l'écran
   le permet — sans point de rupture à maintenir. */
/* 🔴 LE DÉFAUT DE CASCADE QUI RENDAIT LES SÉLECTEURS DE VUE INOPÉRANTS.
   `.mnx-results .mnx-product-grid` porte DEUX classes (spécificité 0,2,0) ;
   `.mnx-product-grid--3col` n'en porte qu'une (0,1,0). La règle du conteneur
   l'emportait donc TOUJOURS, quelle que soit la vue choisie.

   Mesuré le 2026-09-27 sur une catégorie de 7 produits : la classe changeait
   bien au clic (`--3col` → `--list` → `--2col`), et les colonnes restaient
   `232px × 4` dans les trois cas. Le marchand cliquait, la classe bougeait,
   le rendu non — un contrôle qui ne montre rien est pire que pas de contrôle.

   `:where()` ramène la spécificité du conteneur à ZÉRO : il pose un défaut,
   et toute vue explicite le remplace. Même correctif que le garde-fou d'image
   du moteur. La grille sans vue choisie rend EXACTEMENT comme avant. */
:where(.mnx-results) .mnx-product-grid {
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 18px;
}

.mnx-product-grid--3col { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.mnx-product-grid--2col { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.mnx-product-grid--list { grid-template-columns: 1fr; gap: 14px; }
.mnx-product-grid--list .sws-product-card { flex-direction: row; }
.mnx-product-grid--list .sws-product-card__image-wrap {
  flex: 0 0 168px;
  aspect-ratio: 1 / 1;
}
.mnx-product-grid--list .sws-product-card__body { justify-content: center; }

/* 🔴 LES POINTS DE RUPTURE NE TOUCHENT PAS UNE VUE CHOISIE.
   Ils réécrivaient `.mnx-product-grid` — une classe, comme `--2col` et
   `--list`, et déclarée APRÈS eux : sous 1024 px la vue choisie perdait
   toujours. Mesuré le 2026-09-29 (prod, mobile) : les trois boutons
   rendaient la même grille. Les règles de repli visent donc la grille SANS
   vue (grilles de produits de l'accueil) et la vue dense `--3col` ; `--2col`
   et `--list` ont leurs propres déclinaisons.

   Sur petit écran, chaque bouton doit montrer AUTRE CHOSE : « Grille 3 » =
   la plus dense, « Grille 2 » = une carte plus grande, « Liste » = une
   rangée par produit, image à côté du texte. */
@media (max-width: 1024px) {
  .mnx-product-grid:not(.mnx-product-grid--2col):not(.mnx-product-grid--list) {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (max-width: 860px) {
  .mnx-product-grid:not(.mnx-product-grid--2col):not(.mnx-product-grid--list) {
    grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px;
  }
  .mnx-product-grid--2col { grid-template-columns: 1fr; gap: 16px; }
}
@media (max-width: 480px) {
  /* La liste RESTE une rangée : repliée en colonne, elle rendait exactement
     « Grille 2 ». Le visuel se réduit pour laisser la place au texte. */
  .mnx-product-grid--list .sws-product-card__image-wrap { flex: 0 0 104px; }
  .mnx-product-grid--list .sws-product-card__body { padding: 10px 12px; }
}
@media (max-width: 340px) {
  /* Deux colonnes tiennent jusqu'aux téléphones de 360 px ; en dessous, une
     seule — jamais de carte écrasée. */
  .mnx-product-grid:not(.mnx-product-grid--2col):not(.mnx-product-grid--list) {
    grid-template-columns: 1fr;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   PAGE CATÉGORIE — filtres à gauche, résultats à droite
   ═══════════════════════════════════════════════════════════════════════════
   Le markup (facettes, tri, pagination) appartient au listing du socle : on
   n'habille que la charpente et les surfaces, jamais le comportement.
   ═══════════════════════════════════════════════════════════════════════════ */

.sws-v4-slot--category_header {
  background: var(--color-surface);
  padding-block: 28px 30px;
  border-bottom: 1px solid var(--color-border);
}
.sws-v4-slot--category_header h1 {
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  margin-bottom: .35em;
}

.sws-v4-slot--category_listing { padding-block: 28px; }

/* 🔴 LA GÉOMÉTRIE SIDEBAR + GRILLE EXISTE DÉJÀ DANS LE SOCLE.
   Il rend `<div class="sws-container mnx-category-layout">` contenant
   `<aside class="mnx-sidebar">` et `<div class="mnx-results">`. Sans styler
   `.mnx-category-layout`, les deux s'empilent : les filtres devenaient un
   BANDEAU horizontal pleine largeur au-dessus des produits, et la grille
   perdait sa colonne (constaté au rendu réel — rien à voir avec la maquette).

   220px : même largeur que la référence `modern-luxe`, calée sur les libellés
   de facettes les plus longs sans rogner la grille. */
.mnx-category-layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 30px;
  align-items: start;
}

/* ── Sidebar de filtres ───────────────────────────────────────────────── */

.mnx-sidebar {
  position: sticky;
  /* Juste sous le header collant (topbar + header ≈ header-height + 38px). */
  top: calc(var(--header-height, 72px) + 24px);
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 16px;
}

.mnx-sidebar__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--color-border);
}

.mnx-sidebar__title {
  font-family: var(--font-family-heading);
  font-size: 12px;
  font-weight: 700;
  text-transform: var(--text-transform-label, uppercase);
  letter-spacing: var(--letter-spacing-label, .10em);
  color: var(--color-primary-dark);
}

/* Facettes : le balisage vient du moteur de listing, on n'habille que les
   surfaces et la typographie. */
.mnx-facets { display: flex; flex-direction: column; gap: 14px; }
.mnx-sidebar-section__label,
.mnx-facets label {
  font-size: 13px;
  color: var(--color-text);
}
.mnx-sidebar-section__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  font-family: var(--font-family-heading);
  font-size: 12px;
  font-weight: 700;
  color: var(--color-primary-dark);
  cursor: pointer;
}
.mnx-sidebar-section__count { color: var(--color-text-muted); font-weight: 400; }

/* ── Barre de résultats (compteur, vues, tri) ─────────────────────────── */

.mnx-results { min-width: 0; }

.mnx-results-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 14px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  margin-bottom: 18px;
}
.mnx-results-topbar__count {
  font-size: 13px;
  color: var(--color-text-muted);
}
.mnx-results-topbar__right {
  display: flex;
  align-items: center;
  gap: 10px;
}
.mnx-results-topbar select {
  height: 32px;
  padding-inline: 8px;
  font-size: 13px;
  color: var(--color-text);
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
.mnx-view-toggle { display: flex; gap: 3px; }
.mnx-view-btn {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  color: var(--color-text-muted);
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.mnx-view-btn:hover,
.mnx-view-btn.is-active {
  color: var(--color-primary);
  border-color: var(--color-primary);
}

/* ── Repli tablette / mobile ──────────────────────────────────────────── */

@media (max-width: 900px) {
  /* Une colonne : les filtres passent AU-DESSUS et cessent d'être collants
     (une sidebar sticky pleine largeur masquerait les produits au défilement). */
  .mnx-category-layout { grid-template-columns: 1fr; gap: 20px; }
  .mnx-sidebar { position: static; top: auto; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   FICHE PRODUIT
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Galerie : miniatures VERTICALES à gauche (maquette) ──────────────── */

.mnx-pdp__gallery {
  display: grid;
  /* Miniatures | image principale — l'ordre du DOM place les miniatures en
     premier, la grille les range donc naturellement à gauche. Sans cette
     grille elles s'empilaient AU-DESSUS de l'image (constaté au rendu réel). */
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}

.mnx-pdp__thumbs {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 520px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.mnx-pdp__thumb {
  display: block;
  width: 72px;
  height: 72px;
  padding: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  cursor: pointer;
}
.mnx-pdp__thumb img { width: 100%; height: 100%; object-fit: cover; }
.mnx-pdp__thumb:hover { border-color: var(--color-accent); }
.mnx-pdp__thumb--active { border-color: var(--color-primary); border-width: 2px; }

.mnx-viewer-gallery img,
.mnx-pdp__gallery > img {
  width: 100%;
  border-radius: var(--radius);
  background: var(--color-surface);
}

@media (max-width: 640px) {
  /* Sur mobile, les miniatures passent SOUS l'image et défilent à l'horizontale
     — une colonne de 72px y coûterait un cinquième de la largeur. */
  .mnx-pdp__gallery { grid-template-columns: 1fr; }
  .mnx-pdp__thumbs {
    flex-direction: row;
    order: 2;
    max-height: none;
    overflow-x: auto;
  }
}

/* ── Colonne d'informations ───────────────────────────────────────────── */

.mnx-pdp__title {
  font-size: clamp(22px, 3.2vw, 32px);
  margin-bottom: 10px;
}

.mnx-pdp__price-block { margin-bottom: 16px; }
.mnx-pdp__price {
  font-family: var(--font-family-heading);
  font-size: 26px;
  font-weight: 700;
  color: var(--color-primary-dark);
}

.mnx-pdp__meta { display: flex; flex-direction: column; gap: 6px; margin-bottom: 18px; }
.mnx-pdp__meta-row { display: flex; gap: 8px; font-size: 14px; }
.mnx-pdp__meta-label { color: var(--color-text-muted); min-width: 92px; }
.mnx-pdp__meta-value { color: var(--color-text); }
.mnx-pdp__meta-value--stock { color: var(--color-success); font-weight: 600; }
.mnx-pdp__stock-dot {
  display: inline-block;
  width: 8px; height: 8px;
  margin-inline-end: 6px;
  background: var(--color-success);
  border-radius: 999px;
}

/* ── Achat : quantité + bouton ────────────────────────────────────────── */

.mnx-pdp__buy-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.mnx-pdp__qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-border);
  border-radius: var(--btn-radius);
  overflow: hidden;
}
.mnx-pdp__qty-btn {
  width: 38px; height: 44px;
  background: var(--color-surface);
  border: 0;
  color: var(--color-primary-dark);
  font-size: 16px;
  cursor: pointer;
}
.mnx-pdp__qty-btn:hover { background: var(--color-border); }
.mnx-pdp__qty-input {
  width: 48px; height: 44px;
  border: 0;
  border-inline: 1px solid var(--color-border);
  text-align: center;
  font-size: 15px;
  color: var(--color-text);
}

/* 🔴 LE BOUTON D'ACHAT SORTAIT EN BLEU CLAIR.
   `.sws-btn-primary` du socle retombe sur `--color-accent` (#56B8E8) : le CTA
   principal était plus pâle que les boutons des cartes produit — l'action la
   plus importante de la page, la moins visible. */
/* 🔴 LE BOUTON D'ACHAT SUIT LE CONTRAT DES BOUTONS, pas `--color-primary`.
   Troisième fois que ce défaut apparaît (hero, carte produit, ici) : la
   couleur PRIMAIRE d'un thème est celle du texte et du pied, pas celle de
   l'action. Le bouton disparaissait dans l'identité au lieu d'appeler au clic.

   Mesuré le 2026-09-27 : la fiche rendait `rgb(43,29,22)` — le brun — là où la
   production pose l'orange d'accent `rgb(229,118,46)`. C'est le bouton le plus
   important de la boutique.

   `.sws-btn-primary` du socle commun utilise DÉJÀ `--color-accent` : cette
   règle-ci l'écrasait. On reprend donc la même cascade que les autres boutons
   du moteur, avec `--color-accent` comme repli — ce que le bouton portait
   avant d'être surchargé.

   Au survol, `--color-primary-dark` n'est déclaré par AUCUN thème du parc : le
   fond devenait transparent au passage de la souris. */
.mnx-pdp__add-btn {
  flex: 1 1 220px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding-inline: 24px;
  background: var(--button-background, var(--color-accent, var(--color-primary)));
  border: 1px solid var(--button-background, var(--color-accent, var(--color-primary)));
  border-radius: var(--button-radius, var(--btn-radius, 999px));
  color: var(--button-text, #fff);
  font-size: 15px;
  font-weight: 600;
}
.mnx-pdp__add-btn:hover,
.mnx-pdp__add-btn:focus {
  background: var(--button-hover-background, var(--color-accent-hover, var(--color-primary-dark, var(--color-accent))));
  border-color: var(--button-hover-background, var(--color-accent-hover, var(--color-primary-dark, var(--color-accent))));
  color: var(--button-text, #fff);
}

.mnx-pdp__buy-now {
  display: block;
  margin-top: 10px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: var(--letter-spacing-label, .10em);
  text-transform: uppercase;
  color: var(--color-primary);
}

.mnx-pdp__actions {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--color-border);
}
.mnx-pdp__action-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--color-text-muted);
  cursor: pointer;
}
.mnx-pdp__action-link:hover { color: var(--color-primary); }

/* ── Onglets ──────────────────────────────────────────────────────────── */

.mnx-pdp-tabs-wrap { padding-block: 34px; }

.mnx-pdp-tabs__nav {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 22px;
}

/* Onglets à filet bas, pas des boutons gris : le socle ne rend AUCUN style
   ici, d'où les rectangles nus du rendu par défaut. */
.mnx-pdp-tabs__tab {
  padding: 11px 16px;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  font-family: var(--font-family-heading);
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
}
.mnx-pdp-tabs__tab:hover { color: var(--color-primary); }
.mnx-pdp-tabs__tab--active {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}

/* 🔴 LES PANNEAUX S'AFFICHAIENT TOUS EN MÊME TEMPS.
   Le JS du socle bascule la classe `--active` mais ne pose AUCUN style : sans
   cette règle, description + spécifications + avis + livraison s'empilaient
   à la suite, et les onglets ne servaient à rien (constaté au rendu réel). */
.mnx-pdp-tabs__panel { display: none; }
.mnx-pdp-tabs__panel--active { display: block; }

.mnx-pdp-tabs__desc-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 30px;
  align-items: start;
}
.mnx-pdp-tabs__desc-side {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 18px;
  font-size: 14px;
}

/* Cet aparté n'est rempli que si le produit porte des informations annexes.
   Vide, il rendait un rectangle bleu pâle inexpliqué à droite de la
   description (constaté au rendu réel). `:empty` ne suffit pas — le socle y
   laisse des blancs — d'où `:not(:has(*))`, qui teste l'absence d'ENFANT. */
.mnx-pdp-tabs__desc-side:empty,
.mnx-pdp-tabs__desc-side:not(:has(*)) { display: none; }

/* Sans aparté, la description reprend toute la largeur plutôt que de laisser
   une colonne de 300px vide. */
.mnx-pdp-tabs__desc-layout:not(:has(.mnx-pdp-tabs__desc-side *)) {
  grid-template-columns: 1fr;
}
@media (max-width: 860px) {
  .mnx-pdp-tabs__desc-layout { grid-template-columns: 1fr; gap: 20px; }
}

/* 🔴 RÉASSURANCE EN DOUBLE SUR LA FICHE.
   `product_info` rend déjà son propre encadré (paiement / livraison / retours)
   dans la colonne de droite. Le `feature_grid` du layout répétait les mêmes
   trois messages en bande juste dessous — deux fois la même promesse à
   l'écran. On masque la BANDE et on garde l'encadré, qui est au plus près du
   bouton d'achat, là où la réassurance sert. */
.product-single .mnx-v4-slot--below .mnx-perks,
body[class*="product-"] .mnx-v4-slot--below .mnx-perks { display: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   PANIER
   ═══════════════════════════════════════════════════════════════════════════
   🔴 Le panier rend DÉJÀ ses deux colonnes (`.mnx-cart-layout`) et `cart.js`
   recharge le tout dans `#cartreload`. On habille ses surfaces, on ne
   redéclare AUCUNE grille par-dessus : une seconde grille comprimait la liste
   d'articles dans la moitié gauche et faisait disparaître le récapitulatif.
   ═══════════════════════════════════════════════════════════════════════════ */

.sws-v4-slot--cart_summary { padding-block: 28px; }

.mnx-cart__title { font-size: clamp(24px, 3.4vw, 34px); margin-bottom: 20px; }

/* 🔴 LES DEUX COLONNES DU PANIER N'EXISTAIENT PAS.
   Le socle rend `.mnx-cart-layout` (articles) + l'`<aside>` du récapitulatif,
   mais SANS grille : mesuré `grid-template-columns:none`, tout s'empilait sur
   une colonne — image de 300px, puis titre, puis résumé tout en bas.

   ⚠️ On pose la grille ICI, sur le conteneur que le socle rend DÉJÀ. On ne
   déclare surtout PAS de placement `summary` dans le layout V4 : une seconde
   grille par-dessus comprimerait la liste dans la moitié gauche et casserait
   le rechargement `#cartreload` (voir layouts.php). */
.mnx-cart-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 28px;
  align-items: start;
}

.mnx-cart-main { min-width: 0; display: flex; flex-direction: column; gap: 14px; }

/* ── Ligne d'article ──────────────────────────────────────────────────── */

.mnx-cart-item {
  display: grid;
  /* vignette | informations | quantité+prix */
  grid-template-columns: 88px minmax(0, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 14px;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

/* Sans contrainte, l'image occupait 300px de large et poussait tout le reste
   sous elle. */
.mnx-cart-item__img {
  width: 88px;
  height: 88px;
  object-fit: cover;
  background: var(--color-surface);
  border-radius: var(--radius-sm);
}

.mnx-cart-item__info { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.mnx-cart-item__title {
  font-family: var(--font-family-heading);
  font-size: 15px;
  font-weight: 600;
  /* `inherit` : la bande porte deja sa couleur de texte, et
     `--color-primary-dark` n est declare que par 5 themes sur 20. */
  color: inherit;
}
.mnx-cart-item__title a { color: inherit; }
.mnx-cart-item__title a:hover { color: var(--color-primary); }

.mnx-cart-item__actions { display: flex; gap: 12px; }
.mnx-cart-item__action {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 0;
  background: none;
  border: 0;
  font-size: 12px;
  color: var(--color-text-muted);
  cursor: pointer;
}
.mnx-cart-item__action:hover { color: var(--color-primary); }
.mnx-cart-item__action--remove:hover { color: var(--color-danger); }

.mnx-cart-item__right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.mnx-cart-item__qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-border);
  border-radius: var(--btn-radius);
  overflow: hidden;
}
.mnx-cart-item__qty-btn {
  width: 30px;
  height: 32px;
  background: var(--color-surface);
  border: 0;
  color: var(--color-primary-dark);
  cursor: pointer;
}
.mnx-cart-item__qty-btn:hover { background: var(--color-border); }
.mnx-cart-item__qty-val {
  min-width: 36px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-inline: 1px solid var(--color-border);
  font-size: 14px;
}

.mnx-cart-item__price {
  font-family: var(--font-family-heading);
  font-size: 16px;
  font-weight: 700;
  color: var(--color-primary-dark);
  white-space: nowrap;
}

/* ── Récapitulatif ────────────────────────────────────────────────────── */

.mnx-cart-layout > aside,
.mnx-cart-summary {
  position: sticky;
  top: calc(var(--header-height, 72px) + 24px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 20px;
}
.mnx-cart-layout > aside h2,
.mnx-cart-summary h2 { font-size: 19px; margin-bottom: 14px; }

/* 🔴 LE CTA DE COMMANDE SORTAIT EN BLEU CLAIR (`--color-accent`), comme sur la
   fiche produit : l'action la plus importante du tunnel, la moins visible. */
.mnx-cart-layout .sws-btn-primary,
.mnx-cart-layout [class*="checkout"],
.mnx-cart-summary .sws-btn-primary {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 46px;
  margin-block: 14px 10px;
  background: var(--button-background, var(--color-accent, var(--color-primary)));
  border: 1px solid var(--button-background, var(--color-accent, var(--color-primary)));
  border-radius: var(--btn-radius);
  color: var(--button-text, #fff);
  font-size: 15px;
  font-weight: 600;
}
.mnx-cart-layout .sws-btn-primary:hover,
.mnx-cart-summary .sws-btn-primary:hover {
  background: var(--button-hover-background, var(--color-accent-hover, var(--color-primary-dark, var(--color-accent))));
  border-color: var(--button-hover-background, var(--color-accent-hover, var(--color-primary-dark, var(--color-accent))));
  color: var(--button-text, #fff);
}

/* 🔴 « RETOURS GRATUITS 30 JOURS » — PROMESSE NON VÉRIFIÉE.
   `front/theme/_v4/cart/table.tpl:278` l'écrit EN DUR sous le bouton de
   commande, sur TOUT thème V4, sans consulter la politique de retour de la
   boutique. Sur un distributeur de dispositifs médicaux, s'engager sur des
   retours gratuits qui n'existent pas est un risque commercial, pas un détail
   de style — et c'est exactement ce que `V4StorePreset` neutralise ailleurs
   (`MOTS_LOGISTIQUE_MARCHANDE`).

   On la masque ICI. La réassurance affichée reste celle de `ReassuranceService`
   (bande du bas), qui ne montre que les services réellement configurés.
   ⚠️ Correctif de thème : le défaut subsiste pour les autres thèmes V4 et
   mériterait une correction du socle (lot dédié). */
.mnx-cart-layout .fa-refresh,
.mnx-cart-summary .fa-refresh { display: none; }
.mnx-cart-layout .fa-refresh + *,
.mnx-cart-layout div:has(> .fa-refresh) { display: none; }

/* ── Panier vide ──────────────────────────────────────────────────────── */

.mnx-cart-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding-block: 60px;
  text-align: center;
  color: var(--color-text-muted);
}
.mnx-cart-empty__icon { font-size: 42px; color: var(--color-border); }

@media (max-width: 860px) {
  /* Le récapitulatif passe SOUS les articles et cesse d'être collant. */
  .mnx-cart-layout { grid-template-columns: 1fr; gap: 20px; }
  .mnx-cart-layout > aside,
  .mnx-cart-summary { position: static; top: auto; }
}

@media (max-width: 560px) {
  /* Quantité et prix passent sous les informations : à 3 colonnes, le titre
     se réduisait à deux mots. */
  .mnx-cart-item { grid-template-columns: 64px minmax(0, 1fr); }
  .mnx-cart-item__img { width: 64px; height: 64px; }
  .mnx-cart-item__right {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   AUTHENTIFICATION — connexion, inscription, mot de passe perdu
   ═══════════════════════════════════════════════════════════════════════════
   Gabarits PARTAGÉS du socle (`front/theme/_v4/front/front/`). Ils n'émettent
   AUCUN style : sans ces règles, les champs retombent sur le rendu natif du
   navigateur (mesuré : 32px de haut, bordure `rgb(118,118,118)`, bouton gris
   `rgb(240,240,240)`) — une page d'identification qui ne ressemble à rien.
   ═══════════════════════════════════════════════════════════════════════════ */

.mnx-auth-page { padding-block: 44px 64px; }

/* Deux colonnes : connexion à gauche, création de compte à droite — c'est la
   structure que le gabarit rend déjà (`__login` / `__register`). */
.mnx-auth-card {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: 0;
  max-width: 940px;
  margin-inline: auto;
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.mnx-auth-card__login    { padding: 36px 34px; }
.mnx-auth-card__register {
  padding: 36px 34px;
  background: var(--color-surface);
  border-inline-start: 1px solid var(--color-border);
}

.mnx-auth-card__eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--letter-spacing-label, .10em);
  text-transform: var(--text-transform-label, uppercase);
  color: var(--color-primary);
  margin-bottom: 6px;
}
.mnx-auth-card__title     { font-size: 26px; margin-bottom: 6px; }
.mnx-auth-card__sub       { font-size: 14px; color: var(--color-text-muted); margin-bottom: 22px; }
.mnx-auth-card__reg-title { font-size: 19px; margin-bottom: 6px; }
.mnx-auth-card__reg-sub   { font-size: 14px; color: var(--color-text-muted); margin-bottom: 18px; }

.mnx-auth-card__perks {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 14px;
  color: var(--color-text);
}
.mnx-auth-card__perks li { display: flex; align-items: center; gap: 8px; }
.mnx-auth-card__perks li::before {
  content: "\f00c"; /* fa-check */
  font-family: FontAwesome;
  font-size: 11px;
  color: var(--color-success);
}

/* ── Formulaire ───────────────────────────────────────────────────────── */

.mnx-auth-form__group { margin-bottom: 16px; }

.mnx-auth-form__label {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 600;
  /* `inherit` : la bande porte deja sa couleur de texte, et
     `--color-primary-dark` n est declare que par 5 themes sur 20. */
  color: inherit;
}

.mnx-auth-form__input {
  width: 100%;
  height: 46px;
  padding-inline: 14px;
  font-family: var(--font-family-base);
  font-size: 15px;
  color: var(--color-text);
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: var(--btn-radius);
}
.mnx-auth-form__input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(86, 184, 232, .25);
}

.mnx-auth-form__row-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 18px;
  font-size: 13px;
}
.mnx-auth-form__remember {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--color-text-muted);
  cursor: pointer;
}
.mnx-auth-form__remember input { accent-color: var(--color-primary); }

/* Le lien « mot de passe perdu » : visible, jamais un texte gris perdu. */
.mnx-auth-form__forgot {
  color: var(--color-primary);
  font-weight: 600;
}
.mnx-auth-form__forgot:hover { color: var(--color-primary-dark); text-decoration: underline; }

.mnx-auth-form__submit,
.mnx-auth-card__reg-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 46px;
  padding-inline: 20px;
  font-family: var(--font-family-base);
  font-size: 15px;
  font-weight: 600;
  border-radius: var(--btn-radius);
  cursor: pointer;
}
.mnx-auth-form__submit {
  background: var(--button-background, var(--color-accent, var(--color-primary)));
  border: 1px solid var(--button-background, var(--color-accent, var(--color-primary)));
  color: var(--button-text, #fff);
}
.mnx-auth-form__submit:hover {
  background: var(--color-primary-dark);
  border-color: var(--color-primary-dark);
}
/* Création de compte : action SECONDAIRE — en contour, pour que la connexion
   reste l'action principale de l'écran. */
.mnx-auth-card__reg-btn {
  background: transparent;
  border: 1px solid var(--color-primary);
  color: var(--color-primary);
}
.mnx-auth-card__reg-btn:hover { background: var(--color-primary); color: #fff; }

/* ── Erreurs et messages ──────────────────────────────────────────────── */

.mnx-auth-card__errors {
  margin-bottom: 18px;
  padding: 12px 14px;
  background: rgba(180, 83, 78, .08);
  border: 1px solid var(--color-danger);
  border-radius: var(--radius-sm);
}
.mnx-auth-card__error-item {
  margin: 0;
  font-size: 13px;
  color: var(--color-danger);
}

@media (max-width: 760px) {
  /* Une colonne : la création de compte passe SOUS la connexion et garde son
     fond teinté, qui continue de les séparer. */
  .mnx-auth-card { grid-template-columns: 1fr; max-width: 520px; }
  .mnx-auth-card__register {
    border-inline-start: 0;
    border-top: 1px solid var(--color-border);
  }
  .mnx-auth-card__login,
  .mnx-auth-card__register { padding: 28px 22px; }
  .mnx-auth-page { padding-block: 28px 44px; }
}

/* 🔴 UNE SEULE COLONNE QUAND IL N'Y A PAS DE SECONDE COLONNE.
   `/motdepasseperdu` réutilise `.mnx-auth-card` mais NE rend PAS de bloc
   `__register` : la grille `1.15fr .85fr` y laissait ~400px de vide à droite
   (mesuré — `register_present:false`). `:has()` teste la présence réelle du
   bloc plutôt que d'ajouter une classe au gabarit partagé. */
.mnx-auth-card:not(:has(.mnx-auth-card__register)) {
  grid-template-columns: 1fr;
  max-width: 520px;
}

/* ⚠️ PAS DE CORRECTIF « débordement 3px » SUR LES PAGES AUTH.
   Un `.row` Bootstrap y dépassait de 3px — MAIS uniquement pour un
   visiteur DÉJÀ CONNECTÉ : dans ce cas `/connexion` rend le layout
   ADMIN (`body.admin`, `.admin-shell` dans le <header>), dont les
   gouttières négatives sont scopées `#admin .admin-shell` et hors de
   portée d une feuille de thème.
   Session fermée — le cas réel d un visiteur qui se connecte — les trois
   pages mesurent 0 de débordement. Il n y avait rien à corriger ici :
   les règles ajoutées d abord (neutralisation des marges, masquage de
   #loginModal) ont été retirées, elles ne servaient qu un faux positif. */
.admin-shell [class*="col-"],
[class*="admin-shell"] [class*="col-"],
.mnx-auth-page [class*="col-"] { padding-inline: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   CARTE ILLUSTRÉE EN RANGÉE — la vignette à gauche du texte, sur mobile
   ═══════════════════════════════════════════════════════════════════════════
   Opt-in par `presentation: cartes_rangee`. La forme `cartes` n'est pas touchée :
   aucun preset réglé sur elle ne change d'un pixel.

   🔴 POURQUOI CETTE FORME EXISTE. Mesuré le 2026-09-27 sur la migration
   Miaouleo : la source pose `grid-template-columns: 9.6rem 1fr 2.4rem` sous
   768px — vignette de 96px, texte, chevron — et ne passe en colonne qu'au-delà.
   Le V4 gardait l'image pleine largeur en haut (292×219 contre 96×72) et la
   section mesurait 1231px de haut contre 545 à la source.

   Trois enfants directs (img, h3, p), sans conteneur intermédiaire : la grille
   les place donc explicitement. L'image occupe la colonne 1 sur les deux
   lignes, le texte la colonne 2.

   `em` et non `rem` : trois thèmes du parc posent `html{font-size:62.5%}` et un
   `rem` y vaudrait 10px au lieu de 16. L'`em` se mesure sur l'élément et donne
   la même taille sous les deux racines. */
.sws-v4-feature-grid__item--cartes_rangee {
  display: grid;
  grid-template-columns: 6em 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 1em;
  row-gap: .25em;
}
.sws-v4-feature-grid__item--cartes_rangee > img {
  grid-column: 1;
  grid-row: 1 / span 2;
  width: 6em;
  height: 4.5em;            /* 4/3, le ratio de la source */
  object-fit: cover;
  border-radius: var(--border-radius-sm, 6px);
  align-self: center;
}
.sws-v4-feature-grid__item--cartes_rangee > :not(img) { grid-column: 2; }

/* Au-delà du seuil, la carte s'empile comme une carte illustrée ordinaire :
   c'est le comportement de la source, qui réserve la rangée au mobile. */
@media (min-width: 768px) {
  .sws-v4-feature-grid__item--cartes_rangee {
    display: block;
    padding: 0 0 1.25em;
  }
  .sws-v4-feature-grid__item--cartes_rangee > img {
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    border-radius: 0;
    margin: 0 0 1em;
  }
}

/* ── La description d'une rubrique ─────────────────────────────────────────
   Un chapô de rubrique se BALAIE, il ne se lit pas comme un article : on
   l'élargit donc à 100ch au lieu des 62ch d'un texte suivi. Mesuré le
   2026-09-27 sur une description de 208 caractères : 3 lignes à 62ch, 2 à
   100ch — une ligne de hauteur rendue au catalogue, qui est ce qu'on vient
   voir.

   🔴 UNE BORNE RESTE, elle n'est pas supprimée. Sans elle, le paragraphe
   courrait sur 1232px, soit ~146 caractères par ligne : l'œil perd la ligne
   suivante en revenant à la marge, et c'est précisément ce que `ch` protège.
   On desserre la mesure, on ne l'abandonne pas.

   Atténuée, parce qu'elle accompagne le titre sans lui disputer l'attention.
   Une rubrique sans description ne rend aucun paragraphe — la règle n'a donc
   aucun effet là où il n'y a rien. */
.mnx-category-header__intro {
  max-width: 100ch;
  margin: .75em 0 0;
  font-size: .9375rem;
  line-height: var(--line-height-base, 1.6);
  color: var(--color-text-muted, #6b6b6b);
}

/* ══ QUICK VIEW ═════════════════════════════════════════════════════════════ */

#quickproductview .modal-dialog { max-width: 640px; margin: 3vh auto; }
#quickproductview .modal-content {
  border: none;
  border-radius: var(--border-radius, 0);
  box-shadow: var(--shadow-md, 0 4px 14px rgba(28,27,25,.07), 0 14px 40px rgba(28,27,25,.09));
  overflow: hidden;
}

.mnx-qv {
  padding: 1.75em 2em;
  position: relative;
  display: flex;
  flex-direction: column;
  max-height: 88vh;
}
.mnx-qv__close {
  position: absolute; top: 1em; right: 1em;
  background: none; border: none;
  font-size: 1.1em; color: var(--color-text-muted, #6E6960);
  cursor: pointer; padding: .25em .5em; line-height: 1; z-index: 2;
  transition: color .15s;
}
.mnx-qv__close:hover { color: var(--color-text, #1C1B19); }

.mnx-qv__head { margin-bottom: 1.25em; flex: 0 0 auto; }
.mnx-qv__label {
  font-size: .7em; font-weight: 700;
  letter-spacing: var(--letter-spacing-label, .18em);
  text-transform: uppercase;
  color: var(--color-accent, var(--color-primary, #1C1B19));
  margin: 0 0 .25em;
}
.mnx-qv__title {
  font-family: var(--font-family-heading, Georgia, serif);
  font-size: 1.35em; font-weight: var(--font-weight-heading, 600);
  letter-spacing: -.02em;
  color: var(--color-text, #1C1B19);
  margin: 0;
  line-height: var(--line-height-heading, 1.15);
}

.mnx-qv__body {
  display: grid; grid-template-columns: 220px 1fr;
  gap: 1.75em; align-items: start;
  flex: 1 1 auto; min-height: 0;
}
.mnx-qv__photo {
  border: 1px solid var(--color-border, #E4DDD0);
  border-radius: var(--border-radius, 0);
  overflow: hidden;
  background: var(--color-surface-alt, #F2EDE4);
  aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  align-self: start; position: sticky; top: 0;
}
.mnx-qv__photo img { width: 100%; height: 100%; object-fit: cover; }

.mnx-qv__details {
  display: flex; flex-direction: column; gap: .9em;
  min-height: 0; max-height: 100%;
  overflow-y: auto; overscroll-behavior: contain;
}

.mnx-qv__price-row { display: flex; align-items: center; gap: .6em; flex-wrap: wrap; }
.mnx-qv__price {
  font-family: var(--font-family-heading, Georgia, serif);
  font-size: 1.6em; font-weight: 700;
  color: var(--color-text, #1C1B19);
  letter-spacing: -.02em;
}
.mnx-qv__old-price {
  font-size: 1em;
  color: var(--color-text-muted, #6E6960);
  text-decoration: line-through;
}
.mnx-qv__save-badge {
  background: var(--color-accent, var(--color-primary, #1C1B19));
  color: var(--color-on-accent, #fff);
  font-size: .7em; font-weight: 700;
  padding: .15em .5em; border-radius: 999px;
}

.mnx-qv__form { margin-top: .25em; }
.mnx-qv__buy-row {
  display: grid; grid-template-columns: 100px 1fr; gap: .6em;
}
.mnx-qv__add-btn {
  justify-content: center; height: 44px;
  font-size: .82em; letter-spacing: .04em; white-space: nowrap;
}

.mnx-qv__desc {
  margin: 0;
  font-size: .95em;
  line-height: var(--line-height-base, 1.75);
  color: var(--color-text-muted, #6E6960);
}
.mnx-qv__cta-link {
  display: inline-flex; align-items: center; gap: .4em;
  justify-content: center;
  width: 100%; text-align: center;
}

.mnx-qv__full-link {
  font-size: .82em;
  color: var(--color-accent, var(--color-primary, #1C1B19));
  text-decoration: none; font-weight: 600;
  transition: opacity .15s;
}
.mnx-qv__full-link:hover { opacity: .75; }

@media (max-width: 600px) {
  .mnx-qv { padding: 1.25em 1em; max-height: 90vh; }
  .mnx-qv__body {
    display: flex; flex-direction: column; gap: 1em;
  }
  .mnx-qv__photo {
    position: static; align-self: stretch;
    aspect-ratio: auto; height: 30vh; flex: 0 0 auto;
  }
  .mnx-qv__details { flex: 1 1 auto; padding-right: 0; }
  #quickproductview .modal-dialog { margin: 1vh auto; }
}
