/* =====================================================================
   STELVOREN — COMPOSANTS
   Le CSS des composants qui vivent dans le thème enfant (et non dans
   Elementor) : carte produit, flèches de carrousel, tiroir panier.
   Construits en phase 3 du plan — ce fichier est leur emplacement.
   Tout s'appuie sur les variables de jetons.css.
   ================================================================== */

/* --- Bouton panier [stelvoren_bouton_panier] — ouvre le tiroir (105) - */
.stv-bouton-panier {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
}

.stv-bouton-panier__compteur {
  position: absolute;
  top: -6px;
  right: -10px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 50%;
  background: var(--stv-noir);
  color: var(--stv-blanc);
  font: 500 11px/18px var(--stv-police-texte);
  text-align: center;
}

/* --- Carte produit (tâche 22) ---------------------------------------- */
/*
   Une seule carte, fluide. La maquette en montre deux tailles — 402 x 449
   au catalogue, 384 x 517 sur l'accueil — mais c'est le même composant :
   la photo est carrée, tout le reste est de hauteur constante, donc la
   carte prend la largeur de sa colonne et la hauteur suit.

   Sert sur l'accueil, les archives, la recherche, les produits liés et
   le tiroir panier. Toute retouche ici se voit partout.
*/
.stv-carte-produit {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-8);
  padding: var(--stv-carte-padding);
  background: var(--stv-gris-clair);
  border-radius: var(--stv-rayon);
}

/*
   Photo carrée, jamais recadrée : les visuels produit ont des formes
   très différentes (un reformer est large, un bloc est cubique) et un
   recadrage couperait le matériel. D'où object-fit: contain.

   mix-blend-mode: multiply est ce qui fait tenir l'ensemble : les
   photos du catalogue sont détourées sur fond blanc, et le multiply
   fond ce blanc dans le gris clair de la carte. Sans lui, chaque photo
   affiche un rectangle blanc au milieu du gris.
*/
.stv-carte-produit__media {
  aspect-ratio: 1 / 1;
  overflow: hidden;
}

.stv-carte-produit__image {
  width: 100%;
  height: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}

/*
   Zone du nom à hauteur constante : sans cela, une carte dont le nom passe
   sur deux lignes décale son prix par rapport à ses voisines, et toute la
   grille se désaligne. 48 px = deux lignes de 16 px a 1,5. Au-dela, le nom
   est coupe proprement a deux lignes.

   TEXTE CALÉ EN HAUT depuis le 28/10 (recette d'Estevan R28, tâche 203 :
   « faire en sorte que les titres arrivent tous au même niveau ») : la
   première ligne de chaque nom part à la même hauteur sur toute une
   rangée, un nom d'une ligne laisse sa seconde ligne vide dessous. Il
   était calé en bas depuis la tâche 22.
*/
.stv-carte-produit .stv-carte-produit__nom {
  display: flex;
  align-items: flex-start;
  min-height: 48px;
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
}

.stv-carte-produit__lien {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
}

/*
   Toute la carte est cliquable, mais seul le nom porte le lien : le
   texte reste sélectionnable et les lecteurs d'écran annoncent un seul
   lien, correctement nommé, au lieu d'un bloc entier.
*/
.stv-carte-produit__lien::after {
  content: "";
  position: absolute;
  inset: 0;
}

.stv-carte-produit__lien:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/*
   LE PRIX, V2 — tâche 156, recette d'Estevan R5 (26/10). Composant
   « Product » 331:10271 / 331:10286 / 331:10298 :

     « À partir de »   Inter Light 12 / 1,1, noir à 80 %
     « 2312 € HT »     Inter Medium 14 / 1,5, noir
     point            4 × 4, #323940 — le noir à 80 % posé sur le gris clair
     « 2890 € TTC »    Inter Regular 14 / 1,5, noir à 80 %
     4 entre le HT, le point et le TTC

   Les deux tailles sont des propriétés, pas des valeurs : les variantes
   étroites (catalogue et recherche en mobile, 331:10298) les passent à
   10 / 12 sans réécrire les règles. Le contenu vient de
   stelvoren_prix_carte() (inc/woocommerce.php).

   Sans « À partir de » (produit à prix fixe), LA LIGNE RESTE RÉSERVÉE :
   `--vide` est posée, invisible, à sa hauteur (12 × 1,1). Le nom et le
   prix sont donc à la même place sur toutes les cartes d'une rangée, que
   le prix varie ou non (recette d'Estevan R28, 28/10 ; la décision de
   Logan du 26/10 — la ligne retirée et le nom qui descendait se coller au
   prix — est RÉVOQUÉE). La carte garde sa hauteur, 462 au catalogue. Les
   deux tailles sont déclarées sur la CARTE : les variantes les lisent.
   Seules les cartes EN LIGNE (recherche mobile) retirent la ligne vide :
   chacune y est centrée pour elle-même, il n'y a pas de rangée à aligner.

   Si les deux montants ne tiennent pas sur une ligne (carte de 201, gros
   montant), le TTC passe dessous, le point avec lui ou en fin de ligne :
   jamais de débordement.
*/
.stv-carte-produit {
  --stv-carte-prix-taille: var(--stv-taille-petit);
  --stv-carte-a-partir-taille: var(--stv-taille-copyright);
}

.stv-carte-produit .stv-carte-produit__prix {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin: 0;
  font-family: var(--stv-police-texte);
  font-size: var(--stv-carte-prix-taille);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte-secondaire);
}

.stv-carte-produit .stv-carte-produit__a-partir {
  display: block;
  min-height: calc(var(--stv-carte-a-partir-taille) * 1.1);
  font-size: var(--stv-carte-a-partir-taille);
  font-weight: 300;
  line-height: 1.1;
}

.stv-carte-produit .stv-carte-produit__a-partir--vide {
  visibility: hidden;
}

.stv-carte-produit .stv-carte-produit__montants {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: var(--stv-espace-4);
}

.stv-carte-produit .stv-carte-produit__montant {
  white-space: nowrap;
}

.stv-carte-produit .stv-carte-produit__montant--ht {
  font-weight: 500;
  color: var(--stv-texte);
}

.stv-carte-produit .stv-carte-produit__point {
  flex: none;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
}

/* Promotion : l'ancien prix barré, devant le montant courant, à la graisse du texte.
   29/10 (tâche 168, B.4) : la couleur porte seule la discrétion. L'ancien
   couple `--stv-texte-secondaire` (0,8) × `opacity: 0.6` donnait un noir à
   0,48, soit 3,45:1 sur le gris de la carte ; `--stv-texte-tertiaire` (0,6)
   sans opacité donne ≈ 5,2:1. Même rendu à l'œil, un cran plus foncé. */
.stv-carte-produit .stv-carte-produit__barre {
  margin-right: var(--stv-espace-4);
  font-weight: 400;
  color: var(--stv-texte-tertiaire);
}

/* Produit groupé (rendu de WooCommerce) : la promotion garde son dessin d'avant,
   la couleur remplace l'opacité (même raison). */
.stv-carte-produit__prix del {
  margin-right: var(--stv-espace-6);
  color: var(--stv-texte-tertiaire);
}

.stv-carte-produit__prix ins {
  text-decoration: none;
}

/*
   Grille des archives WooCommerce. Sur l'accueil, c'est Elementor qui
   dispose les cartes ; ici, il faut remplacer la grille du greffon,
   dont les colonnes flottantes ne conviennent pas.
*/
.woocommerce ul.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--stv-gouttiere);
  margin: 0;
  padding: 0;
  list-style: none;
}

.woocommerce ul.products::before,
.woocommerce ul.products::after {
  content: none;
}

.woocommerce ul.products li.product {
  width: auto;
  margin: 0;
  float: none;
}

/* --- Favori : le cœur de la carte (lot « Favoris », 13/10) ------------ */
/*
   Relevé Dev Mode `156:5296` (Catalog), `156:5384` (Mobile), `156:5392`
   (HeroTab), asset exporté : un carré de 32 au coin haut droit de la carte,
   à 16 des deux bords — donc au coin de la photo —, fond `#E2E6E9`
   (`--stv-fond-action`), et le cœur en CONTOUR de 1,33 à l'anthracite 50 %
   (`--stv-texte-indication`), 13,33 × 11,34 : l'icône `favori`.

   DERNIER enfant de la carte, en absolu : il ne déplace rien et ne prend
   aucune case dans les cartes passées en grille (recherche). `z-index: 1` :
   au-dessus du `::after` qui étend le lien du nom à toute la carte.

   ÉCRIT CACHÉ (`hidden`), et c'est le script qui le montre : rien n'annonce
   un service qui ne répond pas. L'attribut perd contre toute règle d'auteur
   qui pose un `display` : la règle `[hidden]` est écrite au-dessus, au
   compte.

   TROIS FOIS LA CLASSE (0,3,0) : c'est un `<button>`. Le kit d'Elementor
   écrit sur `button` à 0,1,1, le `reset.css` de Hello pose
   `[type=button]:hover, [type=button]:focus` à 0,2,0 (fond rose `#c36`) —
   le survol est donc écrit aussi, à 0,4,0.

   DANS LA LISTE (`aria-pressed="true"`) — NON DESSINÉ, provisoire (à
   Estevan) : le même tracé REMPLI, à l'anthracite plein. Le contour au repos
   ne fait que 2,9:1 sur son carré ; un état doit se voir (11,8:1). Survol et
   focus, non dessinés : l'encre passe à l'anthracite plein.
*/
.stv-favori.stv-favori.stv-favori {
  position: absolute;
  z-index: 1;
  top: var(--stv-carte-padding);
  right: var(--stv-carte-padding);
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: 32px;
  height: 32px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  background: var(--stv-fond-action);
  box-shadow: none;
  color: var(--stv-texte-indication);
  line-height: 1;
  cursor: pointer;
}

.stv-favori.stv-favori.stv-favori[hidden] {
  display: none;
}

.stv-favori.stv-favori.stv-favori:hover,
.stv-favori.stv-favori.stv-favori:focus,
.stv-favori.stv-favori.stv-favori[aria-pressed="true"] {
  background: var(--stv-fond-action);
  color: var(--stv-anthracite);
}

.stv-favori.stv-favori.stv-favori:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* Le glyphe ne capte pas le clic ; son trait peut déborder de sa boîte quand il est agrandi (fiche). */
.stv-favori .stv-favori__glyphe {
  overflow: visible;
  pointer-events: none;
}

.stv-favori[aria-pressed="true"] .stv-favori__glyphe {
  fill: currentColor;
}

/*
   La carte EN LIGNE des résultats de recherche en mobile (`238:6864`,
   catalogue.css § 8) ne dessine pas de cœur — le panneau non plus, mais lui
   ne l'écrit pas (`favori` à faux, inc/recherche.php). Ici la carte est
   celle du catalogue, qui le porte en desktop : il s'efface sous 768.
*/
@media (max-width: 767px) {
  .stv-catalogue-page--recherche .stv-grille-produits .stv-favori.stv-favori.stv-favori {
    display: none;
  }
}

/* --- Carte produit : l'état de survol (fiche 192, 26/10) ------------ */
/*
   Recette d'Estevan R5, maquette `331:10310` (« product Catalog Hovered »,
   404 × 449, relevé Dev Mode du 26/10). La zone de la photo (370 × 328 au
   catalogue) se partage en :

     galerie (le reste) 12 segments (0 : tracés dans les 2 du dessus) 12
     « Usage : … » + pastilles (21) 12 « Ajouter au panier » (36)

   — 235 de photo pour 328 de zone, la cote de la maquette. Sans usage ni
   pastilles, pas de rangée : la photo garde 268. Nom, prix et cœur ne
   bougent pas : LA CARTE NE CHANGE PAS DE HAUTEUR.

   LE BLOC EST ÉCRIT APRÈS LE NOM ET LE PRIX (parties/carte-produit.php :
   au clavier et à la lecture, le produit d'abord) et posé PAR-DESSUS LA
   PHOTO : la carte passe en grille d'une colonne, la photo et le bloc dans
   la même case (rangée 1) — le bloc prend exactement la taille de la photo,
   quel que soit son rapport (carré à l'accueil, 370 / 328 au catalogue).
   Nom et prix se placent d'eux-mêmes dessous, dans l'ordre ; le cœur est
   en absolu. `align-content: start` : comme la colonne flexible d'avant,
   une carte étirée (carrousel à hauteur égale) garde son surplus en bas.

   AU REPOS le bloc est là mais transparent et sans clic : ses commandes
   (pastilles, bouton) restent atteignables AU CLAVIER, et le focus montre
   l'état. Sa galerie est en `display: none` : ses images paresseuses ne
   partent qu'au survol (et carrousels.js ne les précharge pas : piste
   différée).

   LE FOCUS QUI MONTRE L'ÉTAT EST LE FOCUS VISIBLE — `:has(:focus-visible)`,
   et non `:focus-within` (recette d'Estevan R26, 28/10, tâche 203). Un clic
   de souris sur une flèche, un segment ou une pastille donne le focus à ce
   bouton (Chrome, Edge, Firefox) : avec `:focus-within`, la carte restait
   en survol après le départ de la souris, jusqu'au clic suivant ailleurs.
   Le focus posé par la souris n'est pas « visible » ; celui du clavier
   l'est. Un navigateur sans `:has()` (Firefox avant 121) garde
   `:focus-within` : la règle de repli est sous `@supports`, plus bas.

   SEULEMENT À LA SOURIS, à partir de 768 : au doigt il n'y a pas de survol
   (un premier toucher ne doit pas ouvrir un état au lieu de la fiche) ; sous
   768, les cartes du catalogue font 353 et celles des résultats de
   recherche sont en ligne — le bloc n'y est pas affiché.

   Non dessinés : survol et focus des commandes, rupture, « Choisir une
   option » — les composants du site (pastilles, petit bouton, flèches de la
   carte des souhaits).

   LE PASSAGE EST ANIMÉ (demande de Logan, 26/10 à 17 h 42 : « plus
   smooth » ; la maquette n'en décrit pas) : un fondu enchainé de 0,35 s — le
   bloc, sur le fond de la carte, recouvre peu à peu la photo du repos, qui
   n'a donc pas à disparaître elle-même —, et la rangée « Usage » et le bouton
   montent de 8 en même temps. Au retour, la même chose à l'envers : la
   galerie reste affichée sous le bloc transparent une fois la carte équipée
   (`data-stv-survol-pret`, carte-produit.js), sans quoi elle disparaîtrait
   d'un coup au début du fondu. Rien sous « mouvement réduit ».
*/
.stv-carte-produit__survol {
  display: none;
}

@media (hover: hover) and (min-width: 768px) {
  .stv-carte-produit.stv-carte-produit--survol {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
  }

  .stv-carte-produit--survol > .stv-carte-produit__media,
  .stv-carte-produit--survol > .stv-carte-produit__survol {
    grid-row: 1;
    grid-column: 1;
  }

  /*
     Le fond de la carte, repris : le bloc est un contexte d'empilement
     (opacité, z-index), le `multiply` des photos ne se fond qu'avec ce qui
     est dedans — sans fond, le blanc des packshots restait blanc.
  */
  .stv-carte-produit--survol > .stv-carte-produit__survol {
    z-index: 1;
    display: flex;
    flex-direction: column;
    gap: var(--stv-espace-12);
    min-width: 0;
    min-height: 0;
    background-color: inherit;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .stv-carte-produit--survol > .stv-carte-produit__survol > .stv-carte-produit__rangee,
  .stv-carte-produit--survol > .stv-carte-produit__survol > .stv-carte-produit__bouton {
    transform: translateY(8px);
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .stv-carte-produit--survol:is(:hover, :has(:focus-visible)) > .stv-carte-produit__survol {
    opacity: 1;
  }

  .stv-carte-produit--survol:is(:hover, :has(:focus-visible)) > .stv-carte-produit__survol > .stv-carte-produit__rangee,
  .stv-carte-produit--survol:is(:hover, :has(:focus-visible)) > .stv-carte-produit__survol > .stv-carte-produit__bouton {
    transform: none;
  }

  /* Les commandes prennent le clic ; entre elles, il retombe sur le lien du nom (toute la carte). */
  .stv-carte-produit--survol:is(:hover, :has(:focus-visible)) > .stv-carte-produit__survol > * {
    pointer-events: auto;
  }

  .stv-carte-produit--survol:is(:hover, :has(:focus-visible)) .stv-carte-produit__vues.stv-carte-produit__vues,
  .stv-carte-produit--survol[data-stv-survol-pret] .stv-carte-produit__vues.stv-carte-produit__vues {
    display: flex;
  }
}

/* Repli sans `:has()` : l'état au clavier par `:focus-within` (le défaut R26 y demeure). */
@supports not selector(:has(*)) {
  @media (hover: hover) and (min-width: 768px) {
    .stv-carte-produit--survol:focus-within > .stv-carte-produit__survol {
      opacity: 1;
    }

    .stv-carte-produit--survol:focus-within > .stv-carte-produit__survol > .stv-carte-produit__rangee,
    .stv-carte-produit--survol:focus-within > .stv-carte-produit__survol > .stv-carte-produit__bouton {
      transform: none;
    }

    .stv-carte-produit--survol:focus-within > .stv-carte-produit__survol > * {
      pointer-events: auto;
    }

    .stv-carte-produit--survol:focus-within .stv-carte-produit__vues.stv-carte-produit__vues {
      display: flex;
    }
  }
}

@media (hover: hover) and (min-width: 768px) and (prefers-reduced-motion: reduce) {
  .stv-carte-produit--survol > .stv-carte-produit__survol,
  .stv-carte-produit--survol > .stv-carte-produit__survol > .stv-carte-produit__rangee,
  .stv-carte-produit--survol > .stv-carte-produit__survol > .stv-carte-produit__bouton {
    transform: none;
    transition: none;
  }
}

/* La galerie (331:10312) et ses segments (331:10313) : une piste, comme celle de la carte des souhaits. */
.stv-carte-produit .stv-carte-produit__galerie {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  gap: var(--stv-espace-12);
  min-height: 0;
}

.stv-carte-produit .stv-carte-produit__cadre {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
}

/* Trois classes : le kit habille `ul` ; défilement natif à accroche, sans barre. */
.stv-carte-produit .stv-carte-produit__vues.stv-carte-produit__vues {
  display: none;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  list-style: none;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.stv-carte-produit .stv-carte-produit__vues::-webkit-scrollbar {
  display: none;
}

.stv-carte-produit .stv-carte-produit__vue {
  flex: 0 0 100%;
  min-width: 0;
  margin: 0;
  padding: 0;
  scroll-snap-align: start;
}

.stv-carte-produit .stv-carte-produit__lien-image {
  display: block;
  width: 100%;
  height: 100%;
}

/*
   La photo n'est PAS recadrée (`contain`, fondue par `multiply`), comme au
   repos et sur la carte des souhaits : la maquette montre une photo
   d'ambiance en recouvrement, un packshot recadré perdrait ses bords. Trois
   classes contre `.elementor img` et `.woocommerce img` (`height: auto`).
*/
.stv-carte-produit .stv-carte-produit__vue-image.stv-carte-produit__vue-image {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: contain;
  mix-blend-mode: multiply;
}

/*
   LES FLÈCHES (331:10329, 331:10331) : celles de la carte des souhaits —
   24 × 24 aux deux bords de la photo, 4 sous sa mi-hauteur, carré
   `--stv-fond-action` à 50 %, pleine opacité au survol, 25 % en bout de
   course. Cachées tant que carrousels.js n'a pas mesuré la piste ; à la
   souris seulement (`tabindex="-1"`). Trois classes : `<button>`.
*/
.stv-carte-produit__fleche.stv-carte-produit__fleche.stv-carte-produit__fleche {
  position: absolute;
  z-index: 1;
  top: calc(50% - 8px);
  display: grid;
  place-items: center;
  box-sizing: border-box;
  width: 24px;
  height: 24px;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  background: var(--stv-fond-action);
  box-shadow: none;
  color: var(--stv-noir);
  opacity: 0.5;
  cursor: pointer;
}

.stv-carte-produit__fleche.stv-carte-produit__fleche.stv-carte-produit__fleche[hidden] {
  display: none;
}

.stv-carte-produit__fleche.stv-carte-produit__fleche.stv-carte-produit__fleche--precedent {
  left: 0;
}

.stv-carte-produit__fleche.stv-carte-produit__fleche.stv-carte-produit__fleche--suivant {
  right: 0;
}

.stv-carte-produit__fleche--suivant .stv-icone {
  transform: rotate(180deg);
}

.stv-carte-produit__fleche.stv-carte-produit__fleche.stv-carte-produit__fleche:hover,
.stv-carte-produit__fleche.stv-carte-produit__fleche.stv-carte-produit__fleche:focus {
  background: var(--stv-fond-action);
  color: var(--stv-noir);
  opacity: 1;
}

.stv-carte-produit__fleche.stv-carte-produit__fleche.stv-carte-produit__fleche[aria-disabled="true"] {
  opacity: 0.25;
  cursor: default;
}

/* Les segments : un par image, 8 d'écart, 2 d'épaisseur tracés au-dessus de leur ligne ; noir pour l'image en vue. */
.stv-carte-produit .stv-segments {
  display: flex;
  flex: none;
  gap: var(--stv-espace-8);
  height: 2px;
  margin-top: -2px;
}

.stv-carte-produit .stv-segments__segment {
  flex: 1 1 0;
  background: var(--stv-filet-liste);
}

.stv-carte-produit .stv-segments__segment[data-actif] {
  background: var(--stv-noir);
}

/* La rangée (331:10318) : « Usage : … » (Inter 14 / 1,5, noir) à gauche, les pastilles (20, écart 4,8) à droite. */
.stv-carte-produit .stv-carte-produit__rangee {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: space-between;
  gap: var(--stv-espace-12);
  min-height: 21px;
}

.stv-carte-produit .stv-carte-produit__usage {
  min-width: 0;
  margin: 0;
  overflow: hidden;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stv-carte-produit__rangee .stv-pastilles {
  flex-wrap: nowrap;
  margin-left: auto;
}

/* « Ajouter au panier » (331:10327, `primarySmall`) : le petit bouton du site, pleine largeur. */
.stv-carte-produit .stv-carte-produit__bouton.stv-carte-produit__bouton {
  flex: none;
  box-sizing: border-box;
  width: 100%;
}

/* --- Carte article (tâche 25) ---------------------------------------- */
/*
   Même parti que la carte produit : fond gris clair, marge 16, aucun
   arrondi. Deux différences tenant au contenu — l'image est en `cover`
   (une photo d'illustration se recadre sans dommage, contrairement à un
   visuel produit détouré) et sans `multiply`, puisqu'elle n'a pas de
   fond blanc à fondre.
*/
.stv-carte-article {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-12);
  padding: var(--stv-carte-padding);
  background: var(--stv-gris-clair);
  border-radius: var(--stv-rayon);
}

.stv-carte-article__media {
  aspect-ratio: 352 / 256;
  overflow: hidden;
}

.stv-carte-article__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Ligne méta : pastille de catégorie et date, alignées sur la base. */
.stv-carte-article .stv-carte-article__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--stv-espace-8);
  margin: 0;
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
}

.stv-carte-article .stv-carte-article__pastille {
  padding: var(--stv-espace-8) var(--stv-espace-16);
  background: var(--stv-pastille);
  color: var(--stv-bleu-petrole);
  /* Les noms de catégorie sont saisis en capitales dans la base ;
     capitalize normalise l'affichage sans toucher aux données. */
  text-transform: capitalize;
}

.stv-carte-article .stv-carte-article__date {
  color: var(--stv-texte-secondaire);
  /* Le nom du mois sort en minuscules de WordPress en français. */
  text-transform: capitalize;
}

/* Titre sur deux lignes au plus, comme la carte produit. */
.stv-carte-article .stv-carte-article__titre {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-carte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
}

.stv-carte-article__lien {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
}

/* Toute la carte est cliquable ; un seul lien réel, porté par le titre. */
.stv-carte-article__lien::after {
  content: "";
  position: absolute;
  inset: 0;
}

.stv-carte-article__lien:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* Repère visuel, pas un lien : voir le commentaire du gabarit.
   margin-top auto le colle en bas dès que la carte est étirée à la
   hauteur de ses voisines — c'est ce que montre la maquette. */
.stv-carte-article__action {
  align-self: flex-start;
  margin-top: auto;
}

/*
   « LIRE L'ARTICLE » : Inter Medium 16 en capitales, souligné, à l'encre
   (156:9440). Jusqu'au 28/09 ce dessin venait de `stv-lien-maj-souligne`,
   une classe GLOBALE du kit Elementor — servie par
   `uploads/elementor/css/global-73-frontend-desktop.css` sous
   `.elementor .stv-lien-maj-souligne` : rien ne l'atteignait hors d'une
   page Elementor, donc pas sur le blog rendu en PHP. Le thème habille
   désormais son propre élément, aux mêmes valeurs ; l'accueil ne change
   pas (les deux règles disent la même chose).
*/
.stv-carte-article .stv-carte-article__action {
  display: inline-flex;
  align-items: center;
  gap: var(--stv-espace-6);
  color: var(--stv-texte);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-position: from-font;
}

/* --- Carte article : l'état de survol (tâche 195) ------------------- */
/*
   Dessiné le 26/10 (331:12485, recette d'Estevan R16), comparé à la
   carte au repos (331:19667) : trois changements, rien ne bouge.
     - le fond passe du gris clair au BLEU CLAIR ;
     - la photo est AGRANDIE dans son cadre : 129,1 % × 141,2 % au survol
       contre le simple `cover` au repos, soit un facteur 1,29 sur les
       deux axes — un zoom, pas un recadrage. RÉDUIT le 28/10 (recette
       d'Estevan R27, tâche 204 : « diminuer le zoom de l'image et
       accélérer l'anim ») : × 1,08 en 0,3 s au lieu de × 1,29 en 0,5 s,
       les jetons `--stv-survol-*` (jetons.css), que les photos du
       méga-menu reprennent (R29) ;
     - « LIRE L'ARTICLE » perd son soulignement et gagne une flèche
       (331:12496), 6 après le libellé.

   La flèche est dans le balisage au repos, invisible et déjà à sa place :
   l'afficher ne change aucune largeur.

   `hover: hover` : sur un écran tactile, le premier toucher ouvrirait
   l'article ET laisserait la carte figée dans son état de survol au
   retour. `:focus-within` donne le même état au clavier, quand le lien
   du titre a le focus. 0,3,0 : devant `.elementor .stv-lien-maj-souligne`
   (0,2,0), qui soulignerait encore le libellé sur l'accueil.
*/
.stv-carte-article {
  transition: background-color 0.3s ease;
}

.stv-carte-article .stv-carte-article__image {
  transition: transform var(--stv-survol-duree) var(--stv-survol-courbe);
}

.stv-carte-article .stv-carte-article__fleche {
  flex: none;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

@media (hover: hover) {
  .stv-carte-article.stv-carte-article:hover {
    background: var(--stv-bleu-clair);
  }

  .stv-carte-article.stv-carte-article:hover .stv-carte-article__image {
    transform: scale(var(--stv-survol-zoom));
  }

  .stv-carte-article.stv-carte-article:hover .stv-carte-article__action {
    text-decoration: none;
  }

  .stv-carte-article.stv-carte-article:hover .stv-carte-article__fleche {
    opacity: 1;
    transform: none;
  }
}

.stv-carte-article.stv-carte-article:focus-within {
  background: var(--stv-bleu-clair);
}

.stv-carte-article.stv-carte-article:focus-within .stv-carte-article__image {
  transform: scale(var(--stv-survol-zoom));
}

.stv-carte-article.stv-carte-article:focus-within .stv-carte-article__action {
  text-decoration: none;
}

.stv-carte-article.stv-carte-article:focus-within .stv-carte-article__fleche {
  opacity: 1;
  transform: none;
}

/* Mouvement réduit : l'état change d'un coup, sans zoom animé. */
@media (prefers-reduced-motion: reduce) {
  .stv-carte-article,
  .stv-carte-article .stv-carte-article__image,
  .stv-carte-article .stv-carte-article__fleche {
    transition: none;
  }
}

/* --- Carte article : les trois modes (tâche 116, lot Blog du 28/09) --- */
/*
   Tout ce qui précède est le mode GRILLE — la carte de l'accueil (55),
   INCHANGÉE : la fiche 116 dit que l'accueil fait foi, et la grille du
   blog (156:9431) la reprend telle quelle. Écart assumé (tranché avec
   Logan le 28/09) : la maquette du blog espace image → méta → titre →
   lien de 24 / 12 / 16 et dessine la pastille rognée aux capitales (26)
   là où l'accueil rend 12 / 12 / 12 et une pastille de 40 ; à 384 de
   large la carte fait 448 au lieu de 450.

   GRANDE — « Dernier article » (156:9364, mobile 156:8061). Dans une
   colonne de 528 : image 496 × 420, 24 jusqu'à la ligne méta (le gap de
   12 + 12 ici), 12 jusqu'au titre, titre Outfit Medium 32 / 1,5, 16
   jusqu'à l'EXTRAIT (Inter 16 / 1,4 anthracite, trois lignes), 16
   jusqu'au lien. Mobile : image 321 × 290, titre 24, extrait sur quatre
   lignes. Même pastille de 40 que la grille : 698 de haut au lieu de 684.

   HORIZONTALE — « Articles populaires » (156:9379, mobile 156:8076).
   960 × 228 : image 368 × 196 à gauche, à droite la ligne méta en haut,
   le titre (Outfit Medium 20 / 1,5) et le lien calés en bas, 16 entre
   eux. Une GRILLE plutôt qu'un flex en ligne : le balisage n'a pas
   d'enveloppe autour du texte (et n'en aura pas — celui de l'accueil ne
   bouge pas), l'image occupe donc la colonne 1 sur toutes les rangées et
   chaque texte prend sa rangée en colonne 2, la deuxième rangée (1fr)
   poussant titre et lien vers le bas. En mobile la carte redevient une
   colonne : image 321 × 180, 12 jusqu'à la méta, 16 jusqu'au titre, 16
   jusqu'au lien.

   Chaque règle bat le mode grille AU COMPTE (0,2,0 contre 0,1,0), jamais
   par l'ordre — et les règles mobiles ci-dessous aussi.
*/
.stv-carte-article--grande .stv-carte-article__media {
  aspect-ratio: 496 / 420;
}

.stv-carte-article--grande .stv-carte-article__meta {
  margin-top: var(--stv-espace-12);
}

.stv-carte-article--grande .stv-carte-article__titre {
  font-size: var(--stv-taille-h3);
  line-height: var(--stv-interligne-texte);
}

.stv-carte-article .stv-carte-article__extrait {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: var(--stv-espace-4) 0 0;
  color: var(--stv-anthracite);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: 1.4;
}

.stv-carte-article--grande .stv-carte-article__action {
  margin-top: var(--stv-espace-4);
}

.stv-carte-article--horizontale {
  display: grid;
  grid-template-columns: 368px minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  column-gap: var(--stv-espace-12);
  row-gap: 0;
}

.stv-carte-article--horizontale .stv-carte-article__media {
  grid-column: 1;
  grid-row: 1 / -1;
  aspect-ratio: 368 / 196;
}

.stv-carte-article--horizontale .stv-carte-article__meta {
  grid-column: 2;
  grid-row: 1;
}

.stv-carte-article--horizontale .stv-carte-article__titre {
  grid-column: 2;
  grid-row: 3;
}

.stv-carte-article--horizontale .stv-carte-article__action {
  grid-column: 2;
  grid-row: 4;
  margin-top: var(--stv-espace-16);
}

/* Sans image à la une : la boîte reste, sur le gris de la pastille (fiche 118). */
.stv-carte-article .stv-carte-article__media--vide {
  background: var(--stv-pastille);
}

@media (max-width: 1024px) {
  .stv-carte-article--grande .stv-carte-article__media {
    aspect-ratio: 321 / 290;
  }

  /* Le titre passe seul de 32 à 24 : `--stv-taille-h3` vaut 24 sous 768 (jetons.css). */

  .stv-carte-article--grande .stv-carte-article__extrait {
    -webkit-line-clamp: 4;
  }

  /* Retour à la colonne du mode grille : le `row-gap: 0` de la grille
     ci-dessus vaut encore, il faut le remettre à 12 — mesuré à 0 le 28/09. */
  .stv-carte-article--horizontale {
    display: flex;
    row-gap: var(--stv-espace-12);
  }

  .stv-carte-article--horizontale .stv-carte-article__media {
    aspect-ratio: 321 / 180;
  }

  .stv-carte-article--horizontale .stv-carte-article__titre,
  .stv-carte-article--horizontale .stv-carte-article__action {
    margin-top: var(--stv-espace-4);
  }
}

/* --- Carte collection (tâche 27) ------------------------------------- */
/*
   Une sous-catégorie : sa vignette en fond, son nom dans un pavé
   anthracite, la carte entière cliquable. Rendue par le shortcode
   [stelvoren_collections], Elementor ne sachant pas boucler sur des
   termes de taxonomie.

   La carte EST le lien : un seul <a>, dont le texte est le nom de la
   collection. Pas de pseudo-élément d'extension à prévoir, et un seul
   lien annoncé par les lecteurs d'écran.
*/
/*
   Piste défilante À TOUTES LES LARGEURS — arbitrage du 02/09/2026
   (tâche 33) : le bloc affiche tout le niveau 3 de l'univers, 15 à 18
   cartes. La grille de quatre colonnes qui était ici n'a donc plus de
   sens en desktop. Même mécanique que `.stv-defile-mobile` plus bas —
   défilement natif, `scroll-snap`, rien à initialiser — avec 4 par vue à
   partir de 1440 et 3 entre 1025 et 1439 : la règle 4 / 3 / 2 / 1 du
   plan (§2-6). Sous 1024, les règles `.stv-defile-mobile` gardent la main
   (1 par vue, gouttière 16) : celles-ci sont bornées à 1025 px et plus.
*/
@media (min-width: 1025px) {
  .stv-collections {
    --stv-defile-vue: 4;
    --stv-defile-gouttiere: var(--stv-gouttiere);
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    gap: var(--stv-defile-gouttiere);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
  }

  .stv-collections::-webkit-scrollbar {
    display: none;
  }

  .stv-collections > * {
    flex: 0 0 calc(
      (100% - (var(--stv-defile-vue) - 1) * var(--stv-defile-gouttiere))
      / var(--stv-defile-vue)
    );
    min-width: 0;
    scroll-snap-align: start;
  }
}

/* Portable, de 1025 à 1439 : trois par vue. */
@media (min-width: 1025px) and (max-width: 1439px) {
  .stv-collections {
    --stv-defile-vue: 3;
  }
}

.stv-carte-collection {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* 384 x 472 dans la maquette : un rapport, pas des pixels, pour que
     la carte suive la largeur de sa colonne. */
  aspect-ratio: 384 / 472;
  /* 32 relevés sur la frame 11:9823 le 02/09 (le pavé du nom à 32 des
     bords), et non les 16 des autres cartes. */
  padding: var(--stv-espace-32);
  overflow: hidden;
  background: var(--stv-gris-clair);
  border-radius: var(--stv-rayon);
  text-decoration: none;
}

/*
   L'image est posée en fond mais reste un <img> : elle profite ainsi du
   chargement différé, du srcset et du texte alternatif, ce qu'une image
   de fond CSS ne permet pas.
*/
.stv-carte-collection .stv-carte-collection__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.stv-carte-collection .stv-carte-collection__libelle {
  position: relative;
  padding: var(--stv-espace-12) var(--stv-espace-32);
  background: var(--stv-anthracite);
  color: var(--stv-blanc);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-align: center;
}

.stv-carte-collection:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/*
   Tablette : plafond de hauteur sur la carte collection.

   Le rapport 384/472 de la maquette est juste tant que la carte fait la
   largeur d'une colonne. En tablette, un élément par vue lui donne près
   de 900 px de large — donc plus de 1 100 px de haut, une carte qui
   remplit l'écran à elle seule. Le plafond casse le rapport et laisse
   l'image se recadrer, ce qu'elle sait faire puisqu'elle est en `cover`.

   Bornée à la tablette seule : en mobile, la carte fait déjà moins de
   500 px de haut et un plafond en vh la rognerait sans raison sur les
   petits écrans.
*/
@media (min-width: 768px) and (max-width: 1024px) {
  .stv-carte-collection {
    max-height: 60vh;
  }
}

/* --- Carte collection : les deux modes du catalogue (lot 3, 25/09) ---- */
/*
   Tout ce qui précède est le mode ACCUEIL. Le catalogue en ajoute deux
   (parties/carte-collection.php, inc/tuiles.php) — le même composant, pas
   un second :

   TUILE (156:6676, mobile 156:7198) — paysage, le nom SOUS l'image, pas
   de pavé. Image 240 × 180 (120 × 90 en mobile, même 4:3) en `contain`
   sur blanc : un packshot, jamais recadré. 16 entre l'image et le nom
   (8 en mobile) ; nom Outfit Regular 16 à 1,5, noir, centré (14 en
   mobile). La largeur vient de la rangée (`.stv-tuiles`, plus bas).

   SUGGESTION (156:10241, mobile 156:7581) — portrait 544 × 804, paysage
   353 × 252 en mobile, la MÊME photo en `cover` sous un voile NOIR : .05
   en haut, .5 à 90 %, .85 en bas. Nom Outfit Medium 32 à 1,5 (24 en
   mobile — les deux valeurs du jeton `--stv-taille-h3`), « Découvrir »
   Outfit Regular 16 en capitales, blancs, centrés, calés en bas à 24 ;
   16 entre eux, 8 en mobile.

   LE VOILE N'EST PAS CELUI DE LA CARTE ÉDITORIALE (.5 à 70 %, .8 en bas,
   catalogue.css § 6.1) : deux voiles noirs voisins, dessinés
   différemment, relevés tels quels — question au designer (88). Pas de
   jeton tant qu'aucun des deux n'est vu deux fois.

   Chaque règle bat le mode accueil AU COMPTE : ses sélecteurs pèsent
   0,2,0 (`.stv-carte-collection .stv-carte-collection__libelle`), ceux des
   modes 0,3,0 ; la carte elle-même 0,1,0 contre 0,2,0, plafond de tablette
   compris.
*/
.stv-carte-collection.stv-carte-collection--tuile {
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: var(--stv-espace-16);
  aspect-ratio: auto;
  max-height: none;
  padding: 0;
  overflow: visible;
  background: none;
  color: var(--stv-noir);
}

.stv-carte-collection.stv-carte-collection--tuile .stv-carte-collection__media {
  position: relative;
  display: block;
  aspect-ratio: 240 / 180;
  overflow: hidden;
  background: var(--stv-blanc);
}

/* La position et la taille viennent du mode accueil (absolue, 100 % × 100 %) ; seul le cadrage change. */
.stv-carte-collection.stv-carte-collection--tuile .stv-carte-collection__image {
  object-fit: contain;
}

/*
   La PHOTO CHOISIE d'une tuile de la racine (03/11, tâche 218 — J3, PDF de
   Jonathan du 29/10) : un fichier du thème (`assets/images/tuile-<clé>.jpg`,
   inc/tuiles.php), pas un packshot détouré. Elle remplit la tuile et se
   recadre (`cover`), centrée. 0,4,0 contre le `contain` ci-dessus (0,3,0).
*/
.stv-carte-collection.stv-carte-collection--tuile .stv-carte-collection__image.stv-carte-collection__image--photo {
  object-fit: cover;
  object-position: center;
}

.stv-carte-collection.stv-carte-collection--tuile .stv-carte-collection__libelle {
  position: static;
  padding: 0;
  background: none;
  color: var(--stv-noir);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-align: center;
  text-wrap: balance;
}

/* Survol : NON DESSINÉ (88) — le nom se souligne, provisoire. */
.stv-carte-collection.stv-carte-collection--tuile:hover .stv-carte-collection__libelle,
.stv-carte-collection.stv-carte-collection--tuile[aria-current="page"] .stv-carte-collection__libelle {
  text-decoration: underline;
  text-underline-position: from-font;
}

/* La piste coupe ce qui dépasse d'elle : le contour du focus passe à l'intérieur. */
.stv-carte-collection.stv-carte-collection--tuile:focus-visible {
  outline-offset: -2px;
}

.stv-carte-collection.stv-carte-collection--suggestion {
  --stv-carte-collection-voile: linear-gradient(
    180deg,
    rgba(2, 10, 18, 0.05) 0%,
    rgba(2, 10, 18, 0.5) 90%,
    rgba(2, 10, 18, 0.85) 100%
  );

  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: var(--stv-espace-16);
  aspect-ratio: 544 / 804;
  max-height: none;
  padding: var(--stv-espace-24);
  background: var(--stv-noir);
  color: var(--stv-blanc);
  text-align: center;
}

.stv-carte-collection.stv-carte-collection--suggestion::before {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 0;
  background: var(--stv-carte-collection-voile);
  pointer-events: none;
}

.stv-carte-collection.stv-carte-collection--suggestion .stv-carte-collection__image {
  z-index: 0;
}

.stv-carte-collection.stv-carte-collection--suggestion .stv-carte-collection__libelle {
  z-index: 2;
  width: 100%;
  padding: 0;
  background: none;
  color: var(--stv-blanc);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-h3);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-wrap: balance;
}

.stv-carte-collection.stv-carte-collection--suggestion .stv-carte-collection__action {
  position: relative;
  z-index: 2;
  color: var(--stv-blanc);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-transform: uppercase;
}

/*
   LE SURVOL (recette d'Estevan R37, 29/10, tâche 215 — non dessiné ; Logan :
   « celui des cartes article »). La photo s'agrandit dans son cadre — mêmes
   jetons que la carte article et les photos du méga-menu (R27 / R29), × 1,08
   en 0,3 s — et s'assombrit un peu, comme au méga-menu : le libellé blanc
   garde son contraste ; « Découvrir » se souligne (le provisoire du lot 3,
   gardé). Souris seulement ; au clavier, le même état au focus visible ;
   rien sous « mouvement réduit ». Le cadre (`overflow: hidden`, mode
   accueil) ne bouge pas.
*/
.stv-carte-collection.stv-carte-collection--suggestion .stv-carte-collection__image {
  transition: transform var(--stv-survol-duree) var(--stv-survol-courbe), filter var(--stv-survol-duree) var(--stv-survol-courbe);
}

@media (hover: hover) {
  .stv-carte-collection.stv-carte-collection--suggestion:hover .stv-carte-collection__image {
    transform: scale(var(--stv-survol-zoom));
    filter: brightness(0.85);
  }

  .stv-carte-collection.stv-carte-collection--suggestion:hover .stv-carte-collection__action {
    text-decoration: underline;
    text-underline-position: from-font;
  }
}

.stv-carte-collection.stv-carte-collection--suggestion:focus-visible .stv-carte-collection__image {
  transform: scale(var(--stv-survol-zoom));
  filter: brightness(0.85);
}

.stv-carte-collection.stv-carte-collection--suggestion:focus-visible .stv-carte-collection__action {
  text-decoration: underline;
  text-underline-position: from-font;
}

@media (prefers-reduced-motion: reduce) {
  .stv-carte-collection.stv-carte-collection--suggestion .stv-carte-collection__image {
    transition: none;
  }
}

/*
   Tablette, 768 à 1 024 — PROVISOIRE (96, lot 5) : trois cartes de 219 à
   304 de large ; un nom en 32 y tiendrait sur trois lignes. Le 24 du
   mobile, en attendant l'arbitrage des largeurs intermédiaires.
*/
@media (min-width: 768px) and (max-width: 1024px) {
  .stv-carte-collection.stv-carte-collection--suggestion .stv-carte-collection__libelle {
    font-size: var(--stv-taille-intertitre);
  }
}

@media (max-width: 767px) {
  .stv-carte-collection.stv-carte-collection--tuile {
    gap: var(--stv-espace-8);
  }

  .stv-carte-collection.stv-carte-collection--tuile .stv-carte-collection__libelle {
    font-size: var(--stv-taille-petit);
  }

  .stv-carte-collection.stv-carte-collection--suggestion {
    gap: var(--stv-espace-8);
    aspect-ratio: 353 / 252;
  }
}

/* --- Tuiles : la rangée défilante des catégories (lot 3, 25/09) ------- */
/*
   Rendue par `stelvoren_tuiles_html()` (inc/tuiles.php) : une liste de
   tuiles dans une piste, deux flèches, une jauge. MÊME MÉCANIQUE QUE LES
   PISTES DE L'ACCUEIL — défilement natif, `scroll-snap`, rien à
   initialiser —, mais ses commandes sont écrites par le thème et câblées
   par `carrousels.js` (bloc « pistes à commandes »), pas construites par
   lui.

   DESKTOP (156:6675, 156:9038) — un cadre de 1 104 centré : 48 de chaque
   côté pour les flèches, puis la piste, 4 × 240 + 3 × 16 = 1 008. Quand
   tout tient, la rangée se centre ; quand elle déborde — plus de quatre
   tuiles à 1 840, moins sous 1 200 —, elle défile et deux flèches de
   40 × 40 se posent à cheval sur le bord du cadre (x = −20 et 1 124,
   `156:9055`), centrées sur la hauteur des tuiles. Fond gris clair,
   flèche noire, la précédente à 50 % en début de course — l'opacité est
   dans le tracé exporté de la maquette : elle appartient ici à l'état.

   MOBILE (156:7196) — tuiles de 120, la piste DÉBORDE jusqu'aux bords de
   l'écran (la quatrième tuile de la maquette part à x = 408, hors écran),
   une seule flèche de 32 à 8 du bord droit du contenu, et une jauge de
   2 px, 24 sous les tuiles : bleu clair sur toute la largeur, bleu
   pétrole sur la part déjà parcourue (156:7214, 272 sur 353).

   LA PRÉSENCE DES FLÈCHES ET DE LA JAUGE SUIT LE DÉBORDEMENT RÉEL
   (`data-stv-piste-deborde`, posé par le script) : il dépend du nombre de
   tuiles ET de la largeur. Les flèches sont en position absolue — les
   montrer ne bouge rien ; la jauge, elle, est dans le flux : sa place est
   réservée par le serveur dès trois tuiles, et seule sa visibilité change.

   Compte : `.stv-tuiles .stv-tuiles__x`, 0,2,0 ; les flèches à 0,3,0 contre
   le `reset.css` de Hello (`[type=button]` 0,1,0, ses survol et focus
   roses à 0,2,0) et le kit Elementor (`button` 0,1,1) quand une section
   Elementor est sur la page.
*/
.stv-tuiles {
  --stv-tuiles-largeur: 240px;
  --stv-tuiles-ecart: var(--stv-espace-16);
  --stv-tuiles-marge: var(--stv-espace-48);
  --stv-tuiles-fleche: 40px;
  /* La piste mobile déborde de cette valeur de chaque côté : la gouttière
     de la page qui l'accueille (catalogue.css). */
  --stv-tuiles-debord: 0px;
}

.stv-tuiles .stv-tuiles__cadre {
  position: relative;
  max-width: calc(4 * var(--stv-tuiles-largeur) + 3 * var(--stv-tuiles-ecart) + 2 * var(--stv-tuiles-marge));
  margin-inline: auto;
  padding-inline: var(--stv-tuiles-marge);
}

.stv-tuiles .stv-tuiles__piste {
  display: flex;
  gap: var(--stv-tuiles-ecart);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}

.stv-tuiles .stv-tuiles__piste::-webkit-scrollbar {
  display: none;
}

.stv-tuiles .stv-tuiles__element {
  flex: 0 0 var(--stv-tuiles-largeur);
  min-width: 0;
  margin: 0;
  padding: 0;
  scroll-snap-align: start;
}

/*
   CENTRAGE « SÛR » : les marges automatiques centrent la rangée quand
   elle tient, et valent zéro dès qu'elle déborde. `justify-content:
   center` ferait déborder la rangée À GAUCHE aussi — le début de la piste
   deviendrait inatteignable.
*/
.stv-tuiles .stv-tuiles__element:first-child {
  margin-inline-start: auto;
}

.stv-tuiles .stv-tuiles__element:last-child {
  margin-inline-end: auto;
}

.stv-tuiles .stv-tuiles__fleche.stv-tuiles__fleche {
  position: absolute;
  z-index: 1;
  top: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--stv-tuiles-fleche);
  height: var(--stv-tuiles-fleche);
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--stv-gris-clair);
  color: var(--stv-noir);
  cursor: pointer;
  transform: translateY(-50%);
  transition: opacity 0.2s, background-color 0.2s;
}

/* Écrit AU-DESSUS du `display` ci-dessus : l'attribut `hidden` du navigateur pèse moins que n'importe quelle règle d'auteur. */
.stv-tuiles .stv-tuiles__fleche.stv-tuiles__fleche[hidden] {
  display: none;
}

.stv-tuiles .stv-tuiles__fleche--precedent {
  left: calc(var(--stv-tuiles-fleche) / -2);
}

.stv-tuiles .stv-tuiles__fleche--suivant {
  right: calc(var(--stv-tuiles-fleche) / -2);
}

/*
   Bout de course : la flèche reste VISIBLE, à 50 % (156:9056). `aria-disabled`
   et non `disabled` : un bouton désactivé perd le focus, et le visiteur
   qui avançait au clavier se retrouverait en haut de la page.
*/
.stv-tuiles .stv-tuiles__fleche.stv-tuiles__fleche[aria-disabled="true"] {
  opacity: 0.5;
  cursor: default;
}

/* Survol : NON DESSINÉ (88) — le bleu clair du bouton secondaire, provisoire. */
.stv-tuiles .stv-tuiles__fleche.stv-tuiles__fleche:not([aria-disabled="true"]):hover {
  background: var(--stv-bleu-clair);
  color: var(--stv-noir);
}

.stv-tuiles .stv-tuiles__fleche.stv-tuiles__fleche:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* La flèche de 20 × 8, 21,5 × 9,5 avec le trait (156:9057). */
.stv-tuiles .stv-tuiles__glyphe {
  display: block;
  flex-shrink: 0;
  width: 21.5px;
  height: 9.5px;
}

.stv-tuiles .stv-tuiles__progression {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .stv-tuiles .stv-tuiles__piste {
    scroll-behavior: auto;
  }
}

@media (max-width: 767px) {
  .stv-tuiles {
    --stv-tuiles-largeur: 120px;
    --stv-tuiles-marge: 0px;
    --stv-tuiles-fleche: 32px;
  }

  .stv-tuiles .stv-tuiles__cadre {
    max-width: none;
  }

  /*
     La piste sort de la colonne de contenu jusqu'aux bords de l'écran ;
     la marge intérieure la ramène au départ, et `scroll-padding` cale les
     tuiles sur ce départ, pas sur le bord de l'écran.
  */
  .stv-tuiles .stv-tuiles__piste {
    margin-inline: calc(-1 * var(--stv-tuiles-debord));
    padding-inline: var(--stv-tuiles-debord);
    scroll-padding-inline: var(--stv-tuiles-debord);
  }

  /* Une seule flèche en mobile (156:7217) : la suivante, à 8 du bord droit du contenu. */
  .stv-tuiles .stv-tuiles__fleche.stv-tuiles__fleche.stv-tuiles__fleche--precedent {
    display: none;
  }

  .stv-tuiles .stv-tuiles__fleche--suivant {
    right: calc(-1 * var(--stv-espace-8));
  }

  /* La même flèche au facteur 0,8 : 16 × 6,4, trait de 1,2 (156:7219). */
  .stv-tuiles .stv-tuiles__glyphe {
    width: 17.2px;
    height: 7.6px;
  }

  .stv-tuiles .stv-tuiles__progression {
    position: relative;
    display: block;
    height: 2px;
    margin-top: var(--stv-espace-24);
    overflow: hidden;
    background: var(--stv-bleu-clair);
  }

  /* Tout tient : la jauge ne dit rien, elle s'efface — sa place reste, rien ne saute. */
  .stv-tuiles:not([data-stv-piste-deborde]) .stv-tuiles__progression {
    visibility: hidden;
  }

  .stv-tuiles .stv-tuiles__parcouru {
    position: absolute;
    inset: 0 auto 0 0;
    width: calc(var(--stv-piste-parcouru, 0) * 100%);
    background: var(--stv-bleu-petrole);
    transition: width 0.15s linear;
  }
}

/* --- Sur-titre : la flèche suit la couleur du texte ------------------- */
/*
   Elementor incorpore le SVG dans la page (élément atomique `e-svg-base`)
   au lieu de le servir en <img> : la forme est donc dans le DOM, et le
   CSS peut la peindre. Le `fill="#001D3D"` du fichier est un ATTRIBUT de
   présentation — la priorité la plus faible du modèle en cascade, sous
   n'importe quelle règle CSS. Une seule classe suffit donc à le battre,
   sans `!important`.

   `currentColor` renvoie la couleur de texte héritée : la flèche prend
   celle du sur-titre, quelle qu'elle soit, y compris sur une section
   sombre où le texte passe en blanc.

   Une condition, une seule : **la couleur doit être posée sur le
   conteneur** du sur-titre (celui qui porte `stv-surtitre`), pas sur le
   paragraphe. Le CSS ne sait pas lire la couleur d'un frère ; si le
   paragraphe se peint tout seul, la flèche ne le suivra pas.

   Pas de `stroke` ici : le tracé n'en a pas, et lui en donner un
   dessinerait un contour autour de la flèche.
*/
.stv-icone-surtitre svg,
.stv-icone-surtitre svg * {
  fill: currentColor;
}

/* --- Références studios (tâche 28) ----------------------------------- */
/*
   La grille des studios, rendue par [stelvoren_references]. Même
   gabarit que les collections : quatre colonnes au-dessus de 1024 px,
   piste défilante en dessous grâce à `stv-defile-mobile`.
*/
.stv-references {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--stv-gouttiere);
}

/* --- Carte référence studio (tâche 28) ------------------------------- */
/*
   Photo en fond, encart blanc en bas : nom, adresse du site, puis une
   pastille grise avec le drapeau et la ville.

   Contrairement aux autres cartes, celle-ci porte DEUX liens possibles
   — l'adresse du studio — et rien d'autre de cliquable. Pas d'extension
   du lien à toute la carte, donc : la carte n'est pas une destination,
   c'est une référence, et son seul lien sort du site.
*/
.stv-carte-reference {
  position: relative;
  display: flex;
  align-items: flex-end;
  aspect-ratio: 384 / 472;
  padding: var(--stv-espace-16);
  overflow: hidden;
  background: var(--stv-gris-clair);
  border-radius: var(--stv-rayon);
}

.stv-carte-reference .stv-carte-reference__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.stv-carte-reference__encart {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stv-espace-6);
  width: 100%;
  padding: var(--stv-espace-16);
  background: var(--stv-blanc);
}

.stv-carte-reference .stv-carte-reference__nom {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-carte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
}

.stv-carte-reference .stv-carte-reference__url {
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 300;
  color: var(--stv-texte-secondaire);
  text-decoration: underline;
}

/* Pastille grise : drapeau et ville, alignés sur la ligne de base. */
.stv-carte-reference .stv-carte-reference__lieu {
  display: inline-flex;
  align-items: center;
  gap: var(--stv-espace-6);
  margin: 0;
  padding: var(--stv-espace-6) var(--stv-espace-12);
  background: var(--stv-gris-clair);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  color: var(--stv-texte);
}

/*
   Le drapeau est un SVG interne, pas une image : il ne peut donc pas
   manquer, ni être mis à jour de travers. Le filet gris lui donne un
   bord sur les drapeaux à bandes blanches — sans lui, le blanc du
   drapeau français se confond avec la pastille.
*/
.stv-drapeau {
  flex: 0 0 auto;
  box-shadow: 0 0 0 1px var(--stv-pastille);
}

/* --- Marques (tâche 54) ---------------------------------------------- */
/*
   Mode « tuiles » de [stelvoren_marques] (le mode « cartes » de la page
   Nos marques suit ce bloc).
   Six logos sur tuiles blanches de 88 px de haut, rendus par
   [stelvoren_marques] depuis assets/images/marques/ (SVG versionnés dans
   le thème, nettoyés le 02/09). Trois colonnes sur deux rangées en
   desktop, deux colonnes sous 1024.

   Les logos vont d'un carré (Mad, NOHRD) à un bandeau de 7 pour 1
   (STIL-FIT) : sans plafond commun, les larges écrasent les compacts.
   D'où la boîte 40 px de haut, 100 % de large au plus, et `width` /
   `height` en `auto` pour que le rapport du fichier fasse foi.
*/
.stv-marques {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--stv-espace-16);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-marque {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 88px;
  padding: 0 var(--stv-espace-24);
  background: var(--stv-blanc);
  border-radius: var(--stv-rayon);
}

.stv-marque .stv-marque__logo {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 40px;
}

/*
   TUILE CLIQUABLE (06/10 — `liens` de stelvoren_marques(), demandé par le
   méga-menu ; l'accueil reste sans lien). Le lien enveloppe le logo et
   remplit la boîte de la tuile — `width` / `height` à 100 % : le
   `max-width` du logo se résout contre lui, STIL-FIT rétrécit comme avant.
   Toute la tuile, marge comprise, est cliquable par le pseudo-élément du
   lien, comme les cartes de Nos marques : un seul lien, nommé par l'alt.

   SURVOL ET FOCUS NON DESSINÉS — provisoire : la tuile fonce d'un ton
   (`--stv-pastille` en ombre intérieure : le fond de la tuile est posé par
   un raccourci `background` à 0,3,0 dans le méga-menu, une ombre ne s'y
   heurte pas, et le ton vaut sur fond gris comme sur fond blanc) ;
   contour 2 px noir sur la tuile entière au focus du clavier.
*/
.stv-marque.stv-marque--lien {
  position: relative;
}

.stv-marque--lien .stv-marque__lien {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: inherit;
}

.stv-marque--lien .stv-marque__lien::after {
  content: "";
  position: absolute;
  inset: 0;
}

.stv-marque.stv-marque--lien:hover {
  box-shadow: inset 0 0 0 100vmax var(--stv-pastille);
}

.stv-marque--lien .stv-marque__lien:focus-visible {
  outline: none;
}

.stv-marque--lien .stv-marque__lien:focus-visible::after {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .stv-marque.stv-marque--lien {
    transition: box-shadow 0.2s ease;
  }
}

@media (max-width: 1024px) {
  .stv-marques {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* --- Marques, mode « cartes » (tâche 110, page Nos marques) ---------- */
/*
   Relevé Dev Mode du 05/10 : grille 156:10327, cartes 156:10328 → 156:10418
   (desktop), 156:7842 → (mobile). Même fonction, même source que les tuiles
   (`stelvoren_marques()`, mode « cartes ») : logo, nom, lien vers l'archive
   de la catégorie de la marque.

   LA GRILLE : 4 × 384 à 48 dans les 1 680 de la maquette, la dernière
   rangée calée à GAUCHE (trois cartes et une case vide, 156:10418).
   Largeurs intermédiaires non dessinées (fiche 109, « à obtenir du
   designer ») : provisoires, réglées par UNE règle sans requête de média.
   `auto-fill` sur une largeur minimale qui est la PLUS GRANDE de deux :
     - le quart de la grille (moins les trois écarts) — jamais plus de
       quatre colonnes : 384 à 1 840, 284 à 1 440 (comme les cartes produit
       de La marque à cette largeur) ;
     - 276, la carte la plus étroite où « DÉCOUVRIR LES PRODUITS » (212,4
       mesuré) tient sur une ligne entre ses deux marges de 32 — d'où trois
       colonnes de 1 366 à 1 085 environ, deux en dessous et en tablette
       étroite, une en mobile (244 : marges de 16).
   Le pixel retiré au quart évite qu'un arrondi à 1 680 pile ne fasse
   tomber la quatrième colonne ; `1fr` rend ce pixel aux cartes (384 tout
   rond, mesuré). `min(100%, …)` : sous la largeur minimale (téléphone de
   320), la colonne prend la place qu'il y a au lieu de déborder.

   Deux classes (0,2,0) : la grille des tuiles (0,1,0, et sa requête de
   1 024) ne doit rien laisser passer.
*/
.stv-marques.stv-marques--cartes {
  --stv-marques-cartes-min: 276px;
  --stv-marques-cartes-ecart: var(--stv-gouttiere);

  grid-template-columns: repeat(
    auto-fill,
    minmax(
      min(100%, max(var(--stv-marques-cartes-min), (100% - 3 * var(--stv-marques-cartes-ecart)) / 4 - 1px)),
      1fr
    )
  );
  gap: var(--stv-marques-cartes-ecart);
}

/*
   LA CARTE (156:10328) : fond blanc, marge 32, colonne centrée à écart 48
   entre la tête (logo + nom) et le lien — 32 + 118 + 48 + 24 + 32 = 254.
   Mobile (156:7842) : marge 16, écart 24 — 198.
   Toute la carte est cliquable par le pseudo-élément du lien, comme la
   carte produit : un seul lien annoncé, le texte reste sélectionnable.
*/
.stv-marques--cartes .stv-marque-carte {
  --stv-marque-carte-marge: var(--stv-espace-32);
  --stv-marque-carte-ecart: var(--stv-espace-48);

  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--stv-marque-carte-ecart);
  margin: 0;
  padding: var(--stv-marque-carte-marge);
  background: var(--stv-blanc);
  border-radius: var(--stv-rayon);
  text-align: center;
}

.stv-marques--cartes .stv-marque-carte__tete {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--stv-espace-8);
  width: 100%;
}

/*
   LE LOGO : une boîte de 80 de haut, logo centré à SA hauteur de maquette
   (`--stv-marque-hauteur`, posée par le PHP : 40 pour Align-Pilates et
   Stil-Fit, 64 pour JK Fitness et Fitness Mad, 80 pour Yoga Mad, Nohrd et
   Water Rower), à 50 % d'opacité — c'est ce qui grise les logos noirs du
   thème (156:10330, `opacity-50`). `object-fit: contain` : si la carte est
   plus étroite que le logo (Stil-Fit, 286 de large), il rétrécit sans se
   déformer.
*/
.stv-marques--cartes .stv-marque-carte__cadre {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 80px;
  opacity: 0.5;
}

.stv-marques--cartes .stv-marque-carte__logo {
  display: block;
  width: auto;
  height: var(--stv-marque-hauteur, 64px);
  max-width: 100%;
  object-fit: contain;
}

/*
   LE NOM (156:10348) : Inter Medium 20 / 1,5, +2 % (0,4 px). Un H2 : la page
   a son H1 « Nos marques », chaque carte est une entrée. Deux classes
   (0,2,0) devant `.elementor-kit-44301 h2` (0,1,1) et la marge de Hello.
*/
.stv-marques--cartes .stv-marque-carte__nom {
  margin: 0;
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-carte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--stv-noir);
}

/*
   LE LIEN (156:10349) : Inter Medium 16 / 1,5, souligné, en capitales par
   `text-transform` — le calque est écrit en minuscules. Deux classes
   (0,2,0) devant le lien du kit (`.elementor-kit-44301 a`, 0,1,1) et le
   § 0 du socle ; le survol à 0,3,0 devant `.elementor-kit-44301 a:hover`.
*/
.stv-marques--cartes .stv-marque-carte__lien {
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  letter-spacing: normal;
  text-transform: uppercase;
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-decoration-skip-ink: none;
  text-underline-position: from-font;
  color: var(--stv-noir);
}

.stv-marques--cartes .stv-marque-carte__lien::after {
  content: "";
  position: absolute;
  inset: 0;
}

.stv-marques--cartes .stv-marque-carte__lien:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* Le nom de la marque, pour les lecteurs d'écran seulement. */
.stv-marques--cartes .stv-marque-carte__cache {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/*
   SURVOL ET FOCUS — NON DESSINÉS (fiche 109, au designer). Provisoire : le
   logo reprend sa pleine couleur, le lien garde son dessin. Rien ne bouge,
   rien ne change de taille : un état qui se remplace sans reprendre la
   mise en page.
*/
.stv-marques--cartes .stv-marque-carte:hover .stv-marque-carte__cadre,
.stv-marques--cartes .stv-marque-carte:focus-within .stv-marque-carte__cadre {
  opacity: 1;
}

.stv-marques--cartes .stv-marque-carte .stv-marque-carte__lien:hover {
  color: var(--stv-noir);
  text-decoration: underline;
}

@media (prefers-reduced-motion: no-preference) {
  .stv-marques--cartes .stv-marque-carte__cadre {
    transition: opacity 0.2s ease;
  }
}

/* Mobile (156:7841) : cartes 353 de large à 16 l'une de l'autre. */
@media (max-width: 767px) {
  .stv-marques.stv-marques--cartes {
    --stv-marques-cartes-min: 244px;
    --stv-marques-cartes-ecart: var(--stv-espace-16);
  }

  .stv-marques--cartes .stv-marque-carte {
    --stv-marque-carte-marge: var(--stv-espace-16);
    --stv-marque-carte-ecart: var(--stv-espace-24);
  }
}

/* --- Cartes : la typographie des liens de titre ---------------------- */
/*
   Le Theme Style d'Elementor déclare « .elementor-kit-NNN a » — la
   typographie des liens du site, Inter 400 16. Sa spécificité (0,1,1)
   bat celle d'une classe seule (0,1,0). Or dans nos cartes, le texte
   visible du titre n'est pas porté par le h3 mais par le LIEN qu'il
   contient : le h3 sortait bien en Outfit 500 / 20, et le lien à
   l'intérieur écrasait tout en Inter 400 / 16.

   Défaut particulièrement retors : l'inspection du h3 donne la bonne
   réponse, et l'écran la mauvaise. Relevé le 25/08 sur la carte article,
   la carte produit était atteinte de la même façon.

   `font: inherit` fait suivre au lien famille, graisse, taille et
   interligne de son titre — un seul endroit à régler, aujourd'hui comme
   pour les cartes à venir.

   RÈGLE GÉNÉRALE, tirée de ce défaut : dans une carte, tout sélecteur
   qui porte de la typographie est écrit `.stv-carte-X .stv-carte-X__y`
   et non `.stv-carte-X__y`. Le Theme Style cible `.elementor-kit-NNN h3`
   et `.elementor-kit-NNN a`, tous deux en 0,1,1 : une classe seule perd,
   deux classes gagnent. Sans cette précaution, le nom de produit sortait
   en Outfit 500 / 20 (la valeur du H3 global) au lieu de son Outfit 400
   / 16 — juste sur les archives WooCommerce, faux dans Elementor, où la
   feuille du kit est chargée.
*/
.stv-carte-article__titre .stv-carte-article__lien,
.stv-carte-produit__nom .stv-carte-produit__lien {
  font: inherit;
  color: inherit;
  text-decoration: none;
}

/* --- Cartes : deux correctifs de mise en page ------------------------ */
/*
   HAUTEUR DES IMAGES. Elementor déclare « .elementor img { height: auto } ».
   Sa spécificité (0,1,1 — une classe et un élément) l'emporte sur une
   classe seule (0,1,0) : notre `height: 100%` était ignoré, l'image
   gardait ses proportions natives et débordait de sa boîte, rognée par
   l'overflow. Mesuré le 25/08 : une image de 265 px de haut dans une
   boîte de 193. D'où des hauteurs de visuel inégales d'une carte à
   l'autre, alors même que `object-fit: cover` était bien appliqué.

   La parade est de remonter la spécificité à 0,2,0 en nommant le parent,
   plutôt que d'écrire !important — qui gagnerait aussi, mais fermerait
   la porte à tout ajustement ultérieur.
*/
.stv-carte-produit__media .stv-carte-produit__image,
.stv-carte-article__media .stv-carte-article__image {
  height: 100%;
}

/*
   IMAGE QUI NE CHARGE PAS (26/10, signalé par Logan sur « Nos articles »
   de l'accueil). Une image cassée n'est plus un élément remplacé : le
   navigateur la rend comme une boîte en ligne à la largeur de son
   attribut width (768) et de son texte alternatif. Dans la grille de la
   boucle Elementor (colonnes en 1fr, soit minmax(auto, 1fr)), cette
   largeur devient le minimum de la colonne : mesuré 891 px par carte au
   lieu de 408, la grille débordait de 2 000 px et la page défilait
   latéralement. Même cause, même effet sur les cartes produit.

   Deux verrous, indépendants :
   — l'image est posée en absolu dans sa boîte (qui a toujours un
     aspect-ratio ou une taille fixée) : chargée ou non, elle ne compte
     plus dans la largeur de la carte — comme les cartes collection,
     référence et éditoriale, qui le font déjà ;
   — les éléments de boucle ont min-width: 0 : la colonne ne dépend plus
     de ce qu'elle contient.
   Le texte alternatif reste lisible dans la boîte, rogné par son overflow.
*/
.stv-carte-produit__media,
.stv-carte-article__media {
  position: relative;
}

.stv-carte-produit__media .stv-carte-produit__image,
.stv-carte-article__media .stv-carte-article__image {
  position: absolute;
  inset: 0;
  width: 100%;
}

.e-loop-item {
  min-width: 0;
}

/*
   HAUTEUR DES CARTES. « Hauteur égale » du carrousel étire la
   DIAPOSITIVE, pas ce qu'elle contient. Sans cette chaîne, la carte
   garde la hauteur de son contenu : les fonds gris s'arrêtent à des
   hauteurs différentes et l'égalisation ne se voit pas.

   Chaque maillon compte — diapositive, conteneur, widget, enveloppe du
   shortcode — car il suffit qu'un seul reste en hauteur automatique pour
   que la chaîne casse. Tout est porté sous `.e-loop-item` : hors boucle,
   une carte garde sa hauteur naturelle.
*/
.e-loop-item,
.e-loop-item > .e-con,
.e-loop-item .elementor-widget-shortcode,
.e-loop-item .elementor-widget-container,
.e-loop-item .elementor-shortcode {
  height: 100%;
}

.e-loop-item .stv-carte-produit,
.e-loop-item .stv-carte-article {
  height: 100%;
}

/* --- Flèches de piste défilante (tâches 26 et 27) -------------------- */
/*
   Deux boutons de 40 x 40 espacés de 16, relevés sur les nœuds Figma
   11:9832 (desktop) et 11:10174 (mobile). Ils doublent le défilement au
   doigt : sans eux, une piste défilante ne se voit pas à la souris.

   Placement : centré sous la piste, comme la maquette mobile. En
   desktop, la maquette les pose en haut à droite, sur la ligne des
   onglets — une ligne qui appartient au widget Elementor, pas à notre
   balisage : réglé plus bas pour les collections, par positionnement
   absolu dans le widget Onglets.
*/
/*
   PRÉSENCE de la barre : décidée ici, par un point de rupture, et non en
   JavaScript après mesure.

   La mesure a été essayée d'abord — masquer la barre tant que la piste
   ne déborde pas. Elle a un défaut rédhibitoire dans un onglet : un
   panneau fermé est en `display: none`, donc large de zéro, donc « sans
   débordement ». La barre apparaissait après coup, une fois l'onglet
   ouvert et la piste mesurable, et la section grandissait de 64 px sous
   les yeux — le sursaut signalé le 26/08.

   Or la condition n'a jamais eu besoin d'être mesurée : sous 1024 px, un
   élément par vue occupe 100 % de la piste, et le script n'équipe que
   les pistes d'au moins deux éléments. Le débordement est donc certain.
   Au-dessus, une rangée fixe ne défile jamais : des flèches y seraient
   inertes — sauf pour les collections, qui défilent à toutes les
   largeurs depuis le 02/09 (15 à 18 cartes), et dont la barre est donc
   affichée partout, voir plus bas.

   Décidée par le CSS, la barre est là dès la première image, identique
   dans tous les onglets. Plus rien ne change de taille au changement
   d'onglet, donc plus rien à masquer.
*/
.stv-fleches {
  display: none;
  justify-content: center;
  gap: var(--stv-espace-16);
  margin-top: var(--stv-espace-24);
}

@media (max-width: 1024px) {
  .stv-fleches {
    display: flex;
  }
}

/*
   Collections en desktop : la barre monte sur la ligne des onglets, à
   droite — nœud Figma 11:9823, relevé le 02/09 : deux boutons 40 × 40
   sur fond gris clair, gouttière 16, alignés au bord droit du contenu et
   centrés sur la ligne des onglets.

   La barre est rendue APRÈS la piste, dans le panneau de l'onglet actif.
   Pour la positionner par rapport au widget Onglets, rien entre les deux
   ne doit être positionné : Elementor pose `position: relative` sur
   chaque widget et chaque conteneur, on les remet à `static` sur ce seul
   chemin. Les panneaux inactifs sont en `display: none`, donc une seule
   barre est visible à la fois — celle de l'onglet ouvert.
*/
@media (min-width: 1025px) {
  .e-n-tabs:has(.stv-collections) {
    /*
       Hauteur de la ligne d'onglets, pour y centrer les 40 px de la
       barre : 54 avec les onglets à 20 px de la maquette (30 de ligne
       + 2 × 12 de marge intérieure), 50 tant qu'ils sont à 16. À ajuster
       si la typographie du widget change.
    */
    --stv-onglets-hauteur: 54px;
    position: relative;
  }

  .e-n-tabs:has(.stv-collections) .e-n-tabs-content,
  .e-n-tabs:has(.stv-collections) .e-n-tabs-content > .e-con,
  .e-n-tabs:has(.stv-collections) .elementor-widget-shortcode {
    position: static;
  }

  .stv-collections + .stv-fleches {
    display: flex;
    position: absolute;
    top: calc((var(--stv-onglets-hauteur) - 40px) / 2);
    right: 0;
    margin: 0;
    justify-content: flex-end;
  }
}

.stv-fleches .stv-fleches__bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  /* Fond gris clair, relevé sur la frame 11:9823 (02/09) — et non
     transparent. currentColor : les flèches prennent la couleur du texte
     de leur bloc, comme les points de pagination. */
  background-color: var(--stv-gris-clair);
  color: currentColor;
  cursor: pointer;
  transition: opacity 0.2s;
}

/*
   Une flèche inutilisable reste VISIBLE mais atténuée, et le navigateur
   la sort du parcours au clavier. La faire disparaître déplacerait sa
   voisine à chaque extrémité de course — un repère qui bouge est pire
   qu'un repère éteint.
*/
.stv-fleches .stv-fleches__bouton:disabled {
  opacity: 0.3;
  cursor: default;
}

.stv-fleches .stv-fleches__bouton:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* --- Flèches de carrousel 40 × 40 (phase 2) -------------------------- */

/* --- Défilement tactile tablette et mobile (tâche 26) ---------------- */
/*
   Une rangée fixe au-dessus de 1024 px, une piste défilante au doigt en
   dessous, sans carrousel. Le navigateur fait tout : `scroll-snap` cale
   chaque élément, et l'inertie tactile est celle du système — celle à
   laquelle l'utilisateur est habitué, qu'aucune bibliothèque n'imite
   vraiment.

   Pourquoi pas un Nested Carousel : il chargerait Swiper sur desktop
   pour une rangée qui ne bouge pas, avec grille d'accroche et écouteurs
   à la clé. C'est exactement le composant qui a coûté deux incidents le
   25/08 (largeur nulle en onglet masqué, navigation rattachée en double).
   Ici, rien à initialiser, rien à recalculer, rien à réinitialiser.

   NOMBRE D'ÉLÉMENTS PAR VUE : une seule variable, `--stv-defile-vue`.
   2 en tablette, 1 en mobile. Un seul chiffre à changer par palier, la
   largeur des éléments s'en déduit — gouttières comprises.

   Le nom de la classe dit « mobile » parce qu'il a été posé avant que
   le palier ne descende à la tablette ; la forme `#stv-defile-mobile`
   est tolérée pour la même raison. Une CLASSE reste préférable : un
   identifiant est unique par page, et ce motif servira aussi aux
   marques et aux références.
*/
/*
   OÙ S'APPLIQUE LA PISTE. Un conteneur Elementor en mode « boxed »
   enveloppe ses enfants dans un `.e-con-inner` : ses enfants directs se
   réduisent alors à cette seule enveloppe. Relevé le 25/08 — le
   conteneur portait bien l'identifiant, mais n'avait qu'UN enfant, d'où
   un défilement sans effet et aucune pagination.

   Les règles ciblent donc l'enveloppe interne quand elle existe, et le
   conteneur lui-même sinon. Les deux modes de conteneur fonctionnent,
   sans rien changer à la mise en page.
*/
@media (max-width: 1024px) {

  .stv-defile-mobile,
  #stv-defile-mobile {
    /*
       Un élément par vue, occupant TOUTE la largeur du contenu. Aucun
       aperçu du voisin : la gouttière suffit à le repousser hors champ.

       Un aperçu de 20 px avait été tenté le 26/08 — le voisin affleurait
       et l'élément visible ne remplissait plus le conteneur. Abandonné :
       ce sont les points de pagination qui signalent qu'il y a autre
       chose à voir, et c'est plus lisible qu'un fragment coupé.
    */
    --stv-defile-vue: 1;
    --stv-defile-gouttiere: var(--stv-espace-16);
  }

  .stv-defile-mobile > .e-con-inner,
  #stv-defile-mobile > .e-con-inner,
  .stv-defile-mobile:not(:has(> .e-con-inner)),
  #stv-defile-mobile:not(:has(> .e-con-inner)) {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    gap: var(--stv-defile-gouttiere);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /*
       `overflow` découpe à la boîte de REMPLISSAGE, pas à la boîte de
       contenu : une marge intérieure sur la piste laisserait donc voir
       le voisin à travers elle, alors même que l'élément fait 100 %.
       C'est ce qui produisait les fragments d'argument sur les côtés.
       La marge de section reste portée par le conteneur extérieur.
    */
    padding-inline: 0;

    /* La barre de défilement est masquée : la pagination en tient lieu,
       et la maquette n'en montre pas. Le défilement reste possible. */
    scrollbar-width: none;
  }

  .stv-defile-mobile > .e-con-inner::-webkit-scrollbar,
  #stv-defile-mobile > .e-con-inner::-webkit-scrollbar,
  .stv-defile-mobile:not(:has(> .e-con-inner))::-webkit-scrollbar,
  #stv-defile-mobile:not(:has(> .e-con-inner))::-webkit-scrollbar {
    display: none;
  }

  /*
     `flex-basis` plutôt qu'une largeur : sur un élément flexible, la base
     flex l'emporte sur `width`, y compris sur celle qu'Elementor pose par
     variable. min-width: 0 lève la taille minimale automatique, sans quoi
     un contenu large empêcherait l'élément de tenir dans sa part.
  */
  .stv-defile-mobile > .e-con-inner > *,
  #stv-defile-mobile > .e-con-inner > *,
  .stv-defile-mobile:not(:has(> .e-con-inner)) > *,
  #stv-defile-mobile:not(:has(> .e-con-inner)) > * {
    /*
       N éléments par vue, séparés de N-1 gouttières. Avec N = 1, le
       calcul se réduit à 100 % : l'élément occupe exactement la largeur
       du contenu, et le suivant commence une gouttière plus loin, donc
       hors de la zone visible.
    */
    flex: 0 0 calc(
      (100% - (var(--stv-defile-vue) - 1) * var(--stv-defile-gouttiere))
      / var(--stv-defile-vue)
    );
    min-width: 0;
    scroll-snap-align: start;
  }
}

/*
   Le palier mobile n'a plus rien à redéclarer : un élément par vue de
   la tablette au téléphone. Si un jour la tablette doit en montrer
   deux, c'est ici, et c'est le seul chiffre à changer.
*/

/* Pagination : construite par carrousels.js, donc absente du balisage
   d'Elementor. Masquée là où la rangée est fixe. */
.stv-points {
  display: none;
}

@media (max-width: 1024px) {
  .stv-points {
    display: flex;
    justify-content: center;
    gap: var(--stv-espace-8);
    /*
       La barre est posée DANS la section, sous la piste : elle hérite
       ainsi du fond et de la couleur du texte du bloc. Posée dehors,
       elle se retrouvait blanche sur le blanc de la page — invisible,
       constaté le 26/08.

       L'espace au-dessus des points vient de la piste, pas d'une marge
       de la barre : c'est un remplissage vers le bas, pour que le fond
       de la section descende SOUS les points plutôt que de s'arrêter à
       leur hauteur.
    */
    padding-bottom: var(--stv-espace-32);
    width: 100%;
  }
}

@media (max-width: 767px) {
  .stv-points {
    padding-bottom: var(--stv-espace-16);
  }
}

/*
   Deux classes, pas une : le Theme Style déclare
   « .elementor-kit-NNN button » — fond anthracite, marges 12/24 — en
   spécificité 0,1,1. Une classe seule perd, et les points sortaient en
   48 x 24 au lieu de 16 x 4, mesuré le 25/08. Troisième occurrence du
   même piège dans ce fichier ; voir le commentaire des cartes.
*/
.stv-points .stv-points__point {
  width: 16px;
  height: 4px;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  /* currentColor : le point prend la couleur du texte de son bloc, donc
     le beige sur la réassurance sombre, sans réglage supplémentaire. */
  background-color: currentColor;
  opacity: 0.3;
  cursor: pointer;
  transition: opacity 0.2s;
}

.stv-points .stv-points__point[aria-current="true"] {
  opacity: 1;
}

.stv-points .stv-points__point:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

/* --- Onglets soulignés (phase 2) ------------------------------------- */

/* --- Tiroir panier (spec panier-tiroir-specs.md) --------------------- */

/* --- Correctif : arrondi des elements atomiques V4 ------------------ */
/*
   Elementor pose « border-radius: 2px » sur `.elementor .e-button-base`,
   le socle de ses boutons atomiques V4. Cette regle (0,2,0) l'emporte
   sur celle du Theme Style, `.elementor-kit-NNN button` (0,1,1), ou le
   rayon 0 de la tache 19 est pourtant declare : releve en rendu le
   24/08, tous les boutons atomiques sortaient a 2 px.

   La maquette ne comporte AUCUN arrondi. Le correctif vit ici plutot
   que dans une classe Elementor : il couvre tout bouton atomique a
   venir, il est versionne, et il survit aux regenerations.

   Le « !important » n'est pas une facilite : mesure faite le 24/08, un
   style INLINE pose sur le bouton ne l'emportait pas non plus. La
   declaration d'Elementor est donc elle-meme prioritaire, et rien
   d'ordinaire ne passe devant. Portee reduite au strict minimum : une
   seule propriete, un seul socle d'element.
*/
.elementor .e-button-base,
.elementor button.e-button-base {
  border-radius: var(--stv-rayon) !important;
}

/* --- Icônes de l'interface (tâche 42) -------------------------------- */
/*
   Les icônes sont intégrées au balisage par inc/icones.php et peintes
   en `currentColor` : elles suivent la couleur du texte de leur bloc,
   donc blanches sur l'en-tête transparent du hero et foncées sur
   l'en-tête plein, sans une ligne de réglage.

   `flex: none` les protège du rétrécissement quand elles voisinent un
   libellé long dans un conteneur flexible.
*/
.stv-icone {
  display: block;
  flex: none;
}

/* --- Logo ------------------------------------------------------------ */
/*
   Le logo n'est PAS une image mais un masque appliqué sur un aplat de
   `currentColor`. Trois raisons, dans cet ordre :

   1. Il change de couleur avec l'en-tête — blanc sur le hero, foncé
      ailleurs — sans deuxième fichier, sans bascule à écrire et sans
      le clignotement d'une image échangée en cours de défilement.
   2. Son tracé pèse 31 Ko (11,5 Ko compressés). Intégré au balisage,
      il alourdirait CHAQUE page ; en fichier, le navigateur le met en
      cache une fois pour tout le site.
   3. Le fichier vit dans le thème, donc son adresse ne porte pas le
      domaine du site et survit à la mise en ligne — contrairement à
      une image téléversée dans la médiathèque.

   LE LOGO A ÉTÉ REDESSINÉ LE 01/10/2026 (demande du client) : symbole
   « S » hexagonal, « STELVOREN », accroche « Équipements de Pilates |
   Yoga | Fitness ». Fichiers livrés dans MEDIAS\logo def. Le nouveau
   fait 1210 × 198 — rapport 6,1 contre 4,4 pour l'ancien 182 × 41 : à
   largeur égale il perdait un tiers de sa hauteur et l'accroche devenait
   illisible.

   RÈGLE RETENUE AVEC LOGAN (01/10) : le logo prend la HAUTEUR du
   logo-texte de la maquette — 48 dans l'en-tête de bureau (156:4958,
   192 × 48), 24 en mobile (I156:7837;156:5187, 96 × 24), 81,3 dans le
   pied (I156:10424;156:6443, 320 × 81,3). « STELVOREN » garde ainsi la
   taille dessinée (capitales de 23 dans l'en-tête). On règle une
   largeur, la hauteur suit le rapport du fichier.

   Les versions beige, blanche et sombre livrées ont EXACTEMENT la même
   silhouette (comparées au pixel à 2 420 de large) : ce masque les
   couvre toutes, la couleur vient de l'état de l'en-tête — beige sur le
   bleu pétrole, blanc sur le hero, sombre sur fond blanc. La version
   « couleur » (symbole bleu / rouge) ne servait pas sur le site,
   décision de Logan du 01/10 ; elle fait le favicon (inc/identite.php).
   RÉVISÉ LE 26/10 POUR LE PIED SEUL (recette d'Estevan R7, tâche 181) :
   le pied sort le logo couleur en <img> (assets/images/logo-couleur.svg),
   voir « Étage 1 » plus bas. L'en-tête garde ce masque.

   `?v=` : le fichier a changé de forme sous le même nom. Sans version,
   un navigateur qui garde l'ancien masque en cache l'étirerait dans la
   nouvelle boîte. À changer à chaque nouvelle livraison du fichier.
*/
.stv-logo {
  display: block;
  /*
     293 × 48 à partir de 1 600 px ; en dessous il revient linéairement
     à 192 × 31, sa largeur d'avant, atteinte à 1 240 et gardée jusqu'à
     1 025. La barre de bureau devait déjà tenir à 1 025 avec 11 px de
     jeu et un logo de 192 (§ « Le rythme horizontal se resserre avant
     de rompre ») : rien ne change sous 1 240.

     Pourquoi 1 600 et non 1 440 : la navigation (382 + 4 × rythme) vit
     dans la demi-piste de gauche, (largeur − 2 × rythme − logo) / 2.
     Avec 293 dès 1 440, il ne restait que 31 px entre « Professionnels »
     et le logo — l'écart entre deux entrées de menu, le logo se lisait
     comme une sixième entrée (mesuré le 01/10 ; 82 avec l'ancien logo).
     Rampe jusqu'à 1 600 : 27 px à 1 280, 42 à 1 366, 54 à 1 440, 89 à
     1 536, 111 à 1 600 ; à 1 240 (20,6) rien ne change. Pas de requête
     de média, comme le rythme.
  */
  width: clamp(192px, calc(192px + (100vw - 1240px) * 101.33 / 360), calc(48px * 1210 / 198));
  aspect-ratio: 1210 / 198;
  background-color: currentColor;
  -webkit-mask: url("../images/logo.svg?v=2026-10-01") no-repeat center / contain;
          mask: url("../images/logo.svg?v=2026-10-01") no-repeat center / contain;
}

/* Mobile : 146,7 × 24, la hauteur du logo-texte de la maquette mobile. */
@media (max-width: 1024px) {
  .stv-logo {
    width: calc(24px * 1210 / 198);
  }
}

/* --- Bouton du menu mobile, qui se plie en croix --------------------- */
/*
   Les trois barres reprennent la géométrie exacte de menu.svg : 16 de
   large, 2 de haut, aux ordonnées 0, 7 et 14. Au repos, le dessin est
   celui du fichier ; à l'ouverture, la première descend de 7 et pivote
   d'un quart de tour, la dernière remonte d'autant en sens inverse, et
   celle du milieu s'efface — les deux extrêmes se croisent donc au
   centre exact du bouton.

   La zone cliquable fait 40 px pour rester confortable au doigt, sans
   que le dessin grossisse.
*/
/*
   DEUX classes, et pour une fois ce n'est pas de la prudence : le Theme
   Style d'Elementor cible `.elementor-kit-NNN button` en 0,1,1. Avec la
   seule classe `.stv-burger` (0,1,0), le bouton reprenait le fond rose,
   le rayon et les marges internes des boutons du site -- une pastille
   coloree autour de l'icone. Releve le 27/08, sixieme occurrence du
   meme piege sur le projet.

   Le bouton n'a NI fond NI marge interne : il fait la taille de son
   dessin, ce qui aligne l'icone exactement sur la marge de la barre.
   La zone tactile, elle, est agrandie par un pseudo-element qui deborde
   sans rien deplacer -- 16 px de dessin ne se visent pas au doigt.
*/
.stv-entete .stv-burger {
  position: relative;
  display: none;
  align-items: center;
  justify-content: center;
  width: auto;
  height: auto;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  line-height: 0;
  cursor: pointer;
}

.stv-entete .stv-burger::before {
  content: "";
  position: absolute;
  inset: -13px -12px;
}

.stv-burger__barres {
  position: relative;
  display: block;
  width: 16px;
  height: 16px;
}

.stv-burger__barres span {
  position: absolute;
  left: 0;
  width: 16px;
  height: 2px;
  background: currentColor;
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.16s linear;
}

.stv-burger__barres span:nth-child(1) { top: 0; }
.stv-burger__barres span:nth-child(2) { top: 7px; }
.stv-burger__barres span:nth-child(3) { top: 14px; }

.stv-burger[aria-expanded="true"] .stv-burger__barres span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.stv-burger[aria-expanded="true"] .stv-burger__barres span:nth-child(2) {
  opacity: 0;
}

.stv-burger[aria-expanded="true"] .stv-burger__barres span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

.stv-burger:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/*
   Le pliage est un agrément, pas une information : qui demande moins de
   mouvement obtient la croix sans transition, pas un bouton figé.
*/
@media (prefers-reduced-motion: reduce) {
  .stv-burger__barres span {
    transition: none;
  }
}

/* --- Méga-menu : le panneau d'un univers (tâche 43, refait par la 190) --- */
/*
   RECETTE D'ESTEVAN R6 / R9 / R10 (tâche 190, 26/10). Maquettes 331:9812
   (Pilates), 331:9883 (Yoga), 331:9951 (Fitness) : chaque entrée de la barre
   ouvre directement son panneau — pas d'entrée « Produits » ni d'onglets
   d'univers (Logan, 26/10 : la planche 331:20644 n'est pas à suivre).

   Le contenu d'un univers, sur fond gris clair (subSubMenu) : colonnes de 242
   espacées de 48 depuis x = 32, 80 sous la plus longue ; « Nos marques »
   n'est plus qu'un titre (R6 — une colonne sans liens du menu) ; trois
   visuels espacés de 8 qui finissent AU BORD du cadre, sans marge à droite
   ni en bas, et qui prennent la hauteur des colonnes (`stretch`) : 394 pour
   Pilates (314 + 80), comme 331:9869.

   R10 — RIEN NE DÉBORDE PLUS ENTRE 1 025 ET 1 840. Avant, les visuels
   gardaient 648 quelle que soit la largeur : à 1 100, les colonnes
   s'empilaient sur 900 de haut et le panneau sortait de l'écran sans
   défiler. Comme la référence (roche-bobois.com, menu Produits), liste et
   images se PARTAGENT la largeur : les visuels prennent ce qui reste une
   fois trois colonnes posées, entre 320 et 648 (deux visuels sous 480) ;
   sous 1 280 les colonnes passent à la ligne (« Nos marques » sous la
   première) ; et le panneau défile s'il dépasse l'écran (`.stv-panneau`,
   plus bas).
*/
.stv-megamenu {
  display: flex;
  align-items: stretch;
  gap: var(--stv-espace-48);
  padding: var(--stv-espace-48) 0 0 var(--stv-espace-32);
}

/*
   Au-delà de 1 840 (règle du cadre, 26/10 — tâche 193), le contenu du
   panneau reste le cadre de 1 840 de la maquette, centré : colonnes à
   l'aplomb de la navigation (32 + 1 776), visuels au bord droit de ce
   cadre comme à 1 840. Le fond et l'ombre restent ceux du panneau,
   pleine largeur.
*/
.stv-panneau .stv-megamenu {
  max-width: calc(var(--stv-largeur-navigation) + 2 * var(--stv-espace-32));
  margin-inline: auto;
}

/*
   La rangée de logos « Nos marques » (tâche 43, 02/09 → 06/10) est retirée
   le 26/10 (R6) : « Nos marques » est une colonne sans liens du menu.

   Des colonnes de 242 qui ne s'étirent PAS, rangées à gauche : Pilates et
   Yoga en ont trois (deux, plus « Nos marques »), une colonne de 532 aurait
   fait flotter « Blocs et briques » au milieu. `auto-fill` en pose autant
   que la largeur en tient — quatre à 1 840 (1 112 = 4 × 242 + 3 × 48, le
   cadre 331:20690 au pixel), deux à 1 025 — et renvoie les autres à la
   ligne, 48 plus bas.
*/
.stv-megamenu__colonnes {
  flex: 1 1 0;
  min-width: 242px;
  display: grid;
  grid-template-columns: repeat(auto-fill, 242px);
  align-content: start;
  gap: var(--stv-espace-48);
  padding-bottom: var(--stv-espace-80);
}

/*
   Le titre de colonne EST un lien : dans la maquette il désigne une
   catégorie réelle, et un intitulé de rubrique non cliquable oblige à
   passer par un de ses enfants pour voir le rayon complet.

   Outfit Medium 16 / 1,5 noir (331:20692), 8 au-dessus du premier lien.
*/
.stv-megamenu .stv-megamenu__titre {
  display: block;
  margin-bottom: var(--stv-espace-8);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
  text-decoration: none;
}

/* « Nos marques » : un titre sans liste, donc sans marge dessous. */
.stv-megamenu .stv-megamenu__titre:last-child {
  margin-bottom: 0;
}

/*
   Police, taille et interligne posés sur la LISTE aussi : le `li` fabrique
   sa propre ligne, à l'interligne et dans la police du corps — dix liens
   faisaient 344, puis 324 (Inter et Outfit ne partagent pas leur ligne de
   base), au lieu des 314 de 331:20700. Même piège que le menu mobile.
*/
.stv-megamenu__liens {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-8);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-petit);
  line-height: var(--stv-interligne-texte);
}

/* Outfit Regular 14 / 1,5 anthracite (331:20693), 8 entre deux liens. */
.stv-megamenu .stv-megamenu__liens a {
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-anthracite);
  text-decoration: none;
}

.stv-megamenu .stv-megamenu__titre:hover,
.stv-megamenu .stv-megamenu__titre:focus-visible,
.stv-megamenu .stv-megamenu__liens a:hover,
.stv-megamenu .stv-megamenu__liens a:focus-visible {
  color: var(--stv-texte);
  text-decoration: underline;
}

/* --- Les mises en avant, à droite ------------------------------------ */
/*
   648 à 1 840 (331:20726 : 3 × 210,67 + 2 × 8), ce que laissent TROIS
   colonnes en dessous — chaque univers en a trois, « Nos marques » comprise,
   qui restent ainsi sur une ligne jusqu'à 1 280 —, jamais moins de 320. Le
   pourcentage est celui de la rangée : 100 % − 870 = la largeur une fois
   l'écart de 48 et trois colonnes (3 × 242 + 2 × 48 = 822) déduits.
   1 440 → 538 ; 1 280 → 378 ; 1 100 et 1 025 → 320 (deux colonnes).

   Sous 480 de large, deux visuels au lieu de trois : trois cartes de 120
   ne seraient plus que des lanières (requête de conteneur, sans seuil
   d'écran à tenir à jour).
*/
.stv-megamenu__avant {
  flex: 0 0 clamp(320px, 100% - 870px, 648px);
  display: flex;
  gap: var(--stv-espace-8);
  container-type: inline-size;
}

@container (max-width: 479px) {
  .stv-megamenu .stv-avant:nth-child(n + 3) {
    display: none;
  }
}

/*
   DEUX classes dans le sélecteur, et ce n'est pas un excès de prudence.
   Le Theme Style d'Elementor cible `.elementor-kit-NNN a` en spécificité
   0,1,1 : une classe seule perd. Relevé ici même le 26/08 — la carte
   sortait en rose souligné, `rgb(204, 51, 102)`, alors que la règle
   ci-dessous demandait l'inverse. C'est la cinquième fois que ce piège
   se présente sur le projet ; la parade est toujours la même.

   Libellé Outfit 14 blanc, centré, à 24 du bas (331:20727 / 331:20728).
   Le fond blanc ne se voit que sans photo (pointillé « en attente »).
*/
.stv-megamenu .stv-avant {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  min-height: 240px;
  padding: 0 var(--stv-espace-8) var(--stv-espace-24);
  overflow: hidden;
  background: var(--stv-blanc);
  color: var(--stv-blanc);
  text-decoration: none;
}

.stv-megamenu .stv-avant__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--stv-survol-duree) var(--stv-survol-courbe), filter var(--stv-survol-duree) var(--stv-survol-courbe);
}

/*
   LE SURVOL DES PHOTOS (recette d'Estevan R29, 28/10, tâche 204 — non
   dessiné : « un peu comme les cartes articles de blog », après la
   retouche R27). La photo s'agrandit dans son cadre comme celle de la carte
   article — mêmes jetons, × 1,08 en 0,3 s — et s'assombrit un peu
   (`brightness`, le voile paraît plus dense) : le libellé blanc gagne en
   contraste au lieu d'en perdre. Le cadre (`overflow: hidden`) ne bouge
   pas. Au clavier, le même état au focus visible. Souris seulement, à
   partir de 1 025 (le panneau du bureau) ; rien sous « mouvement réduit ».
*/
@media (hover: hover) and (min-width: 1025px) {
  .stv-megamenu .stv-avant:hover .stv-avant__image {
    transform: scale(var(--stv-survol-zoom));
    filter: brightness(0.85);
  }
}

.stv-megamenu .stv-avant:focus-visible .stv-avant__image {
  transform: scale(var(--stv-survol-zoom));
  filter: brightness(0.85);
}

@media (prefers-reduced-motion: reduce) {
  .stv-megamenu .stv-avant__image {
    transition: none;
  }
}

/*
   Le voile de la maquette (331:20727) : noir 5 % en haut, 50 % à 90 %,
   85 % au pied — le libellé est posé sur la partie la plus sombre.
*/
.stv-megamenu .stv-avant:has(.stv-avant__image)::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(2, 10, 18, 0.05) 0%, rgba(2, 10, 18, 0.5) 90%, rgba(2, 10, 18, 0.85) 100%);
  pointer-events: none;
}

.stv-megamenu .stv-avant__libelle {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-petit);
  line-height: var(--stv-interligne-texte);
  text-align: center;
  color: var(--stv-blanc);
  /*
     Contraste mesuré pixel par pixel sous chaque libellé (26/10) : ≥ 5:1
     partout sauf « Accessoires de musculation » (2 % des pixels sous
     4,5:1, le tapis blanc au sol). Une ombre douce, hors maquette, suffit.
  */
  text-shadow: 0 1px 4px rgba(2, 10, 18, 0.5);
}

/* --- L'entrée du panneau --------------------------------------------- */
/*
   Chaque colonne arrive D'UN BLOC — titre et liens ensemble — en fondu
   montant de 24 px, les colonnes décalées l'une après l'autre.

   Un seul nombre à régler : `--stv-decalage`. Avec 60 ms et une durée
   de 300, la quatrième colonne finit à 480 ms.

   L'animation se rejoue à chaque ouverture parce qu'un panneau fermé est
   en `display: none` : repasser en visible relance les animations CSS.
*/
.stv-megamenu {
  --stv-decalage: 60ms;
}

/*
   Seules les COLONNES entrent en fondu montant. Les visuels de droite
   sont la des l'ouverture, sans decalage : ils tiennent lieu d'image du
   panneau, et les voir arriver apres coup ferait clignoter le bloc le
   plus grand de l'ecran. Decision du 27/08.
*/
@media (prefers-reduced-motion: no-preference) {
  .stv-megamenu__colonne {
    animation: stv-monte 300ms cubic-bezier(0.16, 1, 0.3, 1) both;
    animation-delay: calc(var(--stv-rang, 0) * var(--stv-decalage));
  }
}

@keyframes stv-monte {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (max-width: 1024px) {
  /* En mobile, le panneau est un accordéon : une colonne par ligne, et
     pas de mises en avant — elles ont leur propre menu, en pied. */
  .stv-megamenu {
    display: block;
    padding: 0;
  }

  .stv-megamenu__colonnes {
    grid-template-columns: minmax(0, 1fr);
    min-width: 0;
    padding-bottom: 0;
  }

  /* Pas de visuels dans l'accordéon : des liens, rien d'autre. */
  .stv-megamenu__avant {
    display: none;
  }
}

/* ==================================================================== *
   EN-TÊTE (tâches 42 à 46)
   ==================================================================== */
/*
   Mesures relevées sur la maquette (nœuds 11:3694, 11:3726, 11:3859 et
   leurs pendants mobiles) : barre d'annonce 48 / 30, barre de navigation
   96 / 56, marge intérieure 32, logo 192 / 96, champ de recherche
   220 × 32, icônes espacées de 16, entrées de navigation espacées de 32.

   Revu le 17/09 sur le nœud 156:4944 (variante « Hovered ») : la barre
   au repos passe du blanc au bleu pétrole, texte et logo en beige, et
   le champ de recherche s'élargit à 320. Les deux zones latérales y
   valent 792 chacune — 792 + 192 + 792 + 2 × 32 = 1840, la grille
   `1fr auto 1fr` est confirmée telle quelle.

   Logo redessiné le 01/10 : 293 × 48 au-dessus de 1 600, 192 × 31 de
   1 240 à 1 025, fluide entre les deux, 146,7 × 24 en mobile (règle et
   calcul : § « Logo »).
*/
/*
   Les deux hauteurs vivent sur :root et non sur l'en-tete. La cale est
   son FRERE, pas son enfant : declarees sur l'en-tete, les variables
   auraient ete invisibles pour elle, `height` serait tombee a zero et le
   contenu serait passe dessous. Constate ici meme le 27/08.
*/
:root {
  --stv-annonce-h: var(--stv-annonce-hauteur);
  --stv-barre-h: var(--stv-entete-hauteur);
  /*
     LA BARRE D'ANNONCE N'EST VISIBLE QU'EN HAUT DE PAGE (26/10 — recette
     d'Estevan R1, tâche 189, référence pieddebiche-paris.com). En défilant,
     elle part avec la page, pixel pour pixel, et la navigation se cale en
     haut de l'écran ; elle revient en remontant tout en haut.

     `--stv-annonce-retrait` (0 → la hauteur de la barre) est posé sur
     <html> par assets/js/entete.js à chaque défilement qui le change ;
     sans script il vaut 0 et l'en-tête reste celui d'avant.
     `--stv-annonce-visible` est ce qu'il reste de la barre à l'écran : c'est
     LA valeur à ajouter pour poser quelque chose sous l'en-tête (menu
     mobile, colonne collante de l'article, image collante de la fiche).
  */
  --stv-annonce-visible: calc(var(--stv-annonce-h) - var(--stv-annonce-retrait, 0px));
}

.stv-entete {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

/*
   La barre d'administration de WordPress est elle aussi fixee en haut.
   Elle decale le document par une marge sur <html>, ce qui ne deplace
   PAS un element fixe : sans ce decalage, elle recouvre la barre
   d'annonce pendant tout le developpement.

   UNE VARIABLE et non deux regles : le menu mobile doit se poser sous
   l'en-tete, il a donc besoin de la meme valeur. Deux regles separees
   avaient laisse le menu mobile sous la barre d'administration, ou il
   recouvrait le burger -- plus aucun moyen de le refermer. Releve le
   27/08. Les hauteurs (32 et 46) sont celles de WordPress, et son propre
   point de rupture est 782 px.

   Ne concerne que les connectes : en production, personne ne la voit.
*/
.admin-bar {
  --stv-decalage-admin: 32px;
}

@media screen and (max-width: 782px) {
  .admin-bar {
    --stv-decalage-admin: 46px;
  }
}

/* Remonté du retrait de la barre d'annonce (voir :root ci-dessus). `top` et
   non `transform` : une transformation ferait de l'en-tête le bloc
   contenant du menu mobile, fixe et logé dedans, qui ne couvrirait plus
   l'écran. */
.stv-entete {
  top: calc(var(--stv-decalage-admin, 0px) - var(--stv-annonce-retrait, 0px));
}

/*
   L'EN-TÊTE SE RETIRE EN DESCENDANT, REVIENT EN REMONTANT — BUREAU SEUL
   (demande de Logan, 26/10 à 17 h 42). `stv-entete-cachee` est posée sur
   <html> par assets/js/entete.js : passé la hauteur de l'en-tête, le
   défilement vers le bas (8 px de tolérance) le fait glisser hors de
   l'écran ; le premier pixel vers le haut le ramène. Il reste là tant qu'un
   panneau du méga-menu est ouvert ou que le focus clavier y est.

   `transform` ICI, et non `top` : la réserve de la règle précédente porte
   sur le menu mobile, qui n'existe pas au-delà de 1 024 ; et la classe n'a
   aucun effet en dessous — tablette et mobile gardent l'en-tête d'avant.
   Sans script, rien ne bouge.

   `--stv-barre-visible` : ce qu'il reste de la barre de navigation à
   l'écran (sa hauteur, ou 0 quand elle est retirée). Les éléments
   collants sous l'en-tête (colonne de l'article, image des onglets de la
   fiche) la lisent à la place de `--stv-barre-h` et remontent avec elle.
*/
:root {
  --stv-barre-visible: var(--stv-barre-h);
}

@media (min-width: 1025px) {
  .stv-entete {
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  }

  html.stv-entete-cachee {
    --stv-barre-visible: 0px;
  }

  html.stv-entete-cachee .stv-entete {
    transform: translateY(-100%);
  }
}

@media (min-width: 1025px) and (prefers-reduced-motion: reduce) {
  .stv-entete {
    transition: none;
  }
}

/*
   La cale rend au flux la hauteur que l'en-tête fixe lui prend.

   Sur l'accueil elle ne vaut QUE la barre d'annonce : le hero démarre
   sous la barre opaque et passe sous la navigation transparente. Ailleurs
   elle vaut les deux. C'est ce qui permet de traiter les deux cas sans
   une seule marge négative.
*/
.stv-entete__cale {
  height: calc(var(--stv-annonce-h) + var(--stv-barre-h));
}

.stv-entete[data-accueil="oui"] + .stv-entete__cale {
  height: var(--stv-annonce-h);
}

/* --- La barre d'annonce ---------------------------------------------- */

.stv-entete__annonce {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--stv-annonce-h);
  padding-inline: var(--stv-page-gouttiere);
  overflow: hidden;
  background: var(--stv-anthracite);
  color: var(--stv-beige);
}

/*
   Beige et non blanc : la maquette 156:4944 écrit le bandeau en
   `--beige, #fef5ec` sur `--grisanthracite, #24262e`. L'écart est
   minime à l'œil, mais c'est le même beige que la barre en dessous —
   les deux bandes de l'en-tête partagent désormais une seule encre.
*/
/*
   LES QUATRE BÉNÉFICES (26/10 — R1, tâche 189, note Figma 331:12130) :
   ceux de la réassurance du bas, un à la fois, centrés comme l'ancien
   message (topBar 331:12126 : 48 de haut, texte de 16). Le suivant monte
   par le bas pendant que le courant sort par le haut ; toutes les 4,5 s,
   en pause au survol, hors écran et sous « mouvement réduit »
   (assets/js/entete.js). Sans script : le message `data-actif` seul (la
   livraison, celui d'avant).

   Les messages sont empilés au même endroit (`inset: 0`) : la barre garde
   sa hauteur quel que soit le texte. Ceux qui attendent sont sous la barre,
   transparents ; celui qui sort passe au-dessus.
*/
.stv-entete .stv-annonces {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-entete .stv-annonces__item {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  margin: 0;
  /* Outfit 16 (topBar 331:12126) ; c'était Inter 14 avant le 26/10. */
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-beige);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(100%);
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.6s ease;
}

.stv-entete .stv-annonces__item[data-actif] {
  opacity: 1;
  transform: none;
}

.stv-entete .stv-annonces__item[data-sortant] {
  opacity: 0;
  transform: translateY(-100%);
}

/* Un texte trop long pour la largeur se coupe proprement au lieu de déborder. */
.stv-entete .stv-annonces__long,
.stv-entete .stv-annonces__court {
  overflow: hidden;
  text-overflow: ellipsis;
}

.stv-entete .stv-annonces__court {
  display: none;
}

/* Téléphone : la forme courte (le titre ; l'ancien message pour la livraison),
   en 14 dans la barre de 30. */
@media (max-width: 767px) {
  .stv-entete .stv-annonces__item {
    font-size: var(--stv-taille-petit);
  }

  .stv-entete .stv-annonces__long {
    display: none;
  }

  .stv-entete .stv-annonces__court {
    display: block;
  }
}

@media (prefers-reduced-motion: reduce) {
  .stv-entete .stv-annonces__item {
    transition: none;
  }
}

/* =====================================================================
   LE RYTHME HORIZONTAL SE RESSERRE AVANT DE ROMPRE

   Relevé du 17/09, à 1 025 px — la dernière largeur où l'en-tête de
   bureau est encore affiché : les icônes compte et panier sortaient de
   la barre de 69 px, hors de l'écran. Le défaut est antérieur au bleu
   pétrole ; il tient à un écart entre la maquette et le site.

   La maquette dessine TROIS entrées de menu. Le site en a CINQ —
   Pilates, Yoga, Fitness, Conseils, Professionnels — soit 382 px de
   texte et quatre écarts. À 32, la navigation réclame 510 px. Le compte
   complet, au plus serré : 2 × 32 de marge + 510 + 192 de logo + (220
   de champ + 32 + 93 d'icônes) = 1 111 px. Il en manquait cent.

   Plutôt que de rogner un élément, c'est l'ESPACE ENTRE eux qui cède :
   marges de la barre, écart entre les entrées, écart avant les icônes
   passent ensemble de 32 à 16 entre 1 440 et 1 025 px. Le total tombe à
   999 px et tient. Un seul jeton pour les trois, sinon ils divergeront.

   La valeur fluide ne vit que dans la requête de bureau, et le jeton
   garde 32 en dehors. Non pas que le mobile s'en serve — il repose ses
   deux valeurs lui-même, marge 16 et écart 16 — mais un `var()` sans
   repli sur un jeton non déclaré est invalide, et `gap` retomberait
   alors à zéro : les icônes se toucheraient sous 1 024 px. Le jeton
   doit donc exister partout, fluide seulement ici.

   Ce que cela ne répare pas : entre 1 025 et ~1 180 px la navigation
   dépasse encore sa demi-piste, la colonne de droite est donc plus
   étroite que celle de gauche et le logo glisse jusqu'à 53 px à droite
   du milieu. C'est le repli choisi — un logo décentré plutôt qu'un
   panier hors de l'écran. Une sixième entrée de menu reprendrait les
   99 px de marge : le point de rupture de l'en-tête devrait alors
   remonter vers 1 180.
   ================================================================== */

.stv-entete {
  --stv-entete-rythme: var(--stv-espace-32);
}

@media (min-width: 1025px) {
  .stv-entete {
    /* 16 à 1 025 px, 32 à 1 440, linéaire entre les deux. */
    --stv-entete-rythme: clamp(
      var(--stv-espace-16),
      calc(var(--stv-espace-16) + (100vw - 1025px) * 16 / 415),
      var(--stv-espace-32)
    );
  }
}

/* --- La barre de navigation ------------------------------------------ */
/*
   Trois zones et un logo exactement centré : `1fr auto 1fr` place le
   milieu au centre de la barre quelle que soit la largeur des côtés.
   La maquette le confirme — logo à x=824 sur 192 de large dans un cadre
   de 1840, donc centre à 920, soit la moitié pile.

   CADRE DE 1 776 (26/10 — 331:20582, tâche 193) : au-delà de 1 840, la
   marge grandit pour que navigation, logo et services tiennent dans
   1 776 centrés ; le fond de la barre, lui, reste pleine largeur. En
   dessous, c'est le rythme qui gagne, comme avant.
*/
.stv-entete__barre {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: var(--stv-barre-h);
  padding-inline: max(var(--stv-entete-rythme), (100% - var(--stv-largeur-navigation)) / 2);
  background: var(--stv-blanc);
  color: var(--stv-texte);
  transition: background-color 0.25s ease, color 0.25s ease;
}

.stv-entete[data-etat="transparent"] .stv-entete__barre {
  background: transparent;
  color: var(--stv-blanc);
}

/*
   Un panneau ouvert repasse la barre en plein, quel que soit l'état :
   le panneau est blanc, une barre transparente au-dessus flotterait sur
   rien. Fait en CSS plutôt qu'en JavaScript — c'est une conséquence de
   l'ouverture, pas une décision.
*/
.stv-entete:has(.stv-panneau:not([hidden])) .stv-entete__barre,
.stv-entete[data-recherche="ouverte"] .stv-entete__barre {
  background: var(--stv-blanc);
  color: var(--stv-texte);
}

/*
   AU REPOS, LA BARRE EST BLEU PÉTROLE — nœud 156:4944, relevé le 17/09.

   Elle ne naît plus blanche : fond bleu pétrole, texte et logo en beige.
   Le blanc ne subsiste que pour un panneau ouvert, et la transparence
   que sur le hero — les deux règles ci-dessus pèsent 0,2,0 contre 0,1,0
   ici, elles passent devant quelle que soit leur place dans le fichier.
   Rien à répéter, rien à annuler : c'est le plancher qui change.

   DANS UNE REQUÊTE DE MÉDIA, et non sur la règle de base. « Cette
   modification n'affecte que le desktop » (Logan, 17/09) : sous 1024 px
   la maquette garde une barre blanche, et c'est aussi ce qui permet au
   panneau de recherche mobile — blanc, collé sous la barre — de rester
   lisible. Le seuil est celui de l'en-tête (le pendant exact du
   `max-width: 1024px` plus bas), pas un nouveau point de rupture.
*/
@media (min-width: 1025px) {
  .stv-entete__barre {
    background: var(--stv-bleu-petrole);
    color: var(--stv-beige);
  }
}

/*
   TOUS les liens de l'en-tête suivent la couleur de la barre.

   `.elementor-kit-44301 a` pèse 0,1,1 et battait chaque `color:
   inherit` posé sur une seule classe. Conséquence visible seulement
   depuis qu'un hero sombre est derrière : le logo, les entrées de
   navigation et les icônes compte et panier restaient sombres sur
   l'en-tête transparent, quand la loupe et le cœur — un `<button>` et
   un `<span>`, que la règle du kit ne vise pas — étaient blancs. Un
   en-tête à moitié lisible, et la moitié fautive était exactement celle
   des balises `<a>`.

   La classe est doublée pour atteindre 0,2,1. Une règle unique et non
   une par composant : le prochain lien ajouté dans l'en-tête héritera
   sans qu'on y pense, ce qui est précisément le défaut qu'on vient de
   corriger trois fois.
*/
.stv-entete.stv-entete a {
  color: inherit;
}

/*
   Le logo reste à part : il lui faut aussi `display` et sa colonne de
   grille.
*/
.stv-entete .stv-entete__logo {
  grid-column: 2;
  display: block;
  color: inherit;
  text-decoration: none;
}

/* Même raison pour les liens de la barre et les icônes de service. */
.stv-entete .stv-entete__logo:hover,
.stv-entete .stv-entete__logo:focus-visible {
  color: inherit;
}

/* --- La navigation --------------------------------------------------- */

.stv-nav {
  grid-column: 1;
  grid-row: 1;
}

.stv-nav__liste {
  display: flex;
  align-items: center;
  gap: var(--stv-entete-rythme);
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
   Une entrée qui ouvre un panneau est un BOUTON, pas un lien : elle ne
   mène nulle part. Il faut donc lui retirer l'habillage de bouton du
   navigateur et celui du Theme Style, d'où les deux classes.
*/
.stv-entete .stv-nav__lien {
  display: inline-flex;
  align-items: center;
  gap: var(--stv-espace-6);
  padding: 0;
  border: 0;
  background: none;
  min-height: 0;
  /* Outfit 16 (navBar 331:20645 et ses variantes, 26/10) ; c'était Inter. */
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

.stv-entete .stv-nav__lien:hover,
.stv-entete .stv-nav__lien[aria-expanded="true"] {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.stv-nav__chevron {
  transition: transform 0.2s ease;
}

.stv-nav__lien[aria-expanded="true"] .stv-nav__chevron {
  transform: rotate(180deg);
}

/*
   Le panneau se déploie sur TOUTE la largeur de l'en-tête : son bloc
   contenant est donc la barre, pas l'entrée survolée. `position: static`
   sur l'item empêche celui-ci de devenir le référent.
*/
.stv-nav__item--panneau {
  position: static;
}

.stv-panneau {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  background: var(--stv-gris-clair);
  color: var(--stv-texte);
  box-shadow: 0 12px 24px rgba(2, 10, 18, 0.08);
}

/*
   R10 (tâche 190, 26/10) : le panneau ne sort plus jamais de l'écran. Il
   tient sous ce qui reste de l'en-tête (barre d'administration, annonce
   encore visible, barre) et défile lui-même au-delà — un portable de
   1 366 × 768 voit Pilates entier, un 1 024 × 600 le parcourt. Fond gris
   clair : celui du contenu (subSubMenu de 331:9812).
*/
.stv-panneau {
  max-height: calc(100vh - var(--stv-decalage-admin, 0px) - var(--stv-annonce-visible) - var(--stv-barre-h));
  max-height: calc(100dvh - var(--stv-decalage-admin, 0px) - var(--stv-annonce-visible) - var(--stv-barre-h));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* --- Les services ---------------------------------------------------- */

.stv-services {
  grid-column: 3;
  grid-row: 1;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--stv-entete-rythme);
}

/*
   LE CHAMP DE RECHERCHE RESPIRE ENTRE 320 ET 220.

   La maquette le pose à 320 (156:4967). À cette largeur la barre
   réclame 1 132 px pour tenir : 320 + 32 + 86 d'icônes = 438 par côté,
   deux côtés, plus le logo de 192 et les deux marges de 32. Or
   l'en-tête de bureau descend jusqu'à 1 025 px, où chaque colonne `1fr`
   ne fait plus que 384. Une largeur fixe y aurait débordé, et le logo
   — centré par la grille — aurait cessé de l'être.

   `flex: 0 1 320px` demande 320 et accepte de rendre ; `min-width` pose
   le plancher à l'ancienne valeur, 220, celle de la maquette d'origine.
   Entre les deux, le champ suit l'écran : 320 au-dessus de 1 132, 266 à
   1 025, jamais moins de 220. Aucune requête de média — la piste `1fr`
   ne descend pas sous le min-content de la zone, donc la grille se
   charge seule de l'arbitrage, et le logo reste au milieu.

   `flex-grow` reste à 0 : sans lui le champ mangerait tout l'espace
   libre d'un écran large et dépasserait les 320 de la maquette.
*/
.stv-entete .stv-recherche {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 1 320px;
  min-width: 220px;
  height: 32px;
  padding-inline: var(--stv-espace-16);
  gap: var(--stv-espace-12);
  background: var(--stv-gris-clair);
  border-radius: var(--stv-rayon);
  color: var(--stv-texte);
}

/* =====================================================================
   UN CHAMP À NOUS, DÉBARRASSÉ DE TOUT HABILLAGE VENU D'AILLEURS

   Relevé du 01/09 : le champ de recherche sortait avec un fond
   `#F2F6F8`, une bordure `1px solid rgba(36,38,46,.35)` et un
   `padding: 8px 12px` que ce fichier ne pose nulle part. Un style de
   champ GLOBAL — Elementor, le thème parent, ou les deux — vise
   `input:not([type="button"]):not([type="submit"])`, soit 0,3,1. Aucun
   enchaînement d'ancêtres raisonnable ne passe devant : trois classes
   font 0,3,0, et perdent sur le compte d'éléments.

   D'où la classe RÉPÉTÉE quatre fois — 0,4,0. C'est laid et c'est
   assumé. L'autre voie aurait été d'empiler des parents (`.stv-entete
   .stv-services .stv-recherche …`), ce qui aurait lié le composant à sa
   place dans la page : le même champ dans le pied de page aurait exigé
   une seconde règle, et la troisième occurrence aurait divergé.

   La remise à zéro est explicite et non partielle : la règle d'en face
   pose aussi une hauteur, un rayon et une ombre, qu'un simple
   `background: none` laisserait en place.
   ================================================================== */

/*
   Le champ e-mail du formulaire Elementor du pied (tâche 37) rejoint la
   règle, avec un sélecteur à HUIT classes — 0,8,0. Le widget Formulaire
   écrit sa propre feuille (post-N.css), chargée APRÈS celle-ci puisque
   le pied est rendu en fin de page, et sa règle de fond de champ pèse
   0,7,0 : `.elementor-N .elementor-element.elementor-element-id
   .elementor-field-group:not(.elementor-field-type-upload)
   .elementor-field:not(.elementor-select-wrapper)`. L'ordre ne peut pas
   nous sauver, seule la spécificité le peut. Le détail de ce compte
   est dans la section « La colonne infolettre ».
*/
.stv-recherche__champ.stv-recherche__champ.stv-recherche__champ.stv-recherche__champ,
/* =====================================================================
   POURQUOI QUATRE `.stv-pied` DANS CE QUI SUIT — relevé du 23/09.

   L'ORDRE DES FEUILLES NE NOUS SAUVE PAS, IL NOUS DESSERT. Les feuilles
   du thème enfant sont mises en file dans cet ordre : `jetons.css`,
   `style.css`, **`composants.css`, puis `socle.css`**. Le socle est donc
   la DERNIÈRE chargée : à compte de spécificité égal, c'est lui qui
   gagne, jamais ce fichier.

   Or le § 9 du socle habille tout formulaire Elementor — champ à fond
   gris, filet, marge 8/12, bouton anthracite de 48 — avec des
   sélecteurs à 0,8,0. Les règles d'ici, qui remettent la barre
   d'infolettre à ce que la maquette demande (champ transparent sans
   filet ni marge, bouton en simple texte souligné), pesaient 0,8,0 pour
   le champ et 0,6,0 pour le bouton. Elles perdaient les deux, et le
   pied sortait avec une boîte grise et un bouton noir à la place de sa
   barre blanche. Vu le 23/09, sur toutes les pages et à toutes les
   largeurs.

   Quatre répétitions portent le champ à 0,11,0 et le bouton à 0,9,0 :
   au-dessus du socle, quel que soit l'ordre des fichiers. C'est laid et
   c'est assumé — l'alternative aurait été de faire du socle une règle
   qui connaît le pied, or le socle n'a pas à le connaître.

   LA RÈGLE GÉNÉRALE QUI EN SORT : une barre de formulaire — infolettre
   du pied, recherche de l'en-tête, et tout champ posé dans une ligne de
   hauteur fixe — écrit ses règles AU-DESSUS de celles du socle, par la
   spécificité et non par l'ordre.
   ================================================================== */
.stv-infolettre__champ.stv-infolettre__champ.stv-infolettre__champ.stv-infolettre__champ,
.stv-pied.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-form-fields-wrapper .elementor-field-group .elementor-field.elementor-field-textual {
  height: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  background: none;
  box-shadow: none;
  -webkit-appearance: none;
          appearance: none;
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
}

.stv-recherche__champ.stv-recherche__champ::placeholder,
.stv-infolettre__champ.stv-infolettre__champ::placeholder,
.stv-pied.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-form-fields-wrapper .elementor-field-group .elementor-field.elementor-field-textual::placeholder {
  color: var(--stv-texte-champ);
  opacity: 1;
}

.stv-recherche__champ.stv-recherche__champ:focus,
.stv-infolettre__champ.stv-infolettre__champ:focus,
.stv-pied.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-form-fields-wrapper .elementor-field-group .elementor-field.elementor-field-textual:focus {
  outline: none;
  box-shadow: none;
  border: 0;
  background: none;
}

/* La part qui reste propre à la recherche : elle occupe la pastille. */
.stv-entete .stv-recherche .stv-recherche__champ {
  width: 100%;
}

.stv-entete .stv-recherche:focus-within {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.stv-services__icones {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-16);
}

/*
   La loupe-bouton n'existe qu'en mobile : sur le bureau, le champ est
   déjà ouvert dans la barre et porte sa propre loupe. Deux classes pour
   passer devant `.elementor-kit-NNN button`, qui poserait sinon son fond
   et ses marges — le piège relevé six fois sur ce projet.
*/
.stv-entete .stv-service--loupe {
  display: none;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  background: none;
  color: inherit;
  cursor: pointer;
}

.stv-service {
  position: relative;
  display: inline-flex;
  align-items: center;
  color: inherit;
  text-decoration: none;
}

/*
   Le compteur est une pastille de 16 posée sur le coin de l'icône : fond
   plein de la couleur du texte, chiffre de la couleur de la barre. Sur le
   hero il est donc blanc à chiffre sombre, et l'inverse une fois la barre
   pleine.

   DEUX variables et non `currentColor` : un fond en `currentColor` avec
   un texte redéfini juste après donne un chiffre de la couleur de son
   propre fond, donc invisible. Constaté au premier rendu, le 27/08.
*/
.stv-entete {
  --stv-pastille-fond: var(--stv-texte);
  --stv-pastille-texte: var(--stv-blanc);
}

.stv-entete[data-etat="transparent"] {
  --stv-pastille-fond: var(--stv-blanc);
  --stv-pastille-texte: var(--stv-texte);
}

.stv-entete:has(.stv-panneau:not([hidden])),
.stv-entete[data-recherche="ouverte"] {
  --stv-pastille-fond: var(--stv-texte);
  --stv-pastille-texte: var(--stv-blanc);
}

/*
   Sur la barre bleu pétrole, la pastille s'inverse elle aussi : beige
   plein, chiffre bleu pétrole. Sans cela elle restait sombre sur fond
   sombre — le compteur du panier serait devenu illisible au repos,
   c'est-à-dire dans l'état le plus fréquent.

   APRÈS les deux règles d'état, et non avant : elle ne pèse que 0,1,0,
   donc elle doit sa préséance sur le plancher à l'ordre du fichier, et
   son effacement devant la transparence et le panneau ouvert à leur
   0,2,0. Même mécanique que la couleur de la barre plus haut.
*/
@media (min-width: 1025px) {
  .stv-entete {
    --stv-pastille-fond: var(--stv-beige);
    --stv-pastille-texte: var(--stv-bleu-petrole);
  }
}

.stv-service__compteur {
  position: absolute;
  top: -6px;
  right: -8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--stv-pastille-fond);
  font-family: var(--stv-police-texte);
  font-size: 10px;
  line-height: 1;
  color: var(--stv-pastille-texte);
}

/* --- Le bouton du menu mobile ---------------------------------------- */

.stv-entete .stv-burger {
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
}

/* --- Utilitaire ------------------------------------------------------ */

.stv-cache {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ==================================================================== *
   EN-TÊTE — tablette et mobile
   ==================================================================== */

@media (max-width: 1024px) {
  :root {
    --stv-annonce-h: var(--stv-annonce-hauteur-mobile);
    --stv-barre-h: var(--stv-entete-hauteur-mobile);
  }

  .stv-nav,
  .stv-entete .stv-recherche .stv-recherche__champ {
    display: none;
  }

  /* La maquette mobile place le burger a x=16 et arrete les icones a
     16 du bord droit : la marge de la barre vaut donc 16, pas 32.
     24 en tablette depuis la règle du cadre (331:20599, 26/10) : le
     jeton porte les deux valeurs (jetons.css). */
  .stv-entete__barre {
    padding-inline: var(--stv-entete-gouttiere);
  }

  .stv-entete .stv-burger {
    display: inline-flex;
  }

  .stv-entete .stv-service--loupe {
    display: inline-flex;
  }

  /*
     Le champ ouvert ne tient pas dans une barre de 56 : sous 1024 px le
     formulaire quitte la barre et devient un panneau pleine largeur
     juste dessous, déplié par la loupe. Il est ABSOLU dans
     `.stv-entete__barre`, seul ancêtre positionné : `top: 100%` le colle
     au bas de la barre sans avoir à recalculer la hauteur de l'annonce.

     Aucun `[hidden]` ici : l'attribut vaudrait aussi pour le bureau, où
     le champ doit rester visible. L'état vit donc sur l'en-tête, et le
     CSS ne le lit que dans cette requête de média.
  */
  .stv-entete .stv-recherche {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 98;
    display: none;
    width: auto;
    height: var(--stv-entete-hauteur-mobile);
    /* Aligné sur la barre au-dessus : 24 en tablette, 16 en mobile. */
    padding-inline: var(--stv-entete-gouttiere);
    background: var(--stv-blanc);
    border-top: 1px solid var(--stv-filet-onglets);
  }

  .stv-entete[data-recherche="ouverte"] .stv-recherche {
    display: flex;
  }

  .stv-entete[data-recherche="ouverte"] .stv-recherche .stv-recherche__champ {
    display: block;
  }

  /*
     Le panneau du menu commence sous la barre : quand la recherche est
     ouverte, il descend d'autant. Les deux ne s'ouvrent jamais ensemble
     — le JavaScript ferme l'un en ouvrant l'autre — mais la règle évite
     un recouvrement si l'un des deux venait à s'ouvrir autrement.
  */
  .stv-entete[data-recherche="ouverte"] .stv-mobile {
    top: calc(var(--stv-decalage-admin, 0px) + var(--stv-annonce-visible) + var(--stv-barre-h) + var(--stv-entete-hauteur-mobile));
  }

  /*
     La maquette mobile ne garde que DEUX services dans l'en-tete : la
     loupe et le panier. Les favoris et le compte descendent dans la barre
     basse du menu. Les laisser ici serrait le logo contre les icones --
     ils se chevauchaient sous 400 px, releve le 27/08.
  */
  /* Le panier devis (R35, 05/11) descend avec eux : inc/entete.php, stelvoren_mobile_pied(). */
  .stv-service--favoris,
  .stv-service--compte,
  .stv-service--devis {
    display: none;
  }

  .stv-services {
    gap: var(--stv-espace-16);
  }

  /* --- Le panneau mobile --------------------------------------------- */

  .stv-mobile {
    position: fixed;
    /* Sous ce qui reste de l'en-tête : la barre d'annonce peut être partie (R1, 26/10). */
    top: calc(var(--stv-decalage-admin, 0px) + var(--stv-annonce-visible) + var(--stv-barre-h));
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 99;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--stv-blanc);
    color: var(--stv-texte);
  }

  /*
     `display: flex` ci-dessus est une declaration d'AUTEUR : elle bat le
     `display: none` que le navigateur applique a [hidden], qui vient de
     sa feuille par defaut. Sans cette regle, le menu mobile est ouvert en
     permanence et le burger ne le referme jamais -- il change bien
     `hidden`, mais l'attribut n'a plus aucun effet. Releve le 27/08.

     Meme piege que sur les fleches de carrousel en son temps : poser un
     `display` sur un element qu'on masque par attribut oblige toujours a
     redonner la priorite a l'attribut.
  */
  .stv-mobile[hidden] {
    display: none;
  }

  /*
     RYTHME VERTICAL du menu, releve sur le noeud 11:3985 : un libelle de
     premier niveau fait 21 de haut et le suivant commence 33 plus bas.
     La marge interne de 6 sur chaque ligne donne donc les 12 d'ecart
     voulus ET une cible de 33 px au doigt, la ou un simple `gap` aurait
     laisse 21. Les 10 du haut completent ces 6 pour poser le premier
     libelle a 16 du bord, comme la maquette.
  */
  .stv-mobile__liste {
    margin: 0;
    padding: 10px var(--stv-espace-16) 0;
    list-style: none;
  }

  .stv-entete .stv-mobile__lien {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: var(--stv-espace-6) 0;
    border: 0;
    background: none;
    min-height: 0;
    font-family: var(--stv-police-titres);
    font-size: var(--stv-taille-carte);
    font-weight: 500;
    /* 24 de hauteur de texte pour 20 de corps, comme la maquette. */
    line-height: 1.2;
    color: var(--stv-texte);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
  }

  .stv-mobile__chevron {
    transition: transform 0.2s ease;
  }

  .stv-mobile__bascule[aria-expanded="true"] .stv-mobile__chevron {
    transform: rotate(180deg);
  }

  /*
     Les sous-categories sont decalees de 24 vers la droite par rapport a
     leur univers : c'est ce decalage, et non un puce ou un filet, qui dit
     la hierarchie dans la maquette.

     10 en haut completent les 6 de la ligne du dessus pour faire les 16
     d'ecart releves ; 6 en bas font les 12 qui precedent l'univers suivant.
  */
  .stv-mobile__panneau {
    padding: 10px 0 var(--stv-espace-6) var(--stv-espace-24);
  }

  /*
     TAILLES DE POLICE par niveau, releves sur la maquette mobile :
     20 pour l'univers (deja acquis), 16 pour la sous-categorie, 14 pour
     ses entrees. Les hauteurs de texte du fichier — 24, 21 et 18 — donnent
     les interlignes : 1,2 puis 1,3.

     Deux classes dans le selecteur pour battre les regles du panneau
     desktop, qui sont a 0,2,0 et plus haut dans le fichier.
  */
  /*
     Valeurs en dur, et non les jetons de taille : `--stv-taille-surtitre`
     tombe a 14 sous 767 px, ce qui ecrasait la sous-categorie a la meme
     taille que ses entrees. Ces trois tailles appartiennent au menu, pas
     a l'echelle typographique du site.
  */
  .stv-mobile .stv-megamenu__titre {
    font-size: 16px;
    line-height: 1.3;
    margin-bottom: var(--stv-espace-12);
  }

  /*
     La taille et l'interligne sont poses sur la LISTE : le `li` fabrique
     sa propre ligne, et il heritait de l'interligne du corps de page —
     24 px au lieu de 18, soit 32 d'ecart entre deux entrees au lieu des
     26 de la maquette. Regler le seul `a` ne suffisait pas.
  */
  .stv-mobile .stv-megamenu__liens {
    gap: var(--stv-espace-8);
    font-size: 14px;
    line-height: 1.3;
  }

  .stv-mobile .stv-megamenu__liens a {
    font-size: inherit;
    line-height: inherit;
  }

  .stv-mobile .stv-megamenu__colonnes {
    gap: var(--stv-espace-24);
  }

  /*
     Le mobile ne pose PAS son libelle sur l'image, contrairement au
     desktop : la maquette met une vignette de 96 x 120 et le texte en
     dessous. Deux colonnes de 96 alignees a gauche, pas etirees sur la
     largeur — c'est ce que montre le fichier (x=0 et x=104 dans un bloc
     de 361).
  */
  .stv-mobile__avant {
    display: grid;
    grid-template-columns: repeat(2, 96px);
    justify-content: start;
    gap: var(--stv-espace-8);
    padding: var(--stv-espace-16);
  }

  .stv-mobile .stv-avant {
    display: flex;
    flex-direction: column;
    gap: var(--stv-espace-4);
    padding: 0;
    background: none;
    color: var(--stv-texte);
    text-decoration: none;
  }

  .stv-mobile .stv-avant__image {
    width: 96px;
    height: 120px;
    object-fit: cover;
  }

  .stv-mobile .stv-avant__libelle {
    font-family: var(--stv-police-texte);
    font-size: var(--stv-taille-texte);
    line-height: 1.3;
    text-shadow: none;
  }

  /* Un emplacement sans image garde la place de sa vignette. */
  .stv-mobile .stv-avant:not(:has(img))::before {
    content: "";
    display: block;
    width: 96px;
    height: 120px;
    background: var(--stv-gris-clair);
    outline: 1px dashed var(--stv-filet-onglets);
    outline-offset: -6px;
  }

  /*
     La barre basse colle au bas du panneau et non au bas de la page :
     `position: sticky` dans une zone défilante, ce qui la garde visible
     pendant qu'on parcourt les catégories.
  */
  /* Trois entrees depuis le 05/11 (le panier devis) : elles passent a la ligne sur un ecran etroit. */
  .stv-mobile__pied {
    position: sticky;
    bottom: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--stv-espace-16);
    margin-top: auto;
    padding: var(--stv-espace-16);
    background: var(--stv-gris-clair);
  }

  /*
     14 comme les entrees du menu, et non 16 : la barre basse est un
     rappel de services, pas un niveau de navigation. Taille en dur pour
     la meme raison que plus haut — l'echelle du site bouge sous 767 px,
     celle du menu non.
  */
  .stv-entete .stv-mobile__service {
    display: inline-flex;
    align-items: center;
    gap: var(--stv-espace-8);
    position: relative;
    font-family: var(--stv-police-texte);
    font-size: 14px;
    line-height: var(--stv-interligne-texte);
    color: var(--stv-texte);
    text-decoration: none;
  }
}

/*
   Le verrou de défilement pendant que le menu mobile est ouvert. Posé
   sur <html> : sur <body>, iOS continue de faire glisser la page
   derrière le panneau.
*/
html.stv-verrouille {
  overflow: hidden;
}

/*
   Un emplacement de mise en avant sans image ne doit pas ressembler à un
   bloc gris cassé : le pointillé dit qu'il attend son visuel.
*/
.stv-avant:not(:has(img)) {
  outline: 1px dashed var(--stv-filet-onglets);
  outline-offset: -8px;
}

.stv-avant:not(:has(img)) .stv-avant__libelle {
  color: var(--stv-texte);
  text-shadow: none;
}

/* =====================================================================
   LE PIED DE PAGE
   Relevé du 31/08 sur les nœuds 11:4887 (desktop) et 11:4977 (mobile).

   Géométrie desktop : cadre de 80 tout autour, trois étages séparés de
   80, contenu de 1678 — soit 528 + 4 × 240 + 4 × 48, exactement la
   grille de `--stv-largeur-contenu`. Les colonnes sont donc en `fr`
   proportionnels et non en pixels : entre 1024 et 1680 elles se
   resserrent au lieu de déborder.
   ================================================================== */

.stv-pied {
  background: var(--stv-gris-clair);
  color: var(--stv-texte);
  padding: var(--stv-espace-80);
  font-family: var(--stv-police-texte);
}

.stv-pied__interieur {
  max-width: var(--stv-largeur-contenu);
  margin-inline: auto;
}

/* --- Étage 1 : l'identité -------------------------------------------- */

.stv-pied__identite {
  display: flex;
  justify-content: center;
}

/*
   Le masque du logo porte déjà l'accroche : une seule largeur à régler,
   la hauteur suit par `aspect-ratio` (déclaré sur .stv-logo).

   Logo du 01/10 : 497 × 81,3, la hauteur du logo-texte du pied de la
   maquette (I156:10424;156:6443, 320 × 81,3) — même règle que l'en-tête.
   `max-width` le borne à la colonne si elle devient plus étroite.
*/
.stv-pied .stv-pied__logo {
  width: calc(81.33px * 1210 / 198);
  max-width: 100%;
}

/*
   Logo COULEUR du pied (R7, 26/10) : une vraie image et non plus le
   masque, parce qu'un masque ne peint qu'une couleur. Mêmes largeurs que
   le masque (règles ci-dessus et mobile) ; la hauteur suit le rapport
   du fichier, déclaré ici puisque .stv-logo n'est plus sur l'élément.
   `height: auto` défait la hauteur 198 de l'attribut, posée pour
   réserver la place avant chargement.
*/
.stv-pied img.stv-pied__logo--couleur {
  display: block;
  height: auto;
  aspect-ratio: 1210 / 198;
}

/* --- Étage 2 : les cinq colonnes ------------------------------------- */

.stv-pied__colonnes {
  display: grid;
  grid-template-columns: minmax(0, 528fr) repeat(4, minmax(0, 240fr));
  gap: var(--stv-espace-48);
  align-items: start;
  margin-top: var(--stv-espace-80);
}

.stv-pied .stv-pied__titre {
  margin: 0 0 var(--stv-espace-24);
  font-family: var(--stv-police-titres);
  font-weight: 500;
  font-size: var(--stv-taille-carte);
  line-height: 1.25;
  color: var(--stv-texte);
}

.stv-pied__liens {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-12);
}

.stv-pied .stv-pied__lien {
  display: inline-block;
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
  text-decoration: none;
}

.stv-pied .stv-pied__lien:hover,
.stv-pied .stv-pied__lien:focus-visible {
  text-decoration: underline;
}

/*
   Un libellé posé en attendant sa page cible. Il garde la couleur du
   texte — la colonne doit avoir sa forme définitive — mais le curseur
   dit qu'il n'emmène pas.
*/
.stv-pied .stv-pied__lien--inerte {
  cursor: default;
  text-decoration: none;
}

/* --- La colonne infolettre ------------------------------------------- */

.stv-pied .stv-pied__accroche {
  margin: 0;
  max-width: 384px;
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
}

/*
   Deux états (tâche 37, inc/pied.php) : `data-etat="elementor"` quand
   la section enregistrée « Pied — infolettre » existe — c'est alors le
   formulaire Elementor Pro qui est rendu ici — et `data-etat="attente"`
   sinon, avec le champ inerte d'origine. Le conteneur porte ce qui vaut
   pour les deux : la largeur de colonne et la marge sous l'accroche.

   COMPTE DE SPÉCIFICITÉ, relevé le 04/09 sur post-44689.css. Le widget
   Formulaire génère sa feuille avec `{{WRAPPER}}` = `.elementor-N
   .elementor-element.elementor-element-id`, soit 0,3,0 AVANT toute
   cible ; et cette feuille est chargée après la nôtre, puisque le pied
   est rendu en fin de page. Ce qu'il émet par défaut, sans qu'on ait
   touché à l'onglet Style :
     - `… .elementor-field-group` : 0,4,0 — marges intérieures 5 px et
       marge basse 10 px (les « espacements » du widget) ;
     - `… .elementor-form-fields-wrapper` : 0,4,0 — marges NÉGATIVES
       de compensation, -5 / -5 / -10 ;
     - `… .elementor-button[type="submit"]` : 0,5,0 — texte BLANC,
       0,6,0 au survol ;
     - `… .elementor-field-group:not(…) .elementor-field:not(…)` :
       0,7,0 — fond blanc du champ.
   Le 04/09, avec des sélecteurs à 0,4,0, le bouton sortait blanc sur
   blanc et la rangée était décalée de 5 px et haussée de 5 : c'est ce
   compte qui a été perdu. D'où la base commune ci-dessous, 0,4,0 à
   elle seule (`.stv-pied .stv-infolettre[data-etat="elementor"]
   .elementor-form`), à laquelle chaque règle ajoute ses cibles.
*/
.stv-infolettre {
  max-width: 384px;
  margin-top: var(--stv-espace-24);
}

/*
   LA BARRE BLANCHE de la maquette : champ à gauche, « S'inscrire » à
   droite, 48 de haut. C'est un seul dessin pour deux balisages — le
   `div` d'attente, ou la rangée de champs du formulaire Elementor
   (`.elementor-form-fields-wrapper`, un flex à retour de ligne que l'on
   remet sur une ligne). `position: relative` pour y accrocher l'erreur
   de champ, voir plus bas. 0,5,0 pour le second : devant les marges
   négatives du widget.
*/
.stv-infolettre__barre,
.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-form-fields-wrapper {
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--stv-espace-16);
  height: var(--stv-bouton-hauteur);
  margin: 0;
  padding-inline: var(--stv-espace-24);
  background: var(--stv-blanc);
}

/* Mise en page seulement : l'habillage vient de la règle mutualisée. */
.stv-pied .stv-infolettre .stv-infolettre__champ {
  flex: 1 1 auto;
  min-width: 0;
}

/*
   Le champ et le bouton portent `disabled` tant que la section
   Elementor n'existe pas. On NEUTRALISE le grisage par défaut du
   navigateur : la maquette doit se lire telle quelle en recette, la
   promesse est retirée par l'attribut, pas par la couleur.
*/
.stv-pied .stv-infolettre__champ:disabled,
.stv-pied .stv-infolettre__bouton:disabled {
  opacity: 1;
  -webkit-text-fill-color: currentColor;
  cursor: default;
}

/*
   Le bouton : un texte souligné, rien d'autre. Même dessin pour le
   bouton d'attente et pour le `.elementor-button` du formulaire —
   0,6,0 pour ce dernier, devant le texte blanc que le widget lui donne
   à 0,5,0 ; 0,7,0 au survol, devant son 0,6,0.
*/
.stv-pied .stv-infolettre__bouton,
.stv-pied.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-type-submit .elementor-button {
  flex: 0 0 auto;
  width: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  background: transparent;
  box-shadow: none;
  font-family: inherit;
  font-weight: 400;
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
  text-decoration: underline;
  white-space: nowrap;
}

.stv-pied.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-type-submit .elementor-button:hover,
.stv-pied.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-type-submit .elementor-button:focus {
  background: transparent;
  color: var(--stv-texte);
}

.stv-pied.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-type-submit .elementor-button:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/*
   L'ENVELOPPE ELEMENTOR, ramenée à rien : le conteneur de la section
   (marge intérieure du kit, largeur de contenu — 0,4,0 devant les
   variables que le conteneur pose à 0,3,0), le widget (marge basse),
   les groupes de champs (0,5,0 devant les espacements du widget à
   0,4,0 ; largeurs en colonnes). Ce qui reste, c'est le `form`, sa
   rangée, un champ et un bouton.
*/
.stv-pied .stv-infolettre[data-etat="elementor"] .e-con,
.stv-pied .stv-infolettre[data-etat="elementor"] .e-con-inner {
  --padding-top: 0;
  --padding-right: 0;
  --padding-bottom: 0;
  --padding-left: 0;
  --margin-top: 0;
  --margin-right: 0;
  --margin-bottom: 0;
  --margin-left: 0;
  max-width: none;
  min-height: 0;
  margin: 0;
  padding: 0;
}

.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-widget-form,
.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form {
  margin: 0;
}

/* =====================================================================
   TROIS RÈGLES REMONTÉES À 0,7,0 — relevé du 22/09, sur le pied en
   mobile.

   LE SYMPTÔME : sous 768, la barre d'infolettre passait en deux lignes
   — champ au-dessus, bouton en dessous — alors que la barre est haute
   de 48 et ne bouge pas. Les deux groupes débordaient donc par le bas,
   et le bouton venait couvrir la mention CNIL écrite sous elle.

   LA CAUSE : le § 11 de `socle.css` empile les groupes de champ sous
   768 — `flex: 1 1 100%; width: 100%`, « un champ par ligne » — avec un
   sélecteur à 0,6,0, cinq répétitions de `.elementor-form` héritées du
   § 9. Les règles d'ici pesaient 0,5,0. Elles perdaient, sans bruit, et
   depuis le lot socle.

   POURQUOI LA CORRECTION EST ICI ET PAS DANS LE SOCLE : « un champ par
   ligne » est juste pour un FORMULAIRE DE PAGE, et c'est ce que le § 11
   décrit. La barre d'infolettre n'en est pas un : c'est un champ et un
   bouton sur UNE ligne, à toutes les largeurs, dans une boîte de
   hauteur fixe. L'exception appartient au composant qui la porte, comme
   les quatre autres règles de cette section — pas au socle, qui n'a pas
   à connaître le pied.

   `flex-wrap: nowrap` est ajouté sur la barre pour la même raison : ce
   qui ne doit jamais passer à la ligne se dit, plutôt que de dépendre
   d'un calcul de largeurs qui tient aujourd'hui.
   ================================================================== */
.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-form-fields-wrapper {
  flex-wrap: nowrap;
}

.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-group {
  position: static;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0;
}

.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-type-email {
  flex: 1 1 auto;
  min-width: 0;
}

.stv-pied.stv-pied.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-type-submit {
  flex: 0 0 auto;
  width: auto;
}

/*
   Le pot de miel ne prend pas de place, quoi qu'en fasse le widget.
   Relevé du 04/09 : il sort SANS la classe de groupe, dans un simple
   `div.elementor-field-type-text` au champ masqué en ligne — vide,
   mais enfant de la rangée, donc un écart de 16 px de plus entre le
   champ et le bouton. Tout enfant de la rangée qui n'est pas un groupe
   de champ est retiré du flux.
*/
.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-field-type-honeypot,
.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-form-fields-wrapper > :not(.elementor-field-group) {
  display: none;
}

/*
   LES MESSAGES. Elementor ajoute le message de succès (ou d'échec) en
   fin de `form`, APRÈS la rangée : il tombe sous la barre, à sa taille
   à lui — on ne garde que sa couleur, verte ou rouge, qui dit quelque
   chose. L'erreur DE CHAMP (« adresse invalide »), elle, est injectée
   dans le groupe du champ, donc dans la barre de 48 : on la sort de la
   rangée et on la pose sous la barre, accrochée à la rangée relative.
   Quand elle est là, le message d'échec général — « votre envoi a
   échoué » — ne dit rien de plus : on le tait.
*/
.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-message {
  margin: var(--stv-espace-8) 0 0;
  font-size: var(--stv-taille-petit);
  line-height: var(--stv-interligne-texte);
}

.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form .elementor-form-help-inline {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: var(--stv-espace-8) 0 0;
}

.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form:has(.elementor-form-help-inline) > .elementor-message-danger {
  display: none;
}

/* Sous la barre, la place de l'erreur de champ, pour qu'elle ne couvre pas la mention. */
.stv-pied .stv-infolettre[data-etat="elementor"] .elementor-form:has(.elementor-form-help-inline) {
  padding-bottom: calc(var(--stv-espace-8) + var(--stv-taille-petit) * var(--stv-interligne-texte));
}

/*
   LA MENTION D'INFORMATION (CNIL) : 12 px — la taille du copyright,
   demande du 04/09 —, secondaire, sous la barre, dans la largeur de la
   colonne. Le lien vers la politique de confidentialité HÉRITE de la
   taille : le kit donne à tout `a` la taille du texte courant
   (`.elementor-kit-N a`, 0,2,1), et le lien sortait à 16 dans une
   mention à 14.
*/
.stv-pied .stv-infolettre__mention {
  margin: var(--stv-espace-12) 0 0;
  font-size: var(--stv-taille-copyright);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte-secondaire);
}

.stv-pied .stv-infolettre__mention a {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
  text-decoration: underline;
}

.stv-pied__contact {
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-8);
  margin-top: var(--stv-espace-48);
}

.stv-pied .stv-pied__coordonnee {
  align-self: start;
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
  text-decoration: underline;
}

/* --- Étage 3 : la barre basse ---------------------------------------- */

/*
   Calés en BAS, comme la maquette (331:11966, `items-end`) : réseaux de 20,
   copyright de 18 et cartes de 24 partagent la même ligne de pied.
*/
.stv-pied__barre {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: end;
  margin-top: var(--stv-espace-80);
  padding-top: var(--stv-espace-32);
  border-top: 1px solid var(--stv-noir);
}

.stv-pied__reseaux {
  display: flex;
  gap: var(--stv-espace-16);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* L'élément de liste en flex : sans cela sa ligne de texte ajoute la place des jambages sous le picto, qui ne tombe plus sur la ligne de pied de la barre. */
.stv-pied__reseaux > li {
  display: flex;
}

.stv-pied .stv-pied__reseau {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  color: var(--stv-texte);
}

.stv-pied .stv-pied__reseau svg {
  width: 100%;
  height: auto;
  fill: currentColor;
}

.stv-pied .stv-pied__copyright {
  margin: 0;
  font-weight: 300;
  font-size: var(--stv-taille-copyright);
  line-height: 1.5;
  color: var(--stv-texte);
  text-align: center;
}

/* Le lien « Gérer mes cookies » (tâche 41), branché le 10/09. */
.stv-pied__mentions {
  margin-left: var(--stv-espace-8);
}

/*
   C'est un `button` et non un lien : il ouvre le panneau de Complianz,
   il n'emmène nulle part — et un `<a>` sans `href`, la forme donnée en
   exemple par leur documentation, ne prend pas le focus au clavier.
   Reste à défaire tout l'habillage natif, sans quoi le navigateur pose
   un fond gris et une bordure au milieu de la ligne de copyright.

   Souligné au repos, comme les coordonnées de la colonne infolettre et
   contrairement aux liens des menus : sur un dispositif de
   consentement, il faut qu'on voie sans chercher qu'on peut cliquer.
*/
.stv-pied .stv-pied__cookies {
  appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.stv-pied .stv-pied__cookies:hover,
.stv-pied .stv-pied__cookies:focus-visible {
  text-decoration-thickness: 2px;
}

.stv-pied__paiements {
  display: flex;
  gap: var(--stv-espace-8);
  list-style: none;
  margin: 0;
  padding: 0;
  justify-self: end;
}

.stv-pied__paiement {
  display: inline-flex;
  width: 38px;
  height: 24px;
}

.stv-pied__paiement svg,
.stv-pied__paiement img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/*
   Un picto qu'on attend encore : même vocabulaire que les mises en avant
   sans image — un pointillé, qui se lit comme une place réservée et non
   comme un affichage cassé.
*/
.stv-picto-attendu {
  display: inline-block;
  width: 100%;
  height: 100%;
  border: 1px dashed var(--stv-filet-onglets);
}

.stv-picto-attendu--reseau {
  width: 20px;
  height: 20px;
}

.stv-picto-attendu--paiement {
  width: 100%;
  height: 100%;
}

/* --- Bascule mobile (relevé 11:4977) --------------------------------- */

/*
   Ce bloc couvrait 0 – 1024 : le pied s'empilait donc en une colonne dès
   1024, sur des écrans où il y avait la place pour deux. Il est ramené au
   téléphone (≤ 767), et l'intervalle tablette est traité juste après —
   arbitrage du 02/09.
*/
@media (max-width: 767px) {
  /*
     Cadre de 32 en haut et en bas, 20 sur les côtés. Le 20 est celui de
     la maquette du pied ; l'en-tête, lui, est relevé à 16 — les deux
     blocs n'ont aucun élément à aligner l'un sur l'autre.
  */
  .stv-pied {
    padding: var(--stv-espace-32) 20px;
  }

  /*
     Logo du 01/10 : la hauteur du logo-texte mobile (I156:7954;156:6550,
     251,8 × 63,6) donnerait 388,8 de large — plus que la colonne (353 à
     393). Le `max-width: 100%` du desktop le ramène à la colonne : 353 ×
     57,8 à 393, la plus grande taille qui tienne.
  */
  .stv-pied .stv-pied__logo {
    width: calc(63.62px * 1210 / 198);
  }

  .stv-pied__colonnes {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--stv-espace-48);
  }

  .stv-pied__barre {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    gap: var(--stv-espace-24);
    padding-top: 17px;
  }

  /*
     La maquette mobile range réseaux, paiements, puis copyright. Le DOM
     garde l'ordre du desktop — réseaux, copyright, paiements — parce
     qu'il est le bon à la lecture ; seul l'affichage est réagencé.
  */
  .stv-pied .stv-pied__copyright {
    order: 3;
  }

  .stv-pied__paiements {
    justify-self: center;
  }

  .stv-pied__paiement {
    width: 25.33px;
    height: 16px;
  }
}

/* --- Tablette 768 – 1024 (arbitrage du 02/09, sans frame) ------------- */

/*
   La maquette ne décrit que deux états, 1840 et 393. Entre les deux, il
   a fallu trancher : infolettre pleine largeur, puis les quatre menus
   deux par deux. C'est la seule règle DÉCIDÉE ; le reste de ce bloc est
   du jugement de développement, à soumettre au designer.

   Le cadre passe à 48 et non aux 20 px du téléphone : sur un écran de
   1024, 20 px de marge donnaient une bande de contenu presque collée au
   bord. 48 est déjà la gouttière des colonnes, donc une valeur de la
   grille et non un chiffre inventé.

   La barre basse garde sa forme de bureau — réseaux à gauche, copyright
   au centre, paiements à droite —, qui tient largement à 768 : trois
   pictos de 20, une ligne de copyright et trois vignettes de 38. Sa
   version empilée n'a de raison d'être qu'au téléphone.
*/
@media (min-width: 768px) and (max-width: 1024px) {
  /* Côtés : 32, la marge des pages en tablette (règle du cadre, 26/10 —
     331:20602) ; le pied ne dépasse plus le contenu de 16 de chaque côté.
     Le 48 vertical reste celui de l'arbitrage du 02/09. */
  .stv-pied {
    padding: var(--stv-espace-48) var(--stv-page-gouttiere);
  }

  .stv-pied__colonnes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--stv-espace-48);
    margin-top: var(--stv-espace-48);
  }

  /*
     L'infolettre est le premier enfant du bloc (inc/pied.php la rend
     avant les quatre colonnes de menus) : elle prend toute la largeur,
     les menus se rangent dessous.
  */
  .stv-pied__colonnes > :first-child {
    grid-column: 1 / -1;
  }

  .stv-pied__barre {
    margin-top: var(--stv-espace-48);
  }
}

/* =====================================================================
   LE BOUTON
   Relevé du composant Figma 11:4234, redessiné le 26/10 avec ses états
   de survol (331:10548 — recette d'Estevan R4, tâche 191). Primaire,
   secondaire et petite sont employées ; la tertiaire est posée depuis
   le 26/10 parce que la maquette en dessine enfin le survol — elle
   attend son premier emploi.
   ================================================================== */

/*
   Deux fois la même classe : 0,2,0, ce qu'il faut pour passer devant
   `.elementor-kit-NNN a` et `.elementor-kit-NNN button`, qui pèsent
   0,1,1 et poseraient sinon leur fond, leurs marges et leur graisse.
   C'est le piège relevé sept fois sur ce projet. Un sélecteur de portée
   n'irait pas ici : le bouton est un composant, il doit tenir partout.
*/
.stv-bouton.stv-bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--stv-bouton-hauteur);
  margin: 0;
  padding: var(--stv-bouton-padding);
  border: 0;
  border-radius: var(--stv-rayon);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: var(--stv-bouton-transition);
}

.stv-bouton.stv-bouton--primaire {
  background: var(--stv-bouton-primaire-fond);
  color: var(--stv-bouton-primaire-texte);
}

.stv-bouton.stv-bouton--secondaire {
  background: var(--stv-bouton-secondaire-fond);
  color: var(--stv-bouton-secondaire-texte);
}

.stv-bouton.stv-bouton--tertiaire {
  background: var(--stv-bouton-tertiaire-fond);
  color: var(--stv-bouton-tertiaire-texte);
}

/*
   SURVOLS — dessinés le 26/10 (331:10551, 331:10557, 331:10563) ; ils
   remplacent les survols provisoires d'avant (noir / blanc, sans lueur).
   Fond + lueur intérieure, valeurs dans jetons.css. Le focus clavier
   prend le même état : un bouton atteint au clavier doit se voir autant
   qu'un bouton survolé.
*/
.stv-bouton.stv-bouton--primaire:hover,
.stv-bouton.stv-bouton--primaire:focus-visible {
  background: var(--stv-bouton-primaire-survol-fond);
  box-shadow: var(--stv-bouton-primaire-survol-lueur);
}

.stv-bouton.stv-bouton--secondaire:hover,
.stv-bouton.stv-bouton--secondaire:focus-visible {
  background: var(--stv-bouton-secondaire-survol-fond);
  box-shadow: var(--stv-bouton-secondaire-survol-lueur);
}

.stv-bouton.stv-bouton--tertiaire:hover,
.stv-bouton.stv-bouton--tertiaire:focus-visible {
  background: var(--stv-bouton-tertiaire-survol-fond);
  color: var(--stv-bouton-tertiaire-survol-texte);
}

/*
   LE WIDGET « BOUTON » D'ELEMENTOR (« Notre histoire », « Toutes nos
   marques », « Voir le showroom »…). Son allure de repos vient du kit
   (Réglages du site → Boutons : anthracite, Inter 500, 12 / 24), qui
   ne pose AUCUN survol. Le survol est donc donné ici, le même que le
   primaire, plutôt que dans le kit : un fichier du thème part avec le
   déploiement, un réglage de kit doit être réimporté. 0,4,0 : devant
   le `.elementor-kit-NNN .elementor-button` (0,2,0) ; un survol réglé
   sur un widget précis dans l'éditeur (0,4,0 et chargé après) garde la
   main, ce qui est voulu.
*/
.elementor-widget-button.elementor-widget-button .elementor-button {
  transition: var(--stv-bouton-transition);
}

.elementor-widget-button.elementor-widget-button .elementor-button:is(:hover, :focus-visible) {
  background-color: var(--stv-bouton-primaire-survol-fond);
  box-shadow: var(--stv-bouton-primaire-survol-lueur);
  color: var(--stv-bouton-primaire-texte);
}

.stv-bouton.stv-bouton:disabled {
  cursor: default;
}

/*
   LA PETITE — premier emploi réel le 29/09 (lot Compte) : « Voir » de la
   liste des commandes (`156:5909`, variante `primarySmall` du composant
   Figma : 6 / 12, 36 de haut, Inter Medium 16). Même graisse que les deux
   autres (400 : décision de Logan du 23/09, écart assumé).
*/
.stv-bouton.stv-bouton.stv-bouton--petit {
  min-height: 36px;
  padding: var(--stv-espace-6) var(--stv-espace-12);
}

/* =====================================================================
   LE HERO
   Relevé du 01/09 sur les nœuds 11:9724 (desktop) et 11:10096 (mobile).

   Hauteur : la maquette donne 796 en desktop et 654 en mobile, dessinés
   SOUS une barre de navigation de 96. Or sur l'accueil cette barre est
   transparente et recouvre le contenu — c'est l'arbitrage du 24/08, et
   la cale de l'en-tête ne réserve alors que la barre d'annonce. La
   hauteur du bloc vaut donc la hauteur dessinée PLUS celle de la barre :
   la partie visible sous la navigation retrouve les 796 de la maquette.
   ================================================================== */

/*
   Posé dans un widget Shortcode d'Elementor, le hero se retrouve dans
   TROIS enveloppes qui le rétrécissent chacune à leur façon :
   `.elementor-shortcode`, le widget, et surtout `.e-con-inner`, qui
   porte `max-width: min(100%, <largeur de contenu>)` — c'est ce dernier
   qui laissait des bandes blanches de part et d'autre alors que le
   conteneur lui-même était déjà sans marges.

   Le hero est un bloc PLEINE LARGEUR par nature : on lève le plafond là
   où il se trouve, plutôt que de dépendre d'un réglage à refaire à
   chaque montage. Côté Elementor, régler le conteneur sur « Pleine
   largeur » reste le bon geste — cette règle le rend seulement
   facultatif, et protège du jour où quelqu'un le remettra sur « Boîte ».
*/
.elementor .e-con-inner:has(.stv-hero),
.elementor .elementor-widget-shortcode:has(.stv-hero),
.elementor .elementor-widget-shortcode:has(.stv-hero) > .elementor-widget-container {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
}

/*
   Le plafond ne vient pas d'un `max-width` en dur mais de
   `max-width: min(100%, var(--content-width))`. Le lever d'un côté sans
   neutraliser la variable de l'autre laisse la porte ouverte : Elementor
   la relit ailleurs, notamment pour centrer. On coupe donc les deux.
*/
.elementor .e-con:has(.stv-hero),
.elementor .e-con-inner:has(.stv-hero) {
  --content-width: 100%;
}

/*
   Ce que la CALE de l'en-tête laisse au-dessus du hero, et qu'il faut
   donc retrancher pour occuper la fenêtre exactement (voir la règle de
   pleine hauteur plus bas). Sur l'accueil, l'en-tête est transparent :
   la cale ne vaut que la barre d'annonce, le hero passe SOUS la
   navigation. Ailleurs — les pages d'essai de la recette, où le hero
   est posé par son code court — l'en-tête est plein et la cale vaut les
   deux barres. La variable dit lequel des deux cas s'applique, plutôt
   qu'un chiffre en dur qui serait faux la moitié du temps.
*/
.stv-hero {
  --stv-hero-cale: var(--stv-annonce-h);
}

.stv-entete[data-accueil="non"] ~ .stv-hero,
.stv-entete[data-accueil="non"] ~ * .stv-hero {
  --stv-hero-cale: calc(var(--stv-annonce-h) + var(--stv-barre-h));
}

/*
   CADRE DU CONTENU (26/10 — 331:20582, recette d'Estevan R12, tâche 193) :
   l'affiche et la vidéo restent pleine largeur, le TEXTE se borne au
   cadre de 1 680 — au-delà de 1 840, il s'aligne sur les sections du
   dessous au lieu de rester collé à 80 du bord gauche de l'écran.
*/
.stv-hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  width: 100%;
  min-height: calc(796px + var(--stv-barre-h, 96px));
  padding-block: calc(var(--stv-espace-80) + var(--stv-barre-h, 96px)) var(--stv-espace-80);
  padding-inline: max(var(--stv-page-gouttiere), (100% - var(--stv-largeur-contenu)) / 2);
  overflow: hidden;
  color: var(--stv-blanc);
}

/*
   PLEINE HAUTEUR EN DESKTOP — demande du 04/09.

   Le hero occupe toute la fenêtre : sa hauteur vaut celle de la fenêtre
   MOINS ce qui le précède, c'est-à-dire la cale de l'en-tête et, pour
   les connectés seulement, la barre d'administration de WordPress (elle
   décale le document par une marge sur <html>, que `100vh` ignore : sans
   ce retrait, le bas du hero tomberait 32 px sous la ligne de flottaison
   pendant tout le développement, et nulle part en production).

   `min-height` et non `height` : si un jour le titre passe à trois
   lignes sur un écran bas, le bloc grandit au lieu de rogner le texte.

   La valeur de la maquette (796 + 96) reste la règle de base au-dessus :
   c'est elle qui s'applique en tablette, et elle sert de repli si un
   navigateur ne sait pas résoudre le calcul.
*/
@media (min-width: 1025px) {
  .stv-hero {
    min-height: calc(100vh - var(--stv-hero-cale) - var(--stv-decalage-admin, 0px));
  }
}
/*
   Quatre plans empilés dans le contexte créé par `isolation` : l'affiche,
   la vidéo par-dessus, le voile, puis le contenu. Des z-index positifs
   plutôt que négatifs — un enfant en z-index négatif passe DERRIÈRE le
   fond de son parent, ce qui interdirait d'en donner un au hero plus
   tard.
*/
.stv-hero .stv-hero__affiche,
.stv-hero .stv-hero__video,
.stv-hero .stv-hero__voile {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
}

.stv-hero .stv-hero__affiche {
  z-index: 0;
}

/*
   `object-fit` sur le `<picture>` ne ferait rien : ce n'est pas un
   élément remplacé. C'est l'image à l'intérieur qui recadre.
*/
.stv-hero .stv-hero__affiche img {
  width: 100%;
  height: 100%;
  min-width: 100%;
  min-height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: center;
}

/*
   La vidéo n'apparaît qu'une fois la lecture réellement commencée : le
   script pose `data-video` sur l'événement `playing`. Sans cela, un
   cadre noir clignoterait entre le chargement et la première image.
*/
/*
   `min-width` et `min-height` en plus de `width`/`height` : le thème
   parent et Elementor posent tous deux `video { max-width: 100%;
   height: auto }`. Le sélecteur à deux classes suffit à passer devant,
   les minima ne coûtent rien et ferment la porte à la prochaine
   extension qui aura la même idée.
*/
.stv-hero .stv-hero__video {
  z-index: 1;
  opacity: 0;
  min-width: 100%;
  min-height: 100%;
  object-fit: cover;
  object-position: center;
  transition: opacity 0.6s ease;
}

.stv-hero[data-video="oui"] .stv-hero__video {
  opacity: 1;
}

.stv-hero .stv-hero__voile {
  z-index: 2;
  background: var(--stv-voile-hero);
}

.stv-hero .stv-hero__contenu {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: 974px;
}

.stv-hero .stv-hero__surtitre {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-4);
  margin: 0;
  font-family: var(--stv-police-titres);
  font-weight: 500;
  font-size: var(--stv-taille-surtitre);
  line-height: 1.1;
  color: inherit;
}

.stv-hero__puce {
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  background: currentColor;
}

.stv-hero .stv-hero__titre {
  margin: var(--stv-espace-8) 0 0;
  font-family: var(--stv-police-titres);
  font-weight: 500;
  font-size: var(--stv-taille-hero);
  line-height: var(--stv-interligne-titre);
  letter-spacing: -0.01em;
  color: inherit;
}

.stv-hero .stv-hero__accroche {
  max-width: 964px;
  margin: var(--stv-espace-24) 0 0;
  font-family: var(--stv-police-texte);
  font-weight: 400;
  font-size: var(--stv-taille-accroche);
  line-height: var(--stv-interligne-texte);
  letter-spacing: 0;
  color: inherit;
}

.stv-hero__actions {
  display: flex;
  gap: var(--stv-espace-16);
  margin-top: var(--stv-espace-48);
}

/* --- Bascule mobile (relevé 11:10096) -------------------------------- */

@media (max-width: 1024px) {
  /*
     Le contenu passe du bas de cadre au CENTRE : la maquette mobile le
     place à 123,5 du haut comme du bas de la zone visible, ce qui est un
     centrage exact et non un alignement. Le cadre latéral est celui des
     pages : 20 en mobile, 32 en tablette (règle du cadre, 26/10 — il
     valait 20 aux deux).
  */
  .stv-hero {
    align-items: center;
    min-height: calc(654px + var(--stv-barre-h, 56px));
    padding: calc(20px + var(--stv-barre-h, 56px)) var(--stv-page-gouttiere) 20px;
  }

  .stv-hero__actions {
    flex-direction: column;
    align-items: stretch;
  }

  .stv-hero .stv-bouton {
    width: 100%;
  }
}

/* =====================================================================
   PANNEAU LATÉRAL (off-canvas) — tâche 105, réutilisé par la 92
   ---------------------------------------------------------------------
   Un `<dialog class="stv-lateral">` ouvert par `showModal()`
   (assets/js/lateral.js). Le tiroir panier en est le premier emploi ; le
   panneau de filtres du catalogue sera le second, avec la même classe et
   le même script — seule sa largeur ou son côté changeront, par variable
   ou modificateur.

   Relevé Dev Mode du 23/09 : panneau blanc de 608 (`156:11304`) sur toute
   la hauteur, à droite ; voile `156:11328`, bleu pétrole à 40 % et flou
   de 2 px (la « opacité du voile » que la fiche 104 demandait au designer
   était dans la maquette).

   POIDS. `<dialog>` a des styles d'agent utilisateur (bordure, marge
   automatique, largeur au contenu, `max-height` rogné) : n'importe quelle
   règle d'auteur les bat. La classe est doublée pour passer devant les
   `dialog`/`[open]` qu'une feuille tierce pourrait écrire à 0,1,1.
   ================================================================== */

/*
   Le verrou de défilement, posé par lateral.js tant qu'un panneau est
   ouvert. `scrollbar-gutter: stable` garde la place de la barre de
   défilement : sans lui, la page s'élargit de 15 px sous Windows à
   l'ouverture et tout saute d'autant — y compris l'en-tête fixe.
   Classe distincte du verrou du menu mobile (`stv-verrouille`) : fermer
   l'un ne doit pas déverrouiller l'autre.
*/
html.stv-lateral-ouvert {
  overflow: hidden;
  scrollbar-gutter: stable;
}

.stv-lateral.stv-lateral {
  position: fixed;
  inset: 0 0 0 auto;
  box-sizing: border-box;
  width: var(--stv-lateral-largeur);
  max-width: 100vw;
  height: 100vh;
  height: 100dvh;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--stv-rayon);
  background: var(--stv-blanc);
  color: var(--stv-texte);
  overflow: hidden;
  /*
     Glissement depuis la droite, à l'ouverture COMME à la fermeture :
     `allow-discrete` garde le panneau affiché le temps de sortir, alors
     que `close()` retire `[open]` tout de suite. `transform` et jamais
     `right` : le compositeur anime sans recalculer la page.
  */
  transform: translateX(100%);
  transition:
    transform 0.3s ease,
    overlay 0.3s ease allow-discrete,
    display 0.3s ease allow-discrete;
}

.stv-lateral.stv-lateral[open] {
  display: flex;
  flex-direction: column;
  transform: none;
}

@starting-style {
  .stv-lateral.stv-lateral[open] {
    transform: translateX(100%);
  }
}

/*
   Le voile. La valeur est répétée en repli dans `var()` : avant Chrome
   122, `::backdrop` n'héritait de rien — pas même des variables de
   `:root` — et le voile serait sorti transparent.
*/
.stv-lateral::backdrop {
  background-color: transparent;
  backdrop-filter: blur(0);
  transition:
    background-color 0.3s ease,
    backdrop-filter 0.3s ease,
    overlay 0.3s ease allow-discrete,
    display 0.3s ease allow-discrete;
}

.stv-lateral[open]::backdrop {
  background-color: var(--stv-voile-lateral, rgba(0, 29, 61, 0.4));
  backdrop-filter: blur(2px);
}

@starting-style {
  .stv-lateral[open]::backdrop {
    background-color: transparent;
    backdrop-filter: blur(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .stv-lateral.stv-lateral,
  .stv-lateral::backdrop {
    transition: none;
  }
}

/* =====================================================================
   TIROIR PANIER — tâche 105
   ---------------------------------------------------------------------
   Maquette `156:11304`, relevé Dev Mode du 23/09. Les cotes d'août
   (`panier-tiroir-specs.md`, relevées à l'œil) sont confirmées au pixel,
   À UNE EXCEPTION PRÈS : le − du sélecteur a le MÊME fond gris que le +.
   Le fond est peint dans le SVG du − (`156:11412`), ce qu'un relevé à
   l'œil ne pouvait pas voir — l'« asymétrie volontaire » d'août n'existe
   pas.

   Colonne intérieure 544 (608 − 2 × 32). En-tête 30 ; 32 jusqu'à la
   première section ; libellé de section 20 + 12 ; lignes à 10 ; sections
   à 48 (pour les suggestions de la 107). Pied : totaux (30 + 4 + 30), 32,
   bouton 48 ; 32 sous le bouton.

   POIDS. Le tiroir est posé au `wp_footer`, dans le `<body>` — donc sous
   `.elementor-kit-44301` sur toute page Elementor (titres 0,1,1, boutons
   0,1,1 et leur survol 0,2,1) et sous `body.woocommerce` sur la fiche
   (`.woocommerce img` 0,1,1, `.woocommerce .quantity .qty` 0,3,0). Tout
   est donc écrit sous `.stv-tiroir` ou `.stv-ligne-panier` (0,2,0 au
   moins), les survols à 0,3,0, le champ quantité à 0,4,1. Il n'est PAS
   sous `.page-content` : la règle de soulignement de Hello (0,1,1) ne
   l'atteint pas.
   ================================================================== */

.stv-tiroir .stv-tiroir__entete {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  gap: var(--stv-espace-16);
  height: 30px;
  margin: var(--stv-espace-32) var(--stv-espace-32) 0;
}

/* `156:11307` : Outfit Regular 24, interligne « normal » — 30 dans la maquette. */
.stv-tiroir .stv-tiroir__titre {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: 24px;
  font-weight: 400;
  line-height: 30px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--stv-noir);
}

/*
   La croix : 16 dessinés (`156:11308`), 17 avec le trait. Le bouton garde
   la boîte de 16 de la maquette ; sa zone de clic est élargie à 32 par un
   pseudo-élément, sans rien déplacer.
*/
.stv-tiroir .stv-tiroir__fermer {
  position: relative;
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 16px;
  height: 16px;
  margin: 0;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--stv-noir);
  cursor: pointer;
}

.stv-tiroir .stv-tiroir__fermer::before {
  content: "";
  position: absolute;
  inset: -8px;
}

.stv-tiroir .stv-tiroir__fermer svg {
  display: block;
  width: 17px;
  height: 17px;
  margin: -0.5px;
}

.stv-tiroir .stv-tiroir__fermer:hover,
.stv-tiroir .stv-tiroir__fermer:focus {
  background: transparent;
  color: var(--stv-anthracite);
}

.stv-tiroir .stv-tiroir__fermer:focus-visible {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: 6px;
}

.stv-tiroir .stv-tiroir__contenu {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
}

.stv-tiroir .stv-tiroir__contenu[aria-busy="true"] {
  cursor: progress;
}

/* Chargement et erreur — non dessinés (fiche 104). */
.stv-tiroir .stv-tiroir__etat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stv-espace-16);
  margin: var(--stv-espace-32);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte-secondaire);
}

.stv-tiroir .stv-tiroir__etat p {
  margin: 0;
}

/* --- Le contenu (mini-cart.php) ------------------------------------- */

.stv-tiroir .stv-panier-mini {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
}

/*
   Le corps défile, le pied reste. `overscroll-behavior: contain` : arrivé
   au bout de la liste, le défilement ne passe pas à la page derrière.
   Barre fine : sans lignes en trop, pas de barre et la colonne fait 544
   au pixel ; avec, elle ne mange que quelques pixels.
*/
.stv-tiroir .stv-panier-mini__corps {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--stv-espace-48);
  min-height: 0;
  padding: var(--stv-espace-32);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.stv-tiroir .stv-panier-mini__section {
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-12);
}

/* `156:11311` : Outfit Regular 16, interligne « normal » — 20 dans la maquette. */
.stv-tiroir .stv-panier-mini__libelle {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: 20px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--stv-noir);
}

.stv-tiroir .stv-panier-mini__liste {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Une erreur d'action (stock maximal, validation) — non dessinée (fiche 104), liseré des messages du socle. */
.stv-tiroir .stv-panier-mini__message {
  margin: 0;
  padding: var(--stv-espace-12) var(--stv-espace-16);
  border-left: 2px solid var(--stv-message-erreur);
  background: var(--stv-gris-clair);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte);
}

/* Panier vide — non dessiné (fiche 104) : une phrase et le catalogue. */
.stv-tiroir .stv-panier-mini__vide {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stv-espace-24);
}

.stv-tiroir .stv-panier-mini__vide-texte {
  margin: 0;
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte-secondaire);
}

/* --- Le pied (`156:11319`) ------------------------------------------ */

.stv-tiroir .stv-panier-mini__pied {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  gap: var(--stv-espace-32);
  padding: 0 var(--stv-espace-32) max(var(--stv-espace-32), env(safe-area-inset-bottom));
}

.stv-tiroir .stv-panier-mini__totaux {
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-4);
  margin: 0;
}

/* `156:11321` : Outfit Regular 24 des deux côtés, 30 de haut. */
.stv-tiroir .stv-panier-mini__total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--stv-espace-16);
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: 24px;
  font-weight: 400;
  line-height: 30px;
  color: var(--stv-noir);
}

.stv-tiroir .stv-panier-mini__montant {
  white-space: nowrap;
}

/* `156:11325` : Outfit 14 à 80 %, 18 de haut centrés dans une rangée de 30. */
.stv-tiroir .stv-panier-mini__mention {
  margin: 0;
  padding: 6px 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: 18px;
  color: var(--stv-texte-secondaire);
}

.stv-tiroir .stv-panier-mini__boutons {
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-12);
  margin: 0;
}

/*
   « Commander » : le bouton primaire du site, pleine largeur. Graisse 400
   et non le Medium 500 de `156:11327` — décision de Logan du 23/09 sur
   `.stv-bouton`, tenue ici comme partout.
*/
.stv-tiroir .stv-panier-mini__commander.stv-bouton {
  display: flex;
  box-sizing: border-box;
  width: 100%;
}

/*
   « Voir le panier » — 103.5, tranché le 28/09 (Logan) : la commande par
   le bouton, la page panier par ce lien, sans quoi elle n'est plus atteinte
   que par son adresse. NON DESSINÉ : le lien texte du site (Inter Medium 14,
   souligné sous la graisse, noir), centré sous le bouton à l'écart de 12 de
   la rangée. Deux classes : le kit écrit sur `a` à 0,1,1.
*/
.stv-tiroir .stv-panier-mini__voir {
  align-self: center;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-decoration: underline;
  text-underline-position: from-font;
}

.stv-tiroir .stv-panier-mini__voir:hover,
.stv-tiroir .stv-panier-mini__voir:focus-visible {
  color: var(--stv-anthracite);
}

/* =====================================================================
   LIGNE D'ARTICLE DE PANIER — composant du registre (tâche 105)
   ---------------------------------------------------------------------
   `parties/ligne-panier.php`. Mode « empilée » : le tiroir (`156:11313`).
   Mode « tableau » : la page panier (143, 28/09), plus bas — qui reprend
   sous 1024 le dessin empilé. Mode « lecture » : le récapitulatif de la
   commande et le détail d'une commande passée (146, 147 — 29/09), plus bas.
   ================================================================== */

.stv-ligne-panier.stv-ligne-panier--empilee {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-16);
  box-sizing: border-box;
  min-height: 144px;
  margin: 0;
  padding: var(--stv-espace-16);
  background: var(--stv-gris-clair);
  list-style: none;
}

.stv-ligne-panier--empilee .stv-ligne-panier__media {
  flex: 0 0 112px;
  width: 112px;
  height: 112px;
}

/* `.woocommerce img { height: auto }` (0,1,1) sur la fiche : d'où les deux classes. */
.stv-ligne-panier .stv-ligne-panier__image {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  margin: 0;
  object-fit: cover;
}

/* La colonne droite : haut et bas écartés sur toute la hauteur de la vignette. */
.stv-ligne-panier .stv-ligne-panier__corps {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-self: stretch;
  justify-content: space-between;
  gap: var(--stv-espace-12);
  min-width: 0;
}

.stv-ligne-panier .stv-ligne-panier__haut {
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-4);
}

/* `156:11406` : nom et prix sur une ligne, alignés par le bas. */
.stv-ligne-panier .stv-ligne-panier__titre {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--stv-espace-16);
  margin: 0;
}

.stv-ligne-panier .stv-ligne-panier__nom {
  min-width: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-noir);
  text-decoration: none;
}

/* Survol PROVISOIRE — non dessiné (fiche 104). */
.stv-ligne-panier a.stv-ligne-panier__nom:hover,
.stv-ligne-panier a.stv-ligne-panier__nom:focus-visible {
  color: var(--stv-noir);
  text-decoration: underline;
}

.stv-ligne-panier .stv-ligne-panier__prix {
  flex: 0 0 auto;
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-noir);
  white-space: nowrap;
  transition: opacity 0.15s ease;
}

/* Pendant l'écriture d'une quantité, le prix est périmé : on le dit sans rien masquer. */
.stv-ligne-panier[aria-busy="true"] .stv-ligne-panier__prix {
  opacity: 0.4;
}

.stv-ligne-panier .stv-ligne-panier__declinaison {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  color: var(--stv-texte-secondaire);
}

.stv-ligne-panier .stv-ligne-panier__bas {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-12);
}

/*
   Le sélecteur compact (`156:11411`) : − n + à 8, boutons de 24 sur noir
   à 10 %, trait de 0,75, quantité Inter Medium 14. MÊME BALISAGE que la
   fiche (`woocommerce_quantity_input()` + les deux boutons de
   inc/fiche-achat.php) ; seule la présentation est ici.
*/
.stv-ligne-panier .quantity.quantity {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--stv-espace-8);
  margin: 0;
}

.stv-ligne-panier .quantity .stv-quantite__bouton {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 24px;
  height: 24px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--stv-fond-quantite);
  color: var(--stv-noir);
  cursor: pointer;
}

.stv-ligne-panier .quantity .stv-quantite__bouton svg {
  display: block;
  width: 10.75px;
  height: 10.75px;
}

/* Survol PROVISOIRE — non dessiné (fiche 104) : un pas de plus vers le noir. */
.stv-ligne-panier .quantity .stv-quantite__bouton:hover,
.stv-ligne-panier .quantity .stv-quantite__bouton:focus {
  background: rgba(2, 10, 18, 0.2);
  color: var(--stv-noir);
}

.stv-ligne-panier .quantity .stv-quantite__bouton:focus-visible {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: 2px;
}

/*
   Quantité figée (minimum = maximum, stock géré à 1 par exemple — 28/09) :
   le chiffre seul, à l'encre et à la graisse du champ, sans − ni +.
*/
.stv-ligne-panier .quantity .stv-quantite__valeur {
  min-width: 1ch;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-align: center;
}

/*
   Au minimum (103.4) et au stock maximal. Non dessiné : la maquette montre
   un − ordinaire à la quantité 1 (fiche 104) ; atténué ici, parce qu'un
   bouton qui ne répond pas doit le dire.
*/
.stv-ligne-panier .quantity .stv-quantite__bouton:disabled {
  background: var(--stv-fond-quantite);
  opacity: 0.4;
  cursor: default;
}

/*
   Le champ : un `input[type=number]` qui a l'air d'un chiffre. Il le reste
   pour le clavier numérique sur mobile et pour la saisie directe. Sa
   largeur suit le contenu là où `field-sizing` existe (1 → 10 sans saut
   de mise en page), 2ch ailleurs. 0,4,1 : devant Hello (0,1,1), le kit
   (0,3,1) et WooCommerce (0,3,0).
*/
.stv-ligne-panier .quantity.quantity input.qty {
  box-sizing: content-box;
  width: 2ch;
  min-width: 1ch;
  height: 21px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-align: center;
  appearance: textfield;
  -moz-appearance: textfield;
}

@supports (field-sizing: content) {
  .stv-ligne-panier .quantity.quantity input.qty {
    width: auto;
    field-sizing: content;
  }
}

.stv-ligne-panier .quantity.quantity input.qty::-webkit-outer-spin-button,
.stv-ligne-panier .quantity.quantity input.qty::-webkit-inner-spin-button {
  margin: 0;
  -webkit-appearance: none;
}

.stv-ligne-panier .quantity.quantity input.qty.qty:focus {
  border: 0;
  outline: 0;
  box-shadow: none;
}

.stv-ligne-panier .quantity.quantity input.qty.qty:focus-visible {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: 2px;
}

/*
   La corbeille (`156:11419`) : 11,14 × 12,38 dessinés, 11,89 × 13,13 avec
   le trait. Même principe que la croix : la boîte de la maquette, une
   zone de clic élargie par un pseudo-élément.
*/
.stv-ligne-panier .stv-ligne-panier__supprimer {
  position: relative;
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 11.89px;
  height: 13.13px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--stv-noir);
  cursor: pointer;
}

.stv-ligne-panier .stv-ligne-panier__supprimer::before {
  content: "";
  position: absolute;
  inset: -6px -8px;
}

.stv-ligne-panier .stv-ligne-panier__supprimer svg {
  display: block;
}

.stv-ligne-panier .stv-ligne-panier__supprimer:hover,
.stv-ligne-panier .stv-ligne-panier__supprimer:focus {
  background: transparent;
  color: var(--stv-anthracite);
}

.stv-ligne-panier .stv-ligne-panier__supprimer:focus-visible {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: 6px;
}

/* --- L'ajout en cours sur la fiche (tâche 106) ----------------------- */

/*
   Le temps de l'aller-retour, le bouton « Ajouter au panier » le dit. Pas
   `disabled` : la barre collante recopie l'état désactivé du bouton
   principal, et afficherait « Choisir une option » pendant l'envoi.
   0,6,0 : le bouton de la fiche est habillé à 0,5,0 (fiche-produit.css).
*/
.stv-fiche .stv-achat.stv-achat .single_add_to_cart_button.single_add_to_cart_button.stv-envoi {
  cursor: progress;
  opacity: 0.7;
}

/* --- Mobile ---------------------------------------------------------- */

/*
   AUCUNE MAQUETTE MOBILE (fiche 104). La spec d'août prévoit
   `min(608px, 100vw)` : le panneau prend tout l'écran sous 608. La
   gouttière passe à 16 comme sur tout le site, la vignette à 80 comme les
   lignes de la page panier (`156:10700`).
*/
@media (max-width: 767px) {
  .stv-tiroir .stv-tiroir__entete {
    margin: var(--stv-espace-24) var(--stv-espace-16) 0;
  }

  .stv-tiroir .stv-panier-mini__corps {
    padding: var(--stv-espace-24) var(--stv-espace-16);
  }

  .stv-tiroir .stv-panier-mini__pied {
    gap: var(--stv-espace-24);
    padding: 0 var(--stv-espace-16) max(var(--stv-espace-16), env(safe-area-inset-bottom));
  }

  .stv-tiroir .stv-tiroir__etat {
    margin: var(--stv-espace-24) var(--stv-espace-16);
  }

  .stv-ligne-panier.stv-ligne-panier--empilee {
    align-items: flex-start;
    min-height: 0;
  }

  .stv-ligne-panier--empilee .stv-ligne-panier__media {
    flex-basis: 80px;
    width: 80px;
    height: 80px;
  }
}

/* --- Mode « tableau » — la page panier (tâche 143, 28/09) ------------ */

/*
   `156:10693` : une RANGÉE de tableau par article (`<tr>`, cinq cellules),
   même composant que le tiroir — seul le placement change. Vignette 80 en
   `cover`, 16 jusqu'au nom ; nom (Outfit 16 / 1,5) et déclinaison (Outfit
   14 à 80 %) à 4 ; prix unitaire et total en Inter 14 / 1,5 noir, le total
   à droite ; sélecteur compact et corbeille à 12 — les règles du mode
   empilé ci-dessus, reprises telles quelles (prix, nom, déclinaison,
   sélecteur, corbeille).

   Rythme relevé : chaque rangée à 16 sous la précédente, 80 de contenu,
   8 puis un filet de 1 (`--stv-filet-panier`, `156:10699`) ; la dernière
   sans filet ni marge basse (231 de tableau en tout, en-tête compris).
   Les largeurs de colonnes (96 | 288 | 144 | 246 | reste) sont posées par
   le `<colgroup>` de `cart/cart.php` — panier.css.

   POIDS. Hello pose sur `table td, table th` une marge de 15, un filet et
   un fond une rangée sur deux (`table tbody > tr:nth-child(odd) > td`,
   0,1,4) ; `th` en graisse 700. Les cellules sont donc écrites à 0,2,1.
   La dernière rangée se reconnaît par `:has()` : la rangée des actions du
   formulaire la suit toujours, `:last-child` ne la verrait pas.
*/
.stv-ligne-panier.stv-ligne-panier--tableau {
  background: transparent;
}

.stv-ligne-panier.stv-ligne-panier--tableau > :is(td, th) {
  padding: var(--stv-espace-16) 0 var(--stv-espace-8);
  border: 0;
  border-bottom: 1px solid var(--stv-filet-panier);
  background: transparent;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-align: left;
  vertical-align: middle;
}

.stv-ligne-panier.stv-ligne-panier--tableau:not(:has(~ .stv-ligne-panier--tableau)) > :is(td, th) {
  padding-bottom: 0;
  border-bottom: 0;
}

.stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__media {
  padding-right: var(--stv-espace-16);
}

/* 0,3,0 : `.woocommerce img { height: auto }` (0,1,1) et la règle partagée, qui remplit sa boîte. */
.stv-ligne-panier--tableau .stv-ligne-panier__image.stv-ligne-panier__image {
  width: 80px;
  height: 80px;
}

/*
   16 avant la colonne des prix : la maquette colle la colonne du nom (288)
   à celle du prix, et un nom long (« Ecrou pour rail à ressort Very Light
   pour reformer ») touchait « 2,50€ » — relevé le 28/09 sur le jeu d'essai.
*/
.stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__produit {
  padding-right: var(--stv-espace-16);
}

.stv-ligne-panier--tableau .stv-ligne-panier__produit .stv-ligne-panier__nom {
  display: block;
}

.stv-ligne-panier--tableau .stv-ligne-panier__produit .stv-ligne-panier__declinaison {
  display: block;
  margin-top: var(--stv-espace-4);
}

.stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__total {
  text-align: right;
}

.stv-ligne-panier--tableau .stv-ligne-panier__bas .product-remove {
  display: flex;
  flex: 0 0 auto;
}

/*
   SOUS 1024 — PAS DE MAQUETTE (141.7, appliquée par défaut) : la rangée
   prend le dessin du tiroir, « une pile de lignes du tiroir ». Même
   balisage — donc un seul champ de quantité par ligne dans le formulaire —,
   placé en grille : vignette à gauche sur toute la hauteur ; en haut le
   produit et le total alignés sur leur ligne de base ; en bas le sélecteur
   et la corbeille. Carte grise à 16 de marge, 144 de haut au moins, 112
   de vignette ; 80 sous 768, comme le tiroir en mobile. Le prix unitaire
   n'y est pas (le tiroir ne le montre pas ; le total, lui, reste).

   Les rôles ARIA posés par le gabarit (`row`, `cell`, `rowheader`) gardent
   la sémantique du tableau que certains navigateurs retirent dès que
   l'affichage de ses éléments change.
*/
@media (max-width: 1024px) {
  .stv-ligne-panier.stv-ligne-panier--tableau {
    display: grid;
    grid-template-columns: 112px minmax(0, 1fr) auto;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "media produit total"
      "media quantite quantite";
    column-gap: var(--stv-espace-16);
    row-gap: var(--stv-espace-12);
    align-items: start;
    box-sizing: border-box;
    min-height: 144px;
    padding: var(--stv-espace-16);
    background: var(--stv-gris-clair);
  }

  .stv-ligne-panier.stv-ligne-panier--tableau > :is(td, th) {
    display: block;
    padding: 0;
    border: 0;
  }

  .stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__media {
    grid-area: media;
    align-self: center;
    width: 112px;
    height: 112px;
    padding: 0;
  }

  .stv-ligne-panier--tableau .stv-ligne-panier__image.stv-ligne-panier__image {
    width: 112px;
    height: 112px;
  }

  .stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__produit {
    grid-area: produit;
    align-self: baseline;
    min-width: 0;
    padding: 0;
  }

  .stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__unitaire {
    display: none;
  }

  .stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__total {
    grid-area: total;
    align-self: baseline;
  }

  .stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__quantite {
    grid-area: quantite;
    align-self: end;
  }
}

@media (max-width: 767px) {
  .stv-ligne-panier.stv-ligne-panier--tableau {
    grid-template-columns: 80px minmax(0, 1fr) auto;
    min-height: 0;
  }

  .stv-ligne-panier.stv-ligne-panier--tableau > .stv-ligne-panier__media {
    align-self: start;
    width: 80px;
    height: 80px;
  }

  .stv-ligne-panier--tableau .stv-ligne-panier__image.stv-ligne-panier__image {
    width: 80px;
    height: 80px;
  }
}

/* --- Mode « lecture » — la commande et la confirmation (146, 147 — 29/09) --- */

/*
   NON DESSINÉ (la colonne droite de la commande, `156:10839`, est une
   capture) : la rangée du mode tableau, sans rien à changer. Tranché le
   29/09 : vignette, nom, déclinaison, quantité, total. Une rangée `<tr>` de
   trois cellules dans le tableau des articles du récapitulatif
   (`.stv-recapitulatif__articles`) — écrite par `parties/ligne-panier.php`
   (commande, ligne de panier) et par `order/order-details-item.php`
   (confirmation et compte, ligne de commande), mêmes classes.

   Vignette 64 en `cover`, 16 jusqu'au produit ; nom Outfit 16 / 1,5 (sans
   lien dans la commande, avec lien sur une commande passée), déclinaison et
   données de ligne Outfit 14 à 80 % à 4, « Quantité : n » Inter 14
   anthracite à 4 ; total Inter 14 noir à droite. 16 entre deux rangées, un
   filet `--stv-filet-panier` entre elles ; ni marge ni filet aux bouts.

   POIDS : Hello habille `table td, th` (marge de 15, filet, fond une rangée
   sur deux à 0,1,4, `th` en 700) — cellules à 0,2,1 comme le mode tableau.
*/
.stv-recapitulatif .stv-recapitulatif__articles.stv-recapitulatif__articles {
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-collapse: collapse;
  border-spacing: 0;
  background: transparent;
  font-size: var(--stv-taille-petit);
  table-layout: auto;
}

.stv-ligne-panier.stv-ligne-panier--lecture {
  background: transparent;
}

.stv-ligne-panier.stv-ligne-panier--lecture > :is(td, th) {
  padding: var(--stv-espace-16) 0;
  border: 0;
  border-bottom: 1px solid var(--stv-filet-panier);
  background: transparent;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-align: left;
  vertical-align: middle;
}

.stv-ligne-panier.stv-ligne-panier--lecture:first-child > :is(td, th) {
  padding-top: 0;
}

.stv-ligne-panier.stv-ligne-panier--lecture:not(:has(~ .stv-ligne-panier--lecture)) > :is(td, th) {
  padding-bottom: 0;
  border-bottom: 0;
}

.stv-ligne-panier.stv-ligne-panier--lecture > .stv-ligne-panier__media {
  width: 64px;
  padding-right: var(--stv-espace-16);
}

.stv-ligne-panier--lecture .stv-ligne-panier__image.stv-ligne-panier__image {
  width: 64px;
  height: 64px;
}

.stv-ligne-panier.stv-ligne-panier--lecture > .stv-ligne-panier__produit {
  padding-right: var(--stv-espace-16);
}

.stv-ligne-panier--lecture .stv-ligne-panier__produit .stv-ligne-panier__nom {
  display: block;
}

.stv-ligne-panier--lecture .stv-ligne-panier__produit .stv-ligne-panier__declinaison,
.stv-ligne-panier--lecture .stv-ligne-panier__produit .stv-ligne-panier__quantite {
  display: block;
  margin-top: var(--stv-espace-4);
}

.stv-ligne-panier--lecture .stv-ligne-panier__produit .stv-ligne-panier__quantite {
  color: var(--stv-anthracite);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
}

/*
   Les données d'une ligne de COMMANDE : `wc_display_item_meta()` écrit une
   liste (`ul.wc-item-meta`, « Couleur : Noir ») — le dessin de la déclinaison.
*/
.stv-ligne-panier--lecture .stv-ligne-panier__produit .wc-item-meta {
  margin: var(--stv-espace-4) 0 0;
  padding: 0;
  color: var(--stv-texte-secondaire);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-petit);
  list-style: none;
}

.stv-ligne-panier--lecture .stv-ligne-panier__produit .wc-item-meta li {
  margin: 0;
}

.stv-ligne-panier--lecture .stv-ligne-panier__produit .wc-item-meta :is(strong, p) {
  display: inline;
  margin: 0;
  font-weight: 400;
}

.stv-ligne-panier.stv-ligne-panier--lecture > .stv-ligne-panier__total {
  text-align: right;
  white-space: nowrap;
}

/* La note d'achat d'un produit (commande passée) : sous sa ligne, à l'encre de la mention. */
.stv-recapitulatif__articles .product-purchase-note > td {
  padding: 0 0 var(--stv-espace-16);
  border: 0;
  background: transparent;
  color: var(--stv-texte-mention);
  font-size: var(--stv-taille-petit);
}

/* =====================================================================
   FIL D'ÉTAPES DU TUNNEL — `stv-etapes` (tâche 143, 28/09)
   ---------------------------------------------------------------------
   `parties/fil-etapes.php`, maquette `156:10679` : « Panier › Passer la
   commande › Commande terminée », sur le panier, la commande et la
   confirmation.

   LE DESSIN EST CELUI DE `stv-ariane`, relevé au pixel (Inter Light 14
   noir, étape en cours Inter Regular à 50 %, chevron 4 × 8 à 8, 33 de
   haut) : le composant porte les classes `stv-ariane__*` et n'écrit ici
   que ce qui diffère. Une étape À VENIR n'est pas un lien — elle a le
   dessin d'un maillon sans en être un. En mobile, pas de fondu à droite ni
   de défilement : trois étapes tiennent à 393, et une étape à demi effacée
   se lirait comme une étape grisée.
   ================================================================== */

.stv-etapes .stv-etapes__etape {
  color: var(--stv-noir);
  font-weight: 300;
}

@media (max-width: 767px) {
  .stv-ariane.stv-etapes {
    overflow: visible;
    white-space: normal;
    -webkit-mask-image: none;
    mask-image: none;
  }

  .stv-etapes .stv-ariane__liste {
    flex-wrap: wrap;
    row-gap: var(--stv-espace-4);
  }

  .stv-etapes .stv-ariane__liste::after {
    content: none;
  }

  .stv-etapes .stv-etapes__etape {
    font-weight: 400;
  }
}

/* =====================================================================
   RÉCAPITULATIF DE COMMANDE — `stv-recapitulatif` (tâche 143, 28/09)
   ---------------------------------------------------------------------
   `woocommerce/cart/cart-totals.php`, maquette : le composant « Panier »
   `156:10738`, variantes « Frais calculés » `156:5564` et « Neutre »
   `156:5507`. La commande (145) le reprendra, le compte (150) en lecture ;
   le pied « Total estimé » du tiroir en est la version réduite.

   Carte `--stv-gris-clair` (le `lightGrey` des cartes produit), 528 de
   large, marge 32, écart 32 entre ses blocs : titre (Outfit 20), lignes,
   Alma (506 / 89), bouton (48), code promo (42). Lignes : libellé Inter 16
   anthracite, valeur Inter Medium 16 noir, 16 entre deux lignes, 32 avant
   le total ; « (dont … TVA) » en Inter 14 anthracite ; l'expédition empile
   à droite montant, méthode (14 anthracite), destination (Medium 14) à 8,
   puis « Modifier l'adresse » (Medium 14 souligné) à 12.

   LES TEXTES SONT ROGNÉS AUX CAPITALES dans la maquette (`text-box-trim`) :
   une ligne de 16 y fait 14, pas 24. Ici par la vraie propriété
   (`text-box-trim` / `text-box-edge`), et non par un interligne réduit
   comme la pagination : les montants, la méthode et l'adresse peuvent
   passer sur deux lignes, et un interligne de 12 les ferait se chevaucher.
   Sans la propriété (Firefox au 28/09), les boîtes gardent leur interligne
   de 1,5 : la carte s'allonge d'une dizaine de pixels par ligne, rien ne
   se chevauche.

   POIDS. woocommerce.css habille `.cart_totals` à 0,3,0 (flottant, 48 %),
   ses cellules à 0,3,2 (filet gris, 35 % de large), le bouton à 0,3,1
   (1,25 em, marge d'un em) ; Hello, `table`, `th`, `td` et les rangées
   impaires (0,1,4). D'où 0,4,0 sur la carte et 0,4,1 sur les cellules.
   ================================================================== */

.stv-recapitulatif.stv-recapitulatif.stv-recapitulatif.stv-recapitulatif {
  --stv-recapitulatif-largeur: 528px;
  --stv-recapitulatif-marge: var(--stv-espace-32);
  --stv-recapitulatif-ecart: var(--stv-espace-32);

  display: flex;
  flex-direction: column;
  gap: var(--stv-recapitulatif-ecart);
  box-sizing: border-box;
  float: none;
  width: 100%;
  max-width: var(--stv-recapitulatif-largeur);
  margin: 0;
  padding: var(--stv-recapitulatif-marge);
  background: var(--stv-gris-clair);
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
}

/* `156:5566` : Outfit Regular 20, rogné aux capitales. Deux classes : le kit écrit sur `h2` à 0,1,1. */
.stv-recapitulatif .stv-recapitulatif__titre {
  margin: 0;
  color: var(--stv-noir);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-carte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  letter-spacing: 0;
  text-transform: none;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

/* --- Les lignes ----------------------------------------------------- */

.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes.stv-recapitulatif__lignes {
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-collapse: collapse;
  border-spacing: 0;
  background: transparent;
  font-size: var(--stv-taille-texte);
  table-layout: auto;
}

/*
   Une ligne fait 14 (`156:5569`) : la hauteur est posée, le texte rogné
   centré dedans. `content-box` : Hello met tout en `border-box`, et la
   marge haute de 16 mangerait alors la hauteur.
*/
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes.stv-recapitulatif__lignes :is(th, td) {
  box-sizing: content-box;
  height: 14px;
  padding: var(--stv-espace-16) 0 0;
  border: 0;
  background: transparent;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-align: right;
  vertical-align: middle;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes.stv-recapitulatif__lignes th {
  width: 1%;
  padding-right: var(--stv-espace-16);
  color: var(--stv-anthracite);
  font-weight: 400;
  text-align: left;
  white-space: nowrap;
}

.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes.stv-recapitulatif__lignes tr:first-child > * {
  padding-top: 0;
}

/* Le total à 32 de ce qui le précède (`156:5567` : deux groupes à 32). */
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes.stv-recapitulatif__lignes tr.order-total > * {
  padding-top: var(--stv-recapitulatif-ecart);
}

/* « 2954,90€ (dont 7,50€ TVA) » : le montant en Medium 16, la mention en Regular 14 anthracite. */
.stv-recapitulatif .stv-recapitulatif__lignes .order-total strong {
  font-weight: 500;
}

/* 0,4,1 : woocommerce.css grise les `small` du tableau des totaux (`#767676`) à 0,3,2 — mesuré le 28/09. */
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes small.includes_tax {
  color: var(--stv-anthracite);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
}

.stv-recapitulatif .stv-recapitulatif__lignes small.includes_tax .amount {
  font-weight: 400;
}

/* Le code promo appliqué : « -10,00€ » puis le lien de retrait natif, en lien texte du site. */
.stv-recapitulatif .stv-recapitulatif__lignes a.woocommerce-remove-coupon {
  margin-left: var(--stv-espace-8);
  color: var(--stv-noir);
  font-size: var(--stv-taille-petit);
  font-weight: 500;
  text-decoration: underline;
  text-underline-position: from-font;
}

/* --- L'expédition --------------------------------------------------- */

/* Le libellé en haut de sa ligne, la colonne de droite empilée (`156:5572`, `items-start`). */
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes.stv-recapitulatif__lignes .stv-recapitulatif__expedition-ligne > * {
  height: auto;
  vertical-align: top;
}

.stv-recapitulatif .stv-recapitulatif__expedition {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--stv-espace-12);
}

.stv-recapitulatif .stv-recapitulatif__expedition-detail {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--stv-espace-8);
}

.stv-recapitulatif .stv-recapitulatif__expedition :is(p, .stv-recapitulatif__expedition-detail > *) {
  margin: 0;
  text-align: right;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

.stv-recapitulatif .stv-recapitulatif__expedition-montant {
  font-size: var(--stv-taille-texte);
  font-weight: 500;
}

/*
   Le nom de la méthode — et ce que Flexible Shipping écrit dessous au
   crochet `woocommerce_after_shipping_rate` : la description de la méthode
   (« Livraison Standard France Continentale », saisie dans ses réglages),
   en `p.shipping-method-description`. C'est ce texte que la maquette montre
   à cette place ; les deux se lisent donc de la même encre.
*/
.stv-recapitulatif .stv-recapitulatif__expedition-nom,
.stv-recapitulatif .stv-recapitulatif__expedition .shipping-method-description,
.stv-recapitulatif .stv-recapitulatif__expedition-message,
.stv-recapitulatif .stv-recapitulatif__expedition-colis {
  color: var(--stv-anthracite);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
}

.stv-recapitulatif .stv-recapitulatif__expedition-destination {
  font-size: var(--stv-taille-petit);
  font-weight: 500;
}

/* Plusieurs méthodes (non dessiné) : la liste native, alignée à droite. 1,2,1 : woocommerce.css vise `ul#shipping_method li` à 1,1,2. */
.stv-recapitulatif #shipping_method.stv-recapitulatif__methodes {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--stv-espace-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-recapitulatif #shipping_method.stv-recapitulatif__methodes li {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-8);
  margin: 0;
  padding: 0;
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-indent: 0;
}

.stv-recapitulatif #shipping_method.stv-recapitulatif__methodes li input {
  margin: 0;
}

.stv-recapitulatif #shipping_method.stv-recapitulatif__methodes .stv-recapitulatif__methode-montant,
.stv-recapitulatif #shipping_method.stv-recapitulatif__methodes .amount {
  font-weight: 500;
}

/*
   Le calculateur : « Modifier l'adresse » / « Calculer les frais
   d'expédition » (`156:5579`, `156:5517`), Inter Medium 14 noir souligné.
   woocommerce.css pose sur ce lien un flottant, une marge et une icône
   (`::after`) à 0,3,0 et 0,3,1.
*/
/*
   LE FORMULAIRE A SA RANGÉE (`tr.stv-recapitulatif__calcul`, les deux
   colonnes) : fermé, elle ne mesure rien ; ouvert, les champs prennent la
   largeur de la carte, à 24 de ce qui précède. Sa cellule échappe à la
   hauteur de 14 et au rognage des lignes.
*/
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__lignes.stv-recapitulatif__lignes tr.stv-recapitulatif__calcul > td {
  height: auto;
  padding: 0;
  text-align: left;
  text-box-trim: none;
}

.stv-recapitulatif .stv-calculateur {
  display: block;
  width: 100%;
  margin: 0;
}

.stv-recapitulatif.stv-recapitulatif .shipping-calculator-button.shipping-calculator-button {
  display: inline-block;
  float: none;
  margin: 0;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-decoration: underline;
  text-underline-position: from-font;
  text-box-trim: trim-both;
  text-box-edge: cap alphabetic;
}

.stv-recapitulatif.stv-recapitulatif .shipping-calculator-button.shipping-calculator-button::after {
  content: none;
  display: none;
}

.stv-recapitulatif.stv-recapitulatif .shipping-calculator-button.shipping-calculator-button:hover,
.stv-recapitulatif.stv-recapitulatif .shipping-calculator-button.shipping-calculator-button:focus-visible {
  color: var(--stv-anthracite);
}

/*
   Le formulaire ouvert — NON DESSINÉ (142) : les champs habillés du § 9 du
   socle, sur toute la largeur de la colonne, texte à gauche. Pas de
   `display` ici : cart.js ouvre et ferme la section en écrivant le sien.
*/
.stv-recapitulatif.stv-recapitulatif .shipping-calculator-form.stv-calculateur__formulaire {
  box-sizing: border-box;
  width: 100%;
  margin: 0;
  padding-top: var(--stv-espace-24);
  text-align: left;
}

.stv-recapitulatif .stv-calculateur__envoi {
  flex: 1 1 100%;
  margin: 0;
}

/* --- Alma, le bouton ------------------------------------------------ */

.stv-recapitulatif.stv-recapitulatif .wc-proceed-to-checkout {
  display: flex;
  flex-direction: column;
  gap: var(--stv-recapitulatif-ecart);
  margin: 0;
  padding: 0;
}

/*
   woocommerce.css pose sur `.wc-proceed-to-checkout` le « clearfix » de ses
   flottants (`::before` / `::after`, `display: table`) : dans un flex,
   ce sont deux enfants de plus, et deux écarts de 32 — mesuré le 28/09,
   Alma à 64 des lignes au lieu de 32, le code promo à 64 du bouton.
*/
.stv-recapitulatif.stv-recapitulatif .wc-proceed-to-checkout::before,
.stv-recapitulatif.stv-recapitulatif .wc-proceed-to-checkout::after {
  content: none;
  display: none;
}

/*
   L'emplacement Alma (`156:5583`, 506 × 89 à pleine largeur) : le cadre
   réservé quand l'extension est absente (inc/tunnel.php, décision du
   15/09), le conteneur de l'extension quand elle est active
   (`.alma-cart-eligibility`, lu dans son code 6.5.0). Vide et sans
   `alma-default-widget` — widget panier désactivé dans ses réglages —, il
   est masqué : il coûterait un écart de 32. Rendu du widget réel vu le
   07/11 sur staging : voir « Alma, le widget » plus bas.
*/
.stv-recapitulatif .stv-alma.stv-alma--panier,
.stv-recapitulatif .alma-cart-eligibility.alma-default-widget,
.stv-recapitulatif .alma-cart-eligibility.alma-widget-excluded {
  box-sizing: border-box;
  width: 100%;
  margin: 0;
  background: var(--stv-blanc);
}

.stv-recapitulatif .stv-alma.stv-alma--panier {
  display: grid;
  place-items: center;
  aspect-ratio: 506 / 89;
  padding: var(--stv-espace-12) var(--stv-espace-16);
  color: var(--stv-texte-tertiaire);
  font-size: var(--stv-taille-petit);
  line-height: var(--stv-interligne-texte);
  text-align: center;
}

.stv-recapitulatif .alma-cart-eligibility:not(.alma-default-widget):not(.alma-widget-excluded) {
  display: none;
}

/* Même bande de 10 que sur la fiche (fiche-produit.css, tâche 74). */
.stv-recapitulatif .alma-cart-eligibility.alma-default-widget {
  padding-bottom: 0;
}

/* --- Alma, le widget et sa fenêtre (fiche et panier) ----------------- */

/*
   Vu le 07/11 sur staging (Alma active en mode test, fiche R8-PRO et
   panier) : les boutons du widget sortaient anthracite, texte blanc,
   bordure rose, et « 2x / 3x / 4x » coupés. Deux feuilles habillent TOUS
   les `<button>` de la page : le kit Elementor
   (`.elementor-kit-45589 button`, 0,1,1 : fond, couleur, 12 × 24 de
   marge intérieure, Inter 16) et reset.css de Hello (`button`,
   `[type="button"]` : bordure `#c36`). Les classes du widget Alma 4.x
   (widgets.min.css, CDN jsDelivr en `@4.x.x`) pèsent 0,1,0 : elles
   perdent, et ses boutons de 24 de haut gardent 24 de marge.

   On rétablit ses valeurs sous l'identifiant de son conteneur (1,0,1 et
   plus). Ses classes sont hachées (`_planButton_145uq_29`) et changent à
   chaque version : on ne s'appuie que sur ses classes stables
   (`alma-payment-plans-*`) et sur des fragments de nom
   (`[class*="_monochrome_"]`). Couleurs : celles du widget, pas nos
   jetons. Une nouvelle version du widget peut demander de revoir ce bloc.

   Piège de mesure : le kit pose une transition de 0,3 s ; un
   `getComputedStyle` lu juste après un changement rend l'ancienne couleur.
*/
#alma-widget-payment-plans-main-container button {
  font-family: Venn, sans-serif;
  font-size: 12px;
  font-weight: 700;
  line-height: normal;
  letter-spacing: normal;
  text-transform: none;
  color: #1a1a1a;
  background: transparent;
  border: 0;
  border-radius: 4px;
  padding: 2px 10px;
  width: auto;
  box-shadow: none;
}

/* La formule affichée : orange Alma, noir en monochrome (réglage actuel). */
#alma-widget-payment-plans-main-container button.alma-payment-plans-active-option {
  color: #fff;
  background: #fa5022;
}

#alma-widget-payment-plans-main-container button.alma-payment-plans-active-option[class*="_monochrome_"] {
  background: #1a1a1a;
}

#alma-widget-payment-plans-main-container button.alma-payment-plans-active-option[class*="_notEligible_"] {
  color: #4a4a4a;
  background: #fff;
}

/* Le logo « Alma » : le bouton « en savoir plus ». */
#alma-widget-payment-plans-main-container button.alma-payment-plans-know-more-action {
  padding: 3px;
  border-radius: 0;
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

/*
   La fenêtre « Cliquez pour en savoir plus » (vue le 07/11 par Logan) :
   Alma l'ajoute en fin de page (`.ReactModalPortal`), hors du conteneur
   ci-dessus, et le kit l'habille de même — 2x / 4x anthracite sous un
   texte noir (illisibles), « × » à bordure rose, liens des mentions en
   16 au lieu de 10 (`.elementor-kit-45589 a`). Son contenu a un
   identifiant stable, `#alma-widget-modal-main-container`.
   Le cadre orange autour de la fenêtre ou de l'échéancier après un
   choix est le contour de focus d'Alma (`:focus`, `tabindex="-1"`) :
   voulu par Alma pour le clavier, laissé tel quel.
*/
#alma-widget-modal-main-container #payment-plans > button {
  height: 50px;
  min-width: 50px;
  margin: 0;
  padding: 0;
  font-family: Argent, sans-serif;
  font-size: 20px;
  font-weight: 600;
  line-height: 120%;
  letter-spacing: normal;
  text-transform: none;
  color: #1a1a1a;
  background: #fff;
  border: 1px solid #4a4a4a;
  border-radius: 16px;
  box-shadow: none;
}

#alma-widget-modal-main-container #payment-plans > button.alma-eligibility-modal-active-option {
  color: #fff;
  background: #fa5022;
  border: 0;
}

#alma-widget-modal-main-container button.alma-eligibility-modal-close-button {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
  padding: 4px;
  color: #fff;
  background: #1a1a1a;
  border: 0;
  border-radius: 50%;
  box-shadow: none;
}

#alma-widget-modal-main-container a[class*="_disclaimerLink_"] {
  font: inherit;
  color: inherit;
  text-decoration: none;
}

/*
   « Valider la commande » (`156:5584`) : le bouton primaire, pleine
   largeur, 48. 0,5,1 : woocommerce.css écrit
   `.woocommerce-cart .wc-proceed-to-checkout a.checkout-button` à 0,3,1
   (bloc, 1,25 em, marge basse d'un em, marge intérieure d'un em).
*/
.stv-recapitulatif.stv-recapitulatif .wc-proceed-to-checkout a.checkout-button.stv-bouton {
  display: flex;
  box-sizing: border-box;
  width: 100%;
  min-height: var(--stv-bouton-hauteur);
  margin: 0;
  padding: var(--stv-bouton-padding);
  font-size: var(--stv-taille-texte);
}

/* --- Le code promo (141.4) ----------------------------------------- */

/*
   `156:5585` : une barre blanche de 42, filet de champ, 12 à gauche et 6 à
   droite ; « Code promo » en Inter 16 anthracite — l'indication du champ,
   le libellé est présent pour les lecteurs d'écran (une barre, comme
   l'infolettre du pied, pas un formulaire de page) — ; « Valider » en Inter
   Medium 16, anthracite à 50 % sur anthracite à 20 %, 12 / 2.

   Le dessin est l'état AU REPOS, champ vide. Rempli, le bouton passe au
   primaire : non dessiné (142), provisoire — un bouton grisé qui répond se
   lirait comme inactif.

   L'erreur (« Code promo invalide… ») est écrite par cart.js dans la boîte
   `.coupon`, sous la barre ; `panier-page.js` la remet après que cart.js a
   re-rendu le récapitulatif.
*/
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__coupon {
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-8);
  float: none;
  margin: 0;
  padding: 0;
}

.stv-recapitulatif .stv-recapitulatif__coupon-barre {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-12);
  box-sizing: border-box;
  min-height: 42px;
  padding: 0 var(--stv-espace-6) 0 var(--stv-espace-12);
  border: 1px solid var(--stv-filet-champ);
  background: var(--stv-blanc);
}

.stv-recapitulatif .stv-recapitulatif__coupon-barre:focus-within {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: 2px;
}

.stv-recapitulatif .stv-recapitulatif__coupon-barre:has([aria-invalid="true"]) {
  border-color: var(--stv-message-erreur);
  box-shadow: inset 0 0 0 1px var(--stv-message-erreur);
}

/* 0,5,0 : le kit écrit les champs à 0,3,1, Hello à 0,1,1. */
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__coupon .stv-recapitulatif__coupon-champ.input-text {
  flex: 1 1 auto;
  box-sizing: border-box;
  min-width: 0;
  height: 40px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  outline: 0;
  color: var(--stv-anthracite);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
}

.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__coupon .stv-recapitulatif__coupon-champ.input-text::placeholder {
  color: var(--stv-anthracite);
  opacity: 1;
}

.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__coupon .stv-recapitulatif__coupon-bouton {
  flex: 0 0 auto;
  margin: 0;
  padding: 2px var(--stv-espace-12);
  border: 0;
  border-radius: 0;
  background: rgba(36, 38, 46, 0.2);
  color: var(--stv-texte-indication);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-transform: none;
  cursor: pointer;
}

.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__coupon-barre:has(.stv-recapitulatif__coupon-champ:not(:placeholder-shown)) .stv-recapitulatif__coupon-bouton,
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__coupon .stv-recapitulatif__coupon-bouton:hover,
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__coupon .stv-recapitulatif__coupon-bouton:focus-visible {
  background: var(--stv-anthracite);
  color: var(--stv-blanc);
}

.stv-recapitulatif.stv-recapitulatif .coupon-error-notice {
  margin: 0;
  padding: 0;
  color: var(--stv-message-erreur);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-align: left;
}

/* --- La commande et la lecture (146, 147 — 29/09) ------------------ */

/*
   LA COMMANDE (`stv-recapitulatif--commande`, checkout/form-checkout.php) :
   la carte porte le titre « Votre commande » puis `#order_review`, qui
   contient les deux fragments que checkout.js re-rend — articles et totaux
   (`.stv-recapitulatif__revue`), paiement (`#payment`, commande.css). Même
   écart de 32 entre eux qu'entre les blocs de la carte.

   LA LECTURE (`stv-recapitulatif--lecture`, order/order-details.php) : la
   confirmation et « Voir la commande » du compte — titre, articles, totaux
   de la commande, actions (payer, annuler).
*/
.stv-recapitulatif.stv-recapitulatif .stv-commande__revue,
.stv-recapitulatif.stv-recapitulatif .stv-recapitulatif__revue {
  display: flex;
  flex-direction: column;
  gap: var(--stv-recapitulatif-ecart);
  margin: 0;
}

/* Sans adresse complète : « Selon l'adresse de livraison », comme le nom d'une méthode. */
.stv-recapitulatif .stv-recapitulatif__attente {
  color: var(--stv-anthracite);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
}

/*
   Les valeurs d'une commande passée sont du TEXTE autant que des montants
   (« 8,90€ via Livraison Standard France », « Virement bancaire ») : elles
   passent à la ligne, alignées à droite, sans rognage — la hauteur posée de
   14 n'est qu'un minimum pour une cellule de tableau.
*/
.stv-recapitulatif--lecture .stv-recapitulatif__lignes td small.shipped_via {
  color: var(--stv-anthracite);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
}

.stv-recapitulatif .stv-recapitulatif__actions-commande {
  display: flex;
  flex-wrap: wrap;
  gap: var(--stv-espace-12);
  margin: 0;
}

.stv-recapitulatif .stv-recapitulatif__actions-commande .stv-bouton {
  flex: 1 1 auto;
}

/*
   SOUS 1024 — non dessiné : la carte passe sous les articles, à toute la
   largeur ; marge 24 sous 768 (celle de la carte blanche en mobile).
*/
@media (max-width: 1024px) {
  .stv-recapitulatif.stv-recapitulatif.stv-recapitulatif.stv-recapitulatif {
    --stv-recapitulatif-largeur: none;
  }
}

@media (max-width: 767px) {
  .stv-recapitulatif.stv-recapitulatif.stv-recapitulatif.stv-recapitulatif {
    --stv-recapitulatif-marge: var(--stv-espace-24);
  }
}

/* =====================================================================
   CARTE ÉDITORIALE — « Product CTA » (tâche 98, 24/09 ; deux usages
   depuis le 28/09)
   Relevé Dev Mode `156:9082` (desktop, dans la grille du catalogue) et
   `156:7314` (mobile) ; `156:9944` (colonne de droite de l'article,
   384 × 320) — la MÊME instance Figma.

   DÉPLACÉE DEPUIS catalogue.css LE 28/09 (lot « Article ») : la carte
   promo de l'article est ce composant, et catalogue.css n'est chargée
   que sur les archives de produit. Règles reprises telles quelles, aux
   mêmes comptes — `.stv-carte-editoriale.stv-carte-editoriale` (0,2,0)
   remplace `.stv-grille-produits .stv-carte-editoriale` (0,2,0) — ; seule
   la PROPORTION devient une variable, 402 / 449 par défaut (la grille),
   384 / 320 dans l'article (article.css). Non-régression mesurée sur
   Pilates le 28/09.

   Le dessin (relevé du 24/09) : photo en `cover`, voile NOIR — pas le
   bleu pétrole de `--stv-voile-bandeau` : .05 en haut, .5 à 70 %, .8 en
   bas, là où le texte se pose. 16 au-dessus du contenu, 24 sur les côtés
   et dessous, contenu calé en bas et centré ; titre Outfit Medium 24 à
   1,15 blanc, 24 plus bas « Apprenez comment » en Inter 16 et la flèche
   de 20 × 8 à 8. Le relevé de `156:9944` (28/09) donne le même voile, les
   mêmes marges, le titre à 1,5 — écart assumé : 1,15, celui de la grille.

   ÉCART AU PROTOCOLE : il annonçait « un seul jeu de règles photo +
   voile + texte blanc » sur `--stv-voile-bandeau`. Le relevé Dev Mode
   donne un autre voile, noir et plus appuyé. Vu deux fois maintenant, sur
   la même instance : la variable reste celle du composant.

   Deux classes au moins partout : le kit Elementor écrit sur `a` à 0,1,1
   quand une section Elementor est sur la page (zone d'injection), et le
   `theme.css` de Hello souligne `.page-content a` au même poids.
   ================================================================== */

.stv-carte-editoriale.stv-carte-editoriale {
  --stv-carte-editoriale-voile: linear-gradient(
    180deg,
    rgba(2, 10, 18, 0.05) 0%,
    rgba(2, 10, 18, 0.5) 70%,
    rgba(2, 10, 18, 0.8) 100%
  );
  --stv-carte-editoriale-rapport: 402 / 449;

  position: relative;
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: var(--stv-carte-editoriale-rapport);
  overflow: hidden;
  padding: var(--stv-espace-16) var(--stv-espace-24) var(--stv-espace-24);
  background: var(--stv-noir);
  color: var(--stv-blanc);
  text-decoration: none;
}

.stv-carte-editoriale.stv-carte-editoriale::before {
  content: "";
  position: absolute;
  z-index: 1;
  inset: 0;
  background: var(--stv-carte-editoriale-voile);
  pointer-events: none;
}

/* Trois classes, comme avant (0,3,0) : `.woocommerce … img` pèse 0,1,1 et plus. */
.stv-carte-editoriale.stv-carte-editoriale .stv-carte-editoriale__image {
  position: absolute;
  z-index: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

.stv-carte-editoriale .stv-carte-editoriale__contenu {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--stv-espace-24);
  width: 100%;
  text-align: center;
}

.stv-carte-editoriale .stv-carte-editoriale__titre {
  display: block;
  width: 100%;
  color: var(--stv-blanc);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-intertitre);
  font-weight: 500;
  line-height: 1.15;
  text-wrap: balance;
}

/*
   « Apprenez comment » est rogné aux capitales dans la maquette
   (`text-box-trim`) : sa boîte fait 12 et non 24. Même geste que la
   pagination et le menu de tri — un interligne à la hauteur des
   capitales d'Inter (0,727 em, soit 11,6 à 16) — pour que les 24 au-dessus
   et au-dessous tombent là où la maquette les mesure.
*/
.stv-carte-editoriale .stv-carte-editoriale__action {
  display: inline-flex;
  align-items: center;
  gap: var(--stv-espace-8);
  color: var(--stv-blanc);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: 12px;
  white-space: nowrap;
}

/* Boîte de 20 × 8 dans la maquette, 20,75 × 8,75 avec le trait. */
.stv-carte-editoriale .stv-carte-editoriale__fleche {
  flex-shrink: 0;
  width: 20.75px;
  height: 8.75px;
  margin: -0.375px;
}

/* Survol et focus : NON DESSINÉS (88) — le libellé se souligne, provisoire. */
.stv-carte-editoriale.stv-carte-editoriale:hover .stv-carte-editoriale__libelle,
.stv-carte-editoriale.stv-carte-editoriale:focus-visible .stv-carte-editoriale__libelle {
  text-decoration: underline;
  text-underline-position: from-font;
}

.stv-carte-editoriale.stv-carte-editoriale:focus-visible {
  outline: 2px solid var(--stv-blanc);
  outline-offset: -6px;
}

/* Mobile (156:7326, 156:7433) : 353 / 382 dans la grille, titre à 20. */
@media (max-width: 767px) {
  .stv-carte-editoriale.stv-carte-editoriale {
    --stv-carte-editoriale-rapport: 353 / 382;
  }

  .stv-carte-editoriale .stv-carte-editoriale__titre {
    font-size: var(--stv-taille-carte);
    line-height: 1.3;
  }
}

/* =====================================================================
   FIL D'ARIANE DES ARCHIVES — `stv-ariane` (tâche 89, 24/09)
   Relevé Dev Mode `156:6671` (racine), `156:9033` (niveau 1),
   `156:10194` (niveau 3), `156:7193` (mobile).

   Le fil « Tous les produits › … » du catalogue, des catégories et des
   marques (87.8 : sans « Accueil »). Il vit ICI et non dans
   catalogue.css parce qu'il est partagé : la page Nos marques et le blog
   (« Blog › Catégorie › Titre ») ont la même forme.

   Ce n'est PAS le fil de la fiche (`.stv-fil`, fiche-produit.css) : lui
   vient de Yoast ou de WooCommerce, écrit son séparateur en texte et
   part de l'accueil. La consigne du lot était de ne pas y toucher. Deux
   balisages pour un même dessin : l'écart est noté dans le relevé du
   24/09, à résorber quand 87.8 sera tranchée pour la fiche aussi.

   Maillons Inter Light 14 en noir plein, dernier maillon Inter Regular
   14 à 50 % ; chevron de 4 × 8 en noir, à 8 de chaque texte ; 8 au-dessus
   et au-dessous (33 de haut en tout, interligne `normal`).
   ================================================================== */

.stv-ariane {
  padding-block: var(--stv-espace-8);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  line-height: normal;
}

.stv-ariane .stv-ariane__liste {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-ariane .stv-ariane__maillon {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--stv-espace-8);
  margin: 0;
}

/*
   Deux classes : le kit écrit sur `a` à 0,1,1 — taille, graisse et
   interligne, relevé sur le fil de la fiche le 15/09. Et la taille est
   REDÉCLARÉE sur le lien : une valeur héritée perd contre n'importe
   quelle déclaration qui vise `a` directement.
*/
.stv-ariane .stv-ariane__lien {
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 300;
  line-height: normal;
  text-decoration: none;
}

.stv-ariane .stv-ariane__lien:hover,
.stv-ariane .stv-ariane__lien:focus-visible {
  text-decoration: underline;
}

.stv-ariane .stv-ariane__courant {
  color: var(--stv-texte-tertiaire);
  font-weight: 400;
}

/*
   Le chevron : dessiné dans une boîte de 4 × 8 (156:10196), exporté en
   5 × 9 avec son trait. La marge négative rend à la mise en page la
   boîte de la maquette, et l'écart de 8 tombe juste.
*/
.stv-ariane .stv-ariane__chevron {
  flex-shrink: 0;
  width: 5px;
  height: 9px;
  margin: -0.5px;
  color: var(--stv-noir);
}

/*
   MOBILE — relevé `156:7193` : 12 px, pas de marge verticale (15 de
   haut), et le même parti que le fil de la fiche : une seule ligne qui
   glisse sous le doigt, fondue à droite par un masque, plutôt qu'un fil
   replié sur deux lignes. Regular partout : à 12 px, le Light ne tient
   plus le contraste (même arbitrage que la fiche, 15/09).
*/
@media (max-width: 767px) {
  .stv-ariane {
    padding-block: 0;
    font-size: var(--stv-taille-copyright);
    white-space: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, #000 81.6%, transparent);
    mask-image: linear-gradient(to right, #000 81.6%, transparent);
  }

  .stv-ariane::-webkit-scrollbar {
    display: none;
  }

  /* L'espace de fin : un conteneur qui défile ignore sa marge droite. */
  .stv-ariane .stv-ariane__liste::after {
    content: "";
    flex-shrink: 0;
    width: var(--stv-espace-24);
    height: 1px;
  }

  .stv-ariane .stv-ariane__lien {
    font-size: var(--stv-taille-copyright);
    font-weight: 400;
  }
}

/* =====================================================================
   PAGINATION — `stv-pagination` (tâche 93, 24/09)
   Relevé Dev Mode `156:6749` (desktop) et `156:7238` (mobile), identiques.

   UN SEUL CSS DE PAGINATION pour le catalogue (paginate_links(), rendue
   par inc/catalogue.php) et, demain, le Loop Grid d'Elementor du blog :
   les deux écrivent les mêmes classes — `page-numbers`, `current`,
   `prev`, `next`, `dots`. Les règles de chiffre ci-dessous ne visent que
   ces classes ; le blog n'aura à écrire que son conteneur, qui n'est pas
   une liste chez Elementor.

   Chiffres Inter Regular 14 en noir, à 12 l'un de l'autre, les flèches à
   24 des chiffres ; page courante soulignée d'un trait de 0,75 et 11 de
   long (le chiffre plus 1,5 de chaque côté), 15,27 sous le haut des
   capitales ; flèches inactives à 40 % (l'opacité est dans le tracé
   exporté de la flèche « précédente » en page 1).

   L'INTERLIGNE VAUT 10 PX, et c'est voulu. La maquette rogne la boîte du
   texte à la hauteur des capitales (`text-box-trim`, 10 de haut). Pour
   Inter, un interligne de 10 px met le haut de la boîte à 0,1 px du haut
   des capitales et la ligne de base à 10,1 : la boîte de mise en page EST
   celle de la maquette, sans `text-box-trim` — que Firefox ne connaît
   pas. Les jambages dépassent de la boîte sans être coupés.
   ================================================================== */

.stv-pagination .stv-pagination__liste {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--stv-espace-12);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-pagination .stv-pagination__liste > li {
  display: flex;
  align-items: center;
  margin: 0;
}

/*
   Les flèches à 24 des chiffres : 12 d'écart de liste + 12 ici. Le
   sélecteur nomme la liste : la règle des éléments, juste au-dessus,
   pèse 0,2,1 et remettait la marge à zéro — mesuré le 24/09, 12 au lieu
   de 24 des deux côtés.
*/
.stv-pagination .stv-pagination__liste > .stv-pagination__precedent {
  margin-inline-end: var(--stv-espace-12);
}

.stv-pagination .stv-pagination__liste > .stv-pagination__suivant {
  margin-inline-start: var(--stv-espace-12);
}

/*
   Deux classes : le kit écrit sur `a` à 0,1,1. Les liens gagnent une zone
   de clic de 26 de haut par une marge intérieure que la marge négative
   rend aussitôt : la boîte de mise en page reste celle de la maquette.
*/
.stv-pagination .page-numbers {
  position: relative;
  display: block;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: 10px;
  text-decoration: none;
}

.stv-pagination a.page-numbers {
  margin: calc(-1 * var(--stv-espace-8)) calc(-1 * var(--stv-espace-4));
  padding: var(--stv-espace-8) var(--stv-espace-4);
}

.stv-pagination a.page-numbers:hover,
.stv-pagination a.page-numbers:focus-visible {
  text-decoration: underline;
  text-decoration-thickness: 0.75px;
  text-underline-offset: 5px;
}

/* La page courante : le trait de la maquette (156:6755), pas un soulignement de texte. */
.stv-pagination .page-numbers.current::after {
  content: "";
  position: absolute;
  top: 15.25px;
  left: -1.5px;
  right: -1.5px;
  height: 0.75px;
  background: currentColor;
}

/*
   Les flèches : dessinées dans une boîte de 5 × 10, exportées en 6 × 11
   avec leur trait ; la marge négative rend la boîte de la maquette.
*/
.stv-pagination .stv-pagination__fleche {
  display: block;
  width: 6px;
  height: 11px;
  margin: -0.5px;
}

.stv-pagination .stv-pagination__inactif {
  opacity: 0.4;
}


/* =====================================================================
   PUCES DE FILTRE — `stv-puces` (tâche 117, lot Blog du 28/09)
   Relevé Dev Mode `156:9415` (desktop) et `156:8112` (mobile).

   Une rangée de liens qui passent à la ligne, à 12 l'un de l'autre ;
   chaque puce 16 / 8 de marge intérieure, Inter Regular 16 sur le gris
   de la pastille (`--stv-pastille`, bleu pétrole à 10 %), texte bleu
   pétrole. La puce ACTIVE (« Tous » dans la maquette) est bleu pétrole
   plein, texte blanc : c'est `aria-current="page"` qui la désigne — le
   CSS et le lecteur d'écran lisent le même attribut.

   L'INTERLIGNE VAUT 12 PX, comme les 10 de la pagination pour Inter 14 :
   la maquette rogne la boîte du texte aux capitales (12 de haut pour
   Inter 16), la puce fait 8 + 12 + 8 = 28. Les jambages débordent de la
   boîte sans être coupés.

   Rendue par `stelvoren_blog_puces_html()` (inc/blog.php) sur `/blog/`
   et ses archives ; blog.js suit les liens sans recharger. Le survol
   n'est pas dessiné (fiche 115) : bleu pétrole à 20 %, provisoire.
   ================================================================== */

.stv-puces .stv-puces__liste {
  display: flex;
  flex-wrap: wrap;
  gap: var(--stv-espace-12);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-puces .stv-puces__liste > li {
  margin: 0;
}

/* Deux classes : le kit écrit sur `a` à 0,1,1, Hello souligne `.page-content a` à 0,1,1. */
.stv-puces .stv-puces__puce {
  display: block;
  padding: var(--stv-espace-8) var(--stv-espace-16);
  background: var(--stv-pastille);
  color: var(--stv-bleu-petrole);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: 12px;
  text-decoration: none;
  white-space: nowrap;
}

.stv-puces .stv-puces__puce:hover {
  background: rgba(0, 29, 61, 0.2);
}

.stv-puces .stv-puces__puce:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

.stv-puces .stv-puces__puce[aria-current] {
  background: var(--stv-bleu-petrole);
  color: var(--stv-blanc);
}


/* =====================================================================
   ACCORDÉON — variante « plus » (`stv-faq--plus`) — ajoutée le 24/09
   FAQ de catégorie (156:10128, mobile 156:7437), lot « Sections de
   catégorie » (101).

   LE MÊME ACCORDÉON QUE LA FICHE, UN AUTRE HABILLAGE. Même balisage
   (`<details>` / `<summary>`, rendu par `stelvoren_faq_html()`,
   inc/faq.php), autre dessin : filet anthracite à 20 % SOUS chaque
   question (aucun au-dessus de la première), 20 au-dessus et au-dessous
   de la question, un + de 24 à droite à 24 du texte, qui devient − à
   l'ouverture ; 24 entre la question et sa réponse. L'habillage de la
   fiche (chevron, filet bleuté des deux côtés) reste dans
   fiche-produit.css, qui ne se charge que sur la fiche : les deux ne se
   rencontrent jamais.

   Ici et non dans catalogue.css : c'est le dessin de la page FAQ aussi
   (156:9158, 132 → 135), à confirmer au relevé de cette page — la
   variante sera déjà chargée partout où elle servira.

   ÉCART : la question est en Inter SEMI-BOLD (600) dans la maquette. Le
   600 n'est pas livré (polices auto-hébergées 300 / 400 / 500) ; le
   navigateur le simulerait en graissant le 500 à la main. 500, comme
   l'accordéon de la fiche — piège « graisses non livrées » du protocole.

   Le + et le − sont les tracés EXPORTÉS du Dev Mode (156:10139,
   156:10133), posés en MASQUE sur un aplat de `currentColor` : la couleur
   suit la question (noir du site ; #001233 dans le fichier Figma, la
   couleur de sa bibliothèque d'icônes). Le − est un contour de 0,98 de
   haut au trait de 1 — il est plein ici, ce qui revient au même à l'œil.

   Deux classes (0,2,0) partout : `reset.css` de Hello écrit sur `summary`
   à 0,0,1, le kit Elementor (présent quand une section Elementor est sur
   la page) sur `a` à 0,1,1 — les liens des réponses sont ceux de la
   prose du socle, à 0,3,1.
   ================================================================== */

.stv-faq--plus .stv-faq__question {
  margin: 0;
  border-bottom: 1px solid var(--stv-filet-liste);
}

.stv-faq--plus .stv-faq__resume {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--stv-espace-24);
  /* 20 au-dessus, 19 + le filet dessous : Figma dessine le filet À
     L'INTÉRIEUR des 64 de la question (156:10136, contour intérieur),
     une bordure CSS s'ajoute à la boîte. Mesuré le 24/09 : 65 avec 20 / 20. */
  padding: 20px 0 19px;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  list-style: none;
  cursor: pointer;
}

.stv-faq--plus .stv-faq__resume::-webkit-details-marker {
  display: none;
}

.stv-faq--plus .stv-faq__resume::after {
  content: "";
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M11.6638 3.74447C11.7799 3.62832 11.8864 3.59048 12.0001 3.59048C12.1136 3.59054 12.2197 3.62794 12.3357 3.74378C12.4518 3.85989 12.4896 3.96642 12.4897 4.08007V11.5102H12.9896L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894H12.4897V19.9195C12.4896 20.0332 12.4518 20.1397 12.3357 20.2558C12.2197 20.3717 12.1136 20.4091 12.0001 20.4091C11.8864 20.4091 11.7799 20.3713 11.6638 20.2551C11.5477 20.139 11.5098 20.0325 11.5098 19.9188V12.4901H11.0099L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095H11.5098V4.08076C11.5098 3.9671 11.5477 3.86057 11.6638 3.74447Z' fill='black' stroke='black'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M11.6638 3.74447C11.7799 3.62832 11.8864 3.59048 12.0001 3.59048C12.1136 3.59054 12.2197 3.62794 12.3357 3.74378C12.4518 3.85989 12.4896 3.96642 12.4897 4.08007V11.5102H12.9896L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894H12.4897V19.9195C12.4896 20.0332 12.4518 20.1397 12.3357 20.2558C12.2197 20.3717 12.1136 20.4091 12.0001 20.4091C11.8864 20.4091 11.7799 20.3713 11.6638 20.2551C11.5477 20.139 11.5098 20.0325 11.5098 19.9188V12.4901H11.0099L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095H11.5098V4.08076C11.5098 3.9671 11.5477 3.86057 11.6638 3.74447Z' fill='black' stroke='black'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
}

.stv-faq--plus .stv-faq__question[open] > .stv-faq__resume::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095L12.9896 11.5102L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894L11.0099 12.4901L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642Z' fill='black' stroke='black'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095L12.9896 11.5102L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894L11.0099 12.4901L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642Z' fill='black' stroke='black'/%3E%3C/svg%3E");
}

.stv-faq--plus .stv-faq__resume:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* 24 entre la question et la réponse (19 + 5), 19 + le filet sous la
   réponse : 160 pour la question ouverte de la maquette (156:10129). */
.stv-faq--plus .stv-faq__reponse {
  padding: 5px 0 19px;
}

/*
   LA QUATRIÈME SOURCE : LE WIDGET ACCORDÉON D'ELEMENTOR (05/10, tâche 127,
   FAQ de page des guides — 156:9664, mobile 156:8810).

   Une page éditée dans Elementor garde ses questions dans Elementor : le
   client les écrit dans le widget Accordéon (« nested-accordion », le seul
   que le panneau propose depuis Elementor 3.15), qui porte `stv-faq
   stv-faq--plus` dans ses Classes CSS. Son balisage est déjà un `<details>`
   natif — `details.e-n-accordion-item` > `summary.e-n-accordion-item-title`
   (la question dans `.e-n-accordion-item-title-text`) + le conteneur de la
   réponse —, le même objet que le nôtre sous d'autres classes. D'où le MÊME
   dessin qu'au-dessus, réécrit pour ce balisage plutôt qu'un second
   habillage : filet sous la question, 20 / 19, question Inter 500 16 noire,
   + / − de 24 en masque (les tracés exportés, ci-dessus), réponse à 24.

   L'ADVERSAIRE : widget-nested-accordion.min.css (relu le 05/10, Elementor
   4.2.2) — bordure de 1 px #d5d8dc tout autour du titre ET du conteneur de
   réponse, marge de 10, titre à 20 px, couleur #1f2124, le tout à 0,2,0 —
   et la marge intérieure de 10 de tout conteneur (`.e-con`). Trois classes
   ici (0,3,0), cinq sur le conteneur de réponse.

   Pas d'icône du widget : son réglage « Icône » est laissé vide dans la
   mise en page (aucune `.e-n-accordion-item-title-icon` n'est écrite) — le
   + / − est le `::after` du résumé, comme pour le `<details>` du thème.
   Le comportement est celui du widget (une question ouverte à la fois, la
   première ouverte à l'arrivée : réglages « Max Items Expanded : One » et
   « Default State : First expanded ») ; sans son script, le `<details>`
   natif s'ouvre et se ferme seul. Le FAQPage : inc/conseils.php.
*/
.stv-faq--plus.stv-faq--plus .e-n-accordion-item {
  margin: 0;
  border-bottom: 1px solid var(--stv-filet-liste);
}

.stv-faq--plus.stv-faq--plus .e-n-accordion-item > .e-n-accordion-item-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--stv-espace-24);
  margin: 0;
  padding: 20px 0 19px;
  border: 0;
  border-radius: 0;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  list-style: none;
  cursor: pointer;
}

.stv-faq--plus.stv-faq--plus .e-n-accordion-item-title-header,
.stv-faq--plus.stv-faq--plus .e-n-accordion-item-title-text {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  color: inherit;
  font: inherit;
  letter-spacing: normal;
  text-transform: none;
}

.stv-faq--plus.stv-faq--plus .e-n-accordion-item > .e-n-accordion-item-title::after {
  content: "";
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M11.6638 3.74447C11.7799 3.62832 11.8864 3.59048 12.0001 3.59048C12.1136 3.59054 12.2197 3.62794 12.3357 3.74378C12.4518 3.85989 12.4896 3.96642 12.4897 4.08007V11.5102H12.9896L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894H12.4897V19.9195C12.4896 20.0332 12.4518 20.1397 12.3357 20.2558C12.2197 20.3717 12.1136 20.4091 12.0001 20.4091C11.8864 20.4091 11.7799 20.3713 11.6638 20.2551C11.5477 20.139 11.5098 20.0325 11.5098 19.9188V12.4901H11.0099L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095H11.5098V4.08076C11.5098 3.9671 11.5477 3.86057 11.6638 3.74447Z' fill='black' stroke='black'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M11.6638 3.74447C11.7799 3.62832 11.8864 3.59048 12.0001 3.59048C12.1136 3.59054 12.2197 3.62794 12.3357 3.74378C12.4518 3.85989 12.4896 3.96642 12.4897 4.08007V11.5102H12.9896L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894H12.4897V19.9195C12.4896 20.0332 12.4518 20.1397 12.3357 20.2558C12.2197 20.3717 12.1136 20.4091 12.0001 20.4091C11.8864 20.4091 11.7799 20.3713 11.6638 20.2551C11.5477 20.139 11.5098 20.0325 11.5098 19.9188V12.4901H11.0099L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095H11.5098V4.08076C11.5098 3.9671 11.5477 3.86057 11.6638 3.74447Z' fill='black' stroke='black'/%3E%3C/svg%3E") center / 24px 24px no-repeat;
}

.stv-faq--plus.stv-faq--plus .e-n-accordion-item[open] > .e-n-accordion-item-title::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095L12.9896 11.5102L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894L11.0099 12.4901L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642Z' fill='black' stroke='black'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M3.74406 11.6642C3.86021 11.548 3.96664 11.5102 4.08035 11.5102L11.0099 11.5095L12.9896 11.5102L19.9191 11.5095C20.0328 11.5095 20.1393 11.5475 20.2554 11.6635C20.3716 11.7797 20.4094 11.8861 20.4094 11.9998C20.4094 12.1135 20.3716 12.2199 20.2554 12.3361C20.1393 12.4521 20.0328 12.4901 19.9191 12.4901L12.9896 12.4894L11.0099 12.4901L4.08035 12.4894C3.96664 12.4894 3.86021 12.4516 3.74406 12.3354C3.62812 12.2194 3.59076 12.1134 3.59076 11.9998C3.59076 11.8862 3.62812 11.7803 3.74406 11.6642Z' fill='black' stroke='black'/%3E%3C/svg%3E");
}

.stv-faq--plus.stv-faq--plus .e-n-accordion-item > .e-n-accordion-item-title:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* La réponse : le conteneur qui suit le résumé — sans bordure, sans la
   marge de 10 d'un conteneur Elementor, 5 dessus et 19 dessous comme
   `.stv-faq__reponse`. Cinq classes : devant `.e-con` et ses variantes. */
.stv-faq--plus.stv-faq--plus .e-n-accordion-item > .e-con.e-con {
  --gap: 0px;
  --row-gap: 0px;
  --column-gap: 0px;

  margin: 0;
  padding: 5px 0 19px;
  border: 0;
}


/* =====================================================================
   ONGLETS — `stv-onglets` — déplacés ici le 25/09 (lot FAQ, tâche 134)
   Fiche produit (118:5911 / 118:5749, tâche 77) et page FAQ (156:9164,
   variante `stv-onglets--sobre`).

   ILS VIVAIENT DANS fiche-produit.css, qui n'est chargé que sur la fiche :
   la page FAQ aurait rendu des onglets nus — le piège de la prose du
   21/09, à l'identique. Les valeurs de la fiche n'ont pas bougé ; elles
   sont passées en VARIABLES, parce que la FAQ reprend la même mécanique
   avec un autre dessin (une classe, des réglages). Même balisage partout
   (`stelvoren_onglets_html()`, inc/onglets.php), même script (onglets.js).

   Ce qui reste dans fiche-produit.css : la description sur deux colonnes,
   le tableau des attributs, les vidéos, l'accordéon et les avis.

   CORRIGÉ AU PASSAGE (mesuré sur la fiche le 25/09, « Tapis de yoga Studio
   Travel ») : une fois les onglets montés, le PREMIER panneau était à 48
   de la rangée et tous les autres à 0 — la règle qui ramenait à 0 l'écart
   entre panneaux empilés (`--monte … + …`, 0,3,0) écrasait aussi l'écart
   sous la rangée. Un panneau masqué par `hidden` ne prend aucune place :
   chacun garde donc simplement son écart, empilé ou monté.
   ================================================================== */

.stv-onglets {
  --stv-onglet-soulignement: 2px;                        /* 118:5914, border-b-2 */
  --stv-onglets-police: var(--stv-police-texte);         /* Inter (118:5913) */
  --stv-onglets-taille: var(--stv-taille-carte);         /* 20, 16 en mobile */
  --stv-onglets-couleur: var(--stv-onglet-inactif);      /* inactifs à 0,8 */
  --stv-onglets-couleur-actif: var(--stv-anthracite);
  --stv-onglets-graisse-actif: 500;                      /* Medium (118:5915) */
  --stv-onglets-soulignement-survol: transparent;
  --stv-onglets-filet: var(--stv-filet-onglets);         /* anthracite 40 % */
  --stv-onglets-bas: 6px;                                /* sous le texte, soulignement compris */
  --stv-onglets-ecart: var(--stv-espace-48);             /* rangée → panneau */
}

/* --- Sans script : des sections empilées --------------------------- */

/*
   Tant que onglets.js n'a pas monté la liste, la page se lit de haut en
   bas : la rangée d'onglets sert de sommaire (des liens vers des
   ancres), et chaque panneau garde son titre. Le montage ajoute
   `.stv-onglets--monte` : les titres de panneau disparaissent — l'onglet
   actif les dit déjà — et les panneaux inactifs portent `hidden`.
*/
.stv-onglets--monte .stv-onglets__titre {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.stv-onglets__titre {
  margin: 0 0 var(--stv-espace-24);
  font-size: var(--stv-taille-carte);
  font-weight: 500;
  line-height: var(--stv-interligne-titre);
}

.stv-onglets__panneau {
  margin-top: var(--stv-onglets-ecart);
}

.stv-onglets__panneau:focus-visible {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: var(--stv-espace-8);
}

/* --- La rangée ------------------------------------------------------- */

/*
   LA RANGÉE FAIT LA LARGEUR DE SES ONGLETS. Dans la maquette (`118:5913`)
   la rangée mesure 905 dans une carte de 1584 : son filet de 1 px
   s'arrête avec le dernier libellé, il ne court pas sur toute la carte.
   D'où `width: fit-content`. Sous l'onglet actif, le soulignement de
   2 px anthracite recouvre le filet — c'est la mécanique des onglets de
   l'accueil (« Explorez nos collections »), et celle demandée par Logan
   le 15/09. La FAQ dessine la même (156:9165 : 561 de large, filet
   dessous, trait de 2 sous « Mes commandes »).

   Le filet est une OMBRE INTÉRIEURE et non une bordure : en mobile la
   rangée défile (`overflow-x: auto`), et une bordure basse du conteneur
   serait hors de la zone de défilement — le soulignement des onglets,
   qui doit la recouvrir, en serait rogné d'un pixel. L'ombre intérieure
   se peint dans la boîte, sous les onglets, et reste fixe pendant le
   défilement : exactement le rectangle de 321 de la maquette mobile.
*/
.stv-onglets__liste {
  display: flex;
  align-items: flex-end;
  width: fit-content;
  max-width: 100%;
  box-shadow: inset 0 -1px 0 var(--stv-onglets-filet);
}

/*
   `.stv-onglets .stv-onglets__onglet` : deux classes, le kit écrit sur
   `a` — couleur, graisse, taille, soulignement, tout ce qu'on règle ici.
   Hauteur d'un onglet = interligne + `--stv-onglets-bas` : 30 + 6 = 36 sur
   la fiche, 24 + 7 = 31 sur la FAQ (le trait de 2 y recouvre le filet, à
   31 du haut : 156:9167).
*/
.stv-onglets .stv-onglets__onglet {
  display: block;
  flex: 0 0 auto;
  box-sizing: border-box;
  margin: 0;
  padding: 0 var(--stv-espace-12) calc(var(--stv-onglets-bas) - var(--stv-onglet-soulignement));
  border-bottom: var(--stv-onglet-soulignement) solid transparent;
  color: var(--stv-onglets-couleur);
  font-family: var(--stv-onglets-police);
  font-size: var(--stv-onglets-taille);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  white-space: nowrap;
  text-decoration: none;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.stv-onglets .stv-onglets__onglet:hover,
.stv-onglets .stv-onglets__onglet:focus-visible {
  color: var(--stv-onglets-couleur-actif);
  border-bottom-color: var(--stv-onglets-soulignement-survol);
  text-decoration: none;
}

/* Actif : Medium sur la fiche (`118:5915`), et non seulement plus sombre. */
.stv-onglets .stv-onglets__onglet[aria-selected="true"] {
  color: var(--stv-onglets-couleur-actif);
  border-bottom-color: var(--stv-anthracite);
  font-weight: var(--stv-onglets-graisse-actif);
}

.stv-onglets .stv-onglets__onglet:focus-visible {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: 2px;
}

/*
   LA VARIANTE SOBRE — page FAQ (156:9164, relevé Dev Mode du 25/09).

   Même mécanique, autre dessin : Outfit Regular 16 à 1,5, TOUS les onglets
   à l'encre du site (#020a12) — l'actif ne se distingue QUE par son trait
   anthracite de 2 (156:9167, `stroke #24262E`), pas de graisse ; filet de
   la rangée à 20 % (`--stv-filet-liste`, celui de l'accordéon qu'il
   surmonte) ; 12 de marge de chaque côté, 6 sous le texte + le trait
   (onglet de 31) ; rangée CENTRÉE, par marges automatiques pour qu'elle
   défile correctement quand elle déborde (règle des pistes, 25/09) ; 80
   jusqu'aux questions (156:9175 à y = 111 sous une rangée de 31).

   Le survol n'est pas dessiné (fiche 132, « à obtenir du designer ») :
   l'encre ne pouvant pas foncer, un trait à 40 % préfigure l'actif.
   Provisoire, une variable à changer.
*/
.stv-onglets--sobre {
  --stv-onglets-police: var(--stv-police-titres);
  --stv-onglets-taille: var(--stv-taille-texte);
  --stv-onglets-couleur: var(--stv-noir);
  --stv-onglets-couleur-actif: var(--stv-noir);
  --stv-onglets-graisse-actif: 400;
  --stv-onglets-soulignement-survol: var(--stv-filet-onglets);
  --stv-onglets-filet: var(--stv-filet-liste);
  --stv-onglets-bas: 7px;
  --stv-onglets-ecart: var(--stv-espace-80);
}

.stv-onglets--sobre .stv-onglets__liste {
  margin-inline: auto;
}

/* --- Mobile ---------------------------------------------------------- */

@media (max-width: 767px) {
  /* 16 px en mobile (`118:5753`, texte de 24 = 16 à 1,5). */
  .stv-onglets {
    --stv-onglets-taille: var(--stv-taille-texte);
  }

  /* FAQ mobile : 32 de la rangée aux questions (156:8322 à y = 63). */
  .stv-onglets--sobre {
    --stv-onglets-ecart: var(--stv-espace-32);
  }

  /*
     La rangée défile sous le doigt et se termine par le même fondu que
     le fil d'Ariane (`118:5764`, même mécanisme, même jeton). La barre
     est masquée ; l'onglet actif est ramené en vue par onglets.js.
     La FAQ dessinait une liste déroulante (156:8350) : décision 132.5 par
     défaut, le défilement de la fiche — un seul comportement.
  */
  /* Le rectangle de fondu de la maquette (`118:5764`) part de 78 %. */
  .stv-onglets__barre {
    -webkit-mask-image: linear-gradient(to right, #000 78%, transparent);
    mask-image: linear-gradient(to right, #000 78%, transparent);
  }

  .stv-onglets__liste {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .stv-onglets__liste::-webkit-scrollbar {
    display: none;
  }

  .stv-onglets__liste::after {
    content: "";
    flex: 0 0 var(--stv-espace-32);
  }
}


/* =====================================================================
   FAQ — le bloc `[stelvoren_faq]` (`stv-faq-bloc`) et la page /faq/
   (`stv-faq-page`, `stv-mosaique`) — 25/09, tâches 134 et 135.
   Relevé Dev Mode : 156:9160 (section 1840 × 803), H1 156:9161, onglets
   156:9164, liste 156:9175, mosaïque 156:9203 ; mobile 156:8305.

   LE BLOC : les onglets sobres ci-dessus, et dans chaque panneau
   l'accordéon de la catégorie (`stv-faq--plus`, plus haut dans ce
   fichier : les valeurs de 156:9176 sont celles de 156:10129, au pixel).
   Une colonne de 1 104 centrée (156:9175 à x = 288 dans 1 680).

   AVANT LE MONTAGE, DÉJÀ DES ONGLETS. La rangée est en haut de l'écran :
   empiler les quatre thèmes le temps que onglets.js arrive, puis les
   replier, ferait sauter la page sous les yeux du visiteur (et compter
   un décalage de mise en page à Lighthouse). La FAQ montre donc, en CSS
   seul, le premier panneau — ou celui que vise l'ancre (`:target`, un
   lien vers /faq/#faq-livraison) — et masque les autres. Sans script, les
   onglets restent des liens d'ancre : chacun montre son thème, rien n'est
   perdu. Une fois monté, c'est `hidden` qui décide, et ces règles
   s'effacent (`:not(.stv-onglets--monte)`). Seule concession : avant le
   montage, avec une ancre, le trait reste sous le premier onglet (le CSS
   ne sait pas relier un panneau à son onglet) — le temps que le script,
   non différé, le déplace. Sans `:has()` (navigateur
   ancien), les panneaux s'empilent : l'état d'avant, lisible.
   Les titres de panneau (H2, un par thème) sont masqués visuellement dès
   le départ : la rangée d'onglets les dit déjà.
   ================================================================== */

.stv-faq-bloc {
  --stv-faq-bloc-largeur: 1104px;
}

.stv-faq-bloc .stv-faq {
  max-width: var(--stv-faq-bloc-largeur);
  margin-inline: auto;
}

.stv-faq-bloc .stv-onglets__titre {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.stv-faq-bloc .stv-onglets:not(.stv-onglets--monte):not(:has(.stv-onglets__panneau:target)) .stv-onglets__panneau:not(:first-of-type),
.stv-faq-bloc .stv-onglets:not(.stv-onglets--monte):has(.stv-onglets__panneau:target) .stv-onglets__panneau:not(:target) {
  display: none;
}


/*
   LA SECTION DU HAUT (156:9160) — H1 centré, 48 jusqu'aux onglets, le bloc.
   Un élément V4 `stv-section stv-faq-page` dans la page Elementor : la
   section générique du socle porte la gouttière et les 80 de haut et de
   bas (32 en mobile), cette classe l'écart et le titre. Classe répétée
   trois fois comme les enveloppes du socle (l'atomique V4 pose
   `display: block; padding: 10px` à 0,2,0, après nous).

   Le H1 est un widget Titre (fiche 135) : sa classe arrive sur l'enveloppe
   du widget, la règle descend au titre par `:where()` — même parade que
   `stv-split__titre`. Outfit Medium 62 à 1,1 et −1 % (156:9162), 42 en
   mobile (156:8309) : le H1 de page du site (`--stv-taille-hero`).
*/
.stv-faq-page.stv-faq-page.stv-faq-page {
  gap: var(--stv-espace-48);
}

.stv-faq-page .stv-faq-page__titre.stv-faq-page__titre,
.stv-faq-page .stv-faq-page__titre :where(h1, h2, p, .elementor-heading-title) {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-hero);
  font-weight: 500;
  line-height: var(--stv-interligne-titre);
  letter-spacing: -0.01em;
  color: var(--stv-texte);
  text-align: center;
}

/*
   LA MOSAÏQUE (156:9203) — une grande photo et deux petites, sur le fond
   crème d'une `stv-section--creme` : 1 104 × 1 044 à gauche, une colonne
   de 560 à droite avec deux photos de 514, 16 d'écart partout. Décorative
   mais pas vide de sens : les trois photos ont un texte alternatif.

   UNE GRILLE, PAS DEUX COLONNES : la grande photo occupe les deux rangées
   et DONNE la hauteur (son rapport 1104 / 1044) ; les deux petites se
   partagent cette hauteur — leur image sort du flux (`position:
   absolute`), sans quoi sa hauteur naturelle dicterait la rangée (la
   leçon de `stv-split--image-pleine`, 23/09). Les deux colonnes sont en
   proportion (1104 fr / 560 fr) : à 1 840 elles redonnent exactement la
   maquette, en dessous la mosaïque se resserre d'un bloc.

   Mobile (156:8353) : la grande en tête sur toute la largeur (353 × 220),
   les deux petites côte à côte dessous (168,5 × 180).

   Les photos sont des widgets Image d'Elementor : la classe arrive sur
   l'enveloppe du widget, d'où la descente vers `img` (même parade que
   `stv-split__image`). L'enveloppe porte la taille (rapport ou rangée),
   l'image la remplit hors du flux — pour les trois. Classe répétée sur
   l'enveloppe (0,3,0) : l'espacement des widgets d'Elementor et
   `.elementor-widget-image` écrivent au même compte que 0,2,0.
*/
.stv-mosaique.stv-mosaique.stv-mosaique {
  display: grid;
  grid-template-columns: minmax(0, 1104fr) minmax(0, 560fr);
  grid-template-rows: 1fr 1fr;
  gap: var(--stv-espace-16);
  padding: 0;
}

.stv-mosaique .stv-mosaique__image.stv-mosaique__image {
  position: relative;
  min-width: 0;
  margin: 0;
  overflow: hidden;
}

.stv-mosaique .stv-mosaique__image :where(.elementor-widget-container, figure) {
  margin: 0;
}

.stv-mosaique .stv-mosaique__image :where(img) {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

.stv-mosaique .stv-mosaique__image--grande.stv-mosaique__image--grande {
  grid-row: 1 / span 2;
  aspect-ratio: 1104 / 1044;
}

@media (max-width: 767px) {
  .stv-faq-page.stv-faq-page.stv-faq-page {
    gap: var(--stv-espace-32);
  }

  .stv-mosaique.stv-mosaique.stv-mosaique {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto;
  }

  .stv-mosaique .stv-mosaique__image--grande.stv-mosaique__image--grande {
    grid-row: auto;
    grid-column: 1 / -1;
    aspect-ratio: 353 / 220;
  }

  .stv-mosaique .stv-mosaique__image--petite.stv-mosaique__image--petite {
    aspect-ratio: 337 / 360;
  }
}


/* =====================================================================
   MENU DE TRI — `stv-tri` (tâche 91, 24/09 ; partagé depuis le 25/09)
   ---------------------------------------------------------------------
   Déplacé ICI depuis catalogue.css (§ 2.2) le 25/09, au lot « Recherche » :
   il a désormais trois places — la barre d'outils du catalogue (156:6699),
   l'en-tête de la page de résultats et le panneau de recherche (238:7926,
   957:8527), qui est sur toutes les pages. Règles recopiées telles quelles,
   mêmes sélecteurs, même poids : sur le catalogue rien ne change, seule la
   feuille qui les porte. catalogue.css ne garde que la place du formulaire
   dans sa barre.

   Un `<details>` : voir parties/catalogue-tri.php. Le bouton est le
   `<summary>`, « Pertinence » + chevron à 16 ; la liste s'ouvre 6 sous
   la ligne du bouton, fond blanc, filet du champ de formulaire (anthracite
   à 35 %), 142 de large, cinq lignes de 12 / 16 de marge intérieure.

   AUCUNE RÈGLE DU SOCLE NE L'ATTEINT, même chargé avant lui : le § 9 de
   socle.css ne vise les boutons de WooCommerce que dans `.form-row`, et le
   formulaire de tri n'en a pas (vérifié le 25/09).
   ================================================================== */

/* La liste se pose sous le bouton : le menu est son repère. */
.stv-tri.stv-tri {
  position: relative;
}

.stv-tri .stv-tri__bouton {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-16);
  color: var(--stv-noir);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  list-style: none;
  cursor: pointer;
  user-select: none;
}

.stv-tri .stv-tri__bouton::-webkit-details-marker {
  display: none;
}

.stv-tri .stv-tri__bouton:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* Le chevron : boîte de 8 × 4 dans la maquette, 9,33 × 5,33 avec le trait. */
.stv-tri .stv-tri__chevron {
  flex-shrink: 0;
  width: 9.33px;
  height: 5.33px;
  margin: -0.667px;
  transition: transform 0.15s ease;
}

.stv-tri .stv-tri__menu[open] .stv-tri__chevron {
  transform: rotate(180deg);
}

.stv-tri .stv-tri__liste {
  position: absolute;
  z-index: 20;
  top: calc(100% + var(--stv-espace-6));
  left: 0;
  width: max-content;
  min-width: 142px;
  margin: 0;
  padding: 0;
  border: 1px solid var(--stv-filet-champ);
  background: var(--stv-blanc);
  list-style: none;
}

.stv-tri .stv-tri__liste > li {
  margin: 0;
  border-bottom: 1px solid var(--stv-filet-champ);
}

.stv-tri .stv-tri__liste > li:last-child {
  border-bottom: 0;
}

/*
   Une option (156:6869) : Inter Regular 14, texte rogné aux capitales
   dans la maquette, 16 au-dessus et au-dessous, 12 sur les côtés — 43
   avec le filet. Même geste que la pagination : un interligne de 10 px
   fait, pour Inter, la boîte des capitales.

   TROIS classes contre le `reset.css` de Hello : `[type=submit]` y pèse
   0,1,0 et ses états `:hover` / `:focus` 0,2,0 (bordure rose, fond
   `#c36`) ; les états ci-dessous pèsent 0,4,0.
*/
.stv-tri .stv-tri__option.stv-tri__option {
  display: block;
  width: 100%;
  margin: 0;
  padding: var(--stv-espace-16) var(--stv-espace-12);
  border: 0;
  border-radius: 0;
  background: var(--stv-blanc);
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: 10px;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

/* Survol et focus : NON DESSINÉS (fiche 88) — le gris des cartes, provisoire. */
.stv-tri .stv-tri__option.stv-tri__option:hover,
.stv-tri .stv-tri__option.stv-tri__option:focus {
  background: var(--stv-gris-clair);
  color: var(--stv-noir);
}

.stv-tri .stv-tri__option.stv-tri__option:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: -2px;
}

/* Le tri en cours : NON DESSINÉ non plus. Medium, pour qu'on le voie sans la couleur seule. */
.stv-tri .stv-tri__option.stv-tri__option[aria-current="true"] {
  font-weight: 500;
}

/*
   VARIANTE « Tri par … » (`stv-tri--recherche`) — 957:8527 et 238:7926.
   « Tri par » en Outfit Regular anthracite, le tri en Outfit Medium noir,
   dans UNE boîte (`stv-tri__texte`) : l'écart de 16 du bouton ne tombe
   qu'avant le chevron.
*/
.stv-tri--recherche .stv-tri__texte {
  white-space: nowrap;
}

.stv-tri--recherche .stv-tri__prefixe {
  color: var(--stv-anthracite);
  font-weight: 400;
}

.stv-tri--recherche .stv-tri__libelle {
  color: var(--stv-noir);
  font-weight: 500;
}


/* =====================================================================
   RECHERCHE — le panneau (lot « Recherche », 25/09/2026)
   ---------------------------------------------------------------------
   Maquettes 238:7861 (desktop, repos), 238:7912 (desktop, saisie), 238:7807
   (mobile, repos) et 238:7810 (mobile, saisie) — relevé Dev Mode du 25/09.
   Le balisage : parties/recherche-panneau.php et inc/recherche.php.

   UN PANNEAU LATÉRAL POSÉ EN HAUT. C'est le `<dialog class="stv-lateral">`
   du tiroir panier, avec le modificateur `--haut` : même voile (238:7862 =
   156:11328, bleu pétrole à 40 %, flou de 2), même verrou, même script. Le
   designer en a fait une variante du composant d'en-tête : le panneau
   RECOUVRE l'en-tête, il ne s'ouvre pas dessous.

   DESKTOP (≥ 1 025, la largeur où l'en-tête montre son champ) : blanc,
   ombre 0 4 4 noire à 10 %, 48 en haut, 80 en bas, 32 entre la barre et le
   corps. Barre : le champ de 816 (filet noir dessous, 12 / 16 de marge
   intérieure, loupe de 14 à 12 du texte) et la croix de 20, à 48 l'un de
   l'autre, CENTRÉS ENSEMBLE — le champ va de 478 à 1 294, la croix est à
   1 342. Corps : une colonne de 384 (catégories), 48, et le reste
   (produits) ; 80 de marge, plafond de contenu à 1 680 comme partout.
   Repos 558 de haut, saisie 592.

   MOBILE (< 1 025) : plein écran. La barre (49 : 12 + 24 + 12 + le filet)
   reste en haut quand le corps défile ; flèche de retour à gauche, rond
   barré à droite dès qu'on a tapé. Catégories en pastilles défilantes sous
   une ombre (0 0 4, noir à 12 %), produits en cartes en ligne de 353 × 122.
   En saisie, pas de catégories (238:7810).

   POIDS. Les boutons à 0,3,0 et leurs états à 0,4,0 : le `reset.css` de
   Hello pèse 0,1,0 et 0,2,0 au survol, le kit Elementor 0,1,1 et 0,2,1 —
   et le kit est chargé sur les pages Elementor, dont l'accueil, où le
   panneau s'ouvre aussi. Titres, liens et listes à 0,2,0 contre le kit
   (`h2`, `a`, 0,1,1). Le champ reprend `stv-recherche__champ`, la remise à
   zéro à 0,4,0 du champ de l'en-tête.
   ================================================================== */

.stv-recherche-panneau {
  --stv-recherche-marge: var(--stv-espace-80);
  --stv-recherche-gouttiere: max(
    var(--stv-recherche-marge),
    (100% - var(--stv-largeur-contenu)) / 2
  );
  --stv-recherche-carte: 201px;
  --stv-recherche-ecart: var(--stv-espace-16);
  --stv-recherche-fleche: 40px;
}

@media (max-width: 1439px) {
  .stv-recherche-panneau {
    --stv-recherche-marge: var(--stv-espace-48);
  }
}

/* --- Le panneau lui-même : le modificateur `--haut` ------------------ */

/*
   `.stv-lateral.stv-lateral` pèse 0,2,0 et son état ouvert 0,3,0 : le
   modificateur se répète pour passer devant, sans dépendre de l'ordre.
   Hauteur au contenu, plafonnée à l'écran ; au-delà, le panneau défile.
*/
.stv-lateral.stv-lateral--haut.stv-lateral--haut {
  inset: 0 0 auto 0;
  width: 100%;
  max-width: none;
  height: auto;
  max-height: 100vh;
  max-height: 100dvh;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateY(-100%);
}

.stv-lateral.stv-lateral--haut.stv-lateral--haut[open] {
  transform: none;
}

@starting-style {
  .stv-lateral.stv-lateral--haut.stv-lateral--haut[open] {
    transform: translateY(-100%);
  }
}

.stv-recherche-panneau.stv-recherche-panneau.stv-recherche-panneau {
  gap: var(--stv-espace-32);
  padding: var(--stv-espace-48) 0 var(--stv-espace-80);
  background: var(--stv-blanc);
  box-shadow: 0 4px 4px rgba(0, 0, 0, 0.1);
}

/* --- La barre : champ et croix --------------------------------------- */

.stv-recherche-panneau .stv-recherche-panneau__barre {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  gap: var(--stv-espace-48);
  margin: 0;
  padding-inline: var(--stv-recherche-gouttiere);
  background: var(--stv-blanc);
}

.stv-recherche-panneau .stv-recherche-panneau__cadre {
  display: flex;
  flex: 0 1 var(--stv-largeur-texte);
  align-items: center;
  gap: var(--stv-espace-12);
  min-width: 0;
  padding: var(--stv-espace-12) var(--stv-espace-16);
  border-bottom: 1px solid var(--stv-noir);
  color: var(--stv-noir);
}

/* Focus : NON DESSINÉ — le filet s'épaissit d'un pixel. Le champ a le focus dès l'ouverture. */
.stv-recherche-panneau .stv-recherche-panneau__cadre:focus-within {
  box-shadow: 0 1px 0 var(--stv-noir);
}

.stv-recherche-panneau .stv-recherche-panneau__champ {
  flex: 1 1 auto;
  min-width: 0;
}

/* Le texte d'attente de la maquette : anthracite à 50 % (957:8021). */
.stv-recherche-panneau .stv-recherche__champ.stv-recherche__champ::placeholder {
  color: var(--stv-texte-indication);
}

/* Ni loupe ni croix du navigateur dans un champ `search` : nos glyphes suffisent. */
.stv-recherche__champ::-webkit-search-decoration,
.stv-recherche__champ::-webkit-search-cancel-button,
.stv-recherche__champ::-webkit-search-results-button,
.stv-recherche__champ::-webkit-search-results-decoration {
  -webkit-appearance: none;
  appearance: none;
  display: none;
}

/* La loupe : 14 dans la maquette. */
.stv-recherche-panneau .stv-recherche-panneau__loupe {
  display: block;
  flex-shrink: 0;
  width: 14px;
  height: 14px;
}

/* Les trois boutons : retour, effacer, fermer. */
.stv-recherche-panneau .stv-recherche-panneau__bouton.stv-recherche-panneau__bouton {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--stv-noir);
  cursor: pointer;
}

.stv-recherche-panneau .stv-recherche-panneau__bouton.stv-recherche-panneau__bouton:hover,
.stv-recherche-panneau .stv-recherche-panneau__bouton.stv-recherche-panneau__bouton:focus {
  background: none;
  color: var(--stv-noir);
}

.stv-recherche-panneau .stv-recherche-panneau__bouton.stv-recherche-panneau__bouton:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* Écrit AU-DESSUS du `display` ci-dessus : l'attribut `hidden` pèse moins que toute règle d'auteur. */
.stv-recherche-panneau .stv-recherche-panneau__bouton.stv-recherche-panneau__bouton[hidden] {
  display: none;
}

/* Le retour et l'effacement n'existent qu'en mobile. */
.stv-recherche-panneau .stv-recherche-panneau__retour.stv-recherche-panneau__retour,
.stv-recherche-panneau .stv-recherche-panneau__effacer.stv-recherche-panneau__effacer {
  display: none;
}

/* La croix (957:8028) : 20 dessinés, 21,67 avec le trait. */
.stv-recherche-panneau .stv-recherche-panneau__fermer {
  width: 20px;
  height: 20px;
}

.stv-recherche-panneau .stv-recherche-panneau__fermer svg {
  display: block;
  flex-shrink: 0;
  width: 21.67px;
  height: 21.67px;
  margin: -0.835px;
}

/* --- Le corps : deux colonnes ---------------------------------------- */

.stv-recherche-panneau .stv-recherche-panneau__corps {
  flex-shrink: 0;
}

.stv-recherche-panneau .stv-recherche-resultats {
  display: flex;
  align-items: flex-start;
  gap: var(--stv-espace-48);
  padding-inline: var(--stv-recherche-gouttiere);
}

.stv-recherche-panneau .stv-recherche-resultats__categories {
  display: flex;
  flex: 0 0 var(--stv-colonne);
  flex-direction: column;
  gap: var(--stv-espace-16);
  min-width: 0;
}

.stv-recherche-panneau .stv-recherche-resultats__produits {
  display: flex;
  flex: 1 1 0;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stv-espace-16);
  min-width: 0;
}

/* « Catégories populaires », « Produits populaires » : Outfit Medium 20 à 1,5, anthracite. */
.stv-recherche-resultats .stv-recherche-resultats__titre {
  margin: 0;
  color: var(--stv-anthracite);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-carte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  letter-spacing: normal;
  text-transform: none;
}

.stv-recherche-resultats .stv-recherche-resultats__liste {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stv-espace-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-recherche-resultats .stv-recherche-resultats__categorie {
  margin: 0;
  padding: 0;
}

/* Une catégorie : Outfit Regular 14 à 1,5, anthracite (957:8039). */
.stv-recherche-resultats .stv-recherche-resultats__lien {
  display: block;
  color: var(--stv-anthracite);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-petit);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  text-decoration: none;
}

/* Survol : NON DESSINÉ — le lien se souligne, provisoire (même pas que les tuiles). */
.stv-recherche-resultats .stv-recherche-resultats__lien.stv-recherche-resultats__lien:hover {
  color: var(--stv-noir);
  text-decoration: underline;
}

.stv-recherche-resultats .stv-recherche-resultats__lien:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* Saisie sans résultat : NON DESSINÉ — le message, au-dessus des produits populaires. */
.stv-recherche-resultats .stv-recherche-resultats__message,
.stv-recherche-panneau .stv-recherche-resultats__erreur {
  margin: 0;
  color: var(--stv-anthracite);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
}

.stv-recherche-panneau .stv-recherche-resultats__erreur {
  padding: 0 var(--stv-recherche-gouttiere) var(--stv-espace-24);
}

/* « Voir tous les résultats de recherche » (957:8520) : Inter Medium 16, capitales, souligné, flèche à 8. */
.stv-recherche-resultats .stv-recherche-resultats__tout {
  display: inline-flex;
  align-items: center;
  gap: var(--stv-espace-8);
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-texte);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  text-decoration: underline;
  text-decoration-skip-ink: none;
  text-underline-position: from-font;
  text-transform: uppercase;
}

.stv-recherche-resultats .stv-recherche-resultats__tout.stv-recherche-resultats__tout:hover {
  color: var(--stv-noir);
  text-decoration: none;
}

.stv-recherche-resultats .stv-recherche-resultats__tout:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* La flèche : 20 × 8 dessinés, 21,67 × 9,67 avec le trait. */
.stv-recherche-resultats .stv-recherche-resultats__fleche {
  display: block;
  flex-shrink: 0;
  width: 21.67px;
  height: 9.67px;
  margin: -0.835px;
}

/* --- Le bilan : « 8 résultats trouvés - Tri par Pertinence » -------------

   957:8509 dans le panneau, 238:7920 sur la page : Outfit Regular 16 à 1,5
   anthracite, un tiret de 5,4 × 1,7 (un aplat, pas un caractère) à 8 de
   part et d'autre, puis le tri. En mobile : 12, nombre à gauche et tri à
   droite, sans tiret (238:7810).
*/
.stv-recherche-bilan {
  display: flex;
  align-items: center;
  gap: var(--stv-espace-8);
}

.stv-recherche-bilan .stv-recherche-bilan__compte {
  margin: 0;
  color: var(--stv-anthracite);
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-texte);
  font-weight: 400;
  line-height: var(--stv-interligne-texte);
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
}

.stv-recherche-bilan .stv-recherche-bilan__tiret {
  flex-shrink: 0;
  width: 5.424px;
  height: 1.664px;
  background: var(--stv-anthracite);
}

/*
   Le formulaire de tri de la page garde `woocommerce-ordering` : woocommerce.css
   lui donne un flottant et 1 em de marge (0,2,0) — même parade que dans la
   barre d'outils du catalogue.
*/
.stv-recherche-bilan .stv-tri.stv-tri {
  float: none;
  margin: 0;
}

/* --- La piste des cartes ----------------------------------------------

   957:8067 : cartes de 201, 16 d'écart, la sixième coupée par un fondu blanc
   (les 10 derniers % de la rangée, 957:8190). Une flèche de 40 à cheval sur
   le bord droit, centrée sur les cartes (957:8556 — le carrousel des tuiles,
   même tracé, même fond). La piste est celle de carrousels.js : la présence
   des flèches suit le débordement mesuré (`data-stv-piste-deborde`).

   ÉCART VOULU À LA MAQUETTE : elle ne dessine que la flèche suivante. Avec
   douze cartes il faut aussi revenir : la précédente paraît dès qu'on a
   avancé ; en bout de course, la flèche qui ne mène plus nulle part
   s'efface (au lieu des 50 % des tuiles) — c'est ce qui rend, au repos,
   exactement le dessin de la maquette.
*/
.stv-recherche-piste {
  align-self: stretch;
  min-width: 0;
}

.stv-recherche-piste .stv-recherche-piste__cadre {
  position: relative;
}

.stv-recherche-piste .stv-recherche-piste__liste {
  display: flex;
  gap: var(--stv-recherche-ecart, 16px);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}

.stv-recherche-piste .stv-recherche-piste__liste::-webkit-scrollbar {
  display: none;
}

.stv-recherche-piste .stv-recherche-piste__element {
  display: flex;
  flex: 0 0 var(--stv-recherche-carte, 201px);
  min-width: 0;
  margin: 0;
  padding: 0;
  scroll-snap-align: start;
}

/* Le fondu, seulement quand il reste des cartes à droite. */
.stv-recherche-piste .stv-recherche-piste__cadre::after {
  content: "";
  position: absolute;
  inset: 0 0 0 auto;
  width: 10%;
  background: linear-gradient(to right, rgba(255, 255, 255, 0), var(--stv-blanc));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
}

.stv-recherche-piste[data-stv-piste-deborde]:has(.stv-recherche-piste__fleche--suivant[aria-disabled="false"]) .stv-recherche-piste__cadre::after {
  opacity: 1;
}

.stv-recherche-piste .stv-recherche-piste__fleche.stv-recherche-piste__fleche {
  position: absolute;
  z-index: 1;
  top: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--stv-recherche-fleche, 40px);
  height: var(--stv-recherche-fleche, 40px);
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--stv-gris-clair);
  color: var(--stv-noir);
  cursor: pointer;
  transform: translateY(-50%);
  transition: background-color 0.2s;
}

.stv-recherche-piste .stv-recherche-piste__fleche.stv-recherche-piste__fleche[hidden],
.stv-recherche-piste .stv-recherche-piste__fleche.stv-recherche-piste__fleche[aria-disabled="true"] {
  display: none;
}

.stv-recherche-piste .stv-recherche-piste__fleche--precedent {
  left: calc(var(--stv-recherche-fleche, 40px) / -2);
}

.stv-recherche-piste .stv-recherche-piste__fleche--suivant {
  right: calc(var(--stv-recherche-fleche, 40px) / -2);
}

/* Survol : NON DESSINÉ — le bleu clair des flèches des tuiles, provisoire. */
.stv-recherche-piste .stv-recherche-piste__fleche.stv-recherche-piste__fleche:hover {
  background: var(--stv-bleu-clair);
  color: var(--stv-noir);
}

.stv-recherche-piste .stv-recherche-piste__fleche.stv-recherche-piste__fleche:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

.stv-recherche-piste .stv-recherche-piste__glyphe {
  display: block;
  flex-shrink: 0;
  width: 21.5px;
  height: 9.5px;
}

@media (prefers-reduced-motion: reduce) {
  .stv-recherche-piste .stv-recherche-piste__liste {
    scroll-behavior: auto;
  }
}

/*
   LA CARTE DU PANNEAU (`productInSearch`, 238:6852, 331:10286) — une variante,
   pas une correction : image 169 × 169 à 16 de marge, 16 sous l'image, nom en
   14, 4 jusqu'au prix. Le prix est celui de toutes les cartes depuis le 26/10
   (156) : « À partir de » puis HT • TTC, en 12 / 14 ici, en 10 / 12 en mobile.
   Des marges plutôt que l'écart de la carte, pour que 16 et 4 coexistent.
*/
.stv-recherche-piste .stv-carte-produit {
  flex: 1 1 auto;
  gap: 0;
}

.stv-recherche-piste .stv-carte-produit .stv-carte-produit__nom {
  margin-top: var(--stv-espace-16);
  font-size: var(--stv-taille-petit);
  letter-spacing: normal;
  text-transform: none;
}

.stv-recherche-piste .stv-carte-produit .stv-carte-produit__prix {
  margin-top: var(--stv-espace-4);
  line-height: var(--stv-interligne-texte);
}

/* --- Mobile et tablette (< 1 025) : plein écran ---------------------- */

@media (max-width: 1024px) {
  .stv-recherche-panneau {
    --stv-recherche-gouttiere: 20px;
  }

  .stv-lateral.stv-lateral--haut.stv-lateral--haut {
    height: 100vh;
    height: 100dvh;
    max-height: none;
  }

  /* Un bloc qui défile, et non une colonne flexible : le corps ne doit pas rétrécir. */
  .stv-lateral.stv-lateral--haut.stv-lateral--haut[open] {
    display: block;
  }

  .stv-recherche-panneau.stv-recherche-panneau.stv-recherche-panneau {
    padding: 0;
    box-shadow: none;
  }

  /* La barre reste en haut quand le corps défile. */
  .stv-recherche-panneau .stv-recherche-panneau__barre {
    position: sticky;
    z-index: 2;
    top: 0;
    gap: 0;
    padding-inline: 0;
  }

  .stv-recherche-panneau .stv-recherche-panneau__cadre {
    flex: 1 1 auto;
  }

  .stv-recherche-panneau .stv-recherche-panneau__loupe,
  .stv-recherche-panneau .stv-recherche-panneau__fermer.stv-recherche-panneau__fermer {
    display: none;
  }

  /* Le retour (957:9918) : la flèche du lien, retournée — 20 × 8 dans une zone de 20 × 24. */
  .stv-recherche-panneau .stv-recherche-panneau__retour.stv-recherche-panneau__retour {
    display: inline-flex;
    width: 20px;
    height: 24px;
  }

  .stv-recherche-panneau .stv-recherche-panneau__glyphe-retour {
    display: block;
    flex-shrink: 0;
    width: 21.67px;
    height: 9.67px;
    margin: -0.835px;
    transform: rotate(180deg);
  }

  /* Le rond barré (957:10075) : 16 dessinés, 17 avec le trait, anthracite. */
  .stv-recherche-panneau .stv-recherche-panneau__effacer.stv-recherche-panneau__effacer {
    display: inline-flex;
    width: 16px;
    height: 16px;
    margin-left: auto;
    color: var(--stv-anthracite);
  }

  .stv-recherche-panneau .stv-recherche-panneau__effacer.stv-recherche-panneau__effacer[hidden] {
    display: none;
  }

  .stv-recherche-panneau .stv-recherche-panneau__effacer svg {
    display: block;
    flex-shrink: 0;
    width: 17px;
    height: 17px;
    margin: -0.5px;
  }

  .stv-recherche-panneau .stv-recherche-resultats {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-inline: 0;
  }

  /* Les catégories en pastilles (957:9826) : 12 / 20 / 16, sous une ombre. */
  .stv-recherche-panneau .stv-recherche-resultats__categories {
    position: relative;
    z-index: 1;
    flex: 0 0 auto;
    gap: var(--stv-espace-12);
    padding: var(--stv-espace-12) var(--stv-recherche-gouttiere) var(--stv-espace-16);
    background: var(--stv-blanc);
    box-shadow: 0 0 4px rgba(0, 0, 0, 0.12);
  }

  /* En saisie, pas de catégories (238:7810) ; sans résultat, si — les populaires. */
  .stv-recherche-panneau__corps[data-etat="resultats"] .stv-recherche-resultats__categories {
    display: none;
  }

  .stv-recherche-panneau .stv-recherche-resultats__produits {
    flex: 0 0 auto;
    align-items: stretch;
    padding: var(--stv-espace-16) var(--stv-recherche-gouttiere) var(--stv-espace-32);
  }

  /* Les titres : Outfit Medium 12 (957:9827, 957:9927). */
  .stv-recherche-resultats .stv-recherche-resultats__titre {
    font-size: var(--stv-taille-copyright);
  }

  /* La rangée de pastilles défile jusqu'aux bords de l'écran. */
  .stv-recherche-resultats .stv-recherche-resultats__liste {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    margin-inline: calc(-1 * var(--stv-recherche-gouttiere));
    padding-inline: var(--stv-recherche-gouttiere);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }

  .stv-recherche-resultats .stv-recherche-resultats__liste::-webkit-scrollbar {
    display: none;
  }

  .stv-recherche-resultats .stv-recherche-resultats__categorie {
    flex-shrink: 0;
  }

  .stv-recherche-resultats .stv-recherche-resultats__lien {
    padding: 2px var(--stv-espace-4);
    background: var(--stv-gris-clair);
    white-space: nowrap;
  }

  /*
     Le lien vers la page de résultats — NON DESSINÉ en mobile : en 16 il
     tient sur 368 et passe à la ligne dans 353 ; en 14, il tient.
  */
  .stv-recherche-resultats .stv-recherche-resultats__tout {
    align-self: flex-start;
    font-size: var(--stv-taille-petit);
  }

  /*
     Le bilan : 12, nombre à gauche, tri à droite, sans tiret (957:10055).
     Dans le panneau seulement : la page de résultats a son propre palier,
     celui du catalogue (767, catalogue.css § 8).
  */
  .stv-recherche-panneau .stv-recherche-bilan {
    align-self: stretch;
    justify-content: space-between;
  }

  .stv-recherche-panneau .stv-recherche-bilan .stv-recherche-bilan__compte,
  .stv-recherche-panneau .stv-recherche-bilan .stv-tri .stv-tri__bouton {
    font-size: var(--stv-taille-copyright);
  }

  .stv-recherche-panneau .stv-recherche-bilan .stv-tri .stv-tri__bouton {
    gap: var(--stv-espace-8);
  }

  .stv-recherche-panneau .stv-recherche-bilan .stv-recherche-bilan__tiret {
    display: none;
  }

  /* Le tri est au bord droit : sa liste s'ouvre vers la gauche. */
  .stv-recherche-panneau .stv-recherche-bilan .stv-tri .stv-tri__liste {
    right: 0;
    left: auto;
  }

  /*
     LA PISTE DEVIENT UNE LISTE (957:9840) : cartes en ligne, 8 d'écart. Une
     colonne à 393, deux ou trois sur une tablette plutôt que des cartes de
     980 de long. Plus rien ne déborde : carrousels.js cache les flèches de
     lui-même, le CSS les retire en plus.
  */
  .stv-recherche-piste .stv-recherche-piste__liste {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
    gap: var(--stv-espace-8);
    overflow: visible;
    scroll-snap-type: none;
  }

  .stv-recherche-piste .stv-recherche-piste__fleche.stv-recherche-piste__fleche,
  .stv-recherche-piste .stv-recherche-piste__cadre::after {
    display: none;
  }

  /* Au repos, quatre produits populaires, comme la maquette (957:9840, 512 de haut). */
  .stv-recherche-piste--populaires .stv-recherche-piste__element:nth-child(n+5) {
    display: none;
  }

  /*
     LA CARTE EN LIGNE (`productInSearchMobile`, 238:6864) : 353 × 122, image
     de 81,2 × 90 à gauche, 16 d'écart, le texte centré sur la hauteur de
     l'image — nom en 16 (bloc de 48, calé en haut), 4, prix en 12. Une
     grille à quatre rangées (1fr, nom, prix, 1fr) centre le texte sans
     toucher au balisage de la carte.
  */
  .stv-recherche-piste .stv-carte-produit {
    display: grid;
    grid-template-columns: 81.213px minmax(0, 1fr);
    grid-template-rows: 1fr auto auto 1fr;
    column-gap: var(--stv-espace-16);
    align-items: start;
  }

  .stv-recherche-piste .stv-carte-produit .stv-carte-produit__media {
    grid-column: 1;
    grid-row: 1 / -1;
    align-self: center;
    width: 81.213px;
    height: 90px;
    aspect-ratio: auto;
  }

  .stv-recherche-piste .stv-carte-produit .stv-carte-produit__nom {
    grid-column: 2;
    grid-row: 2;
    align-items: flex-start;
    margin-top: 0;
    font-size: var(--stv-taille-texte);
  }

  .stv-recherche-piste .stv-carte-produit {
    --stv-carte-prix-taille: var(--stv-taille-copyright);
    --stv-carte-a-partir-taille: 10px;
  }

  .stv-recherche-piste .stv-carte-produit .stv-carte-produit__prix {
    grid-column: 2;
    grid-row: 3;
  }

  /* Carte en ligne, centrée en hauteur pour elle-même : pas de rangée à aligner, la ligne vide est retirée (R28, 28/10). */
  .stv-recherche-piste .stv-carte-produit .stv-carte-produit__a-partir--vide {
    display: none;
  }
}


/* =====================================================================
   CONNEXION — `stv-connexion` (commande 146, compte 150)
   ---------------------------------------------------------------------
   Le formulaire de connexion a deux places : la commande
   (`global/form-login.php`, carte grise dépliée sous le formulaire) et le
   compte (`myaccount/form-login.php`, la carte d'accès ; mot de passe
   oublié et nouveau mot de passe aussi). Ses règles vivaient dans
   `commande.css`, chargée sur la commande seulement : sorties ici le
   29/09, telles quelles. Ce qui est propre à chaque place (la carte de la
   commande, celle du compte) reste dans sa feuille.
   ================================================================== */

.stv-connexion .stv-connexion__message p,
.stv-connexion p.stv-connexion__message {
  margin: 0 0 var(--stv-espace-24);
  color: var(--stv-anthracite);
  font-size: var(--stv-taille-petit);
  line-height: var(--stv-interligne-texte);
}

/* `form.` : 0,2,1. Dans commande.css, chargée APRÈS, `.stv-commande .stv-case`
   (0,2,0, la case « Expédier à une adresse différente ») remettait la case
   de la connexion à 0 — elle gagnait à l'ordre dans la même feuille avant le
   déplacement (constaté à la non-régression du 29/09). */
form.stv-connexion .stv-case,
form.stv-connexion .stv-connexion__envoi {
  margin: var(--stv-espace-24) 0 0;
}

.stv-connexion .stv-connexion__envoi .woocommerce-form-login__submit.stv-bouton {
  float: none;
  margin: 0;
}

.stv-connexion .stv-connexion__oubli {
  margin: var(--stv-espace-16) 0 0;
  font-size: var(--stv-taille-petit);
}

.stv-connexion .stv-connexion__oubli a {
  color: var(--stv-noir);
  font-weight: 500;
  text-decoration: underline;
  text-underline-position: from-font;
}


/* =====================================================================
   EN-TÊTE DE SECTION ET SECTION DE PRODUITS — `stv-titre-section`,
   `stv-surtitre-fleche`, `stv-section-produits` (La marque, tâche 131,
   30/09). Relevé Dev Mode : 156:10656 (section 1840 × 840), en-tête
   156:10657 (sur-titre 156:10659, H2 156:10664), cartes 156:10665 ;
   mobile 156:8387.

   POURQUOI DANS LE THÈME. L'accueil dessine le même en-tête avec les
   classes GLOBALES du kit (`stv-entete-section-centre`,
   `stv-surtitre-centre`) et un élément SVG qui pointe une pièce jointe.
   Une classe globale V4 n'est pas référençable depuis une mise en page en
   JSON (son CSS vit en base), et une pièce jointe est un identifiant : ni
   l'un ni l'autre ne se rejoue depuis `outils/pages/notre-marque.json`.
   D'où ces classes-ci, sous des noms qui ne croisent pas ceux du kit
   (`stv-entete-section` et `stv-surtitre` EXISTENT au kit : ne pas les
   reprendre). L'accueil n'est pas touché.

   LE DESSIN — celui du kit, relu au compte le 30/09 sur l'accueil, et
   celui de 156:10657 : bloc centré, 8 entre le sur-titre et le titre ;
   sur-titre Outfit Regular 16 bleu pétrole, flèche de 16, écart 6 (14 en
   mobile : `--stv-taille-surtitre`, comme l'accueil — la maquette mobile
   de La marque garde 16, écart assumé) ; H2 Outfit Medium 50 à 1,1 et
   −0,5 % (32 en mobile).

   Trois répétitions sur les enveloppes (éléments V4) : l'atomique pose
   `display: block; padding: 10px` à 0,2,0, après nous.
   ================================================================== */

/*
   LA SECTION : une `stv-section` (socle : gouttière, 80 / 32 de haut et de
   bas) qui porte un en-tête et un carrousel, à `--stv-entete-grille` l'un
   de l'autre (80, 32 en mobile — la maquette mobile dit 48 : écart
   assumé, le jeton est celui de l'accueil).
*/
.stv-section-produits.stv-section-produits.stv-section-produits {
  gap: var(--stv-entete-grille);
  align-items: stretch;
}

.stv-titre-section.stv-titre-section.stv-titre-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--stv-espace-8);
  padding: 0;
  text-align: center;
}

/*
   Le sur-titre est rendu par `[stelvoren_surtitre]` dans un widget Code
   court : `<p class="stv-surtitre-fleche">` + la flèche du thème + le
   texte. Deux classes (0,2,0) devant le `p` du thème parent et du kit.
   Interligne « normal » dans la maquette : une boîte de 20 pour 16, soit
   1,25 (le même relevé que la ligne de date des pages légales).
*/
.stv-surtitre-fleche.stv-surtitre-fleche {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--stv-espace-6);
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-surtitre);
  font-weight: 400;
  line-height: 1.25;
  color: var(--stv-bleu-petrole);
}

.stv-surtitre-fleche.stv-surtitre-fleche svg {
  flex: 0 0 auto;
  width: var(--stv-espace-16);
  height: var(--stv-espace-16);
}

/*
   Le titre est un widget Titre : sa classe arrive sur l'enveloppe du
   widget, le second sélecteur descend au titre en `:where()` (même parade
   que `stv-split__titre`, socle § 4).
*/
.stv-titre-section .stv-titre-section__titre.stv-titre-section__titre,
.stv-titre-section .stv-titre-section__titre :where(h1, h2, p, .elementor-heading-title) {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-h2);
  font-weight: 500;
  line-height: var(--stv-interligne-titre);
  letter-spacing: -0.005em;
  color: var(--stv-texte);
  text-align: center;
  text-wrap: balance;
}

/* =====================================================================
   PAGES CONSEILS — la colonne de lecture, la section de FAQ, la rangée de
   cartes de catégories (lot B du 05/10, tâche 126). Relevé Dev Mode :
   156:9592 (colonne « Quand un accompagnement en studio reste
   pertinent »), 156:9648 (colonne + trois cartes), 156:9664 (FAQ) ;
   mobile 156:8738, 156:8794, 156:8810.

   Le reste des guides est au socle : bandeau d'en-tête (`stv-bandeau
   --tete`, § 3), sections texte + image (`stv-split`, § 4), encadrés
   (`stv-callout`, § 5), prose et tableau (`stv-prose--conseil`, § 8). Ici,
   ce qui n'a qu'une forme de page de contenu.

   Trois répétitions sur les enveloppes : ce sont des éléments V4.
   ================================================================== */

/*
   LA SECTION AUX BLOCS ESPACÉS — 48 entre ses enfants (156:9648 : la
   colonne, puis la rangée de cartes ; 48 aussi en mobile, 156:8794).
*/
.stv-section--espacee.stv-section--espacee.stv-section--espacee {
  gap: var(--stv-espace-48);
}

/*
   LA COLONNE DE LECTURE — `stv-colonne-lecture` (156:9593, 156:9649) : 816
   centrés, un H2 puis la prose à 48 (48 aussi en mobile, 156:8740). Le
   titre est un widget Titre (sa classe arrive sur l'enveloppe : second
   sélecteur en `:where()`, comme `stv-split__titre`) ; la prose, un Éditeur
   de texte `stv-prose stv-prose--conseil` (socle § 8.4).
*/
.stv-colonne-lecture.stv-colonne-lecture.stv-colonne-lecture {
  display: flex;
  flex-direction: column;
  gap: var(--stv-espace-48);
  width: 100%;
  max-width: var(--stv-largeur-texte);
  margin-inline: auto;
  padding: 0;
}

.stv-colonne-lecture .stv-colonne-lecture__titre,
.stv-colonne-lecture .stv-colonne-lecture__titre :where(h1, h2, p, .elementor-heading-title) {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-h2);
  font-weight: 500;
  line-height: var(--stv-interligne-titre);
  letter-spacing: -0.005em;
  color: var(--stv-texte);
  text-wrap: balance;
}

/*
   LA FAQ DE PAGE — `stv-faq-section` (156:9664) : titre centré, 48, la liste
   de 1 104 centrée ; 32 en mobile (156:8810). Même rythme que la page FAQ
   (`stv-faq-page`), sous un H2 et non un H1. L'accordéon est le widget
   d'Elementor habillé `stv-faq--plus` (plus haut, « ACCORDÉON »).
*/
.stv-faq-section.stv-faq-section.stv-faq-section {
  align-items: center;
  gap: var(--stv-espace-48);
}

.stv-faq-section .stv-faq-section__titre,
.stv-faq-section .stv-faq-section__titre :where(h1, h2, p, .elementor-heading-title) {
  margin: 0;
  font-family: var(--stv-police-titres);
  font-size: var(--stv-taille-h2);
  font-weight: 500;
  line-height: var(--stv-interligne-titre);
  letter-spacing: -0.005em;
  color: var(--stv-texte);
  text-align: center;
  text-wrap: balance;
}

/* Cinq classes (0,5,0) : le widget est un enfant direct d'un conteneur, et
   le kit pose `.elementor.elementor .e-con > .elementor-widget { max-width:
   100% }` (0,4,0) — à 0,3,0 la liste s'étalait sur 1 680 (mesuré le 05/10). */
.stv-faq-section.stv-faq-section.stv-faq-section .stv-faq.stv-faq {
  width: 100%;
  max-width: var(--stv-faq-bloc-largeur, 1104px);
}

/*
   LA RANGÉE DE CARTES DE CATÉGORIES — `[stelvoren_collections
   mode="suggestion"]` (156:9654) : la liste de « Vous pourriez aimer »,
   `stv-suggestions__liste`, trois colonnes au tiers à 24, centrées ; une
   colonne en mobile, à 24 (156:8800).

   SORTIE DE catalogue.css LE 05/10 : elle n'était chargée que sur les
   archives. Mêmes règles, même compte (0,2,0 — `.stv-suggestions
   .stv-suggestions__liste` devient `.stv-suggestions__liste` répétée), sans
   le contexte de la section, que la page n'a pas. Non-régression mesurée
   sur une feuille (relevé du jour).

   `--page` : le nom en Outfit Medium 24 (156:9656) et non 32 — la carte
   de la page partage sa rangée avec le texte qui l'annonce.
*/
.stv-suggestions__liste.stv-suggestions__liste {
  display: flex;
  justify-content: center;
  gap: var(--stv-espace-24);
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

.stv-suggestions__element.stv-suggestions__element {
  display: flex;
  flex: 0 1 calc((100% - 2 * var(--stv-espace-24)) / 3);
  min-width: 0;
  margin: 0;
  padding: 0;
}

.stv-suggestions__element > .stv-carte-collection {
  flex: 1 1 auto;
}

.stv-suggestions__liste--page .stv-carte-collection.stv-carte-collection--suggestion .stv-carte-collection__libelle {
  font-size: var(--stv-suggestion-page-nom, 24px);
}

@media (max-width: 767px) {
  .stv-faq-section.stv-faq-section.stv-faq-section {
    gap: var(--stv-espace-32);
  }

  .stv-suggestions__liste.stv-suggestions__liste {
    flex-direction: column;
  }

  .stv-suggestions__element.stv-suggestions__element {
    flex: 0 0 auto;
  }
}

/* =====================================================================
   PASTILLES DE COULEUR — `stv-pastilles` (lot « Favoris », 13/10)
   Relevé Dev Mode `156:5353` (carte de la liste de souhaits : pastilles de
   20, écart 4,8) ; la nouvelle fiche les dessine au double (`303:10218` :
   40, écart 8) — même composant, UNE variable.

   Une pastille = un cadre et un aplat : filet de 1/26 de la taille (0,77 à
   20 ; 1,54 à 40), marge intérieure de 1/13 (1,54 ; 3,08), aplat de 10/13
   (15,38 ; 30,77). Filet noir à 20 % au repos, NOIR pour la pastille
   choisie (`156:5354`). La couleur vient du terme d'attribut
   (`stelvoren_couleur_terme()`, stelvoren-champs), posée en variable sur la
   pastille ; le nom de la couleur est son libellé accessible — la couleur
   seule ne dit rien à qui ne la voit pas.

   Ce sont des BOUTONS à état (`aria-pressed`) qui commandent une liste
   d'options ; ils ne la remplacent pas. Trois classes : c'est un `<button>`
   (kit 0,1,1, reset de Hello 0,2,0 au survol).

   Survol et focus NON DESSINÉS : le filet monte à 50 %, contour au focus.

   FILET ET MARGE ARRONDIS AU PIXEL (signalé par Logan, 26/10 à 18 h 11 :
   l'aplat n'était pas centré dans son cadre). Chrome arrondit un filet de
   0,77 à 1 px mais garde la marge de 1,54 : l'aplat tombait sur une
   fraction de pixel et s'accrochait à la grille autrement que le cadre —
   1 px d'air à gauche et en haut, 2 à droite et en bas. `round()` rend
   des valeurs entières : 1 + 2 + 14 à 20, 2 + 3 + 30 à 40 ; cadre et aplat
   partagent alors la même fraction et s'arrondissent ensemble. La première
   déclaration est le repli des navigateurs sans `round()` (valeurs à 20).
   ================================================================== */

.stv-pastilles {
  --stv-pastille-taille: 20px;
  --stv-pastille-ecart: 4.8px;

  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--stv-pastille-ecart);
  margin: 0;
  padding: 0;
}

.stv-pastilles[hidden] {
  display: none;
}

.stv-pastilles .stv-pastilles__pastille.stv-pastilles__pastille {
  box-sizing: border-box;
  display: block;
  flex: 0 0 auto;
  width: var(--stv-pastille-taille);
  height: var(--stv-pastille-taille);
  min-height: 0;
  margin: 0;
  padding: 2px;
  padding: round(var(--stv-pastille-taille) / 13, 1px);
  border: 1px solid rgba(2, 10, 18, 0.2);
  border-width: max(1px, round(var(--stv-pastille-taille) / 26, 1px));
  border-radius: var(--stv-rayon);
  background: none;
  box-shadow: none;
  line-height: 0;
  cursor: pointer;
}

.stv-pastilles .stv-pastilles__pastille.stv-pastilles__pastille:hover,
.stv-pastilles .stv-pastilles__pastille.stv-pastilles__pastille:focus {
  border-color: rgba(2, 10, 18, 0.5);
  background: none;
}

.stv-pastilles .stv-pastilles__pastille.stv-pastilles__pastille[aria-pressed="true"] {
  border-color: var(--stv-noir);
}

.stv-pastilles .stv-pastilles__pastille.stv-pastilles__pastille:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

.stv-pastilles .stv-pastilles__couleur {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--stv-pastille-couleur, var(--stv-gris-clair));
}

/* =====================================================================
   MISSION DE L'ACCUEIL — `stv-mission` (recette d'Estevan R30 / R31,
   28/10, tâche 205)
   ---------------------------------------------------------------------
   La section « Stelvoren aide chacun à se remettre en forme… » : conteneur
   6695c50 d'`outils/pages/accueil.json`, classe CSS « stv-mission ». À
   gauche trois lignes de lien (classe globale `stv-conteneur-lien-accueil`,
   libellé `stv-texte-lien-accueil`, flèche e-svg) ; à droite la photo
   (widget Image 606d4a6, `stv-mission__visuel`).

   LE SURVOL — 356:17699 (survol) contre 356:17709 (repos) : la ligne prend
   un fond blanc à 50 % et un retrait de 24 de chaque côté — le libellé
   avance de 24, la flèche recule de 24 (1062 → 1038). Joué en translation
   des deux enfants, pas en padding : rien ne se réagence. Jetons du survol
   (`--stv-survol-duree`, `--stv-survol-courbe`) ; même état au focus
   clavier ; coupé en prefers-reduced-motion. La classe globale pèse
   0,2,0 (`.elementor .stv-…`) : ces règles 0,3,0 au moins.

   LA PHOTO — 565 × 561 dans la maquette (356:17719) : le cadre est tenu par
   aspect-ratio + object-fit, quelle que soit la photo posée.

   L'IMAGE QUI CHANGE AU SURVOL — 358:10630 (trois variantes) : « Notre
   catalogue » = la photo de repos (pas de vue à lui), « Installer son
   studio » = Soda Studio (606d4a7, `--2`), « Espace Pro » = le showroom
   (606d4a8, `--3`). Une vue = un widget Image de la colonne a2ae67c,
   APRÈS 606d4a6, `_css_classes` = « stv-mission__visuel
   stv-mission__visuel--survol stv-mission__visuel--N » (N = rang de la
   ligne) et `_attributes` = « aria-hidden|true » (doublon visuel : rien à
   lire), son média déclaré dans le bloc « medias ». Elle se pose sur la
   photo de repos, au même cadre, et apparaît en fondu quand la ligne N est
   survolée ou a le focus clavier. Sans `:has()` (navigateurs anciens) ou
   au tactile, les vues restent masquées : la photo de repos seule.
   ================================================================== */

.stv-mission.stv-mission .stv-conteneur-lien-accueil {
  transition: background-color var(--stv-survol-duree) var(--stv-survol-courbe);
}

.stv-mission.stv-mission .stv-conteneur-lien-accueil > * {
  transition: transform var(--stv-survol-duree) var(--stv-survol-courbe);
}

@media (hover: hover) {
  .stv-mission.stv-mission .stv-conteneur-lien-accueil:hover {
    background-color: rgba(255, 255, 255, 0.5);
  }

  .stv-mission.stv-mission .stv-conteneur-lien-accueil:hover > :first-child {
    transform: translateX(24px);
  }

  .stv-mission.stv-mission .stv-conteneur-lien-accueil:hover > :last-child {
    transform: translateX(-24px);
  }
}

.stv-mission.stv-mission .stv-conteneur-lien-accueil:focus-visible {
  background-color: rgba(255, 255, 255, 0.5);
}

.stv-mission.stv-mission .stv-conteneur-lien-accueil:focus-visible > :first-child {
  transform: translateX(24px);
}

.stv-mission.stv-mission .stv-conteneur-lien-accueil:focus-visible > :last-child {
  transform: translateX(-24px);
}

.stv-mission .stv-mission__visuel img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 565 / 561;
  object-fit: cover;
  object-position: center;
}

.stv-mission .stv-mission__visuel--survol {
  display: none;
}

@supports selector(:has(*)) {
  @media (hover: hover) and (min-width: 768px) {
    .stv-mission .e-div-block-base:has(> .stv-mission__visuel--survol) {
      position: relative;
    }

    .stv-mission.stv-mission .stv-mission__visuel--survol {
      display: block;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      margin: 0;
      opacity: 0;
      pointer-events: none;
      transition: opacity var(--stv-survol-duree) var(--stv-survol-courbe);
    }

    .stv-mission:has(.stv-conteneur-lien-accueil:nth-child(1):is(:hover, :focus-visible)) .stv-mission__visuel--1,
    .stv-mission:has(.stv-conteneur-lien-accueil:nth-child(2):is(:hover, :focus-visible)) .stv-mission__visuel--2,
    .stv-mission:has(.stv-conteneur-lien-accueil:nth-child(3):is(:hover, :focus-visible)) .stv-mission__visuel--3,
    .stv-mission:has(.stv-conteneur-lien-accueil:nth-child(4):is(:hover, :focus-visible)) .stv-mission__visuel--4 {
      opacity: 1;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .stv-mission.stv-mission .stv-conteneur-lien-accueil,
  .stv-mission.stv-mission .stv-conteneur-lien-accueil > *,
  .stv-mission.stv-mission .stv-mission__visuel--survol {
    transition: none;
  }
}

/* ==========================================================================
   ANCRES SOUS L'EN-TÊTE FIXE (tâche 184, 29/10)

   Un saut d'ancre (lien d'une liste d'erreurs de la commande, lien
   d'évitement « Aller au contenu », ancre d'une page) posait sa cible à
   32 px du haut : WordPress ne compte que sa barre d'administration
   (`html { scroll-padding-top: var(--wp-admin--admin-bar--height) }`,
   admin-bar.css). Le champ en focus restait SOUS l'en-tête fixe (WCAG 2.4.11).

   Le document compte désormais la navigation. Pas l'annonce : elle part
   avec la page dès qu'on a défilé (R1, 26/10). Sur ordinateur l'en-tête se
   retire en descente (entete.js) : le saut vers le bas laisse alors une
   bande vide de la hauteur de la navigation, jamais une cible couverte.
   `:root` (0,1,0) bat le `html` (0,0,1) d'admin-bar.css quel que soit
   l'ordre des feuilles ; la variable de WordPress n'existe qu'avec la barre.

   Conséquence pour les marges de défilement : elles ne comptent plus la
   navigation (intertitres de l'article : socle.css § 8.3 ; liste du blog :
   blog.css). Les défilements écrits en script (`window.scrollTo` de
   commande.js et panier-page.js) ne lisent pas `scroll-padding` : inchangés.
   ========================================================================== */

:root {
  scroll-padding-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--stv-barre-h));
}

/* Un champ visé par une ancre garde aussi son libellé en vue : le libellé
   est AU-DESSUS du champ (145.4), l'ancre vise le champ. */
.woocommerce form .form-row :is(input, select, textarea),
.elementor-form .elementor-field-group :is(input, select, textarea) {
  scroll-margin-top: var(--stv-espace-48, 48px);
}

/* ==========================================================================
   PAGINATION : CIBLES DE 24 × 24 (tâche 168, B.6, 29/10)

   Lighthouse (`target-size`, WCAG 2.5.8) : les numéros étaient des liens de
   17 × 26, centres à 20,6 l'un de l'autre (écart 12 entre des chiffres de
   9) — ni la taille ni l'espacement ne passaient. Chaque numéro, lien ou
   non, devient une case de 24 au moins, collée à la suivante : les chiffres
   sont à 24 d'axe en axe au lieu de 20,6 (+3,4 par pas, écart assumé). Les
   flèches gardent leurs 12 de marge. Le trait du numéro courant, un
   `::after` calé sur une boîte de 10 de large comme son chiffre, devient un
   soulignement du texte, au dessin du survol (0,75, décalé de 5) : il suit
   le chiffre quelle que soit la largeur de la case, « 12 » compris.
   Mêmes sélecteurs que le bloc d'origine, plus bas : ils gagnent par l'ordre.
   ========================================================================== */

.stv-pagination .stv-pagination__liste {
  gap: 0;
}

.stv-pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;
  box-sizing: border-box;
}

.stv-pagination a.page-numbers {
  margin: 0;
  padding: 0 var(--stv-espace-4);
}

.stv-pagination .page-numbers.current {
  text-decoration: underline 0.75px;
  text-underline-offset: 5px;
}

.stv-pagination .page-numbers.current::after {
  content: none;
}

/* ==========================================================================
   ONGLETS DE L'ACCUEIL : TITRE INACTIF LISIBLE (tâche 168, B.5, 29/10)

   Les deux widgets Onglets imbriqués de l'accueil (« Meilleures ventes /
   Nouveautés », « Pilates / Yoga / Fitness ») posent leur titre inactif
   à #24262E80 (anthracite à 0,5) : 3,09:1 sur blanc, pour un texte de 16
   et 20 en graisse 500 — sous les 4,5:1 de WCAG 1.4.3.

   Elementor colore le titre par `color: var(--n-tabs-title-color)` et pose
   la variable sur l'enveloppe du widget (post-73.css). La redéfinir SUR le
   titre l'emporte quel que soit le poids de sa règle : c'est le titre qui
   lit la variable. Valeur : `--stv-onglet-inactif` (0,8, ≈ 8:1), le jeton
   des onglets de la fiche produit — un seul dessin d'onglet inactif.
   Le JSON de l'accueil n'est pas touché : la retouche voyage par git.
   ========================================================================== */

.elementor-widget-n-tabs .e-n-tab-title[aria-selected="false"] {
  --n-tabs-title-color: var(--stv-onglet-inactif);
}

/* ==========================================================================
   CASE À COCHER D'UN FORMULAIRE ELEMENTOR (tâche 165, 29/10)

   Première case d'un widget Formulaire : « Je souhaite une offre de
   financement » sur l'Espace pro. Sans règle, la case native (13 × 13)
   recevait le gris des champs du kit Elementor (0,3,1). Elle prend le dessin
   de la case WooCommerce du socle (§ 9.6 : 12 × 12, filet noir, fond noir et
   coche blanche une fois cochée) ; son libellé reste un `<label for>`, toute
   la ligne est cliquable. Poids 0,5,1 pour passer le champ du kit.
   ========================================================================== */

.elementor-field-type-checkbox.elementor-field-type-checkbox .elementor-field-option {
  display: flex;
  align-items: flex-start;
  gap: var(--stv-espace-8, 8px);
}

.elementor-field-type-checkbox.elementor-field-type-checkbox .elementor-field-option input[type="checkbox"][type="checkbox"] {
  appearance: none;
  flex: 0 0 12px;
  box-sizing: border-box;
  width: 12px;
  height: 12px;
  min-height: 0;
  margin: 0.3em 0 0;
  padding: 0;
  border: 1px solid var(--stv-noir);
  border-radius: var(--stv-rayon);
  background: transparent;
  cursor: pointer;
}

.elementor-field-type-checkbox.elementor-field-type-checkbox .elementor-field-option input[type="checkbox"][type="checkbox"]:checked {
  border-color: var(--stv-noir);
  background: var(--stv-noir) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 6'%3E%3Cpath d='M1 3l2 2 4-4' fill='none' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") center / 8px 6px no-repeat;
}

.elementor-field-type-checkbox.elementor-field-type-checkbox .elementor-field-option input[type="checkbox"][type="checkbox"]:focus-visible {
  outline: 2px solid var(--stv-anthracite);
  outline-offset: 2px;
}

.elementor-field-type-checkbox.elementor-field-type-checkbox .elementor-field-option label {
  cursor: pointer;
}

/* Le bouton « Afficher le mot de passe » de WooCommerce (tâche 168, B.6) :
   22 × 22 dans woocommerce-layout.css (0,2,1), sous les 24 × 24 de WCAG
   2.5.8. Porté à 24, l'icône de 22 centrée dedans — un pixel de décalage,
   rien d'autre. Compte (connexion, inscription, profil) et commande. */
.woocommerce form .show-password-input.show-password-input,
.woocommerce-page form .show-password-input.show-password-input {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 24px;
  min-height: 24px;
}

/* =====================================================================
   TIROIR — LES SUGGESTIONS « Vous pourriez également apprécier… »
   (fiche 107, 29/10 ; maquette `156:11315`, carte `156:11318`)
   ---------------------------------------------------------------------
   La carte EST une ligne empilée (`stv-ligne-panier--empilee` : 544 × 144,
   gris clair, vignette 112, marge et écart 16 — règles plus haut) ; seule
   sa colonne de droite diffère : nom et prix, déclinaison, puis, à 12, les
   pastilles (le composant `stv-pastilles` à sa taille par défaut : carré
   de 15,4 dans un cadre de 0,77, 4,8 d'écart — c'est la cote de la
   maquette) et « + AJOUTER AU PANIER » (Inter Medium 14, capitales,
   souligné, un + de 12 à 6).

   Survol et focus de l'action NON DESSINÉS : le soulignement s'épaissit,
   contour au focus clavier. Le bouton est un <button> : le reset de Hello
   (bordure, fond et couleur de survol) est neutralisé à 0,4,0.
   ================================================================== */

.stv-tiroir .stv-ligne-panier--suggestion .stv-ligne-panier__corps {
  justify-content: flex-start;
  gap: var(--stv-espace-12);
}

.stv-tiroir .stv-ligne-panier--suggestion .stv-ligne-panier__media > a {
  display: block;
  width: 100%;
  height: 100%;
}

.stv-tiroir .stv-panier-suggestion__bas.stv-panier-suggestion__bas {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--stv-espace-12);
}

.stv-tiroir .stv-panier-suggestion__action.stv-panier-suggestion__action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 24px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  color: var(--stv-noir);
  font-family: var(--stv-police-texte);
  font-size: var(--stv-taille-petit);
  font-weight: 500;
  line-height: var(--stv-interligne-texte);
  letter-spacing: 0;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-position: from-font;
  cursor: pointer;
}

.stv-tiroir .stv-panier-suggestion__action.stv-panier-suggestion__action:is(:hover, :focus) {
  border: 0;
  background: none;
  color: var(--stv-noir);
  text-decoration-thickness: 2px;
}

.stv-tiroir .stv-panier-suggestion__action.stv-panier-suggestion__action:focus-visible {
  outline: 2px solid var(--stv-noir);
  outline-offset: 2px;
}

/* Pendant l'ajout (panier-tiroir.js pose `stv-envoi` sur le bouton qui soumet). */
.stv-tiroir .stv-panier-suggestion__action.stv-envoi {
  opacity: 0.4;
  pointer-events: none;
}

.stv-tiroir .stv-panier-suggestion__plus {
  flex: 0 0 12px;
  width: 12px;
  height: 12px;
}

/*
   La pastille de TEXTE — un terme sans couleur saisie (repli de la 107) :
   le même cadre, à la largeur de son nom. Valable partout où le composant
   en rendrait une.
*/
.stv-pastilles .stv-pastilles__pastille.stv-pastilles__pastille--texte {
  width: auto;
  min-width: var(--stv-pastille-taille);
  padding: 0 4px;
}

.stv-pastilles .stv-pastilles__texte {
  display: block;
  font-family: var(--stv-police-texte);
  font-size: 11px;
  font-weight: 500;
  line-height: calc(var(--stv-pastille-taille) - 2px);
  color: var(--stv-noir);
  white-space: nowrap;
}
