/*
 * Fiche produit.
 * Réf design : Figma 14361:20158 (bureau 1440), 14670:5420 (mobile 393),
 * 14412:3088 (variantes de fond), 14380:3530 (sélecteur de coloris).
 *
 * Chargé uniquement sur is_product() (cf. inc/enqueue.php). Premier CSS du
 * thème conditionné à un gabarit.
 *
 * Deux frontières seulement, et elles disent de la MISE EN PAGE, pas la nav :
 *   - 782 : passage d'une colonne à deux. C'est le seuil natif de WordPress
 *     (core/columns s'empile en dessous), on s'aligne dessus plutôt que
 *     d'inventer un troisième chiffre.
 *   - 1328 : gouttière, via .u-gouttiere de main.css.
 * 781 en max-width est la même frontière que 782, écrite de l'autre côté, comme
 * dans items-ronds.css et media-text-decor.css. Ce n'est pas un troisième seuil.
 * Le 1024 de header.css est la bascule du menu, il ne concerne pas ce fichier.
 * ------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
 * Décor de page
 *
 * Le fond et le quadrillage sont portés par le core/group qui enveloppe le hero
 * et les sections, avec l'extension des sections de la home. Il n'y a donc rien
 * à écrire ici : .has-quadrillage vit dans main.css et le fond est natif.
 *
 * .produit-stage ne sert plus qu'au repli du gabarit, quand une fiche ne
 * contient pas le bloc hero (import CSV, duplication d'une vieille fiche). Il
 * lui donne la teinte par défaut pour que le hero ne tombe pas sur du blanc.
 * ------------------------------------------------------------------------- */
.produit-stage {
	background-color: color-mix(in srgb, var(--wp--preset--color--violet, #7631ff) 10%, transparent);
}

/* -------------------------------------------------------------------------
 * Hero
 *
 * Un seul ordre de balisage (décor, en-tête, média, achat) et deux
 * dispositions. En mobile la grille est une colonne et l'ordre du DOM est déjà
 * le bon. Au-delà de 782, le média passe à gauche sur deux rangées, et le
 * décor se pose sous
 * l'en-tête et l'achat en occupant la même surface qu'eux.
 * ------------------------------------------------------------------------- */
.produit-hero {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--wp--preset--spacing--3-xl, 2.5rem);
	width: 100%;

	/*
	 * Plafond de repli seulement. Quand le hero est rendu par le bloc, c'est
	 * l'alignement WordPress du bloc qui commande la largeur (cf. la règle
	 * juste en dessous) : un seul propriétaire à la fois.
	 */
	max-width: var(--wp--custom--layout--container--wide, 1280px);
	margin-inline: auto;

	/*
	 * Le header est en position absolue : il ne pousse rien, c'est au contenu de
	 * réserver sa hauteur. Le hero en gardait 64 là où le header mobile en fait
	 * 120, d'où le fil d'ariane qui passait sous les icônes du panier. On réserve
	 * --dda-header-height, composée dans header.css, plus 16.
	 *
	 * 16 et non les 32 de la maquette : celle-ci dessine une barre de 80, la
	 * nôtre en fait 120 et sa boîte descend 24 plus bas que le logo. Mesurer
	 * l'écart depuis le bas de la boîte le ferait donc paraître trop grand.
	 * Valeur arbitrée par Hubert [2026-10-02].
	 */
	padding-block: calc(var(--dda-header-height, 7.5rem) + 1rem) 0;
	align-items: center;
}

.produit-hero__decor {
	display: none;
}

/*
 * En-tête : fil d'ariane, titre, nom de variation, prix, pastilles.
 *
 * Grille et non colonne flex, pour une seule raison : en mobile la maquette
 * pose le PRIX SUR LA LIGNE DU TITRE, ferré à droite et aligné sur sa base. En
 * flex il aurait fallu les envelopper ensemble, donc un balisage de plus en
 * bureau où ils sont l'un sous l'autre — soit deux DOM, ce que tout ce gabarit
 * s'emploie à éviter.
 *
 * Titre et prix sont placés explicitement en rangée 2. Tout le reste s'auto-
 * place dans l'ordre du DOM, en sautant la rangée occupée : fil en 1, variante
 * en 3, pastilles en 4. La variante vide passe en display:none, donc elle n'est
 * plus un élément de grille du tout et ne laisse pas de rangée derrière elle.
 */
.produit-hero__entete {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;

	/*
	 * 4 partout, c'est le seul écart que les deux maquettes partagent : entre le
	 * titre et le prix, côte à côte en mobile et l'un sous l'autre en bureau. Les
	 * autres écarts ne sont pas les mêmes aux deux tailles, ils se posent donc
	 * sur les éléments concernés et non ici.
	 */
	column-gap: 0.25rem;
	row-gap: 0.25rem;

	/*
	 * Alignement sur le BAS et non sur la ligne de base : le titre fait deux à
	 * quatre lignes en mobile, le prix une seule. Sur la ligne de base ils se
	 * calent sur la PREMIÈRE ligne du titre, et le prix part flotter en haut
	 * d'un pavé de texte. La maquette les cale en bas (Figma 14751:7386).
	 */
	align-items: end;
	min-width: 0;
}

.produit-hero__fil,
.produit-hero__variante,
.produit-hero__pastilles {
	grid-column: 1 / -1;
}

/*
 * Titre et prix : deux points relevés, une droite entre les deux.
 *
 * Les maquettes ne décrivent pas une taille qui respire, elles décrivent DEUX
 * styles. Le bureau pose le nom du produit en h1, 64/72, et le prix en h3,
 * 40/48, tous deux resserrés à -2px. Le mobile pose le titre en h2, 24/32, le
 * prix en h3 mobile, 20/28, et sans resserrage.
 *
 * ATTENTION AU CODE EXPORTÉ PAR FIGMA : il écrit la valeur par DÉFAUT de la
 * variable, jamais celle du mode. `fonts/headings/h2/size` y sort à 48px, sa
 * valeur bureau, alors que le mode mobile vaut 24. Les cotes ci-dessous
 * viennent des variables résolues sur les nœuds eux-mêmes, pas du code exporté.
 *
 * Le pas fluide du thème ne peut pas servir : son plancher est à 2,25rem pour le
 * 6-xl et 1,75rem pour le 3-xl, calibré sur la home en août. Le descendre ici le
 * descendrait partout. D'où trois rampes locales par élément, chacune entre les
 * deux points relevés — 393 et 1440.
 *
 * Le resserrage suit la même logique : à 24px, -2px retire 8% de la chasse et le
 * mot se referme sur lui-même. Il n'arrive qu'avec la taille.
 *
 * Réf : Figma 14743:4364 et 14743:4365 (bureau), 14751:7387 et 14751:7388 (mobile).
 */
.produit-hero__titre {
	grid-column: 1;
	grid-row: 2;
	margin: 0;
	font-size: clamp(1.5rem, 0.5616rem + 3.8204vw, 4rem);
	line-height: clamp(2rem, 1.0616rem + 3.8204vw, 4.5rem);
	letter-spacing: clamp(-2px, 0.7507px - 0.19102vw, 0px);
	color: var(--wp--preset--color--violet-bolder, #28076e);
}

/*
 * Nom de la variation. L'élément existe toujours, même vide, pour que son
 * remplissage au choix d'un coloris ne fasse pas sauter le prix d'une ligne.
 */
.produit-hero__variante {
	margin: 0;
	min-height: 1.4em;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--md, 1rem);
	color: var(--wp--preset--color--noir, #1f2937);
}

/*
 * Vide, la ligne sort de la mise en page. Annuler sa hauteur ne suffisait pas :
 * elle restait un enfant de la colonne flex, donc elle consommait un écart
 * AVANT et un APRÈS — d'où le double espace sur un produit simple, qui n'a pas
 * de coloris à nommer.
 *
 * Contrepartie assumée : sur un produit à variations, remettre la sélection à
 * zéro fait remonter le prix d'un cran. Le cas est rare et court, là où le
 * double espace se voyait sur toutes les fiches sans coloris.
 */
.produit-hero__variante:empty {
	display: none;
}

.produit-hero__prix {
	grid-column: 2;
	grid-row: 2;
	white-space: nowrap;
	font-family: var(--wp--preset--font-family--headings);
	font-size: clamp(1.25rem, 0.7808rem + 1.9102vw, 2.5rem);
	line-height: clamp(1.75rem, 1.2808rem + 1.9102vw, 3rem);
	letter-spacing: clamp(-2px, 0.7507px - 0.19102vw, 0px);
	color: var(--wp--preset--color--violet, #7631ff);
}

.produit-hero__prix del {
	opacity: 0.5;
	font-size: 0.6em;
}

.produit-hero__prix ins {
	text-decoration: none;
}

/*
 * Pastilles.
 *
 * Une sélection d'attributs, pas la liste complète : ce qui se décide dans le
 * bloc. Même silhouette que les étiquettes de la maquette (Figma 14743:4739) :
 * fond blanc, filet léger, ombre portée rose sans flou, rayon plein.
 *
 * L'ombre est une ombre de BOÎTE et non un filtre : la pastille est un
 * rectangle à coins ronds, pas une silhouette découpée, et box-shadow évite de
 * créer un contexte de rendu sur chaque élément d'une liste.
 */
.produit-hero__pastilles {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--md, 1rem);

	/* 16 sous le bloc titre-prix en mobile, dont 4 viennent de l'écart de rangée. */
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
}

/* L'apparence de la pastille est partagée avec les listings : classe .mention,
   dans main.css. */

/* -------------------------------------------------------------------------
 * Média : forme de fond, photo, pastille
 *
 * La forme se dimensionne en pourcentage de la LARGEUR DE LA PHOTO, pas de la
 * colonne : c'est le seul repère qui suit le format du produit. Une affiche
 * portrait et un livret carré n'ont pas la même empreinte, et la forme les
 * suit sans réglage. Le pourcentage saisi en back-office ne fait que corriger.
 *
 * .produit-hero__visuel se dimensionne sur la photo (largeur intrinsèque via
 * inline-block), ce qui donne à la forme un pourcentage de référence utile.
 * ------------------------------------------------------------------------- */
.produit-hero__media {
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 0;
}

.produit-hero__visuel {
	position: relative;
	display: inline-block;

	/*
	 * 560 au plus, et jamais plus que la colonne. Le conteneur porte la largeur
	 * maximale plutôt que la photo : il se dimensionne sur elle, donc la forme
	 * de fond, réglée en pourcentage de sa largeur, se met à l'échelle avec.
	 */
	max-width: min(100%, 35rem);
}

/*
 * La forme est RELATIVE à la photo, et le rapport change avec la taille d'écran.
 *
 * Relevé sur les maquettes : 571,7 de forme pour 404,6 de photo en bureau, soit
 * 141 % ; 352 pour 225,5 en mobile, soit 156 %. La photo rétrécit plus que la
 * forme entre les deux, d'où les 10 % d'écart. Le réglage du bloc reste la
 * valeur BUREAU, celle que règle la fiche produit ; le facteur mobile est une
 * décision de mise en page, pas un réglage par produit.
 *
 * Réf : Figma 14743:4356 et 14743:4357 (bureau), 14751:7390 et 14751:7391.
 */
.produit-hero__forme {
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 0;
	width: calc(var(--produit-shape-scale, 140%) * 1.105);
	transform: translate(-50%, calc(-50% + var(--produit-shape-offset, 0%)));
	pointer-events: none;
}

.produit-hero__forme svg {
	display: block;
	width: 100%;
	height: auto;
}

.produit-hero__image {
	position: relative;
	z-index: 1;
	display: block;

	/*
	 * La photo se pose ENTIÈRE dans une boîte, à son rapport d'origine : une
	 * affiche portrait bute sur la hauteur, un produit en largeur sur la largeur.
	 * Aucun recadrage, aucune déformation. La règle vaut pour n'importe quel
	 * format, c'est ce qui permet de ne rien régler par produit.
	 *
	 * La HAUTEUR de la boîte suit les deux maquettes : 320 à 393, 574 à 1440.
	 * Sans ce plafond, la photo remplissait toute la colonne en mobile, soit 361
	 * de large pour 512 de haut — une page et demie d'écran avant la description.
	 *
	 * width et height en auto pour que le rapport soit celui du fichier, et
	 * max-width en 100% pour que la photo suive le conteneur quand la colonne
	 * descend sous 560.
	 */
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: clamp(20rem, 14.0412rem + 24.2598vw, 35.875rem);

	/*
	 * Ombre sans flou, décalée : c'est l'ombre « sticker » de la charte, la
	 * même que sur les cartes produit.
	 */
	box-shadow: 6.693px 6.693px 0 0 rgb(102 77 154 / 0.4);
	transform: rotate(-2deg);
}

/* -------------------------------------------------------------------------
 * Apparition du visuel
 *
 * Au chargement : la photo monte un peu en tournant dans le sens antihoraire,
 * la forme de fond suit avec un léger retard en tournant dans l'autre sens.
 *
 * Le hero est à l'écran dès l'ouverture : une animation CSS suffit, sans
 * script ni détection d'entrée dans l'écran. Les keyframes ne décrivent que le
 * DÉPART (`from`), l'arrivée est l'état normal de l'élément : sans animation
 * — mouvement réduit, navigateur ancien —, le visuel est simplement là.
 *
 * translate et rotate en propriétés DISTINCTES : elles se composent avec le
 * `transform` déjà posé (inclinaison de la photo, centrage de la forme) au
 * lieu de l'écraser.
 *
 * Pas dans l'éditeur, dont le <body> porte .editor-styles-wrapper : l'aperçu
 * du hero est un rendu serveur refait à chaque réglage, l'animation s'y
 * rejouerait à chaque clic.
 * ------------------------------------------------------------------------- */
:root {
	--produit-apparition-courbe: cubic-bezier(0.33, 1, 0.68, 1);
}

@keyframes produit-image-apparition {
	from {
		opacity: 0;
		translate: 0 4rem;
		rotate: 12deg;
	}
}

@keyframes produit-forme-apparition {
	from {
		opacity: 0;
		rotate: -12deg;
	}
}

body:not(.editor-styles-wrapper) .produit-hero__image {
	animation: produit-image-apparition 700ms var(--produit-apparition-courbe) 600ms backwards;
}

body:not(.editor-styles-wrapper) .produit-hero__forme {
	/*
	 * Pivot au coin haut-gauche de la boîte : c'est le CENTRE visible de la
	 * forme, une fois le translate(-50%, -50%) de son transform appliqué. Au
	 * centre de la boîte, comme par défaut, elle aurait balayé au lieu de
	 * tourner sur place.
	 */
	transform-origin: 0 0;
	animation: produit-forme-apparition 900ms var(--produit-apparition-courbe) 850ms backwards;
}

@media (prefers-reduced-motion: reduce) {

	/* Même poids que les règles ci-dessus, et après elles. */
	body:not(.editor-styles-wrapper) .produit-hero__image,
	body:not(.editor-styles-wrapper) .produit-hero__forme {
		animation: none;
	}
}

/*
 * Pastille.
 * Couleur et libellé sont dans le fichier : cette règle ne fait que la placer.
 * Voir product-carousel.css pour la même pastille sur la carte — les deux ne
 * diffèrent plus que par la position et la taille.
 */
.produit-hero__badge {
	position: absolute;
	z-index: 2;
	top: -5%;
	left: -10%;
	display: block;
	width: 40%;
	max-width: 165px;
	transform: rotate(-8deg);
	pointer-events: none;
}

.produit-hero__badge-image {
	display: block;
	width: 100%;
	height: auto;
}


/* -------------------------------------------------------------------------
 * Achat : résumé, formulaire natif WooCommerce, réassurance
 * ------------------------------------------------------------------------- */
.produit-hero__achat {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--lg, 1.25rem);
	min-width: 0;
}

.produit-hero__resume {
	max-width: 30rem;
	color: var(--wp--preset--color--noir, #1f2937);
	font-size: var(--wp--preset--font-size--md, 1rem);
	line-height: 1.5;
}

/*
 * Accroche.
 *
 * Le premier paragraphe de la description courte est en fonte de titre, plus
 * grand, sur les deux maquettes. Ce n'est pas un champ séparé : le découper en
 * deux donnerait deux endroits où écrire une phrase, et rien n'indiquerait
 * lequel sert à quoi. C'est une règle de style sur le premier paragraphe, et la
 * rédaction fait le reste.
 *
 * :not(:last-child) est la garde qui rend la règle sûre. Un paragraphe SEUL
 * n'est pas une accroche, c'est la description : sans la garde, toute fiche dont
 * la description courte tient en un bloc sortait entièrement en fonte de titre.
 * C'est le cas de toutes les fiches existantes aujourd'hui.
 */
.produit-hero__resume > p:first-child:not(:last-child) {
	font-family: var(--wp--preset--font-family--headings);

	/* 16/24/0 à 393, 20/28/-0,5 à 1440. Même rampe que le titre et le prix. */
	font-size: clamp(1rem, 0.9062rem + 0.38204vw, 1.25rem);
	line-height: clamp(1.5rem, 1.4062rem + 0.38204vw, 1.75rem);
	letter-spacing: clamp(-0.5px, 0.1877px - 0.04775vw, 0px);
}


/*
 * Réassurance, sous le bouton.
 * Du texte libre réglé dans le bloc : lieu de fabrication, délai, port offert.
 */
.produit-hero__reassurance {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--xl, 1.5rem);
	margin: 0;
	padding: 0;
	list-style: none;
	font-family: var(--wp--preset--font-family--headings);
	font-size: var(--wp--preset--font-size--md, 1rem);
	line-height: 1.2;
	color: var(--wp--preset--color--noir, #1f2937);
}

/* -------------------------------------------------------------------------
 * Vignettes de coloris
 * Réf design : Figma 14380:3530.
 *
 * Les vignettes commandent le <select> natif, qui reste dans la page. Quand
 * elles sont là (.produit-coloris--pastilles), le menu natif est masqué
 * visuellement mais reste atteignable au clavier et lisible : c'est lui le
 * champ réellement envoyé, et la seule commande qui marche sans JavaScript.
 *
 * D'où clip-path plutôt que display:none. Un display:none le retirerait de
 * l'ordre de tabulation et, sans JS, la fiche deviendrait inachetable.
 * ------------------------------------------------------------------------- */
.produit-coloris {
	display: flex;
	flex-wrap: wrap;
	align-items: center;

	/* 40 entre le libellé et la rangée, relevé sur la maquette. */
	gap: var(--wp--preset--spacing--3-xl, 2.5rem);
}

.produit-coloris__titre {
	margin: 0;
	max-width: 6em;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--md, 1rem);
	color: var(--wp--preset--color--noir, #1f2937);
}

.produit-coloris__liste {
	display: flex;
	flex-wrap: wrap;
	align-items: center;

	gap: var(--wp--preset--spacing--lg, 1.25rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.produit-coloris__item {
	margin: 0;
}

/*
 * L'emplacement se règle sur l'image, et il ne bouge pas d'un clic à l'autre :
 * c'est la vignette CHOISIE qui grandit à l'intérieur, par une transformation,
 * qui ne reflue pas sur la mise en page. La rangée ne se décale donc jamais.
 */
.produit-coloris__pastille {
	display: flex;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.produit-coloris__vignette {
	display: block;

	/*
	 * Une boîte de 80 sur 64 dans laquelle l'image se pose ENTIÈRE, à son
	 * rapport d'origine. Une affiche, plus haute que large, bute sur les 64 de
	 * hauteur et occupe environ 42 de large ; une carte, plus large que haute,
	 * bute sur les 80 de largeur. Ce sont exactement les deux cotes relevées
	 * dans la maquette, sur deux produits aux proportions différentes.
	 *
	 * L'ancien réglage figeait le rapport de l'affiche pour tout le monde et
	 * recadrait le reste en object-fit:cover : les cartes y perdaient leurs
	 * bords. Deux maximums plutôt qu'un rapport imposé, et chaque produit garde
	 * sa forme.
	 *
	 * width et height en auto : sans cela, les attributs de dimension posés par
	 * wp_get_attachment_image l'emporteraient sur les deux maximums.
	 */
	width: auto;
	height: auto;
	max-height: 4rem;

	/*
	 * La sélection n'est pas un contour mais un agrandissement de 1,25 avec une
	 * légère rotation, comme un sticker qu'on décolle de la rangée. C'est la
	 * grammaire du reste du site — le packshot du hero et les cartes produit
	 * emploient la même inclinaison et la même ombre sans flou.
	 *
	 * transform-origin au centre : la vignette grandit des deux côtés à la fois,
	 * donc elle reste alignée sur ses voisines au lieu de pousser la rangée.
	 *
	 * Les vignettes non retenues sont en retrait, pas absentes : à 60 % elles
	 * restent lisibles et cliquables, mais la sélection se lit d'un coup d'œil.
	 * L'état choisi et le survol remontent à 100 %.
	 */
	opacity: 0.6;
	transition:
		opacity 160ms ease-out,
		transform 240ms var(--dda-spring, ease),
		box-shadow 240ms ease-out;
}

/*
 * La largeur maximale se pose à part, sur un sélecteur descendant : WooCommerce
 * impose `.woocommerce img { max-width: 100% }`, plus spécifique qu'une classe
 * seule, et la boîte de 80 partait à la poubelle. Le défaut ne se voyait pas
 * sur les affiches, bornées par leur hauteur ; les cartes montaient à 90.
 */
.produit-coloris .produit-coloris__vignette {
	max-width: 5rem;
}

/*
 * Le survol ne fait que lever le retrait. Il ne déforme plus rien : la
 * transformation est le langage de la SÉLECTION, l'emprunter au survol rendait
 * les deux états difficiles à distinguer en passant la souris sur la rangée.
 */
.produit-coloris__pastille:hover .produit-coloris__vignette,
.produit-coloris__pastille:focus-visible .produit-coloris__vignette {
	opacity: 1;
}

.produit-coloris__pastille.is-actif .produit-coloris__vignette {
	opacity: 1;
	transform: scale(1.25) rotate(-4deg);
	box-shadow: 3px 3px 0 0 rgb(102 77 154 / 0.4);
}

/*
 * Le contour de focus reste, et en `outline` : c'est le seul repère du clavier,
 * et il ne doit pas se confondre avec l'état sélectionné, qui est une taille.
 */
.produit-coloris__pastille:focus-visible {
	outline: 2px solid var(--wp--preset--color--violet-bolder, #28076e);
	outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {

	.produit-coloris__vignette {
		transition: none;
	}
}

.produit-coloris--pastilles .produit-coloris__natif {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/*
 * Le bloc « une variation choisie » de WooCommerce porte le prix et le bouton.
 * Le prix est déjà en haut de la fiche, on ne le montre pas deux fois.
 */
.produit-hero__achat .woocommerce-variation-price,
.produit-hero__achat .woocommerce-variation-description {
	display: none;
}

.produit-hero__achat .woocommerce-variation-availability {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--md, 1rem);
}

/*
 * Quantité masquée : la maquette n'en montre pas, et les produits se vendent à
 * l'unité. Masquer plutôt que retirer le champ garde le formulaire natif
 * valide et la décision réversible d'une ligne.
 *
 * Le sélecteur reprend la chaîne de WooCommerce (.woocommerce div.product
 * form.cart div.quantity) en y insérant notre conteneur : il faut peser PLUS
 * que lui, pas autant. À poids égal c'est l'ordre de chargement qui tranche, et
 * la feuille du plugin passe après la nôtre.
 *
 * !important pour une raison distincte, et c'est la seule qui le justifie : sur
 * un produit à variations, wc-add-to-cart-variation.js pose `display: block` EN
 * LIGNE sur le champ au moment où un coloris est choisi. Aucune spécificité de
 * sélecteur ne bat un style en ligne. D'où un champ qui restait masqué sur un
 * produit simple et réapparaissait au premier clic sur une vignette.
 */
.woocommerce div.product .produit-hero__achat div.quantity {
	display: none !important;
}

/*
 * Bouton d'achat, taille md du système de boutons [2026-10-02].
 *
 * Il ne reste QUE la taille de police à régler. Toute la géométrie du bouton est
 * en em dans button.css — retrait, rayon, ombre — donc elle suit. C'est tout
 * l'intérêt du système : une taille md ici est la même taille md que partout
 * ailleurs sur le site, et elle le restera si on la retouche là-bas.
 *
 * Il portait avant la taille lg, avec trois valeurs posées à la main par-dessus
 * la base : hauteur minimale, retrait horizontal, rayon. Elles disparaissent
 * toutes les trois, sans quoi on aurait un md au corps de texte et au gabarit
 * d'un lg.
 *
 * .alt est repris explicitement : WooCommerce peint le bouton principal via
 * `.woocommerce button.button.alt`, qui compte un élément en plus de nos trois
 * classes. Sans le rattraper, le violet du plugin l'emportait sur le lilas.
 */
.woocommerce div.product .produit-hero__achat button.single_add_to_cart_button,
.woocommerce div.product .produit-hero__achat button.single_add_to_cart_button.alt {
	--btn-c: var(--wp--preset--color--lilas);

	align-self: start;
	background-color: var(--wp--preset--color--lilas, #e5b0fe);
	color: var(--wp--preset--color--violet-bolder, #28076e);
	font-family: var(--wp--preset--font-family--headings);
	font-size: var(--wp--preset--font-size--md, 1rem);
	font-weight: 700;
	text-transform: none;
}

/*
 * WooCommerce fait flotter le bouton et le formulaire. Le flottement laisse le
 * conteneur sans hauteur et la suite du contenu remonte dessous.
 */
.woocommerce div.product .produit-hero__achat form.cart,
.woocommerce div.product .produit-hero__achat button.single_add_to_cart_button {
	float: none;
}

/*
 * Le formulaire empile ses parties : coloris, message d'état, bouton. En bloc
 * elles se touchent, WooCommerce ne prévoyant aucun écart entre elles — les
 * vignettes et le bouton se collaient. align-items pour que le bouton garde sa
 * largeur de contenu au lieu de s'étirer sur toute la colonne.
 *
 * WooCommerce pose aussi `margin-bottom: 2em` sur le formulaire. C'est le
 * dernier élément de la colonne d'achat : la marge ne sépare de rien et ne fait
 * qu'allonger le bloc. L'espacement de la colonne vient de son propre gap.
 */
.woocommerce div.product .produit-hero__achat form.cart {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--xl, 1.5rem);
	margin-bottom: 0;
}

/* -------------------------------------------------------------------------
 * Contenu Gutenberg
 * ------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
 * Écart entre le hero et la première section
 *
 * Relevé sur la maquette : 160. Les sections apportent 40 par leur padding, on
 * pose les 120 restants sur le bloc hero. C'est le hero qui les porte, et non
 * un
 * conteneur de contenu : il n'y en a plus, le groupe de blocs plafonne et
 * espace lui-même.
 * ------------------------------------------------------------------------- */
.produit-hero-bloc {
	margin-block-end: var(--wp--preset--spacing--7-xl, 7.5rem);
}

/*
 * Dans le bloc, la largeur vient de l'alignement WordPress posé sur l'enveloppe
 * du bloc. Le plafond du partial n'a plus lieu d'être : deux propriétaires
 * donneraient un hero plus étroit que ce que l'alignement demande.
 */
.produit-hero-bloc .produit-hero {
	max-width: none;
}

/* -------------------------------------------------------------------------
 * Fil d'ariane
 * ------------------------------------------------------------------------- */
.produit-hero__fil {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--xs, 0.5rem);
	font-family: var(--wp--preset--font-family--headings);
	font-size: var(--wp--preset--font-size--sm, 0.75rem);
	text-transform: uppercase;
}

.produit-hero__fil a {
	text-decoration: none;
}

/*
 * Couleur ET marge se posent sur le sélecteur DOUBLE : le fil porte aussi la
 * classe woocommerce-breadcrumb, et `.woocommerce .woocommerce-breadcrumb`
 * impose son gris #767676 et sa marge basse de 1em à un poids que
 * `.produit-hero__fil` seul n'atteint pas — et une media query n'ajoute aucun
 * poids, donc l'écart sous le fil doit lui aussi passer par ce sélecteur-là.
 *
 * L'écart au titre vaut 24 aux deux tailles (Figma 14771:1047 et 14743:4361).
 * L'écart de rangée de l'en-tête en fournit 4, la marge complète.
 *
 * Gris littéral et non un token : la palette n'a que `noir` (#1F2937) dans ce
 * registre, plus sombre. À promouvoir en variable le jour où la teinte ressert
 * ailleurs — un token pour un seul usage ne sert à rien.
 */
.produit-hero__fil.woocommerce-breadcrumb {
	margin: 0 0 1.25rem;
	color: #374151;
}

.produit-hero__fil.woocommerce-breadcrumb a {
	color: #374151;
}

/*
 * Puces de séparation. Le SVG mesure 12 au naturel, ramené ici à 6 : la
 * dimension se pose en CSS et pas dans le fichier, qui reste une icône de
 * taille neutre réutilisable ailleurs. Le viewBox fait le reste, le cercle
 * suit à l'échelle.
 *
 * Violet désaturé, c'est-à-dire rose-04 dans la palette — le même que les
 * icônes du header et que les ombres sticker.
 */
.produit-hero__fil-sep {
	display: flex;
	color: var(--wp--preset--color--rose-04, #664d9a);
}

.produit-hero__fil-sep svg {
	display: block;
	width: 0.375rem;
	height: 0.375rem;
}

.produit-hero__fil.woocommerce-breadcrumb a:hover {
	color: var(--wp--preset--color--orange, #fc4c02);
}

/* -------------------------------------------------------------------------
 * Deux colonnes
 *
 * 782 est le seuil natif de WordPress. Le média prend la colonne de gauche sur
 * les deux rangées ; le décor est placé explicitement sur la même surface que
 * l'en-tête et l'achat, en dessous d'eux.
 * ------------------------------------------------------------------------- */
@media (min-width: 782px) {

	.produit-hero {
		grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
		grid-template-areas:
			"media entete"
			"media achat";
		grid-template-rows: auto auto;
		column-gap: var(--wp--preset--spacing--5-xl, 4rem);
		row-gap: var(--wp--preset--spacing--3-xl, 2.5rem);
		padding-block: var(--wp--preset--spacing--7-xl, 7.5rem) 0;
	}

	.produit-hero__entete {
		position: relative;
		z-index: 1;
		grid-area: entete;
		align-self: end;
		padding:
			var(--wp--preset--spacing--3-xl, 2.5rem)
			var(--wp--preset--spacing--3-xl, 2.5rem) 0;

		/* Une colonne : le prix repasse SOUS le titre, comme en maquette bureau. */
		grid-template-columns: minmax(0, 1fr);
	}

	.produit-hero__titre,
	.produit-hero__prix {
		grid-column: 1;
		grid-row: auto;
	}

	/* 24 sous le bloc titre-prix au lieu de 16. L'écart sous le fil, lui, vaut 24
	   aux deux tailles depuis la maquette du 2026-10-02. */
	.produit-hero__pastilles {
		margin-block-start: 1.25rem;
	}


	.produit-hero__media {
		grid-area: media;
	}

	/* Le rapport bureau, celui que règle le bloc. */
	.produit-hero__forme {
		width: var(--produit-shape-scale, 140%);
	}

	.produit-hero__achat {
		position: relative;
		z-index: 1;
		grid-area: achat;
		align-self: start;
		padding:
			0 var(--wp--preset--spacing--3-xl, 2.5rem)
			var(--wp--preset--spacing--3-xl, 2.5rem);
	}

	/*
	 * Le décor n'enveloppe pas l'en-tête et l'achat, il se pose SOUS eux en
	 * occupant la même surface. Les envelopper aurait obligé à les séparer du
	 * média en mobile, donc à tenir deux balisages.
	 */
	.produit-hero__decor {
		/* display: block; */
		position: relative;
		z-index: 0;
		grid-row: 1 / 3;
		grid-column: 2 / 3;

		/*
		 * align-items: center vaut pour toute la grille (le média est centré
		 * face à la carte). Le décor, lui, doit couvrir la surface : sans
		 * stretch il se centre sur une hauteur nulle, et le SVG qu'il contient
		 * n'a plus aucun pourcentage de référence.
		 */
		align-self: stretch;
		pointer-events: none;
	}

	/*
	 * SVG inline et non masque CSS : c'est la convention du thème (cf.
	 * inc/svg.php), et l'ombre portée doit s'appliquer à la silhouette réelle,
	 * pas à la boîte. preserveAspectRatio="none" est conservé sur CETTE forme,
	 * à l'inverse des festons : c'est un aplat souple qui doit s'étirer avec la
	 * hauteur du texte, et rien dedans ne trahit l'étirement.
	 *
	 * Débords VERTICAUX en rem et non en pourcentage : la hauteur de la carte
	 * dépend de la longueur du texte, donc un pourcentage donnerait un débord
	 * qui grandit avec la description. Les valeurs de la maquette sont des
	 * distances, pas des proportions.
	 *
	 * Débord DROIT jusqu'au bord de la page, comme dans la maquette où la forme
	 * sort du cadre. Le hero est plafonné à 1280 et centré : la distance de son
	 * bord droit au bord de l'écran vaut 50vw moins la demi-largeur, jamais
	 * négative en dessous de 1280, d'où le max().
	 */
	.produit-hero__decor-forme {
		position: absolute;
		top: -2.5rem;
		bottom: -4rem;
		left: -14%;
		right: calc(-1 * max(0px, 50vw - 640px) - var(--wp--preset--spacing--xl, 1.5rem));
		filter: drop-shadow(24px 24px 0 var(--wp--preset--color--rose-04, #664d9a));
	}

	.produit-hero__decor svg {
		display: block;
		width: 100%;
		height: 100%;
	}

}


/* -------------------------------------------------------------------------
 * Barre d'achat collante (mobile)
 *
 * Réf design : Figma 14673:5982. Le fond y est un cercle pivoté de 82,57° puis
 * recadré dans une boîte de 198 px sur un écran de 393. Transplanter ces cotes
 * les figerait sur cette largeur-là. On dessine donc le même arc en CSS, par un
 * rayon elliptique : silhouette de la même famille, juste à toutes les
 * largeurs. Si la découpe exacte compte, on remplacera par le SVG de la
 * maquette — c'est un échange local, rien d'autre n'en dépend.
 *
 * La barre est masquée au-dessus de 782 : c'est un geste de pouce, pas une
 * mise en page. Un attribut hidden ne suffit pas à la porter, c'est le script
 * qui le retire ; d'où le display:none qui, lui, ne se laisse pas retirer.
 * ------------------------------------------------------------------------- */
.produit-sticky {
	position: fixed;
	z-index: 20;
	inset: auto 0 0;
	padding: var(--wp--preset--spacing--md, 1rem);
	padding-bottom: max(var(--wp--preset--spacing--md, 1rem), env(safe-area-inset-bottom));
	transform: translateY(0);
	transition: transform 240ms ease-out;
}

.produit-sticky[hidden] {
	display: none;
}

.produit-sticky__fond {
	position: absolute;

	/*
	 * L'arc dépasse largement de chaque côté : c'est ce débord qui rend la
	 * courbe douce plutôt qu'un demi-cercle posé sur la barre.
	 */
	inset: -2.5rem -30% 0;
	background-color: var(--wp--preset--color--blanc, #fff);
	border-radius: 50% 50% 0 0 / 3.5rem 3.5rem 0 0;
	box-shadow: 0 -0.25rem 0 0 rgb(102 77 154 / 0.15);
}

.produit-sticky__contenu {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--md, 1rem);
}

.produit-sticky__media {
	display: block;
	flex: 0 0 auto;
	width: 2.8rem;
}

.produit-sticky__image {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 45 / 64;
	object-fit: cover;
	box-shadow: 5.355px 5.355px 0 0 rgb(102 77 154 / 0.4);
	transform: rotate(2deg);
}

.produit-sticky__bouton {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	min-height: 3rem;
	padding: 0.75rem 1.25rem;
	border: 0;
	border-radius: var(--wp--custom--radius--md, 1rem);
	background-color: var(--wp--preset--color--lilas, #e5b0fe);
	box-shadow: 0 0.5rem 0 0 var(--wp--preset--color--rose-04, #664d9a);
	color: var(--wp--preset--color--violet-bolder, #28076e);
	font-family: var(--wp--preset--font-family--headings);
	font-size: var(--wp--preset--font-size--md, 1rem);
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
}

.produit-sticky__prix {
	white-space: nowrap;
}

.produit-sticky__prix::before {
	content: "-";
	margin-inline-end: 0.35em;
}

@media (prefers-reduced-motion: reduce) {

	.produit-sticky {
		transition: none;
	}
}

@media (min-width: 782px) {

	.produit-sticky {
		display: none;
	}
}

/* -------------------------------------------------------------------------
 * « À découvrir aussi »
 *
 * Hors du décor de la fiche : la maquette lui donne son propre fond, et la
 * teinte du produit s'arrête avant lui.
 *
 * Fond et quadrillage sont relevés sur la maquette (Figma 14371:23195) : un
 * dégradé du rose vers le lilas, chacun à 40 %, du haut vers le bas. Les deux
 * teintes et l'opacité du quadrillage sont en variables ici, pour n'avoir qu'un
 * endroit à toucher si Hubert les ajuste.
 *
 * Le quadrillage réemploie .has-quadrillage de main.css — le même mécanisme que
 * les sections de la home et le décor de la fiche. Sa couleur reprend le lilas
 * du fond, comme le quadrillage du hero reprend son violet.
 * ------------------------------------------------------------------------- */
.produit-suite {
	--produit-suite-haut: color-mix(in srgb, var(--wp--preset--color--pink, #f8c9de) 40%, transparent);
	--produit-suite-bas: color-mix(in srgb, var(--wp--preset--color--lilas, #e5b0fe) 40%, transparent);

	background-image: linear-gradient(to bottom, var(--produit-suite-haut), var(--produit-suite-bas));

	/*
	 * Le fond doit passer SOUS le footer : c'est lui que le trou du nuage laisse
	 * voir. footer.css réserve la hauteur du nuage sur `.site-main > :last-child`,
	 * mais sur une fiche produit ce dernier enfant est le conteneur de
	 * WooCommerce, qui n'a aucun fond — la réserve était bien là, et
	 * transparente. On la déplace donc sur la section qui porte la couleur.
	 *
	 * Les 120 s'ajoutent à la réserve, ils ne la remplacent pas : la hauteur du
	 * nuage est ce que le trou de la drache doit pouvoir révéler, l'entamer
	 * ferait réapparaître le fond de page dans la découpe.
	 */
	padding-bottom: calc(var(--footer-cloud-height) + var(--wp--preset--spacing--7-xl, 7.5rem));
}

/*
 * On neutralise la réserve là où elle ne sert à rien, sinon elle s'ajoute à
 * celle qu'on vient de poser et le footer s'éloigne de deux hauteurs de nuage.
 *
 * !important pour répondre à celui de footer.css, qui existe lui-même pour
 * battre les paddings en style inline des blocs Gutenberg. Et une classe de
 * plus que `.site-main > :last-child` : à poids égal c'est footer.css qui
 * l'emporte, puisqu'il charge après. La classe `product` vient de
 * wc_product_class(), elle est toujours là sur une fiche.
 */
.site-main > .produit.product {
	padding-bottom: 0 !important;
}

/*
 * Le bloc carrousel apporte son propre écart bas. C'est la réserve du nuage qui
 * en tient lieu ici, sans quoi les deux s'additionnent.
 */
.produit-suite > .product-carousel {
	max-width: var(--wp--custom--layout--container--wide, 1280px);
	margin-inline: auto;
	padding-bottom: 0;
}

