/* Fiche produit (zone product) : remplacement du JavaScript ESF (single-product.js), Elementor (onglets,
   accordeons, carrousel) et Swiper par du CSS, et rien d'autre. Portee : .elementor-876, .qm-* et les IDs
   d'elements d'origine ; esf-frontend.css et post-876.css restent la source du dessin. */

/* ---- Galerie ESF (esf-frontend.css : grille 2 colonnes) ----
   Les photos au-dela de la 4e portent .is-hidden ; le bouton « Load More » de single-product.js devient une case
   a cocher (.qm-gal-more, avant la grille) et un label (.esf-sp-gallery__load-more, apres la grille). */
.qm-gallery .qm-gal-more:checked ~ .esf-sp-gallery__grid > .esf-sp-gallery__item.is-hidden {
	display: block;
}
.qm-gallery .esf-sp-gallery__load-more .qm-gal-more-off {
	display: none;
}
.qm-gallery .qm-gal-more:checked ~ .esf-sp-gallery__load-more .qm-gal-more-on {
	display: none;
}
.qm-gallery .qm-gal-more:checked ~ .esf-sp-gallery__load-more .qm-gal-more-off {
	display: inline;
}
.qm-gallery .qm-gal-more:focus-visible ~ .esf-sp-gallery__load-more {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

/* ---- Visionneuse : ancres :target a la place de la lightbox JS ----
   Un calque .esf-sp-lightbox par photo (#qm-lb-PID-N), dessine par esf-frontend.css ; fond et croix visent
   #qm-lb-off, ancre inexistante, donc ni saut de page ni defilement. Pas de verrou du defilement ni d'Echap. */
.esf-sp-lightbox.qm-lb {
	display: none;
}
.esf-sp-lightbox.qm-lb:target {
	display: flex;
}
.qm-lb .esf-sp-lightbox__backdrop {
	display: block;
}
.qm-lb .esf-sp-lightbox__close,
.qm-lb .esf-sp-lightbox__prev,
.qm-lb .esf-sp-lightbox__next,
.qm-lb .esf-sp-lightbox__close:hover,
.qm-lb .esf-sp-lightbox__prev:hover,
.qm-lb .esf-sp-lightbox__next:hover {
	color: #fff;
	text-decoration: none;
}

/* ---- Galerie sur mobile : le Swiper d'ESF est remplace par la grille elle-meme, en defilement horizontal ----
   esf-frontend.css masquait .esf-sp-gallery__desktop au profit du bloc Swiper (non rendu) : on le reaffiche,
   la grille devient une piste scroll-snap d'une photo par vue, toutes les photos comprises, hauteur plafonnee
   a 55vh comme le reglage mobile du widget. */
@media (max-width: 767px) {
	.qm-gallery .esf-sp-gallery__desktop {
		display: block;
	}
	.qm-gallery .esf-sp-gallery__grid {
		display: flex;
		flex-wrap: nowrap;
		gap: var(--esf-sp-image-gap, 8px);
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}
	.qm-gallery .esf-sp-gallery__grid::-webkit-scrollbar {
		display: none;
	}
	.qm-gallery .esf-sp-gallery__grid > .esf-sp-gallery__item {
		flex: 0 0 100%;
		scroll-snap-align: start;
		scroll-snap-stop: always;
		animation: none;
		border-radius: 0;
	}
	.qm-gallery .esf-sp-gallery__grid > .esf-sp-gallery__item.is-hidden {
		display: block;
	}
	.qm-gallery .esf-sp-gallery__image {
		max-height: 55vh;
		object-fit: cover;
	}
	.qm-gallery .esf-sp-gallery__load-more {
		display: none;
	}
}

/* ---- Module Conversions (qm-cvx-rec / qm-cvx-tf / qm-cvx-cta) : typographie et espacements de la fiche ----
   Le module apporte sa propre CSS (Instrument Sans 36/40 px, gris bleute, bouton pilule) concue pour une autre boutique.
   Ici on le rabat sur les styles reels des sections voisines : titres de section Roboto 32/42 400, sous-titres Roboto
   20/30 600, textes Roboto 13/21 400 (#2B2B2E), petits libelles 11 px capitales, bouton = celui de l'achat
   (Instrument Sans 15/600, angles droits, #1a1a1a, hauteur 52 px), sections de 50 px de respiration. */
.qm-native .qm-cvx,
.qm-native .qm-cvx-cta {
	font-family: "Roboto", sans-serif;
	color: #2B2B2E;
}
/* Bandeau « Empfohlen von » */
.qm-native .qm-cvx-rec {
	padding: 22px 0;
	border-color: #eeeae3;
}
.qm-native .qm-cvx-rec .lbl {
	font: 600 11px/21px "Roboto", sans-serif;
	letter-spacing: 1.5px;
	color: #6B6B6B;
}
.qm-native .qm-cvx-rec .lg {
	font: 600 15px/21px "Roboto", sans-serif;
	letter-spacing: .3px;
	color: #9A9A9A;
}
.qm-native .qm-cvx-rec .lg:hover {
	color: #2B2B2E;
}
/* Section « Transformation » */
.qm-native .qm-cvx-tf {
	padding: 50px 0;
}
.qm-native .qm-cvx-tf .head {
	max-width: 690px;
	margin-bottom: 40px;
}
.qm-native .qm-cvx-tf .h2,
.qm-native .qm-cvx-cta .h2 {
	font: 400 32px/42px "Roboto", sans-serif;
	color: #2B2B2E;
	margin: 0 0 10px;
}
.qm-native .qm-cvx-tf .sub,
.qm-native .qm-cvx-cta .sub {
	font: 400 13px/21px "Roboto", sans-serif;
	color: #2B2B2E;
}
.qm-native .qm-cvx-tf .n {
	font: 600 11px/21px "Roboto", sans-serif;
	letter-spacing: 1.5px;
	color: #6B6B6B;
	margin-bottom: 6px;
}
.qm-native .qm-cvx-tf .h3 {
	font: 600 20px/30px "Roboto", sans-serif;
	color: #2B2B2E;
	margin: 0 0 6px;
}
.qm-native .qm-cvx-tf p {
	font: 400 13px/21px "Roboto", sans-serif;
	color: #2B2B2E;
}
.qm-native .qm-cvx-tf .step + .step {
	border-color: #eeeae3;
}
.qm-native .qm-cvx-tf .ic {
	margin-bottom: 16px;
}
.qm-native .qm-cvx-tf .ic svg {
	stroke: #2B2B2E;
}
/* CTA de fin de fiche */
.qm-native .qm-cvx-cta {
	padding: 50px 24px;
	border-top: 0;
	background: #fff;
}
.qm-native .qm-cvx-cta .stars {
	font-size: 17px;
	letter-spacing: 3px;
	margin-bottom: 14px;
}
.qm-native .qm-cvx-cta .h2 {
	max-width: 690px;
	margin-left: auto;
	margin-right: auto;
	text-align: center;
}
.qm-native .qm-cvx-cta .sub {
	max-width: 560px;
	margin: 0 auto 26px;
}
.qm-native .qm-cvx-cta .btn {
	font: 600 15px/18px "Instrument Sans", sans-serif;
	letter-spacing: .15px;
	background: #1a1a1a;
	color: #fff;
	border-radius: 0;
	padding: 0 40px;
	height: 52px;
	gap: 10px;
}
.qm-native .qm-cvx-cta .btn:hover {
	background: #000;
}
.qm-native .qm-cvx-cta .btn svg {
	width: 18px;
	height: 18px;
}
.qm-native .qm-cvx-cta .proof {
	font: 400 13px/21px "Roboto", sans-serif;
	color: #6B6B6B;
	margin-top: 18px;
}
.qm-native .qm-cvx-cta .proof b {
	color: #2B2B2E;
}
.qm-native .qm-cvx-cta .proof .d {
	background: #cfcac2;
}
@media (max-width: 767px) {
	.qm-native .qm-cvx-rec {
		padding: 16px 0;
	}
	.qm-native .qm-cvx-rec .lg {
		font-size: 14px;
	}
	.qm-native .qm-cvx-tf {
		padding: 40px 0 34px;
	}
	.qm-native .qm-cvx-tf .head {
		margin-bottom: 24px;
	}
	.qm-native .qm-cvx-tf .h2,
	.qm-native .qm-cvx-cta .h2 {
		font-size: 26px;
		line-height: 34px;
	}
	.qm-native .qm-cvx-tf .h3 {
		font-size: 18px;
		line-height: 26px;
	}
	.qm-native .qm-cvx-cta {
		padding: 40px 20px;
	}
}

/* Ligne d'avis : texte [phraseaviscourte] en ligne (ESF le posait en inline-flex avec un gap, d'ou un blanc parasite avant le nombre). */
.qm-native .esf-single-product .esf-sp-trustpilot__text {
	display: inline;
	font: 400 14px/22px "Roboto", sans-serif;
	color: #2B2B2E;
}
.qm-native .esf-single-product .esf-sp-trustpilot__score {
	font-weight: 700;
}

/* ---- Rythme vertical du bloc d'achat (30/08) : un seul ecart de 14 px entre pastille, titre, prix, avis, variantes, achat ;
   libelles de variantes aeres (13/21 600, 8 px au-dessus des pastilles, 14 px entre les lignes) ; la boite plugin
   #qm-purchase-compact-css et Woo posent des !important, d'ou les !important ici. ---- */
.qm-native .esf-single-product__summary {
	gap: 14px;
}
.qm-native .esf-single-product__summary .qm-promo-badge,
.qm-native .esf-single-product__summary .qm-bogo-badge {
	margin: 0;
}
.qm-native .esf-single-product__summary .esf-single-product__title,
.qm-native .esf-single-product__summary .esf-single-product__price {
	margin: 0;
}
.qm-native .esf-single-product__summary .esf-single-product__price {
	line-height: 1.1;
}
.qm-native.single-product .esf-single-product__add-to-cart form.cart {
	margin: 0;
}
.qm-native .esf-single-product__summary .esf-sp-info--purchase {
	margin-top: -6px; /* ramene l'ecart avis -> variantes au meme 18 px que les autres blocs (ESF ajoute 8 px internes) */
}
.qm-native.single-product .esf-single-product__add-to-cart form.cart table.variations {
	margin: 2px 0 6px !important;
	border-collapse: collapse;
}
.qm-native.single-product .esf-single-product__add-to-cart table.variations tbody,
.qm-native.single-product .esf-single-product__add-to-cart table.variations tr,
.qm-native.single-product .esf-single-product__add-to-cart table.variations th.label,
.qm-native.single-product .esf-single-product__add-to-cart table.variations td.value {
	display: block !important;
	width: 100%;
}
.qm-native.single-product .esf-single-product__add-to-cart table.variations tr {
	padding: 0 0 14px !important;
	margin: 0 !important;
}
.qm-native.single-product .esf-single-product__add-to-cart table.variations tr:last-child {
	padding-bottom: 0 !important;
}
.qm-native.single-product .esf-single-product__add-to-cart table.variations th.label {
	padding: 0 !important;
	margin: 0 0 8px !important;
	font: 600 13px/21px "Roboto", sans-serif !important;
	color: #2B2B2E;
	text-align: left !important;
	justify-content: flex-start;
}
.qm-native.single-product .esf-single-product__add-to-cart table.variations th.label label {
	display: inline;
	margin: 0;
	font: inherit;
}
.qm-native.single-product .esf-single-product__add-to-cart table.variations th.label .cfvsw-selected-label {
	font-weight: 400;
	color: #6B6B6B;
}
.qm-native.single-product .esf-single-product__add-to-cart table.variations td.value {
	padding: 0 !important;
}
.qm-native.single-product .cfvsw-swatches-container {
	gap: 8px;
}
.qm-native.single-product .cfvsw-swatches-option.cfvsw-label-option {
	padding: 6px 14px;
	min-width: 44px;
	line-height: 1.3;
}
.qm-native.single-product .esf-single-product__add-to-cart .reset_variations {
	display: block !important;
	margin: 6px 0 0 !important;
	font-size: 12px;
	line-height: 18px;
	color: #6B6B6B;
	text-align: left;
}
.qm-native .esf-single-product .qm-pay-icons {
	padding-top: 6px;
}

/* ---- Trait vertical decoratif du bloc « Eigenschaften » (30/08) : CSS pur a la place de la capture d'ecran de 20 x 268 px
   (3 points de 20 px relies par un pointille) ; meme rendu, se reduit avec sa colonne comme l'image (aspect-ratio) ---- */
.qm-native .qm-pd-vline {
	position: relative;
	display: block;
	width: 20px;
	max-width: 100%;
	aspect-ratio: 20 / 268;
	margin: 0;
	background:
		radial-gradient(circle, #1E3A2B 0 45%, transparent 50%) 50% 0 / 100% 7.46% no-repeat,
		radial-gradient(circle, #1E3A2B 0 45%, transparent 50%) 50% 50% / 100% 7.46% no-repeat,
		radial-gradient(circle, #1E3A2B 0 45%, transparent 50%) 50% 100% / 100% 7.46% no-repeat;
}
.qm-native .qm-pd-vline::before {
	content: "";
	position: absolute;
	left: calc(50% - 1px);
	top: 4%;
	bottom: 4%;
	border-left: 2px dotted #1E3A2B;
}

/* ---- Ligne Klarna (30/08) : badge + « 3 zinsfreie Zahlungen von 60,00 € » juste sous les pastilles de variantes (crochet
   woocommerce_after_variations_table), avant la rangee quantite / bouton ---- */
.qm-native .esf-single-product__summary .qm-pd-klarna {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 14px;
}
.qm-native .qm-pd-klarna__badge {
	display: inline-flex;
	align-items: center;
	flex: 0 0 auto;
	line-height: 0;
}
.qm-native .qm-pd-klarna__badge svg {
	display: block;
	width: auto;
	height: 19px;
}
.qm-native .qm-pd-klarna__text {
	font: 500 13.5px/20px "Roboto", sans-serif;
	color: #2B2B2E;
}
.qm-native .qm-pd-klarna__text .woocommerce-Price-amount {
	font-weight: 600;
}
@media (max-width: 767px) {
	.qm-native .qm-pd-klarna__badge svg {
		height: 22px;
	}
	.qm-native .qm-pd-klarna__text {
		font-size: 12.5px;
	}
}

/* ---- « Stark nachgefragt » + 3 atouts [fortdemande1..3] sous le prix (30/08) : point pulsant accent, coches vertes
   (meme vert que les etoiles / le stock), Roboto 13-14 px ; la feuille inline #qm-pf-list-css du plugin (Instrument Sans,
   coche rouge) est surchargee ici par specificite. ---- */
.qm-native .esf-single-product__summary .qm-pd-usp {
	display: flex;
	flex-direction: column;
	gap: 11px;
	margin: 0;
}
.qm-native .qm-pd-demand {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin: 0;
	font: 500 13px/20px "Roboto", sans-serif;
	letter-spacing: 0.01em;
	color: #2B2B2E;
}
/* boite de 18 px comme les coches de la liste (centres alignes, le halo ne deborde plus a gauche) ; point 9 px + halo + anneau pulsant */
.qm-native .qm-pd-demand__dot {
	position: relative;
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
}
.qm-native .qm-pd-demand__dot::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	width: 9px;
	height: 9px;
	margin: -4.5px 0 0 -4.5px;
	border-radius: 50%;
	background: #DD1B1F;
	box-shadow: 0 0 0 3px rgba(221, 27, 31, 0.14);
}
.qm-native .qm-pd-demand__dot::before {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	width: 15px;
	height: 15px;
	margin: -7.5px 0 0 -7.5px;
	border-radius: 50%;
	border: 2px solid #DD1B1F;
	opacity: 0;
	animation: qm-pd-pulse 1.8s ease-out infinite;
}
@keyframes qm-pd-pulse {
	0% { transform: scale(0.55); opacity: 0.85; }
	70% { transform: scale(1.7); opacity: 0; }
	100% { transform: scale(1.7); opacity: 0; }
}
.qm-native .qm-pd-usp .qm-pf-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}
.qm-native .qm-pd-usp .qm-pf-li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 0;
	padding: 0;
	font: 400 14px/22px "Roboto", sans-serif;
	letter-spacing: normal;
	text-transform: none;
	color: #2B2B2E;
}
.qm-native .qm-pd-usp .qm-pf-ic {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	margin-top: 2px;
	fill: #1A1A1A; /* coches noires (demande utilisateur), pas le vert des etoiles */
}
.qm-native .qm-pd-usp .qm-pf-tx {
	display: block;
	font: inherit;
	color: inherit;
	text-transform: none;
	letter-spacing: normal;
}
@media (max-width: 767px) {
	.qm-native .esf-single-product__summary .qm-pd-usp {
		gap: 10px;
	}
	.qm-native .qm-pd-usp .qm-pf-li {
		font-size: 13.5px;
		line-height: 21px;
	}
}
@media (prefers-reduced-motion: reduce) {
	.qm-native .qm-pd-demand__dot::before {
		animation: none;
		opacity: 0.35;
		transform: none;
	}
}

/* ---- Avis clients de la fiche (CPT aps_review) : grille de cartes, typographie de la fiche ----
   Elementor rend .e-con en display:var(--display), variable posee par la CSS de chaque element d'origine : cette section
   n'en a pas, elle tombait en inline et ignorait la largeur boxee (1440 px) ; on la fixe ici. */
.qm-native .qm-pd-reviews {
	--display: flex;
	display: flex;
	flex-direction: column;
	padding: 50px 0;
	background: #fff;
}
.qm-native .qm-pd-reviews > .e-con-inner {
	display: block;
	width: 100%;
	max-width: min(100%, 1440px);
	margin: 0 auto;
	padding-left: 16px;
	padding-right: 16px;
}
@media (min-width: 1473px) {
	.qm-native .qm-pd-reviews > .e-con-inner {
		padding-left: 0;
		padding-right: 0;
	}
}
.qm-native .qm-pd-reviews__head {
	text-align: center;
	margin-bottom: 30px;
}
.qm-native .qm-pd-reviews__head h2 {
	font: 400 32px/42px "Roboto", sans-serif;
	color: #2B2B2E;
	margin: 0 0 10px;
}
.qm-native .qm-pd-reviews__summary {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin: 0;
	font: 400 13px/21px "Roboto", sans-serif;
	color: #6B6B6B;
}
.qm-native .qm-pd-reviews__stars {
	display: inline-flex;
	gap: 1px;
	line-height: 0;
}
.qm-native .qm-pd-reviews__stars .esf-sp-trustpilot__cell {
	width: 18px;
	height: 18px;
	background: #dcdce6;
}
.qm-native .qm-pd-reviews__stars .esf-sp-trustpilot__cell-bg {
	background: #00b67a;
}
.qm-native .qm-pd-reviews__stars .esf-sp-trustpilot__svg {
	width: 11px;
	height: 11px;
}
.qm-native .qm-pd-reviews__avg {
	font-weight: 700;
	color: #2B2B2E;
}
.qm-native .qm-pd-reviews__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 20px;
}
.qm-native .qm-pd-review {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 18px 18px 16px;
	border: 1px solid #eeeae3;
	background: #fff;
}
.qm-native .qm-pd-review__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
}
.qm-native .qm-pd-review__author {
	font: 600 13px/21px "Roboto", sans-serif;
	color: #2B2B2E;
}
.qm-native .qm-pd-review__verified {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font: 400 12px/18px "Roboto", sans-serif;
	color: #6B6B6B;
}
.qm-native .qm-pd-review__verified svg {
	width: 16px;
	height: 16px;
}
.qm-native .qm-pd-review__text p {
	font: 400 13px/21px "Roboto", sans-serif;
	color: #2B2B2E;
	margin: 0;
}
.qm-native .qm-pd-review__photo {
	display: block;
	width: 84px;
	height: 84px;
	margin-top: 4px;
	overflow: hidden;
	border-radius: 4px;
	line-height: 0;
}
.qm-native .qm-pd-review__photo img {
	width: 84px;
	height: 84px;
	object-fit: cover;
}
@media (max-width: 1024px) {
	.qm-native .qm-pd-reviews__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}
@media (max-width: 767px) {
	.qm-native .qm-pd-reviews {
		padding: 40px 0;
	}
	.qm-native .qm-pd-reviews__head h2 {
		font-size: 26px;
		line-height: 34px;
	}
	.qm-native .qm-pd-reviews__grid {
		grid-template-columns: 1fr;
		gap: 12px;
	}
}

/* ---- Logos de paiement sous le bouton d'achat (rangee tout-auto .qm-pay-icons) ----
   tout-auto etire chaque logo sur la largeur de la colonne (flex:1 1 0 + width:100%) : trop grand ici.
   Taille fixe 38x24 comme dans le footer et le tiroir, rangee centree. */
.esf-single-product .qm-pay-icons .payment-icon-wrapper {
	flex: 0 0 auto;
}
.esf-single-product .qm-pay-icons svg.payment-icon,
.esf-single-product .qm-pay-icons img.payment-icon {
	width: 38px;
	height: 24px;
}
.esf-single-product .qm-pay-icons .payment-icons-container {
	gap: 8px;
}

/* ---- Quantite ----
   Sans single-product.js les boutons − / + d'ESF seraient inertes : ils ne sont pas rendus (filtre
   qm_pd_qty_buttons) et le champ nombre retrouve son incrementeur natif dans la meme boite de 52px
   (esf-frontend.css le masquait avec appearance:textfield). */
.qm-qty-native .esf-single-product__add-to-cart .quantity input.qty {
	appearance: auto;
	-webkit-appearance: auto;
	-moz-appearance: auto;
	padding: 0 0.5rem;
}
.qm-qty-native .esf-single-product__add-to-cart .quantity input.qty::-webkit-inner-spin-button,
.qm-qty-native .esf-single-product__add-to-cart .quantity input.qty::-webkit-outer-spin-button {
	appearance: auto;
	-webkit-appearance: inner-spin-button;
	opacity: 1;
	margin: 0;
}

/* ---- Accordeon ESF en <details name="pd-acc-PID"> (un seul volet ouvert) ----
   esf-frontend.css dessine l'en-tete pour un <button> et bascule les chevrons sur .is-open (pose par JS) :
   ici summary + [open]. */
.qm-acc summary.esf-sp-accordion__header {
	list-style: none;
}
.qm-acc summary.esf-sp-accordion__header::-webkit-details-marker {
	display: none;
}
.qm-acc summary.esf-sp-accordion__header:hover,
.qm-acc summary.esf-sp-accordion__header:focus-visible {
	background-color: #fafafa;
}
.qm-acc details[open] > summary .esf-sp-accordion__toggle-icon--closed {
	display: none;
}
.qm-acc details[open] > summary .esf-sp-accordion__toggle-icon--opened {
	display: inline-flex;
}

/* Chevrons SVG (qm-svg-icons) : traces au trait, jamais remplis ; esf-frontend.css et
   widget-nested-accordion.min.css posent un fill sur les svg de ces conteneurs. */
.elementor-876 .esf-sp-accordion__toggle-icon svg.qm-svg-icon,
.elementor-876 .elementor-widget-n-accordion .e-n-accordion-item .e-n-accordion-item-title-icon span > svg.qm-svg-icon {
	fill: none;
}

/* ---- FAQ : onglets imbriques (6c31ebf3) en 4 boutons radio + labels ----
   Les radios precedent .e-n-tabs dans le wrapper .qm-tabs ; le volet N (.e-n-tabs-content > .e-con:nth-child(N))
   s'affiche quand le radio N est coche. widget-nested-tabs.min.css masque deja tout volet sans .e-active. */
.qm-tabs .e-n-tab-title {
	cursor: pointer;
}
.qm-tabs > .e-n-tabs > .e-n-tabs-content > .e-con {
	display: none;
}
.qm-tabs > .qm-tab-radio:nth-of-type(1):checked ~ .e-n-tabs > .e-n-tabs-content > .e-con:nth-child(1),
.qm-tabs > .qm-tab-radio:nth-of-type(2):checked ~ .e-n-tabs > .e-n-tabs-content > .e-con:nth-child(2),
.qm-tabs > .qm-tab-radio:nth-of-type(3):checked ~ .e-n-tabs > .e-n-tabs-content > .e-con:nth-child(3),
.qm-tabs > .qm-tab-radio:nth-of-type(4):checked ~ .e-n-tabs > .e-n-tabs-content > .e-con:nth-child(4) {
	display: var(--display, flex);
}
/* Onglet actif : meme fond que [aria-selected="true"] dans post-876.css. !important : cette CSS figee pose
   background:transparent !important sur .e-n-tab-title, on ne peut passer devant qu'avec la meme importance. */
.elementor-876 .elementor-element-6c31ebf3 > .qm-tab-radio:nth-of-type(1):checked ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(1),
.elementor-876 .elementor-element-6c31ebf3 > .qm-tab-radio:nth-of-type(2):checked ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(2),
.elementor-876 .elementor-element-6c31ebf3 > .qm-tab-radio:nth-of-type(3):checked ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(3),
.elementor-876 .elementor-element-6c31ebf3 > .qm-tab-radio:nth-of-type(4):checked ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(4) {
	background-color: #eeeae3 !important;
}
.qm-tabs > .qm-tab-radio:nth-of-type(1):focus-visible ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(1),
.qm-tabs > .qm-tab-radio:nth-of-type(2):focus-visible ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(2),
.qm-tabs > .qm-tab-radio:nth-of-type(3):focus-visible ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(3),
.qm-tabs > .qm-tab-radio:nth-of-type(4):focus-visible ~ .e-n-tabs > .e-n-tabs-heading > .e-n-tab-title:nth-child(4) {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

/* ---- « Pourquoi choisir » (nested-carousel 92f0b19) : 3 cartes en grille ----
   widget-nested-carousel.min.css, swiper et e-swiper ne sont pas charges. N cartes visibles lu dans la variable
   deja ecrite par post-876.css (3 par defaut ici, 2 sous 1025px, 1 sous 768px) ; quand tout ne tient pas, la
   piste defile horizontalement avec scroll-snap, sans puces ni autoplay. */
.elementor-876 .elementor-element-92f0b19 {
	--e-n-carousel-swiper-slides-to-display: 3;
}
.elementor-876 .elementor-element-92f0b19 > .e-n-carousel {
	display: block;
	min-width: 0;
	overflow: hidden;
}
.elementor-876 .elementor-element-92f0b19 > .e-n-carousel > .swiper-wrapper {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: calc( ( 100% - ( var(--e-n-carousel-swiper-slides-to-display) - 1 ) * var(--e-n-carousel-swiper-slides-gap, 30px) ) / var(--e-n-carousel-swiper-slides-to-display) );
	column-gap: var(--e-n-carousel-swiper-slides-gap, 30px);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}
.elementor-876 .elementor-element-92f0b19 > .e-n-carousel > .swiper-wrapper::-webkit-scrollbar {
	display: none;
}
.elementor-876 .elementor-element-92f0b19 > .e-n-carousel > .swiper-wrapper > .swiper-slide {
	min-width: 0;
	scroll-snap-align: start;
}
.elementor-876 .elementor-element-92f0b19 > .e-n-carousel > .swiper-wrapper > .swiper-slide > .e-con {
	max-width: 100%;
}

/* Conteneur specs : Elementor posait --width:100.785% (11 px de debordement horizontal sans son JS de recalcul). */
.elementor-876 .elementor-element.elementor-element-94ebcf5{--width:100%;}

/* ---- Hierarchie des titres (SEO) : balises changees, rendu identique ----
   Les tailles par balise viennent du kit (post-7.css : .elementor-kit-7 h2 32/42 400, h3 20/30 600, h5 16/26) et de reset.css
   (font-weight:500 quand le kit ne le fixe pas, marges des titres). Les regles ci-dessous reproduisent l'ancien rendu. */

/* Ecrin : titre ex-h5 devenu h2, sous-titre ex-h5 devenu h3 (16px / 26px / 500) ; couleur toujours par post-876.css. */
.elementor-876 .elementor-element.elementor-element-17680233 h2.elementor-heading-title,
.elementor-876 .elementor-element.elementor-element-5ac962e0 h3.elementor-heading-title {
	font-size: 16px;
	line-height: 26px;
	font-weight: 500;
}
/* Accordeon ESF de la colonne d'information : titres d'items ex-span devenus h2. Police, taille, graisse et interligne restent
   ceux de post-876.css (.elementor-element-93e047a .esf-sp-accordion__title, plus specifique que le kit) ; on neutralise ce
   qu'un h2 recoit de sa balise : marges de reset.css et couleur du kit (le span heritait celle de son <summary>). */
.elementor-876 .elementor-element.elementor-element-93e047a h2.esf-sp-accordion__title {
	margin: 0;
	color: inherit;
}
/* FAQ a onglets : questions ex-span devenues h3 dans le <summary>. La taille vient deja de la classe (--n-accordion-title-font-size,
   19px) ; le reste heritait du <summary> : on remet cet heritage a la place des valeurs du kit h3 (20px / 600 / 30px, couleur). */
.elementor-876 .elementor-widget-n-accordion h3.e-n-accordion-item-title-text {
	margin: 0;
	font-family: inherit;
	font-weight: inherit;
	line-height: inherit;
	color: inherit;
}

/* ---- QM PD DESC : debut du bloc ajoute aux feuilles compilees (rejouable, reecrit a l'identique).
   Marqueur : .qm-pd-desc-build
   Les trois blocs de description (H2 + texte, H3 + texte, H3 + texte, decoupes dans la description du
   produit par QM Product Description Fields) reprennent la rangee du bloc « Specs » : flex row, deux
   colonnes de 670px, gouttiere de 100px, align-items:center.
   ALTERNANCE : l'image doit etre a gauche, puis a droite, puis a gauche. On ne touche pas a l'ordre du
   balisage, on inverse la rangee du bloc du milieu — et UNIQUEMENT au-dela du point de rupture mobile,
   parce qu'en dessous la rangee passe en flex column : un row-reverse y deviendrait inutile et un
   column-reverse remonterait le texte au-dessus de l'image, alors qu'on veut l'image en premier partout.
   🚨 Le point de rupture est 1025px, PAS 767px : mesure au navigateur, la rangee du kit est deja en
   flex column a 1024px. Une requete a min-width:768px laissait donc le bloc du milieu en
   row-reverse a 1024 pendant que les deux autres s'empilaient, ce qui cassait la symetrie.
   TEXTE : la colonne portait 4 tuiles de 2 mots, elle porte maintenant des paragraphes et parfois une
   table de caracteristiques ; le corps passe de 13px/21px a 15px/1,7 et la table recoit des cellules
   lisibles, sur le meme modele que la description de categorie.
   🚨 COULEUR : la couleur systeme « Texte » du kit Elementor vaut le ROUGE DE MARQUE (#DD1B1F).
   C'etait voulu pour la valeur des anciennes tuiles, mais un paragraphe entier en rouge est
   illisible : on force la couleur principale du kit (le meme sombre que les titres).
   RESPIRATION : le bloc etait en e-con-full, donc large de 1920px en bord a bord alors que les
   autres sections de la fiche sont plafonnees a min(100%,1440px) et centrees. On aligne donc le
   bloc sur elles. 🚨 Premiere tentative fautive : le retrait avait ete pose sur la RANGEE, ce qui
   decollait aussi l'IMAGE du bord et donnait une largeur differente des sections voisines, d'ou
   une impression de decalage. Mesure du bloc de reference « Eigenschaften » : son image est au RAS
   du bord (droite=0 en 1440, droite=240 en 1920, soit le bord de la zone de contenu) et seul le
   TEXTE est rentre, de 53px en 1440 et 42px en 1024 ; le titre occupe toute la largeur, centre.
   On reproduit exactement ce motif : rien sur la rangee ni sur le titre, un retrait sur le seul
   bloc de texte, qui suit la fenetre et se retrouve donc du bon cote quand la rangee est inversee.
   TITRES : le h2 fait 32px/42px a TOUTES les largeurs, le h3 tenait son 20px de « .elementor-kit-7
   h3 » (0,1,1). A la demande, les h3 de CES blocs seulement passent a la taille du h2. ---- */
.qm-pd-desc-build{--qm-pd-desc:1}
.qm-pd-desc{max-width:min(100%,1440px);margin-inline:auto}
.qm-pd-desc .qm-pd-desc-txt{padding-inline:clamp(20px,3.7vw,53px)}
@media (min-width:1025px){
	.qm-pd-desc .qm-pd-desc-rev{flex-direction:row-reverse}
}
.qm-pd-desc h3.elementor-heading-title{font-size:32px;line-height:42px}
.qm-pd-desc .qm-pd-desc-txt{font-size:15px;line-height:1.7;color:var(--e-global-color-primary,#2B2B2E)}
.qm-pd-desc .qm-pd-desc-txt p{margin:0 0 1em}
.qm-pd-desc .qm-pd-desc-txt p:last-child{margin-bottom:0}
.qm-pd-desc .qm-pd-desc-txt strong{font-weight:600}
.qm-pd-desc .qm-pd-desc-txt a{text-decoration:underline;text-underline-offset:3px}
.qm-pd-desc .qm-pd-desc-txt ul,.qm-pd-desc .qm-pd-desc-txt ol{margin:0 0 1em;padding-left:1.25em}
.qm-pd-desc .qm-pd-desc-txt li{margin:.3em 0}
.qm-pd-desc .qm-pd-desc-txt table{width:100%;margin:.4em 0 0;border-collapse:collapse;font-size:14px}
.qm-pd-desc .qm-pd-desc-txt th,.qm-pd-desc .qm-pd-desc-txt td{padding:9px 12px;text-align:left;vertical-align:top;border-bottom:1px solid rgba(0,0,0,.10)}
.qm-pd-desc .qm-pd-desc-txt tbody tr:last-child th,.qm-pd-desc .qm-pd-desc-txt tbody tr:last-child td{border-bottom:0}
@media (max-width:767px){
	.qm-pd-desc .qm-pd-desc-txt{font-size:15px}
	.qm-pd-desc .qm-pd-desc-txt table{font-size:13px}
	.qm-pd-desc .qm-pd-desc-txt th,.qm-pd-desc .qm-pd-desc-txt td{padding:8px 10px}
}
/* ---- QM PD DESC : fin du bloc. ---- */

/* ---- QM PD GALERIE STICKY : debut du bloc ajoute aux feuilles compilees (rejouable, reecrit a l'identique).
   Marqueur : .qm-pd-gal-sticky-build
   La colonne de gauche (galerie) suit le defilement pendant qu'on lit la colonne de droite (titre, prix,
   variantes, accordeon) au lieu de laisser un grand vide sous les photos : 190 des 374 fiches n'ont qu'une ou
   deux photos, la galerie fait alors 429px de haut face a 950px de colonne d'information (mesure a 1440px).
   CIBLE : .esf-single-product__gallery, enfant direct de .esf-single-product__main, lui-meme flex row avec
   align-items:flex-start (esf-frontend.css) : la galerie garde donc la hauteur de son contenu et dispose de la
   course necessaire pour coller. Aucun JavaScript, position:sticky seul.
   ANCETRES : chaine relevee au navigateur, aucun overflow bloquant, rien a neutraliser. body porte
   overflow-x:clip (reset.css) qui, contrairement a hidden, ne cree PAS de conteneur de defilement ; html porte
   overflow-x:hidden / overflow-y:auto, valeurs propagees au viewport pour l'element racine. Le sidebar collant
   des pages de categorie fonctionne deja sous ces memes ancetres.
   POINT DE RUPTURE 768px, pas 1025px : mesure au navigateur, .esf-single-product__main reste en DEUX COLONNES
   jusqu'a 768px inclus (galerie a 50 % de large entre 768 et 1024, a 60 % au-dela) et ne passe en pile qu'a
   767px, ou la galerie devient une piste scroll-snap horizontale. Le vide sous les photos existe donc aussi
   sur tablette et on y colle egalement ; en dessous de 768px on ne colle pas, aucune photo geante ne peut
   venir se figer en haut de l'ecran.
   DECALAGE HAUT : hauteur mesuree de .custom-sticky-header = 72px, INVARIANTE de 768 a 1920px (relevee a 768,
   800, 900, 1000, 1024, 1025, 1100, 1280, 1366, 1440, 1600 et 1920 : toujours 72). Un seul palier suffit donc.
   C'est aussi la valeur de var(--qm-hdr-h) sur une fiche produit : qm-header.css pose 92px sur :root pour
   l'accueil puis 72px partout ailleurs (.qm-native:not(.home), plus specifique, y compris sous 768px). On y
   ajoute 28px d'AIR pour qu'on voie le fond entre le menu et les photos.
   L'admin bar de WordPress descend l'en-tete collant de 32px, et de 46px en dessous de 783px
   (.admin-bar .qm-hdr{top:32px} puis 46px) : on ajoute donc ce decalage pour les redacteurs connectes.
   GALERIE PLUS HAUTE QUE LA FENETRE : on ne renonce plus a coller, on cale par le BAS. Le calage haut
   (top positif, la galerie se fige sous le menu) laisserait le bas de la galerie hors de l'ecran et les
   dernieres photos inatteignables ; le calage bas (top NEGATIF, la galerie se fige quand son bas arrive a
   28px du bord bas de la fenetre) laisse au contraire defiler toute la galerie avant de la figer, et c'est
   son HAUT qui sort de l'ecran, ce qui est sans importance puisqu'on lit la colonne de droite. Rien n'est
   rogne, aucune max-height.
   🚨 « bottom:28px » seul NE MARCHE PAS ici et c'est contre-intuitif : un decalage sticky vers le haut est
   borne par le bord HAUT du bloc conteneur, or la galerie est deja collee au sommet de
   .esf-single-product__main, donc le decalage possible vaut zero et la regle reste sans effet. Il faut
   exprimer le calage bas comme un top negatif, ce que fait le min() ci-dessous :
     top = min(hauteur d'en-tete + air ; 100vh - hauteur de galerie - air)
   Le premier terme gagne quand la galerie tient sous le menu (calage haut classique), le second quand elle
   est trop haute et devient alors negatif (calage bas). Une seule expression couvre les deux cas, sans
   requete de hauteur de fenetre.
   HAUTEUR DE GALERIE EN CSS PUR : elle est deterministe, mesuree au navigateur sur 5 fiches et 15 largeurs.
   La grille fait deux colonnes carrees, gouttiere de 6px (--esf-sp-image-gap de post-876.css) :
     largeur = 50 % de (fenetre - 32px de marges) entre 768 et 1024px, 60 % de min(fenetre, 1440px) au-dela ;
     une rangee = (largeur - 6px) / 2 ; deux rangees = largeur ; plus 58px quand le bouton « plus de photos »
     est present, c'est-a-dire au-dela de 4 photos.
   Formules verifiees au pixel (largeur exacte a toutes les largeurs testees, hauteur a 2px pres pour une
   rangee) ; on ajoute 4px de marge pour toujours SURESTIMER un peu, une surestimation ne coutant qu'un peu
   plus d'air sous la galerie alors qu'une sous-estimation rognerait son bas.
   La grille rendue contient TOUTES les photos, celles au-dela de la 4e portant .is-hidden (display:none) :
   on compte donc les vignettes VISIBLES avec :nth-child(3):not(.is-hidden), et la presence du bouton
   .esf-sp-gallery__load-more signale les fiches de 5 photos et plus.
   Bouton « plus de photos » coche : la galerie passe a 2227px et devient plus haute que la colonne
   d'information, la course tombe a zero et le nombre de rangees deployees n'est plus previsible ; on repasse
   en statique explicitement, seul cas ou l'on renonce.
   STACKING CONTEXT : position:sticky en cree un. Les calques .qm-lb de la visionneuse (position:fixed,
   z-index 100000) vivent DANS la galerie : sans precaution ils seraient enfermes dans ce contexte et
   passeraient sous l'en-tete (z-index 999). On remonte donc la galerie au-dessus de tout, mais UNIQUEMENT
   quand une photo est ciblee (:has(.qm-lb:target)) ; en temps normal la galerie collee doit rester SOUS
   l'en-tete. Le zoom au survol reste intact, il n'agit que sur des descendants.
   Aucun !important dans tout le bloc : les annulations passent par la specificite apportee par :has(). ---- */
.qm-pd-gal-sticky-build{--qm-pd-gal-sticky:1}
@media (min-width:768px){
	.esf-single-product__main > .esf-single-product__gallery{
		--qm-pd-gal-air:28px;
		--qm-pd-gal-decal:0px;
		--qm-pd-gal-haut:calc(var(--qm-hdr-h,72px) + var(--qm-pd-gal-air) + var(--qm-pd-gal-decal));
		--qm-pd-gal-larg:calc(0.5 * (100vw - 32px));
		--qm-pd-gal-h:calc((var(--qm-pd-gal-larg) - 6px) / 2 + 4px);
		position:sticky;
		top:min(var(--qm-pd-gal-haut),calc(100vh - var(--qm-pd-gal-h) - var(--qm-pd-gal-air)));
		align-self:flex-start;
	}
	/* Deux rangees des la 3e vignette visible, plus le bouton au-dela de la 4e photo.
	   La regle du bouton REPREND le :has() de la precedente : sans cela sa specificite (0,3,0) perdait
	   contre celle de la regle « deux rangees » (0,6,0, le :has() prenant la specificite de son argument),
	   les 58px du bouton n'etaient pas comptes et le bas de la galerie depassait de 26px sous la fenetre.
	   Mesure du 01/09 avant correction : 10 photos a 1440x900 donnaient top:4px au lieu de -54px. */
	.esf-single-product__main > .esf-single-product__gallery:has(.esf-sp-gallery__grid > .esf-sp-gallery__item:nth-child(3):not(.is-hidden)){--qm-pd-gal-h:calc(var(--qm-pd-gal-larg) + 4px)}
	.esf-single-product__main > .esf-single-product__gallery:has(.esf-sp-gallery__grid > .esf-sp-gallery__item:nth-child(3):not(.is-hidden)):has(.esf-sp-gallery__load-more){--qm-pd-gal-h:calc(var(--qm-pd-gal-larg) + 62px)}
	.esf-single-product__main > .esf-single-product__gallery:has(.qm-lb:target){z-index:100001}
	.esf-single-product__main > .esf-single-product__gallery:has(.qm-gal-more:checked){position:static}
	body.admin-bar .esf-single-product__main > .esf-single-product__gallery{--qm-pd-gal-decal:32px}
}
@media (min-width:768px) and (max-width:782px){
	body.admin-bar .esf-single-product__main > .esf-single-product__gallery{--qm-pd-gal-decal:46px}
}
/* Au-dela de 1024px la galerie passe de 50 a 60 % de la largeur, plafonnee par la zone de contenu a 1440px. */
@media (min-width:1025px){
	.esf-single-product__main > .esf-single-product__gallery{--qm-pd-gal-larg:calc(0.6 * min(100vw,1440px))}
}
/* ---- QM PD GALERIE STICKY : fin du bloc. ---- */

/* ==== QM FICHE GALERIE : debut ==== */
/* 01/09 : deux corrections mesurees au navigateur sur la fiche produit, rejouables telles quelles.
   1) UNE SEULE PHOTO, ECRAN LARGE. esf-frontend.css donne a la galerie une grille de DEUX colonnes carrees
      (grid-template-columns:repeat(2,minmax(0,1fr))). Avec une photo unique elle restait dans la cellule de
      GAUCHE : mesure a 1600px, galerie de 864x429 pour une photo de 429x429, donc 435px de trou a sa droite,
      face a une colonne d'information de 950px de haut (521px de vide dessous). Sur tablette c'etait pire :
      a 900px la photo unique tombait a 214px de cote. 139 des 374 fiches n'ont qu'une image.
      On passe la grille a UNE colonne dans ce seul cas : la photo prend toute la largeur de la galerie
      (864px a 1600px, 434px a 900px), le trou de droite disparait et le vide sous la galerie tombe a 86px.
      Aucun recadrage : le cadre reste carre, comme les fichiers sources (800x800 ou 1000x1000), donc rien
      n'est rogne sur les 139 fiches concernees.
      Mobile inchange, d'ou le @media (min-width:768px) : sous 768px la grille est deja une piste scroll-snap
      d'une photo pleine largeur par vue (bloc « Galerie sur mobile » plus haut), sans trou possible.
      La classe qm-gallery--solo est posee par qm_pd_gallery() dans lib-product.php quand le produit compte
      exactement une image ; cette fonction lui donne aussi un attribut sizes correspondant a la largeur
      reellement rendue, sans quoi le navigateur s'en tenait au fichier 600x600 et l'etirait de 44 %.
   2) GALERIE COLLANTE. Le bloc « QM PD GALERIE STICKY » plus haut calcule la hauteur de la galerie pour en
      deduire son offset sticky ; sa formule de base suppose une demi-rangee ((largeur - 6px) / 2). Avec une
      photo unique en pleine largeur la galerie fait une largeur entiere : on corrige --qm-pd-gal-h ici,
      sinon l'offset serait calcule sur 433px au lieu de 868px. Le :has() ajoute un cran de classe au
      selecteur d'origine, donc cette regle gagne sans !important et le comportement collant est conserve.
   3) MOBILE, AIR ENTRE L'EN-TETE ET LA PHOTO. qm-header.css pose
      .qm-native div.elementor-element.elementor-element-0985de8 > div.e-con-inner{padding-top:calc(var(--qm-hdr-h) + 32px)}
      or --qm-hdr-h vaut 72px sur body.qm-native:not(.home) SANS variante mobile, alors que :root le met bien
      a 54px sous 768px. Barre mesuree au navigateur : 72px au-dela de 768px, 54px en dessous. L'air reel
      etait donc de 104 - 72 = 32px sur desktop mais de 104 - 54 = 50px sur mobile, d'ou l'impression de
      trou signalee. On repose 54 + 32 = 86px sous 768px pour CE conteneur seulement (meme selecteur, meme
      specificite, plus loin dans la feuille servie), sans toucher a --qm-hdr-h qui sert ailleurs
      (main.site-main, element-c37b944, formule de la galerie collante).
   ==== */
@media (min-width:768px){
	.qm-gallery--solo .esf-sp-gallery__grid{grid-template-columns:minmax(0,1fr)}
	.esf-single-product__main > .esf-single-product__gallery:has(.qm-gallery--solo){--qm-pd-gal-h:calc(var(--qm-pd-gal-larg) + 4px)}
}
@media (max-width:767px){
	.qm-native div.elementor-element.elementor-element-0985de8 > div.e-con-inner{padding-top:86px}
}
/* ==== QM FICHE GALERIE : fin ==== */

/* ---- QM PD TABLEAU + AERATION : debut du bloc ajoute aux feuilles compilees (rejouable, reecrit a l'identique).
   Marqueur : .qm-pd-tbl-build
   Deux chantiers du 01/09, tous deux AU RENDU : le post_content des 374 fiches n'est pas touche.

   1. TABLEAU DES CARACTERISTIQUES. 371 fiches sur 374 en portent un dans leur description, toujours
      2 colonnes libelle / valeur, de 2 a 7 rangees. Ce qu'il donnait avant, mesure au navigateur :
        - « table td, table th { border:1px solid rgba(128,128,128,.5); padding:15px } » d'une feuille de
          base dessinait une GRILLE GRISE complete ; le bloc precedent ne reecrivait que border-bottom,
          les trois autres cotes restaient donc en place ;
        - « table tbody > tr:nth-child(2n+1) > td { background-color:rgba(128,128,128,.07) } » ajoutait un
          ZEBRE GRIS ;
        - 248 fiches declarent <table border="1"> : l'attribut de presentation ajoute par-dessus un cadre
          « outset » gris ;
        - la table etait collee au texte : margin .4em en haut, 0 en bas, soit 5px mesures au-dessus et
          0px en dessous du paragraphe suivant.
      Le module de rendu (mu-plugins/qm-pd-desc-render.php) nettoie maintenant le balisage : attributs de
      presentation et styles en ligne retires, premiere colonne promue en <th scope="row"> quand la forme
      s'y prete (370 des 371), classes .qm-pd-tbl / .qm-pd-tbl__t / __k / __v posees, enveloppe de
      defilement. Il n'y a donc plus AUCUN style en ligne a battre : pas un seul !important ici.
      DIRECTION ARTISTIQUE, relevee sur la fiche elle-meme et non inventee : fond blanc, rayons nuls
      (bouton d'achat et cartes d'avis sont a angles droits), filet chaud #EEEAE3 (exactement la bordure
      des cartes d'avis), creme #FAF5EA (couleur personnalisee « Cream light » du kit Elementor), encre
      #2B2B2E (couleur systeme « Principal »), rouge de marque #DD1B1F (brand_color de tout-auto, et
      couleur systeme « Texte » du kit). D'ou : filet de tete rouge de 2px comme seul accent, colonne de
      libelles en creme, separateurs de rangees en filet chaud, plus de grille ni de zebre.

   2. AERATION DU TEXTE. Mesure sur les 1262 paragraphes des 374 descriptions : 89 % font 4 phrases ou
      plus, 46 % en font 7 ou plus, jusqu'a 15 ; augmenter l'interligne n'y aurait rien change, il fallait
      regrouper les phrases par trois, ce que fait le module de rendu (3426 paragraphes rendus, dont
      96,6 % de 2 ou 3 phrases).
      🚨 ET SURTOUT : les paragraphes n'avaient AUCUNE marge basse, malgre le
      « .qm-pd-desc .qm-pd-desc-txt p{margin:0 0 1em} » du bloc precedent. Cause racine mesuree au
      navigateur : l'identifiant Elementor reutilise du bloc « Specs » porte
      « .elementor-876 .elementor-element.elementor-element-5de5323 p { margin-block-end:0 } »,
      specificite (0,3,1) en PROPRIETE LOGIQUE, contre (0,2,1) pour la regle maison, qui perdait donc.
      On repasse devant avec quatre classes (0,4,1), sans !important. ---- */
.qm-pd-tbl-build{--qm-pd-tbl:1}

/* --- 1. AERATION : de l'air toutes les trois phrases au maximum --- */
.qm-pd-desc .qm-pd-desc-txt .elementor-widget-text-editor p.qm-pd-p{margin:0 0 1.2em}
.qm-pd-desc .qm-pd-desc-txt .elementor-widget-text-editor p.qm-pd-p:last-child{margin-bottom:0}

/* --- 2. TABLEAU DES CARACTERISTIQUES --- */
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl{
	margin:1.6em 0 1.7em;
	background:#fff;
	border:1px solid #EEEAE3;
	border-top:2px solid #DD1B1F;
	/* Filet de securite : un tableau plus large que sa colonne defile ICI, jamais le <body>. */
	overflow-x:auto;
	-webkit-overflow-scrolling:touch;
}
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl:first-child{margin-top:0}
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl:last-child{margin-bottom:0}
.qm-pd-desc .qm-pd-desc-txt table.qm-pd-tbl__t{
	width:100%;
	margin:0;
	border:0;
	border-collapse:collapse;
	background-color:transparent;
	font-size:14.5px;
	line-height:1.55;
	color:var(--e-global-color-primary,#2B2B2E);
}
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t td,
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t th{
	border:0;
	border-top:1px solid #EEEAE3;
	padding:11px 18px;
	text-align:left;
	vertical-align:top;
	background-color:transparent;
	font-weight:400;
	/* Le libelle le plus long du parc fait 32 caracteres (« Biologische Widerstandsfähigkeit ») et le mot
	   insecable le plus long 26 (« Feuchtigkeitsbeständigkeit ») : sur une colonne de 121px en mobile il
	   faut pouvoir couper. Le document est en lang="de", la cesure automatique est donc correcte. */
	overflow-wrap:break-word;
	hyphens:auto;
}
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t tr:first-child > td,
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t tr:first-child > th{border-top:0}
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t td.qm-pd-tbl__k,
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t th.qm-pd-tbl__k{
	width:32%;
	background-color:#FAF5EA;
	border-right:1px solid #EEEAE3;
	font-weight:600;
}
/* 111 fiches enveloppent leur libelle d'un <strong> et 260 non : meme graisse dans les deux cas. */
.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t strong{font-weight:600}
@media (max-width:767px){
	.qm-pd-desc .qm-pd-desc-txt table.qm-pd-tbl__t{font-size:13.5px}
	.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t td,
	.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t th{padding:10px 13px}
	.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t td.qm-pd-tbl__k,
	.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl__t th.qm-pd-tbl__k{width:38%}
	.qm-pd-desc .qm-pd-desc-txt .qm-pd-tbl{margin:1.4em 0 1.5em}
}
/* ---- QM PD TABLEAU + AERATION : fin du bloc. ---- */

/* ==== QM LIENS DESC : debut ==== bloc delimite, ajoute en fin de feuille, rejouable ====
   LIENS INTERNES DES DESCRIPTIONS PRODUIT (01/09/2026).

   ETAT AVANT, mesure au navigateur : les liens sortaient en rgb(204,51,102), soit #c36, une couleur
   qui n'existe dans aucune palette du site.
   D'OU ELLE VIENT, cherche avant de surcharger quoi que ce soit : ce n'est NI une variable de kit NI
   une couleur globale Elementor. Les quatre globales du kit, relevees sur l'element lui-meme, sont
   --e-global-color-primary #2B2B2E, --secondary #FFFFFF, --text #DD1B1F, --accent #FFF9EA.
   La regle gagnante, identifiee par CSS.getMatchedStylesForNode, est la remise a zero du theme PARENT,
   wp-content/themes/hello-elementor/assets/css/reset.css, premiere ligne :
       a{background-color:transparent;color:#c36;text-decoration:none}
   Ce fichier est la source n°23 de build/product.css d'apres native/build/manifest.json, donc compilee
   APRES qm-product.css qui est la n°20 : le selecteur « a » nu, pourtant de specificite (0,0,1),
   passait devant les regles maison simplement parce qu'il arrive plus tard dans la feuille.
   🚨 La meme ligne est aussi l'origine de la grille grise et du zebre gris des tableaux, plus bas dans
   ce fichier : table td,table th{border:1px solid hsla(0,0%,50%,.502);padding:15px} et
   table tbody>tr:nth-child(odd)>td{background-color:hsla(0,0%,50%,.071)}. Une seule cause racine.
   POURQUOI PAS « A LA SOURCE » : la source est un fichier du theme parent, repris a chaque mise a jour
   de hello-elementor, et il est compile dans les CINQ feuilles servies. Le corriger la-bas obligerait a
   relancer la compilation, ce qui est exclu ici. On repasse donc devant avec un selecteur borne a la
   description produit, ce qui ne change rien ailleurs.

   PORTEE DU DEFAUT, relevee sur cinq types de page (accueil, categorie, deux fiches, panier) : les
   seuls liens roses A TEXTE VISIBLE du site sont ceux des descriptions produit, dans P.qm-pd-p et dans
   TD.qm-pd-tbl__v. Les 102 autres liens roses d'une page de categorie sont des liens d'image ou des
   puces de carrousel, sans texte, donc sans couleur perceptible ; les liens des descriptions de
   categorie sont deja blancs.

   COULEUR RETENUE : le rouge de marque #DD1B1F, c'est-a-dire le brand_color de tout-auto-qm et la
   couleur systeme « Texte » du kit Elementor. Rien d'invente.
   CONTRASTE MESURE sur le fond reel des paragraphes, remonte element par element jusqu'au premier fond
   non transparent, soit #FFFFFF : 4,94:1. Le seuil AA de 4,5:1 est donc tenu (l'ancien rose etait a
   4,96:1 : le defaut n'etait pas le contraste, c'etait la palette).
   Le seul autre fond ou un lien de description peut tomber est la colonne de libelles du tableau,
   #FAF5EA, ou le rapport vaut 4,54:1, toujours au-dessus du seuil. Le lien reel constate dans un
   tableau (fiche 2082) est dans la colonne de VALEURS, sur blanc.
   LE LIEN NE SE DISTINGUE JAMAIS PAR LA SEULE COULEUR : le soulignement est present dans tous les
   etats. Il est discret par son epaisseur (1px) et son decalage (2px), pas par une transparence, ce qui
   evite de descendre sous les 3:1 exiges pour un trait porteur de sens.
   ETATS : :visited est explicitement pose sur la meme couleur, sinon il retombait sur la regle « a » du
   theme parent, donc sur le rose. :hover et :focus-visible gardent la couleur (aucune perte de
   contraste) et epaississent le trait a 2px. :focus-visible ajoute un anneau, sans quoi la navigation
   au clavier n'a plus aucun repere une fois le soulignement deja present. ==== */
.qm-liens-desc-build{--qm-liens-desc:1}
.qm-pd-desc .qm-pd-desc-txt a,
.qm-pd-desc .qm-pd-desc-txt a:visited{
	color:#DD1B1F;
	text-decoration:underline;
	text-decoration-thickness:1px;
	text-underline-offset:2px;
}
.qm-pd-desc .qm-pd-desc-txt a:hover,
.qm-pd-desc .qm-pd-desc-txt a:focus-visible{
	color:#DD1B1F;
	text-decoration-thickness:2px;
}
.qm-pd-desc .qm-pd-desc-txt a:focus-visible{
	outline:2px solid #DD1B1F;
	outline-offset:2px;
}
/* ==== QM LIENS DESC : fin du bloc. ==== */

/* ==== QM GALERIE UNE IMAGE (03/09) : debut ====
   La galerie fiche est une grille 2 colonnes. Avec UNE seule photo, l item n occupait qu une demi-colonne
   (un petit carre a gauche, moitie droite vide). Ici : une seule photo -> pleine largeur, ratio naturel
   (image complete, pas un carre rogne). Cible : le seul cas ou la grille n a pas de 2e item. */
.esf-single-product__gallery .esf-sp-gallery__grid:not(:has(> .esf-sp-gallery__item:nth-child(2))){
	grid-template-columns:minmax(0,1fr);
}
.esf-single-product__gallery .esf-sp-gallery__grid:not(:has(> .esf-sp-gallery__item:nth-child(2))) > .esf-sp-gallery__item{
	aspect-ratio:auto;
}
.esf-single-product__gallery .esf-sp-gallery__grid:not(:has(> .esf-sp-gallery__item:nth-child(2))) > .esf-sp-gallery__item img{
	height:auto;aspect-ratio:auto;object-fit:contain;width:100%;
}
/* ==== QM GALERIE UNE IMAGE : fin ==== */

/* Titre de page : un mot compose allemand (« Badezimmerteppich », 362 px a 40 px) ne se coupe pas
   et sortait de l'ecran sous 402 px de large. Cesure automatique (la page est en lang="de-DE")
   plus un filet qui coupe n'importe ou si le dictionnaire de cesure manque. La taille ne change
   pas : le titre passe sur deux lignes au lieu de deborder. */
h1.elementor-heading-title,
.elementor-page-title h1,
h1.entry-title {
	overflow-wrap: break-word;
	word-break: normal;
	hyphens: auto;
}
/* ==== QM FIX 24/09/2026 : debut ==== */
/* 1. Visionneuse : chevrons centres dans les boutons */
.qm-lb button.esf-sp-lightbox__prev,.qm-lb button.esf-sp-lightbox__next{display:inline-flex;align-items:center;justify-content:center}
.qm-lb button.esf-sp-lightbox__prev::before{transform:translateX(3px) rotate(-135deg)}
.qm-lb button.esf-sp-lightbox__next::before{transform:translateX(-3px) rotate(45deg)}
/* 2. En-tete mobile : le logo (absolu, centre) chevauchait la loupe ; centre dans l'espace libre entre la loupe et le panier ; panier centre verticalement */
@media (max-width:767px){
.qm-hdr .elementor-element.elementor-element-5a8d0c5{position:static;order:3;flex:1 1 auto;min-width:0;display:flex;justify-content:center;align-items:center;transform:none;left:auto;top:auto;margin:0 8px;pointer-events:auto}
.qm-hdr .elementor-element.elementor-element-c52526f{width:100%;max-width:140px}
.qm-hdr .elementor-element.elementor-element-c52526f .qm-hdr-brand img{width:100%;max-width:140px}
.qm-hdr .elementor-element.elementor-element-16b955d{margin-left:0}
}
.qm-hdr .elementor-element.elementor-element-16b955d{display:flex;align-items:center;line-height:0}
/* 3. Titres de fiche passes en <p>/<span> : typographie identique aux anciens h2/h3 */
.elementor-876 .elementor-element.elementor-element-17680233 p.elementor-heading-title,.elementor-876 .elementor-element.elementor-element-5ac962e0 p.elementor-heading-title{font-size:16px;line-height:26px;font-weight:500;margin:0}
.elementor-876 .elementor-element.elementor-element-486ce4ab p.elementor-heading-title,.elementor-876 .e-n-tabs-content .elementor-widget-heading p.elementor-heading-title{font-size:32px;line-height:42px;font-weight:400;margin:0}
.elementor-876 .elementor-widget-n-accordion span.e-n-accordion-item-title-text{display:block;margin:0;font-family:inherit;font-weight:inherit;line-height:inherit;color:inherit}
p.qm-rel__t{margin-top:0}
/* 4. Prix en promo : ancien prix discret barre, nouveau prix en rouge de la charte, pastille de remise */
.qm-native .esf-single-product__price del,.qm-native .woocommerce-variation-price del,.qm-native .price del{text-decoration:line-through;color:rgba(43,43,46,.5);font-weight:400;font-size:.72em;margin-right:.4em}
.qm-native .esf-single-product__price ins,.qm-native .woocommerce-variation-price ins,.qm-native .price ins{text-decoration:none;color:#DD1B1F;font-weight:600;background:transparent}
.qm-native .qm-price__badge{display:inline-block;vertical-align:middle;position:relative;top:-.12em;margin-left:.5em;padding:.18em .62em;border-radius:999px;background:#DD1B1F;color:#FFF9EA;font-family:"Roboto",sans-serif;font-size:.55em;font-weight:600;line-height:1.5;letter-spacing:.03em;white-space:nowrap}
.qm-native .qm-pcard__price del{font-size:.88em}
.qm-native .qm-pcard__price .qm-price__badge{font-size:.78em;padding:.1em .5em}
/* 5. (25/09/2026) Zone tactile de l'icone panier de l'en-tete.
   Mesure Playwright en mobile 390 px : le burger et la loupe font 44x44, mais l'icone panier
   ne faisait que 22x22 (le lien lui-meme, sans parent plus grand pour rattraper) — seule cible
   de l'en-tete sous le seuil de 24 px. Ce n'est pas un choix de design mais un oubli.
   On etend la zone par un ::after absolu : la mise en page ne bouge pas (ni le logo ni le bord
   droit) et la taille visuelle du pictogramme est inchangee. Place disponible verifiee :
   44 px jusqu'au bord droit, 26 px jusqu'au logo -> une zone de 44 px ne chevauche rien. */
.qm-hdr .cart-menu .qm-cart-menu{position:relative}
.qm-hdr .cart-menu .qm-cart-menu::after{content:"";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%)}
/* 6. (26/09/2026) Rangee de categories reduite a UNE seule vignette.
   Mesure Playwright en mobile 390 px : le widget 3b767ba reserve 354 px alors que son
   contenu n'en occupe que 60 -> 294 px de vide sous la rangee, tres visible sur
   tableau-planning.fr (1 seule categorie). Les sites a 17 et 63 vignettes n'ont aucun vide.
   Aucune regle CSS ne fixe cette hauteur : elle est calculee par le moteur de rendu, et
   ni line-height, ni align-items, ni grid-auto-rows ne la corrigent sans tasser les
   libelles (verifie : les libelles d'axelvaska tiennent sur deux lignes, 71 px).
   Parti pris : une rangee de categories qui n'en compte qu'une fait doublon avec le titre
   de section affiche juste en dessous ; on la retire dans ce seul cas. Le selecteur ne
   s'active que s'il n'existe pas de 2e vignette, donc la rangee revient d'elle-meme des
   qu'une categorie est ajoutee, et les autres boutiques ne sont jamais concernees
   (verifie site par site : hauteurs inchangees a 60 et 71 px). */
.elementor-element-3b767ba:not(:has(.swiper-slide:nth-child(2))){display:none !important}
/* 7. (26/09/2026) Bloc editorial de fiche produit (widget 4ceaf4c) : images rognees de 37 %.
   Signale par Nico : sur un sac, la cote « 21CM » imprimee sous la photo etait tranchee en
   deux, donc illisible. Mesure Playwright : image carree 590x590 affichee dans un cadre
   590x372 en object-fit:cover -> ~18 % coupes en haut et autant en bas. Le gabarit impose
   une hauteur fixe (372 px desktop, 400 px, 191 px mobile) heritee du template d'origine,
   concu pour des visuels en format paysage ; or les photos de fournisseur sont CARREES et
   portent cotes et mentions en peripherie, precisement dans la zone sacrifiee.
   Defaut GENERALISE : ~3000 images sur les 3 boutiques (3 par fiche produit).
   Correctif retenu : hauteur naturelle. Teste et compare en capture :
     - object-fit:contain conserve le cadre mais laisse des bandes laterales tres visibles
       (le fond des photos d'ambiance ne correspond pas a celui du cadre) ;
     - height:auto rend l'image entiere, plus grande et sans bande. Le bloc passe de 372 a
       590 px : la page s'allonge un peu, au benefice d'une information complete. */
.elementor-876 .elementor-element.elementor-element-4ceaf4c img{height:auto !important}
/* ==== QM FIX 24/09/2026 : fin ==== */
