/* ============================================================
   CWV Variation Selector — Theme "CBDPURPLE"
   ------------------------------------------------------------
   Skin complet et autonome (structure + style) calque sur la
   maquette "CBD PURPLE - Refonte CRO".
   Ce fichier n'est charge QUE lorsque le theme CBDPURPLE est
   selectionne dans la configuration du module. Le theme
   CBDPASCHERE (views/css/front.css) reste totalement inchange.

   Perimetre : choix de la declinaison + affichage prix +
   choix de quantite + bouton d'ajout au panier.
   ============================================================ */

/* ---------- Tokens de marque (DA CBD Purple) ---------- */
.cwvvs {
  --cwvvs-magenta: rgb(88, 53, 170);
  --cwvvs-purple: #9747ff;
  --cwvvs-violet: #7c43e8;
  --cwvvs-grad: linear-gradient(115deg, #bb3ab0 0%, #9747ff 55%, #7c43e8 100%);
  --cwvvs-teal: #2ea6b3;
  --cwvvs-yellow: #ffd633;
  --cwvvs-red: #e8203a;

  --cwvvs-ink: #1a0f24;
  --cwvvs-text: #211726;
  --cwvvs-muted: #6a5d72;
  --cwvvs-border: rgb(88, 53, 170);
  --cwvvs-line-2: #f4f1f7;
  --cwvvs-tint: #f6eefb;
  --cwvvs-soft: #faf7fc;

  --cwvvs-accent: var(--cwvvs-magenta);
  --cwvvs-radius: 16px;
  --cwvvs-radius-sm: 12px;
  --cwvvs-pill: 999px;
  --cwvvs-shadow: 0 4px 14px rgba(26, 15, 36, .07), 0 12px 32px rgba(26, 15, 36, .06);
  --cwvvs-glow: 0 8px 28px rgba(187, 58, 176, .32);

  color: var(--cwvvs-text);
}

/* ---------- Layout des roots ---------- */
.cwvvs--list {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  flex-grow: 1;
  justify-content: end;
}

.cwvvs--sticky {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 1rem;
}

.cwvvs__sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.cwvvs__select-wrap {
  width: 100%;
  margin-top: 5px;
}

.cwvvs__list-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.55rem;
}

.cwvvs__list-row--guest {
  align-items: stretch;
}

/* ---------- Select natif (fallback + pilote des pills) ---------- */
.cwvvs__select,
.cwvvs__button,
.cwvvs__card {
  min-height: 48px;
}

.cwvvs__select {
  width: 100%;
  padding: 13px 16px;
  border: 1.6px solid var(--cwvvs-border);
  border-radius: var(--cwvvs-radius-sm);
  background: #fff;
  color: var(--cwvvs-text);
  font: inherit;
  appearance: auto;
  font-size: 1rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.cwvvs__select:focus {
  outline: none;
  border-color: var(--cwvvs-magenta);
  box-shadow: 0 0 0 3px rgba(187, 58, 176, .12);
}

.cwvvs__qty-select {
  min-height: 48px;
  width: 78px;
  min-width: 78px;
  max-width: 78px;
  padding: 10px;
  border: 1.6px solid var(--cwvvs-border);
  border-radius: var(--cwvvs-radius-sm);
  background: #fff;
  color: var(--cwvvs-text);
  font: inherit;
  appearance: auto;
  flex: 0 0 auto;
}

.cwvvs__select--sticky {
  min-width: 170px;
  max-width: 260px;
}

.cwvvs__qty-select--sticky {
  width: 72px;
  min-width: 72px;
  max-width: 72px;
}

.cwvvs__qty-select--product {
  width: 62px;
  min-width: 62px;
  max-width: 62px;
  align-self: center;
  flex: 0 0 auto;
}

/* Quand l'amelioration JS (pills/stepper) est active, on masque
   le controle natif correspondant tout en le gardant dans le DOM
   pour que la logique de front.js continue de fonctionner. */
.cwvvs-enhanced > .cwvvs__select-wrap,
.cwvvs-enhanced .cwvvs__qty-select.is-cwvvs-driven {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Pills de declinaison (injectees par le JS en liste) ---------- */
.cwvvs__pills {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(45px, 1fr));
  gap: 8px;
  width: 100%;
}

.cwvvs__pill {
  flex: 1 1 auto;
  min-width: 54px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 9px 10px;
  border: 1.5px solid var(--cwvvs-border);
  border-radius: 10px;
  background: #fff;
  color: var(--cwvvs-muted);
  font: inherit;
  line-height: 1.1;
  cursor: pointer;
  transition: border-color .14s ease, background-color .14s ease, color .14s ease, box-shadow .14s ease;
}

.cwvvs__pill:hover {
  border-color: var(--cwvvs-magenta);
  color: var(--cwvvs-magenta);
}

.cwvvs__pill.is-active {
  border-color: var(--cwvvs-magenta);
  background: #fbeef9;
  color: rgb(88, 53, 170); /* magenta assombri : AA 5:1 sur #fbeef9 (ex var(--cwvvs-magenta) #bb3ab0 = 4.3) */
  box-shadow: 0 0 0 1.5px rgba(187, 58, 176, .35);
}

.cwvvs__pill-label {
  font-size: 0.98rem;
  font-weight: 700;
  letter-spacing: -.01em;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cwvvs__pill-unit {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--cwvvs-muted);
}

.cwvvs__pill.is-active .cwvvs__pill-unit {
  color: #aa35a0;
}

.cwvvs__pill.is-unavailable {
  cursor: not-allowed;
  background: var(--cwvvs-line-2);
  border-color: var(--cwvvs-border);
}

/* Etat indisponible accessible : opacity .5 faisait chuter le contraste du
   libelle a ~2.1:1. On garde l'aspect "estompe" via un gris fonce conforme
   AA (>=4.5:1). La pastille active reste en magenta (regle .is-active). */
.cwvvs__pill.is-unavailable:not(.is-active) .cwvvs__pill-label,
.cwvvs__pill.is-unavailable:not(.is-active) .cwvvs__pill-unit {
  color: #706c73;
}

/* La pastille selectionnee reste lisible meme si la declinaison est
   en rupture (l'etat epuise est porte par le bouton). */
.cwvvs__pill.is-active.is-unavailable {
  opacity: 1;
}

/* ---------- Declinaisons en fiche produit (cartes -> pills DA) ---------- */
.cwvvs__grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 18px;
}

.cwvvs__card {
  position: relative;
  flex: 1 1 auto;
  min-width: 76px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 11px 14px;
  border: 1.6px solid var(--cwvvs-border);
  border-radius: 14px;
  background: #fff;
  text-align: center;
  cursor: pointer;
  outline: none;
  -webkit-tap-highlight-color: transparent;
  transition: border-color .14s ease, background-color .14s ease, box-shadow .14s ease;
}

.cwvvs__card:hover {
  border-color: var(--cwvvs-magenta);
}

.cwvvs__card.is-active {
  border-color: var(--cwvvs-magenta);
  background: #fbeef9;
  box-shadow: 0 0 0 1.5px rgba(187, 58, 176, .35);
}

.cwvvs__card.is-unavailable {
  background: var(--cwvvs-soft);
  border-color: var(--cwvvs-border);
  cursor: not-allowed;
}

/* Etat indispo accessible : opacity .55 faisait chuter le contraste du texte
   jusqu'a ~2.3:1. On garde l'aspect estompe via un gris fonce conforme AA.
   La carte active reste lisible (regle .is-active). */
.cwvvs__card.is-unavailable:not(.is-active) .cwvvs__card-title,
.cwvvs__card.is-unavailable:not(.is-active) .cwvvs__card-unit {
  color: #706c73;
}

.cwvvs__card-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 0;
}

.cwvvs__card-title {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--cwvvs-text);
}

.cwvvs__card.is-active .cwvvs__card-title {
  color: rgb(88, 53, 170);
}

.cwvvs__card-unit,
.cwvvs__unit-inline {
  color: var(--cwvvs-muted);
  font-size: 0.78rem;
  font-weight: 600;
}

.cwvvs__card.is-active .cwvvs__card-unit {
  color: #aa35a0;
}

/* La maquette n'affiche que le grammage + le prix au gramme dans la
   pastille : on masque le prix total/barre interne a la carte. */
.cwvvs__card-prices {
  display: none;
}

/* ---------- Fiche produit : bloc prix + label (iso BuyBox) ---------- */
.cwvvs__product-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 18px;
}

.cwvvs__product-price .cwvvs__price {
  order: 1;
  font-size: 2.2rem;
  font-weight: 800;
  letter-spacing: -.025em;
  color: var(--cwvvs-ink);
}

.cwvvs__product-price .cwvvs__regular {
  order: 2;
  font-size: 1.15rem;
}

.cwvvs__product-price .cwvvs__unit-wrap {
  order: 3;
  color: var(--cwvvs-muted);
  font-weight: 600;
  font-size: 0.85rem;
}

.cwvvs__product-price .cwvvs__unit-wrap[hidden] {
  display: none;
}

.cwvvs__field-label {
  margin-bottom: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--cwvvs-text);
}

.cwvvs__field-label span {
  color: var(--cwvvs-muted);
  font-weight: 500;
}

.cwvvs--product .cwvvs__card-unit {
  font-size: 0.72rem;
}

/* Stepper fiche produit : version large (cf. .qty-lg du handoff). */
.cwvvs--product .cwvvs__stepper button {
  width: 46px;
  height: 46px;
}

.cwvvs--product .cwvvs__stepper-value {
  min-width: 34px;
  font-size: 1rem;
}

/* ---------- Prix ---------- */
.cwvvs__prices {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.1rem 0.55rem;
  min-width: 0;
  line-height: 1.1;
}

.cwvvs__price {
  order: 1;
  font-weight: 800;
  font-size: 1.55rem;
  letter-spacing: -.025em;
  color: var(--cwvvs-ink);
}

.cwvvs__regular {
  order: 2;
  color: var(--cwvvs-red);
  text-decoration: line-through;
  font-size: 1rem;
  font-weight: 700;
}

.cwvvs__unit-inline {
  order: 3;
  margin-left: auto;
  color: var(--cwvvs-muted);
  font-weight: 600;
  font-size: 0.82rem;
}

/* ---------- Stepper de quantite (injecte par le JS) ---------- */
.cwvvs__stepper {
  display: inline-flex;
  align-items: center;
  gap: 0;
  border: 1.6px solid var(--cwvvs-border);
  border-radius: var(--cwvvs-pill);
  background: #fff;
  flex: 0 0 auto;
  overflow: hidden;
}

.cwvvs__stepper button {
  width: 42px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  color: var(--cwvvs-text);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  transition: color .14s ease, background-color .14s ease;
}

.cwvvs__stepper button:focus,
.cwvvs__stepper button:focus-visible {
  outline: none;
  box-shadow: none;
}

.cwvvs__stepper button:hover:not(:disabled) {
  color: var(--cwvvs-magenta);
}

.cwvvs__stepper button:disabled {
  color: var(--cwvvs-border);
  cursor: not-allowed;
}

.cwvvs__stepper-value {
  min-width: 34px;
  text-align: center;
  font-weight: 800;
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
}

/* ---------- Barre d'achat unifiee (vignette) ----------
   Stepper + bouton reunis dans UN seul contour commun, hauteur fixe
   (cf. handoff : .pcard-buy / .pcard-addbtn). */
.cwvvs__cart {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
}

.cwvvs-enhanced .cwvvs__cart {
  height: 42px;
  align-items: stretch;
  gap: 0;
  padding: 2px;
  border: 1.5px solid var(--cwvvs-border);
  border-radius: var(--cwvvs-pill);
  background: #fff;
  overflow: hidden;
}

.cwvvs__cart .cwvvs__stepper {
  flex: 0 0 auto;
  height: 100%;
  border: 0;
  background: transparent;
  border-radius: 0;
}

.cwvvs__cart .cwvvs__button {
  flex: 1 1 auto;
  min-width: 0;
}

/* Le bouton foncé devient une pastille en retrait dans la barre. */
.cwvvs-enhanced .cwvvs__cart .cwvvs__button {
  min-height: 0;
  height: auto;
  box-shadow: none;
}

.cwvvs--list .cwvvs__stepper button {
  width: 32px;
  height: 100%;
  font-size: 1rem;
}

.cwvvs--list .cwvvs__stepper-value {
  min-width: 22px;
  font-size: 0.9rem;
}

.cwvvs--list .cwvvs__button {
  padding: 0 14px;
  gap: 0.4rem;
  font-size: 0.9rem;
}

.cwvvs--list .cwvvs__button-icon svg {
  width: 18px;
}

/* ---------- Indicateur de stock restant (option BO) ---------- */
.cwvvs__stock {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  font-size: 0.8rem;
  font-weight: 700;
  color: #996308; /* contraste AA (5:1 sur blanc) — ex #b8770a (3.7:1) */
  white-space: nowrap;
}

.cwvvs__stock[hidden] {
  display: none;
}

/* Espace reserve : utilise quand la carte possede au moins une declinaison
   susceptible d'afficher l'indicateur. Le bloc reste dans le flux (hauteur
   d'une ligne reservee) et on ne fait varier que l'opacite -> aucun saut de
   mise en page lors du changement de declinaison, avec un fondu doux. */
.cwvvs__stock--reserved {
  min-height: 1.05rem;
  opacity: 0;
  transition: opacity 0.18s ease;
}

.cwvvs__stock--reserved.is-visible {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .cwvvs__stock--reserved {
    transition: none;
  }
}

.cwvvs__stock-icon {
  display: inline-flex;
}

.cwvvs__stock-icon svg {
  display: block;
}

.cwvvs__stock--product {
  margin-top: 10px;
  margin-bottom: 0;
  color: #d81e36; /* rouge assombri : AA 5:1 sur blanc (ex var(--cwvvs-red) #e8203a = 4.46) */
}

/* Pastilles compactes sur une seule ligne : le prix au gramme est
   affiche sur la ligne de prix, aligne a droite (cf. maquette). */
.cwvvs--list .cwvvs__pill {
  min-width: 0;
  padding: 9px 8px;
  outline: none;
}

.cwvvs--list .cwvvs__pill-unit {
  display: none;
}

.cwvvs--list .cwvvs__pill-label {
  font-size: 0.95rem;
}

/* ---------- Boutons ---------- */
.cwvvs__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 13px 20px;
  border: 0;
  border-radius: var(--cwvvs-pill);
  background: var(--cwvvs-ink);
  color: #fff;
  font-weight: 700;
  font-size: 0.96rem;
  letter-spacing: -.01em;
  cursor: pointer;
  white-space: nowrap;
  position: relative;
  box-shadow: 0 4px 14px rgba(26, 15, 36, .18);
  transition: background-color .2s ease, transform .12s ease, box-shadow .2s ease;
}

.cwvvs__button:hover:not(:disabled):not(.is-disabled) {
  background: var(--cwvvs-magenta);
  box-shadow: 0 6px 18px rgba(187, 58, 176, .3);
}

/* CTA principaux (fiche produit + sticky) : degrade de marque */
.cwvvs__button--full,
.cwvvs__button--sticky {
  background: var(--cwvvs-magenta);
  box-shadow: var(--cwvvs-glow);
}

.cwvvs__button--full:hover:not(:disabled):not(.is-disabled),
.cwvvs__button--sticky:hover:not(:disabled):not(.is-disabled) {
  background: var(--cwvvs-magenta);
  filter: brightness(1.06);
  box-shadow: 0 10px 34px rgba(187, 58, 176, .42);
}

.cwvvs__button:active:not(:disabled):not(.is-disabled) {
  transform: translateY(0) scale(.99);
}

.cwvvs__button.is-disabled,
.cwvvs__button:disabled {
  background: #6c6879;
  color: #fff;
  cursor: not-allowed;
  opacity: 1;
  box-shadow: none;
  transform: none;
}

/* ---------- Etat epuise : icone "panier barre" ----------
   Le JS pose .is-disabled sur le bouton uniquement quand la declinaison ou
   le produit est en rupture (l'etat "ajout en cours" utilise .is-loading).
   On masque alors l'icone panier normale et on affiche l'icone barree. */
.cwvvs__button-icon.cwvvs__button-icon--oos {
  display: none;
}

.cwvvs__button.is-disabled .cwvvs__button-icon:not(.cwvvs__button-icon--oos) {
  display: none;
}

.cwvvs__button.is-disabled .cwvvs__button-icon--oos {
  display: inline-flex;
}

.cwvvs__button.is-disabled .cwvvs__button-icon--oos svg path {
  stroke: #fff;
  fill: none;
}

.cwvvs__button--login {
  background: var(--cwvvs-ink);
  box-shadow: none;
}

.cwvvs__button--login:hover {
  filter: brightness(1.12);
  transform: translateY(-2px);
}

.cwvvs__button [data-cwvvs-button-label],
.cwvvs__button-copy {
  font-size: 0.95rem;
  flex: 0 1 auto;
  min-width: 0;
  text-align: left;
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- Etat epuise (liste) : rendu unifie ----------
   Qu'il s'agisse d'un produit simple ou a declinaisons, un produit
   epuise n'a pas besoin de selecteur de quantite. On masque alors le
   stepper et on affiche un unique bouton pleine largeur : le rendu est
   ainsi identique dans les deux cas. Avant, la declinaison gardait la
   barre compacte (bouton en retrait, ~36px) alors que le produit simple
   avait un bouton autonome plus grand (48px) -> difference visible. */
.cwvvs--list.cwvvs-combo-oos .cwvvs__stepper {
  display: none;
}

.cwvvs--list.cwvvs-combo-oos.cwvvs-enhanced .cwvvs__cart {
  border: 0;
}

.cwvvs--list.cwvvs-combo-oos.cwvvs-enhanced .cwvvs__cart .cwvvs__button,
.cwvvs__cart--simple-oos .cwvvs__button {
  margin: 0;
  width: 100%;
  min-height: 34px;
  height: auto;
}

/* Icone panier : forcer le blanc sur le degrade (surcharge les
   attributs SVG inline lime du markup). */
.cwvvs__button-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

.cwvvs__button-icon svg {
  display: block;
  width: 22px;
  height: auto;
  fill: transparent;
}

.cwvvs__button-icon svg path:first-child {
  stroke: #fff;
}

.cwvvs__button-icon svg path:last-child {
  fill: #fff;
}

/* ---------- Bouton pleine largeur (fiche produit) ----------
   Iso BuyBox : contenu centre "Ajouter · {total}". Le prix barre est
   porte par le bloc prix au-dessus, pas sur le bouton. */
.cwvvs__button--full {
  width: 100%;
  justify-content: center;
  align-items: center;
  gap: 0.55rem;
  padding: 16px 24px;
  font-size: 1.02rem;
}

.cwvvs__button--full .cwvvs__button-copy,
.cwvvs__button--full [data-cwvvs-button-label] {
  flex: 0 0 auto;
  text-align: center;
  overflow: visible;
}

.cwvvs__button--full .cwvvs__button-prices {
  margin-left: 0;
  gap: 0;
}

.cwvvs__button--full .cwvvs__button-regular {
  display: none;
}

.cwvvs__button--full .cwvvs__button-price::before {
  content: '\00B7';
  margin: 0 0.4rem 0 0.25rem;
  font-weight: 700;
  opacity: 0.85;
}

/* Quand le stepper est insere avant le bouton pleine largeur,
   le bouton occupe l'espace restant au lieu de deborder. */
.cwvvs__stepper + .cwvvs__button--full {
  flex: 1 1 auto;
  width: auto;
}

.cwvvs--product .cwvvs__button-icon svg {
  width: 26px;
}

.cwvvs__button-prices {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  white-space: nowrap;
  margin-left: auto;
  line-height: 1;
}

.cwvvs__button-regular {
  color: #ffd9f3;
  text-decoration: line-through;
  font-size: 0.88rem;
  font-weight: 700;
}

.cwvvs__button-price {
  font-size: 1.2rem;
  font-weight: 800;
  color: #fff;
}

/* ---------- Bouton sticky ---------- */
.cwvvs__button--sticky {
  min-height: 54px;
}

.cwvvs__sticky-prices {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  white-space: nowrap;
}

.cwvvs__sticky-prices--guest {
  display: none;
}

.cwvvs--sticky .cwvvs__price {
  font-size: 1.4rem;
}

.cwvvs__sticky-controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

/* ---------- Zone CTA fiche produit ---------- */
.cwvvs__product-cta {
  margin-top: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.cwvvs__product-cta--guest {
  justify-content: flex-start;
}

.cwvvs__product-form {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.85rem;
  width: 100%;
}

.cwvvs__subscription {
  width: 100%;
}

.cwvvs__product-submit-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
}

.cwvvs__product-form .form-wrapper,
.cwvvs__product-form .product_page_recurring_block {
  width: 100%;
}

/* ---------- Badge "A partir de .../gr" ---------- */
.cwvvs-badge {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  background: var(--cwvvs-tint);
  color: var(--cwvvs-magenta);
  box-sizing: border-box;
}

.cwvvs-badge__icon {
  display: inline-flex;
  flex: 0 0 auto;
}

.cwvvs-badge__icon svg rect {
  fill: var(--cwvvs-magenta);
}

.cwvvs-badge__icon svg path {
  fill: #fff;
}

.cwvvs-badge__label {
  font-size: 0.9rem;
  font-weight: 600;
}

.cwvvs-badge__value {
  font-size: 1rem;
  font-weight: 800;
}

/* ---------- Spinner ---------- */
.cwvvs__spinner {
  width: 0.95rem;
  height: 0.95rem;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  pointer-events: none;
  display: none;
}

/* Le spinner n'occupe aucune place tant qu'il n'est pas necessaire :
   l'icone reste donc parfaitement centree. Pendant le chargement, on
   masque l'icone et le spinner prend sa place. */
.cwvvs__button.is-loading .cwvvs__spinner {
  display: block;
}

.cwvvs__button.is-loading .cwvvs__button-icon {
  display: none;
}

@keyframes cwvvs-spin {
  to { transform: rotate(360deg); }
}

.fa-spin {
  animation: cwvvs-spin 0.7s linear infinite;
}

/* ---------- Modale de connexion (B2B) ---------- */
.cwvvs-login-open { overflow: hidden; }

.cwvvs-login-modal {
  position: fixed;
  inset: 0;
  z-index: 9999999;
}

.cwvvs-login-modal[hidden] { display: none; }

.cwvvs-login-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(26, 15, 36, 0.6);
}

.cwvvs-login-modal__dialog {
  position: relative;
  width: min(92vw, 560px);
  margin: 7vh auto;
  background: #fff;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(26, 15, 36, 0.28);
}

.cwvvs-login-modal__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 999px;
  background: var(--cwvvs-tint);
  color: var(--cwvvs-magenta);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  z-index: 2;
}

.cwvvs-login-modal__header { padding: 1.5rem 1.5rem 0; }

.cwvvs-login-modal__title {
  margin: 0;
  color: var(--cwvvs-ink);
  font-size: 1.35rem;
  font-weight: 800;
}

.cwvvs-login-modal__form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.5rem;
}

.cwvvs-login-modal__field {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.cwvvs-login-modal__label {
  color: var(--cwvvs-ink);
  font-size: 0.95rem;
  font-weight: 700;
}

.cwvvs-login-modal__input {
  width: 100%;
  min-height: 48px;
  padding: 13px 15px;
  border: 1.6px solid var(--cwvvs-border);
  border-radius: 12px;
  background: #fff;
  color: var(--cwvvs-text);
  font: inherit;
}

.cwvvs-login-modal__input:focus {
  outline: none;
  border-color: var(--cwvvs-magenta);
  box-shadow: 0 0 0 3px rgba(187, 58, 176, .14);
}

.cwvvs-login-modal__message {
  padding: 0.85rem 1rem;
  border-radius: 12px;
  font-size: 0.95rem;
  line-height: 1.4;
}

.cwvvs-login-modal__message.is-error {
  background: #fdecf4;
  color: #b3174a;
}

.cwvvs-login-modal__message.is-success {
  background: #eef8dd;
  color: #2f5e14;
}

.cwvvs-login-modal__submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 50px;
  padding: 12px 16px;
  border: 0;
  border-radius: var(--cwvvs-pill);
  background: var(--cwvvs-grad);
  color: #fff;
  font: inherit;
  font-weight: 800;
  cursor: pointer;
  box-shadow: var(--cwvvs-glow);
}

.cwvvs-login-modal__submit:disabled {
  opacity: 0.8;
  cursor: wait;
}

.cwvvs-login-modal__spinner {
  width: 0.95rem;
  height: 0.95rem;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  opacity: 0;
  transform: scale(0.8);
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.cwvvs-login-modal__submit.is-loading .cwvvs-login-modal__spinner {
  opacity: 1;
  transform: scale(1);
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 991px) {
  .cwvvs-badge { gap: 0.4rem; }
  .cwvvs-badge .cwvvs-badge__label,
  .cwvvs-badge .cwvvs-badge__value { font-size: 0.8rem; }

  .cwvvs__select--sticky,
  .cwvvs__qty-select--sticky,
  .cwvvs__button--sticky {
    width: 100%;
    max-width: none;
  }

  #category .cwvvs__list-row {
    align-items: stretch;
  }

  .cwvvs__button { width: 100%; }

  .cwvvs__button--full { padding: 14px 18px; }

  .cwvvs__card { min-width: 64px; }
  .cwvvs__card-title { font-size: 1rem; }

  .cwvvs__product-cta { margin-top: 0.85rem; gap: 0.65rem; }
  .cwvvs__product-form { gap: 0.7rem; }
  .cwvvs__product-submit-row { gap: 0.65rem; }
  .cwvvs__button-price { font-size: 1rem; }
  .cwvvs__button-regular { font-size: 0.82rem; }
  .cwvvs--product .cwvvs__stepper button { width:30px; }
}

@media (max-width: 575px) {
  /* Vignette catalogue : version compacte */
  #category .product-miniature-container .cwvvs-badge__icon { display: none; }
  #category .product-miniature-container .cwvvs-badge { padding: 0.4rem 0.35rem; }
  #category .product-miniature-container .cwvvs__prices {
    flex-direction: row;
    justify-content: flex-start;
  }
  #category .product-miniature-container .cwvvs__regular { width: auto; }

  /* Place limitee : prix remise + prix barre + prix au gramme ne
     tiennent pas sur une ligne. On renvoie le prix au gramme sur sa
     propre ligne, aligne a gauche. */
  .cwvvs--list .cwvvs__prices { justify-content: flex-start; }
  .cwvvs--list .cwvvs__unit-inline {
    order: 3;
    margin-left: 0;
    flex-basis: 100%;
    width: 100%;
    text-align: left;
  }

  /* Bouton vignette : pas la place pour le texte. Produit disponible =
     icone seule (centree) ; produit epuise = libelle seul (sans icone).
     On masque le libelle VISUELLEMENT (sr-only) au lieu de display:none, pour
     qu'il reste dans l'arbre d'accessibilite : sinon le bouton (icone
     aria-hidden) n'a plus de nom accessible -> echec "button-name". */
  .cwvvs--list .cwvvs__button:not(.is-disabled) [data-cwvvs-button-label] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
  .cwvvs--list .cwvvs__button.is-disabled .cwvvs__button-icon:not(.cwvvs__button-icon--oos) { display: none; }

  .cwvvs--sticky {
    grid-template-columns: auto 67px minmax(0, 1fr);
    gap: 0.55rem;
    align-items: center;
  }

  .cwvvs__sticky-prices { gap: 0.05rem; }
  .cwvvs--sticky .cwvvs__regular { font-size: 0.82rem; }
  .cwvvs--sticky .cwvvs__price { font-size: 1.2rem; line-height: 1; }

  .cwvvs__sticky-controls { display: contents; }

  .cwvvs__select--sticky,
  .cwvvs__qty-select--sticky {
    width: 67px;
    min-width: 67px;
    max-width: 67px;
    padding: 10px 8px;
    text-align: center;
  }

  .cwvvs__button--sticky {
    width: 100%;
    min-height: 50px;
    padding: 10px 14px;
    border-radius: var(--cwvvs-pill);
    justify-content: center;
    gap: 0.5rem;
  }

  .cwvvs__button--sticky .cwvvs__button-prices { display: none; }

  .cwvvs__pill { min-width: 0; padding: 8px; }
  .cwvvs__pill-label { font-size: 0.92rem; }
  .cwvvs__pill-unit { font-size: 0.66rem; }

  .cwvvs__card { min-width: 0; padding: 9px 6px; }
  .cwvvs__card-title { font-size: 0.95rem; }
  .cwvvs__card-unit { font-size: 0.7rem; }

  .cwvvs__price { font-size: 1.3rem; }
  .cwvvs__button--full { gap: 0.6rem; padding: 13px 16px; }
}

/* ============================================================
   Hero "Produit du moment" (hook displayCwvVariationSelectorHero)
   Reutilise les styles .cwvvs--product ; seule la mise en page change :
   grille de grammages -> (prix + bouton sur une ligne) -> stock.
   ============================================================ */
.cwvvs--hero { width: 100%; }

.cwvvs--hero .cwvvs__hero-grid {
  margin-bottom: 16px;
}

/* Cartes de grammage de largeur egale (3G...100G), compactes (cf. maquette) */
.cwvvs--hero .cwvvs__hero-grid .cwvvs__card {
  flex: 1 1 0;
  min-width: 60px;
  padding: 10px 8px;
  border-radius: 12px;
}

.cwvvs--hero .cwvvs__hero-grid .cwvvs__card-title {
  font-size: 0.92rem;
}

.cwvvs--hero .cwvvs__hero-grid .cwvvs__card-unit {
  font-size: 0.72rem;
}

.cwvvs--hero .cwvvs__price {
  font-size: 2.4rem;
}

.cwvvs--hero .cwvvs__product-price .cwvvs__regular {
  font-size: 1.15rem;
}

/* Ligne prix + bouton */
.cwvvs__hero-buy {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px 22px;
}

.cwvvs__hero-buy .cwvvs__hero-price {
  margin-bottom: 0;
  flex: 0 1 auto;
}

.cwvvs__hero-buy .cwvvs__hero-form {
  width: auto;
  flex: 1 1 220px;
  max-width: 340px;
  margin-left: auto;
}

.cwvvs__button--hero {
  width: 100%;
}

/* Stabilite : on reserve la hauteur de l'indicateur de stock pour
   eviter le saut de mise en page quand il apparait / disparait selon la
   declinaison (theme-cbdpurple.js bascule l'attribut [hidden]). On garde
   l'element dans le flux ; seul son contenu devient (in)visible. */
.cwvvs--hero .cwvvs__hero-stock {
  display: inline-flex;
  min-height: 1.15rem;
  margin-top: 12px;
  margin-bottom: 0;
}

.cwvvs--hero .cwvvs__hero-stock[hidden] {
  display: inline-flex;
  visibility: hidden;
}

@media (max-width: 767px) {
  .cwvvs__hero-buy { gap: 12px; }
  .cwvvs__hero-buy .cwvvs__hero-price { flex-basis: 100%; }
  .cwvvs__hero-buy .cwvvs__hero-form { flex-basis: 100%; max-width: none; margin-left: 0; }
}
