/*
Theme Name: Sopragglo
Theme URI: https://www.sopragglo.fr
Author: Sopragglo
Description: Thème blocs (FSE) pour Sopragglo, spécialiste de la préfabrication béton. Design system piloté par theme.json, compositions Gutenberg éditables par le client, sans page builder ni webfont.
Version: 1.0.0
Requires at least: 6.6
Tested up to: 7.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: sopragglo
Tags: full-site-editing, block-patterns, block-styles, custom-colors, custom-menu, wide-blocks, translation-ready
*/

/* --------------------------------------------------------------------------
   Ce fichier ne contient QUE ce que theme.json ne sait pas exprimer :
   états au survol, pseudo-éléments, grilles particulières.
   Toutes les couleurs / tailles / espacements viennent des variables CSS
   générées par theme.json — ne jamais écrire une valeur en dur ici.
   -------------------------------------------------------------------------- */

/* Ancres et en-tête collant ------------------------------------------------

   Un lien interne amène sa cible tout en haut de la fenêtre — c'est-à-dire
   derrière l'en-tête, qui y reste collé. Le visiteur arrive sur un titre qu'il
   ne voit pas, et croit avoir raté sa cible. On réserve donc la hauteur de
   l'en-tête au-dessus de chaque élément atteignable par une ancre, plus un peu
   d'air pour que le titre ne soit pas collé au filet. */
[id] {
	scroll-margin-top: 6rem;
}

/* La barre d'administration s'ajoute à l'en-tête pour les personnes connectées. */
.admin-bar [id] {
	scroll-margin-top: calc(6rem + var(--wp-admin--admin-bar--height, 32px));
}

/* En-tête collant --------------------------------------------------------- */

/* Le collage porte sur la balise <header>, pas sur le groupe qu'elle contient :
   un élément collant ne peut pas se décaler à l'intérieur d'un parent qui fait
   exactement sa hauteur — il défilerait avec lui. */
header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 100;
}

.admin-bar header.wp-block-template-part {
	top: var(--wp-admin--admin-bar--height, 32px);
}

/* Sur mobile, la barre d'administration défile avec la page : lui réserver une
   place laisserait un vide sous l'en-tête collé. */
@media (max-width: 782px) {
	.admin-bar header.wp-block-template-part {
		top: 0;
	}
}

/* Seuil de bascule du menu -------------------------------------------------
   WordPress passe en menu déroulant à 600 px. Ici l'en-tête tient tout sur une
   ligne jusqu'à 1100 px seulement : on bascule donc plus tôt, plutôt que de
   laisser l'en-tête se scinder en deux ou trois lignes. */

@media (max-width: 1099px) {
	.sop-header .wp-block-navigation__responsive-container:not(.is-menu-open) {
		display: none;
	}

	.sop-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	/* Sans cela, le bouton flotterait seul au centre : avec trois blocs, la
	   répartition « espace entre » centre celui du milieu. On le colle donc
	   aux actions, à droite. */
	.sop-header .wp-block-navigation {
		margin-left: auto;
	}
}

/* Téléphone de l'en-tête --------------------------------------------------- */

/* Réduit à une icône pour que l'en-tête tienne sur une seule ligne. Le numéro
   reste lisible au survol et pour les lecteurs d'écran, via title et aria-label. */
.sop-phone {
	display: inline-grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 50%;
	border: 1px solid var(--wp--preset--color--line);
	color: var(--wp--preset--color--accent);
	flex: none;
	transition: border-color 0.15s ease, background-color 0.15s ease;
}

.sop-phone svg {
	width: 20px;
	height: 20px;
	display: block;
}

.sop-phone:hover {
	border-color: var(--wp--preset--color--accent);
	background: var(--wp--preset--color--accent-soft);
}

/* L'en-tête ne doit jamais se scinder : chaque groupe garde sa largeur. */
.sop-header .sop-actions {
	flex: none;
}

/* Bouton du menu mobile ---------------------------------------------------- */

/* Le bouton reste dans le flux, entre le logo et les actions : il se place donc
   naturellement sur la première ligne, et ce sont les actions qui passent
   dessous quand l'écran devient trop étroit. */

.sop-header .wp-block-navigation__responsive-container-open {
	padding: 0.5rem;
}

.sop-header .wp-block-navigation__responsive-container-open svg {
	width: 30px;
	height: 30px;
}

/* Liens de navigation : soulignement animé au survol ----------------------- */

.sop-header .wp-block-navigation-item__content {
	padding-block: 0.4rem;
	border-bottom: 2px solid transparent;
}

.sop-header .wp-block-navigation-item__content:hover,
.sop-header .wp-block-navigation-item.current-menu-item .wp-block-navigation-item__content {
	color: var(--wp--preset--color--accent);
	border-bottom-color: var(--wp--preset--color--accent);
}

/* Méga-menu ----------------------------------------------------------------
   Le bloc Navigation ne propose pas de méga-menu : on transforme en CSS le
   sous-menu de l'entrée marquée `sop-mega`. Aucun JavaScript ajouté —
   l'ouverture au survol et au clavier reste celle de WordPress. */

@media (min-width: 1100px) {

	/* Le panneau doit se caler sur l'en-tête pour en occuper toute la largeur.
	   Il faut donc neutraliser tous les repères de positionnement que le bloc
	   Navigation place entre les deux — sinon le panneau se limite à la
	   largeur du menu. Cantonné au desktop : la superposition mobile, elle,
	   a besoin de ces positionnements. */
	.sop-header nav.wp-block-navigation,
	.sop-header .wp-block-navigation .wp-block-navigation__responsive-container,
	.sop-header .wp-block-navigation .wp-block-navigation__responsive-dialog,
	.sop-header .wp-block-navigation .wp-block-navigation__container,
	.sop-header .wp-block-navigation .sop-mega {
		position: static;

		/* Passerelle de survol : entre le bas de la navigation et le haut du
		   panneau il reste la marge basse de l'en-tête. Sans cette bande, la
		   souris quitte la zone survolée en descendant et le menu se referme.

		   Elle a d'abord été posée en `::before` sur le panneau. Mais le
		   panneau doit pouvoir défiler (voir plus bas), et un défilement rogne
		   ce qui déborde — la passerelle avec. On agrandit donc la zone
		   sensible de l'entrée elle-même, que la marge négative reprend aussitôt
		   pour ne rien déplacer dans l'en-tête. */
		padding-bottom: 1.25rem;
		margin-bottom: -1.25rem;
	}

	.sop-header .sop-mega > .wp-block-navigation__submenu-container {
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		width: auto;
		min-width: 0;
		display: grid;
		grid-template-columns: repeat(3, 1fr);
		gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
		/* Contenu aligné sur la grille du site, fond étendu bord à bord. */
		padding: var(--wp--preset--spacing--40)
			max(var(--wp--preset--spacing--40), calc((100% - 1180px) / 2));
		background: var(--wp--preset--color--base);
		border: 0;
		border-top: 1px solid var(--wp--preset--color--line);
		border-radius: 0;
		box-shadow: 0 18px 30px rgba(30, 25, 20, 0.1);
		/* Garde-fou : le panneau est en surcouche, donc rien ne le fait défiler
		   avec la page. Passé la hauteur de la fenêtre, son bas serait
		   simplement inatteignable — on le borne et on lui donne son propre
		   défilement. Vaut quel que soit le nombre de listes dépliées. */
		max-height: calc(100vh - 5.5rem);
		overflow-y: auto;
		overscroll-behavior: contain;
	}

	/* WordPress remet `overflow: visible` sur le sous-menu ouvert, avec une
	   règle plus spécifique que la précédente :

	     .wp-block-navigation .has-child:not(.open-on-click):hover
	       > .wp-block-navigation__submenu-container { overflow: visible }

	   Le plafond de hauteur s'appliquait donc, mais pas le défilement : sur un
	   écran court, le bas du panneau — « Abreuvoirs et auges », entre autres —
	   n'était accessible par aucun moyen. On repasse devant en désignant aussi
	   l'état ouvert. */
	.sop-header .wp-block-navigation .sop-mega.has-child:hover
		> .wp-block-navigation__submenu-container,
	.sop-header .wp-block-navigation .sop-mega.has-child:focus-within
		> .wp-block-navigation__submenu-container {
		overflow-y: auto;
		overflow-x: hidden;
	}

	/* WordPress ne dévoile le panneau qu'au survol, ou quand le bouton
	   « Sous-menu Produits » a été activé. Un visiteur au clavier qui passe ce
	   bouton sans l'actionner entre pourtant dans le panneau : le focus s'y
	   déplaçait sans que rien ne soit visible à l'écran. */
	.sop-header .sop-mega:focus-within > .wp-block-navigation__submenu-container {
		visibility: visible;
		opacity: 1;
		/* WordPress replie aussi le panneau en hauteur nulle : le rendre visible
		   ne suffit pas, il faut lui rendre sa hauteur. */
		height: auto;
	}

	/* Tout s'empile dans le panneau : les entrées du bloc Navigation sont en
	   flex par défaut, ce qui placerait une sous-liste à côté de son parent. */
	.sop-header .sop-mega .wp-block-navigation__submenu-container li {
		display: block;
	}

	/* Filets verticaux entre les colonnes, sauf en début de rangée. */
	.sop-header .sop-mega > .wp-block-navigation__submenu-container > li:not(:nth-child(3n + 1)) {
		border-left: 1px solid var(--wp--preset--color--line);
		padding-left: var(--wp--preset--spacing--40);
	}

	.sop-header .sop-mega > .wp-block-navigation__submenu-container > li > .wp-block-navigation-item__content {
		display: block;
		padding: 0 0 0.5rem;
		margin-bottom: 0.5rem;
		border-bottom: 1px solid var(--wp--preset--color--line);
		font-size: var(--wp--preset--font-size--large);
		font-weight: 800;
		letter-spacing: -0.01em;
		line-height: 1.2;
	}

	.sop-header .sop-mega > .wp-block-navigation__submenu-container > li > .wp-block-navigation-item__content:hover {
		color: var(--wp--preset--color--accent);
	}

	/* Les niveaux suivants ne sont plus des menus volants : ils se déplient dans
	   la colonne. Le sélecteur vaut pour les deux profondeurs (sous-catégories
	   et produits) : la mise en forme, elle, les distingue plus bas. */
	.sop-header .sop-mega .wp-block-navigation__submenu-container .wp-block-navigation__submenu-container {
		position: static;
		display: block;
		visibility: visible;
		opacity: 1;
		/* WordPress replie ses sous-menus avec une hauteur nulle : on les rouvre. */
		height: auto;
		overflow: visible;
		width: auto;
		min-width: 0;
		padding: 0;
		background: transparent;
		border: 0;
		box-shadow: none;
		transform: none;
	}

	/* WordPress pose sur chaque sous-menu un `::before` absolu, sa propre
	   passerelle de survol pour les menus volants. Ici les niveaux imbriqués
	   sont affichés en statique dans la colonne : la passerelle n'a plus d'objet,
	   mais elle continue d'occuper la zone défilable du panneau. Résultat, une
	   barre de défilement apparaissait sur une trentaine de pixels vides, même
	   sur un grand écran où tout tenait déjà. */
	.sop-header .sop-mega
		.wp-block-navigation__submenu-container
		.wp-block-navigation__submenu-container::before {
		display: none;
	}

	.sop-header .sop-mega .wp-block-navigation__submenu-container .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
		display: block;
		padding: 0.22rem 0;
		border: 0;
		font-weight: 400;
		color: var(--wp--preset--color--contrast-2);
	}

	.sop-header .sop-mega .wp-block-navigation__submenu-container .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
		color: var(--wp--preset--color--accent);
	}

	/* Chevrons décoratifs de WordPress : remplacés par le bouton de dépliage. */
	.sop-header .sop-mega .wp-block-navigation__submenu-container .wp-block-navigation__submenu-icon {
		display: none;
	}

	/* Rythme vertical du panneau -------------------------------------------

	   Deux rangées de trois colonnes demandaient 619 px de hauteur de fenêtre,
	   et 726 px dès qu'une sous-liste était dépliée — ce qui est le cas sur une
	   fiche produit, où le menu ouvre la catégorie courante. Beaucoup de
	   portables n'offrent pas cela une fois la barre d'onglets et les favoris
	   déduits.

	   L'organisation ne bouge pas : mêmes colonnes, mêmes rangées, même ordre.
	   On resserre l'interligne, les marges de titre et le remplissage du
	   panneau. */
	.sop-header .sop-mega > .wp-block-navigation__submenu-container {
		padding-top: var(--wp--preset--spacing--30);
		padding-bottom: var(--wp--preset--spacing--30);
		row-gap: var(--wp--preset--spacing--30);
	}

	.sop-header .sop-mega
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation-item__content {
		padding-bottom: 0.3rem;
		margin-bottom: 0.3rem;
		font-size: var(--wp--preset--font-size--medium);
	}

	.sop-header .sop-mega
		.wp-block-navigation__submenu-container
		.wp-block-navigation__submenu-container
		.wp-block-navigation-item__content {
		padding: 0.08rem 0;
	}

	/* Le retrait des produits sous leur sous-catégorie, et l'espace qui les
	   sépare de la suivante, comptent double sur une fiche produit puisque la
	   liste courante y est ouverte. */
	.sop-header .sop-mega
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container {
		margin-bottom: 0.2rem;
	}

	/* Repère de position : la sous-catégorie d'où l'on vient reste signalée même
	   si sa liste est repliée. C'est ce qui remplace le dépliage automatique,
	   lequel donnait au panneau une hauteur différente selon la page. */
	.sop-header .sop-mega
		.wp-block-navigation__submenu-container
		li[data-sop-courant] > .wp-block-navigation-item__content {
		color: var(--wp--preset--color--accent);
		font-weight: 600;
	}

	/* Sous-catégorie : libellé et chevron sur une même ligne. En colonne étroite
	   le bouton, simple élément en ligne, passait seul à la ligne suivante et
	   coûtait une ligne pour rien. */
	.sop-header .sop-mega
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container
		> li {
		display: flex;
		flex-wrap: wrap;
		align-items: baseline;
		column-gap: 0.3rem;
	}

	.sop-header .sop-mega
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation-item__content {
		/* Le libellé ne prend que sa largeur : le chevron reste contre lui, et
		   non repoussé au bord de la colonne. Il peut rétrécir si le libellé est
		   long, de sorte que le chevron ne passe jamais seul à la ligne. */
		flex: 0 1 auto;
		min-width: 0;
	}

	/* La liste des produits reprend toute la largeur, sous les deux précédents. */
	.sop-header .sop-mega
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container {
		flex: 1 0 100%;
	}

	/* Troisième niveau : les produits, en retrait sous leur sous-catégorie. */
	.sop-header .sop-mega
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container {
		margin: 0 0 0.35rem;
		padding-left: 0.85rem;
		border-left: 1px solid var(--wp--preset--color--line);
	}

	.sop-header .sop-mega
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container
		> li
		> .wp-block-navigation__submenu-container
		.wp-block-navigation-item__content {
		padding: 0.16rem 0;
		font-size: var(--wp--preset--font-size--x-small);
	}
}

/* Dépliage des produits dans le méga-menu --------------------------------
   Hors media query : la superposition mobile affiche elle aussi le menu
   entier, et le même repli y évite une liste interminable. */

/* Le libellé et son chevron s'enchaînent en ligne, la liste des produits passe
   dessous. Volontairement pas en flex : WordPress habille cette rangée
   différemment au survol et dans la superposition mobile, et le chevron finit
   par tomber à la ligne dans l'une des deux. L'affichage en ligne, lui, se
   comporte pareil des deux côtés. */
.sop-header .sop-mega .wp-block-navigation__submenu-container li[data-sop-produits] {
	display: block;
}

/* WordPress étire ce lien avec `flex-grow: 1` depuis un sélecteur à cinq
   classes : il en faut autant pour reprendre la main. */
.sop-header .sop-mega .wp-block-navigation__submenu-container li[data-sop-produits] > .wp-block-navigation-item__content {
	display: inline-flex;
	flex: 0 1 auto;
	vertical-align: middle;
}

.sop-header .sop-mega .wp-block-navigation__submenu-container li[data-sop-produits="replie"] > .wp-block-navigation__submenu-container {
	display: none;
}

.sop-sub-toggle {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	vertical-align: middle;
	width: 1.35rem;
	height: 1.35rem;
	margin-left: 0.35rem;
	padding: 0;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base-2);
	color: var(--wp--preset--color--contrast-2);
	cursor: pointer;
	transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.sop-sub-toggle:hover,
.sop-sub-toggle:focus-visible {
	border-color: var(--wp--preset--color--accent);
	background: var(--wp--preset--color--accent-soft);
	color: var(--wp--preset--color--accent);
}

.sop-sub-toggle svg {
	transition: transform 0.15s ease;
}

.sop-sub-toggle[aria-expanded="true"] svg {
	transform: rotate(180deg);
}

/* Cartes ------------------------------------------------------------------ */

/* L'ombre est portée par une classe plutôt que par un attribut de bloc :
   l'éditeur ne sérialise pas `style.shadow` de la même façon selon les blocs,
   ce qui provoquait des erreurs de validation à l'ouverture des pages. */
.sop-elevated {
	box-shadow: var(--wp--preset--shadow--card);
}

.sop-card {
	transition: border-color 0.15s ease, transform 0.15s ease;
}

.sop-card:hover {
	border-color: var(--wp--preset--color--accent);
	transform: translateY(-2px);
}

/* Cartes de hauteur égale dont le lien reste calé en bas -------------------- */

/* Dans une colonne, la carte occupe toute la hauteur disponible… */
.wp-block-column > .sop-card {
	height: 100%;
}

/* …et empile son contenu, ce qui permet de pousser le lien tout en bas.
   Sans cela, les liens des cartes voisines s'alignent au hasard des textes. */
.sop-card--stack {
	display: flex;
	flex-direction: column;
}

/* La mise en page « contrainte » de WordPress impose `margin-inline: auto`
   à chaque enfant. En contexte flex, ces marges automatiques absorbent
   l'espace libre et rétrécissent l'élément au lieu de l'étirer : on les
   neutralise ici, sans toucher aux marges verticales qui portent l'espacement
   entre blocs. */
.sop-card--stack > *,
.sop-card--stack > .sop-card__body > * {
	margin-left: 0 !important;
	margin-right: 0 !important;
	max-width: none;
}

.sop-card--stack > .sop-card__body {
	flex: 1;
	display: flex;
	flex-direction: column;
}

.sop-card__body > .sop-arrow:last-child,
.sop-card__body > .wp-block-buttons:last-child,
.sop-card--stack > .sop-arrow:last-child,
.sop-card--stack > .wp-block-buttons:last-child {
	margin-top: auto;
}

/* Les deux liens d'une carte « site » tiennent sur une seule ligne. Empilés,
   ils prenaient deux lignes pleines au bas de chaque carte pour dire deux fois
   « allez voir ailleurs ».

   La règle de mise en page de WordPress ferait déjà le travail, mais elle
   dépend d'une feuille générée à part : on la double ici pour que la ligne
   tienne même si cette feuille n'est pas chargée. */
.sop-card__liens {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
}

.sop-card__body > .sop-card__liens:last-child,
.sop-card--stack > .sop-card__liens:last-child {
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--30);
}

.sop-card__liens > p {
	margin: 0;
}

/* Carte entièrement cliquable ---------------------------------------------- */

/* La zone de clic du lien est étendue à toute la carte, sans dupliquer le lien :
   un seul <a> dans le balisage, donc un seul lien pour les lecteurs d'écran
   comme pour les moteurs. */
.sop-card--link {
	position: relative;
}

/* La carte doit être le SEUL repère positionné entre elle et son lien : sinon
   la surcouche se cale sur le conteneur intermédiaire et ne couvre qu'une
   partie de la carte. Les groupes à mise en page contrainte étant en
   `position: relative`, on les remet en `static` ici. */
.sop-card--link .sop-card__body,
.sop-card--link .sop-volet__cache {
	position: static;
}

.sop-card--link .sop-arrow a::before {
	content: "";
	position: absolute;
	inset: 0;
	/* L'emplacement photo est lui-même positionné (rayures en pseudo-élément) :
	   sans z-index il repasserait devant la surcouche et la zone image ne
	   serait pas cliquable. */
	z-index: 1;
}

.sop-card--link:hover .sop-arrow a::after {
	transform: translateX(3px);
}

/* Dans une boucle de requête, c'est le titre de la publication qui porte le
   lien : la ligne fléchée n'est là que comme repère visuel. On étire donc le
   lien du titre, sinon seule sa ligne serait cliquable. */
.sop-card--link .wp-block-post-title a::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.sop-card--link:hover .wp-block-post-title a {
	color: var(--wp--preset--color--accent);
}

/* Produits listés dans une carte catégorie -------------------------------- */

.sop-card__intro {
	margin-bottom: 0.4em;
	color: var(--wp--preset--color--contrast-2);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-weight: 600;
}

/* La carte entière pointe vers la catégorie, via une surcouche en `z-index: 1`.
   Ces liens-ci mènent ailleurs : il faut les faire passer devant, sinon la
   surcouche les avale et tous les clics partent vers la catégorie. */
.sop-card__produits a {
	position: relative;
	z-index: 2;
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
	text-decoration: none;
	box-shadow: inset 0 -1px 0 var(--wp--preset--color--line);
}

.sop-card__produits a:hover,
.sop-card__produits a:focus-visible {
	color: var(--wp--preset--color--accent);
	box-shadow: inset 0 -1px 0 currentColor;
}

/* Listes à coches --------------------------------------------------------- */

.sop-list-check {
	list-style: none;
	padding-left: 0;
	margin-left: 0;
}

.sop-list-check li {
	position: relative;
	padding-left: 1.6em;
	margin-bottom: 0.5rem;
}

.sop-list-check li::before {
	content: "";
	position: absolute;
	left: 0.15em;
	top: 0.42em;
	width: 0.62em;
	height: 0.34em;
	border-left: 2px solid var(--wp--preset--color--accent);
	border-bottom: 2px solid var(--wp--preset--color--accent);
	transform: rotate(-45deg);
}

/* Exclusions. Une coche signalerait une disponibilité : il faut une marque qui
   se lise comme un retrait, sans virer à l'alerte — ce n'est pas une erreur,
   juste un produit qu'on ne trouve pas sur ce site. */
.sop-list-cross {
	list-style: none;
	padding-left: 0;
	margin-left: 0;
}

.sop-list-cross li {
	position: relative;
	padding-left: 1.6em;
	margin-bottom: 0.5rem;
	color: var(--wp--preset--color--contrast-2);
}

.sop-list-cross li::before,
.sop-list-cross li::after {
	content: "";
	position: absolute;
	left: 0.18em;
	top: 0.62em;
	width: 0.62em;
	height: 2px;
	background: var(--wp--preset--color--contrast-3, var(--wp--preset--color--contrast-2));
}

.sop-list-cross li::before {
	transform: rotate(45deg);
}

.sop-list-cross li::after {
	transform: rotate(-45deg);
}

/* Bloc de distribution des fiches de site : il doit se distinguer du reste de
   la carte, puisque c'est l'information qu'on vient y chercher. */
.sop-dispo {
	border-top: 1px solid var(--wp--preset--color--line);
	padding-top: var(--wp--preset--spacing--30);
	margin-top: var(--wp--preset--spacing--30);
}

.sop-dispo__oui {
	display: flex;
	align-items: baseline;
	gap: 0.5em;
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

.sop-dispo__oui::before {
	content: "";
	flex: 0 0 auto;
	width: 0.62em;
	height: 0.34em;
	border-left: 2px solid var(--wp--preset--color--accent);
	border-bottom: 2px solid var(--wp--preset--color--accent);
	transform: rotate(-45deg) translateY(-0.1em);
}

/* Puces neutres (listes de zones, de villes…) */
.sop-list-dot {
	list-style: none;
	padding-left: 0;
	margin-left: 0;
}

.sop-list-dot li {
	position: relative;
	padding-left: 1.2em;
	margin-bottom: 0.4rem;
}

.sop-list-dot li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.62em;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--wp--preset--color--accent);
}

/* Lien fléché ------------------------------------------------------------- */

/* La flèche s'ajoute à tous les liens marqués ; la couleur d'accent ne
   s'applique qu'aux liens texte, pour ne pas écraser un bouton plein. */
.sop-arrow a:not(.wp-block-button__link),
a.sop-arrow:not(.wp-block-button__link) {
	color: var(--wp--preset--color--accent);
	font-weight: 700;
}

/* Sur un lien texte, la flèche reste soudée au dernier mot grâce à l'espace
   insécable — d'où l'absence de `display:inline-block`, qui en ferait une boîte
   autonome pouvant basculer seule à la ligne suivante. */
.sop-arrow a:not(.wp-block-button__link)::after,
a.sop-arrow:not(.wp-block-button__link)::after {
	content: "\00a0\2192";
	transition: transform 0.15s ease;
}

/* Sur un bouton, la flèche est un élément flex aligné avec le libellé.
   Son apparence (pastille ronde) est définie plus bas, avec les boutons. */
.sop-arrow .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	padding-right: 0.6rem;
}

.sop-arrow a:not(.wp-block-button__link):hover::after {
	transform: translateX(3px);
}

/* Icônes ------------------------------------------------------------------ */

.sop-icon svg {
	display: block;
	width: 22px;
	height: 22px;
	color: var(--wp--preset--color--accent);
	flex: none;
}

.sop-icon--lg svg {
	width: 28px;
	height: 28px;
}

/* Pastille ronde autour d'une icône (section « Pourquoi Sopragglo ») */
.sop-icon-circle {
	width: 54px;
	height: 54px;
	border-radius: 50%;
	background: var(--wp--preset--color--accent-soft);
	display: grid;
	place-items: center;
	margin-inline: auto;
}

/* Colonnes centrées, pour les triptyques icône + titre + texte. L'icône se
   centre déjà d'elle-même ; sans cette règle, elle surplombe un texte aligné à
   gauche, et l'ensemble paraît décalé. */
.sop-colonnes-centrees {
	text-align: center;
}

/* Estimateur de besoin ------------------------------------------------------
   Une conversation guidée. Le fil des échanges reste lisible au-dessus de la
   question courante : le visiteur doit pouvoir relire ce qu'il a répondu avant
   de valider une estimation qu'il joindra à sa demande. */

.sop-est {
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	background: var(--wp--preset--color--base);
	padding: var(--wp--preset--spacing--50);
	margin-block: var(--wp--preset--spacing--60);
}

.sop-est__fil > * {
	margin-block: 0 0.75rem;
}

.sop-est__dit,
.sop-est__rep {
	max-width: 42rem;
	padding: 0.7rem 1rem;
	border-radius: var(--wp--custom--radius--small);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
}

.sop-est__dit {
	background: var(--wp--preset--color--base-2);
}

/* La réponse du visiteur se détache par l'alignement, pas par la couleur : une
   pastille colorée à chaque tour rendrait le fil illisible. */
.sop-est__rep {
	margin-left: auto;
	background: var(--wp--preset--color--accent-soft);
	font-weight: 600;
	width: fit-content;
}

.sop-est__aide {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--contrast-2);
	margin-block: -0.4rem 0.9rem;
	padding-inline: 1rem;
}

.sop-est__zone {
	margin-top: var(--wp--preset--spacing--30);
}

.sop-est__choix,
.sop-est__saisie {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	align-items: center;
}

.sop-est__bouton {
	font: inherit;
	font-size: var(--wp--preset--font-size--small);
	padding: 0.55rem 1.1rem;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 999px;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
	transition: border-color 0.15s, background-color 0.15s;
}

.sop-est__bouton:hover,
.sop-est__bouton:focus-visible {
	border-color: var(--wp--preset--color--accent);
	background: var(--wp--preset--color--accent-soft);
}

.sop-est__bouton--plein {
	background: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
	color: #fff;
}

.sop-est__bouton--plein:hover,
.sop-est__bouton--plein:focus-visible {
	background: var(--wp--preset--color--contrast);
	border-color: var(--wp--preset--color--contrast);
	color: #fff;
}

.sop-est__champ {
	font: inherit;
	width: 8rem;
	padding: 0.5rem 0.7rem;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
}

.sop-est__unite {
	color: var(--wp--preset--color--contrast-2);
	font-size: var(--wp--preset--font-size--small);
}

.sop-est__options {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
	gap: var(--wp--preset--spacing--30);
	margin-bottom: var(--wp--preset--spacing--30);
}

.sop-est__option {
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	padding: var(--wp--preset--spacing--40);
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
}

.sop-est__option--conseil {
	border-color: var(--wp--preset--color--accent);
}

.sop-est__badge {
	align-self: flex-start;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
	margin: 0;
}

.sop-est__titre {
	margin: 0;
	font-size: var(--wp--preset--font-size--medium);
}

.sop-est__table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--small);
}

.sop-est__table td {
	padding: 0.25rem 0;
	vertical-align: baseline;
}

.sop-est__qte {
	white-space: nowrap;
	padding-right: 0.6rem;
	font-weight: 700;
}

.sop-est__detail {
	color: var(--wp--preset--color--contrast-2);
	font-size: var(--wp--preset--font-size--x-small);
}

.sop-est__total {
	margin: 0;
	padding-top: 0.6rem;
	border-top: 1px solid var(--wp--preset--color--line);
	font-weight: 600;
}

.sop-est__prix {
	margin: 0;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	color: var(--wp--preset--color--accent);
}

/* Le bouton de dernière ligne se colle en bas, pour que les cartes d'options
   s'alignent malgré des listes de longueurs différentes. */
.sop-est__option > .sop-est__bouton {
	margin-top: auto;
}

.sop-est__lien {
	display: block;
	font: inherit;
	font-size: var(--wp--preset--font-size--x-small);
	background: none;
	border: 0;
	padding: 0;
	margin-bottom: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--contrast-2);
	text-decoration: underline;
	cursor: pointer;
}

/* L'avertissement de fin ne se lit pas comme une aide de champ : il se détache
   du reste, sans quoi il se confond avec la ligne « Recommencer ». */
.sop-est__zone > .sop-est__aide:last-child {
	padding-inline: 0;
	margin-block: 0;
	padding-top: var(--wp--preset--spacing--30);
	border-top: 1px solid var(--wp--preset--color--line);
}

/* Saisie libre du dialogue. La zone de texte prend toute la largeur restante,
   le bouton garde la sienne. `min-width: 0` est indispensable : sans lui, la
   largeur intrinsèque d'un textarea (ses `cols` par défaut) l'empêche de se
   réduire, et le bouton passe à la ligne au lieu de rester à côté. */
.sop-est__saisie--libre {
	align-items: stretch;
}

.sop-est__texte {
	font: inherit;
	font-size: var(--wp--preset--font-size--small);
	flex: 1 1 18rem;
	min-width: 0;
	padding: 0.6rem 0.8rem;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	resize: vertical;
}

.sop-est__texte:focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 1px;
}

/* Estimation jointe, posée dans la carte du formulaire de devis.
   Grisée et bordée : elle se lit comme une pièce jointe verrouillée, pas comme
   une section de la page. C'est ce qui fait comprendre d'un coup d'œil qu'elle
   accompagne le message qu'on s'apprête à écrire. */
.sop-est-jointe {
	background: var(--wp--preset--color--base-2);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	padding: var(--wp--preset--spacing--40);
	margin-bottom: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--contrast-2);
	font-size: var(--wp--preset--font-size--small);
}

.sop-est-jointe > * {
	margin-block: 0 0.5rem;
}

.sop-est-jointe > :last-child {
	margin-bottom: 0;
}

.sop-est-jointe__titre {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--contrast-2);
}

/* Le cadenas dit « verrouillé » sans avoir à l'écrire. */
.sop-est-jointe__marque svg {
	display: block;
	width: 15px;
	height: 15px;
}

.sop-est-jointe__ref {
	margin-left: auto;
	letter-spacing: 0.04em;
	font-weight: 600;
	opacity: 0.75;
}

.sop-est-jointe__objet {
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--medium);
}

.sop-est-jointe__saisie {
	font-size: var(--wp--preset--font-size--x-small);
}

.sop-est-jointe__liste {
	list-style: none;
	padding: 0;
	margin-block: 0 0.6rem;
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem 1.1rem;
	font-size: var(--wp--preset--font-size--x-small);
}

.sop-est-jointe__total {
	padding-top: 0.6rem;
	border-top: 1px solid var(--wp--preset--color--line);
	font-weight: 700;
	color: var(--wp--preset--color--contrast);
}

.sop-est-jointe__note {
	font-size: var(--wp--preset--font-size--x-small);
}

/* Passerelle vers les champs : sans cette ligne, rien n'indiquait qu'il restait
   un message à écrire sous l'estimation. */
.sop-est-jointe__suite {
	margin-block: 0 var(--wp--preset--spacing--30);
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

/* Étiquettes (chips) ------------------------------------------------------ */

.sop-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.625rem;
}

.sop-chip {
	display: inline-flex;
	align-items: center;
	gap: 0.45em;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	padding: 0.5rem 0.75rem;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	line-height: 1.2;
}

.sop-chip svg {
	width: 16px;
	height: 16px;
	color: var(--wp--preset--color--accent);
	flex: none;
}

/* Barre de réassurance : filets verticaux entre les colonnes --------------- */

@media (min-width: 782px) {
	.sop-reassure .wp-block-column + .wp-block-column {
		border-left: 1px solid var(--wp--preset--color--line);
	}
}

/* Tableaux ---------------------------------------------------------------- */

.wp-block-table.is-style-sopragglo table {
	border-collapse: collapse;
	width: 100%;
}

.wp-block-table.is-style-sopragglo th,
.wp-block-table.is-style-sopragglo td {
	padding: 0.875rem 1rem;
	text-align: left;
	vertical-align: top;
	border: 0;
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.wp-block-table.is-style-sopragglo thead th {
	background: var(--wp--preset--color--base-2);
	font-weight: 800;
}

.wp-block-table.is-style-sopragglo tbody tr:last-child th,
.wp-block-table.is-style-sopragglo tbody tr:last-child td {
	border-bottom: 0;
}

.wp-block-table.is-style-sopragglo tbody th {
	font-weight: 700;
}

/* Le tableau reste lisible sur mobile : il défile, la page non */
.wp-block-table.is-style-sopragglo {
	overflow-x: auto;
}

/* Onglets ----------------------------------------------------------------- */

/* Avant l'exécution du script, les panneaux sont simplement empilés : c'est
   l'état servi aux moteurs et aux navigateurs sans JavaScript. */

.sop-tabs__list {
	display: flex;
	gap: 1.6rem;
	border-bottom: 1px solid var(--wp--preset--color--line);
	margin-bottom: var(--wp--preset--spacing--40);
	overflow-x: auto;
	scrollbar-width: thin;
}

.sop-tabs__tab {
	background: none;
	border: 0;
	border-bottom: 2px solid transparent;
	padding: 0.75rem 0;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	color: var(--wp--preset--color--contrast-2);
	white-space: nowrap;
	cursor: pointer;
	transition: color 0.15s ease, border-color 0.15s ease;
}

.sop-tabs__tab:hover {
	color: var(--wp--preset--color--contrast);
}

.sop-tabs__tab[aria-selected="true"] {
	color: var(--wp--preset--color--accent);
	border-bottom-color: var(--wp--preset--color--accent);
}

.sop-tabs__tab:focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 2px;
}

.sop-tabs.is-enhanced .sop-tabs__panel[hidden] {
	display: none;
}

.sop-tabs.is-enhanced .sop-tabs__panel:focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 4px;
}

/* Le titre de section reste dans le DOM — il porte la structure Hn lue par les
   moteurs — mais son texte étant repris par l'onglet, on le masque à l'écran. */
.sop-tabs.is-enhanced .sop-tabs__title {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* À l'impression, on déplie tout. */
@media print {
	.sop-tabs__list {
		display: none;
	}

	.sop-tabs.is-enhanced .sop-tabs__panel[hidden] {
		display: block;
	}

	.sop-tabs.is-enhanced .sop-tabs__title {
		position: static;
		width: auto;
		height: auto;
		margin: 0;
		clip-path: none;
	}
}

/* FAQ / accordéons (bloc « Détails » natif) -------------------------------- */

.sop-faq .wp-block-details {
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	padding: 0;
	margin-bottom: 0.625rem;
}

.sop-faq .wp-block-details summary {
	padding: 0.9rem 1.125rem;
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
	cursor: pointer;
	list-style: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
}

.sop-faq .wp-block-details summary::-webkit-details-marker {
	display: none;
}

.sop-faq .wp-block-details summary::after {
	content: "";
	width: 0.5em;
	height: 0.5em;
	border-right: 2px solid var(--wp--preset--color--accent);
	border-bottom: 2px solid var(--wp--preset--color--accent);
	transform: rotate(45deg) translate(-0.15em, -0.15em);
	transition: transform 0.2s ease;
	flex: none;
}

.sop-faq .wp-block-details[open] summary::after {
	transform: rotate(-135deg) translate(-0.15em, -0.15em);
}

.sop-faq .wp-block-details > :not(summary) {
	padding: 0 1.125rem 1rem;
	margin: 0;
	color: var(--wp--preset--color--contrast-2);
	font-size: var(--wp--preset--font-size--small);
}

/* Listes sans puces (pied de page, documents) ------------------------------ */

.sop-doclist,
.sop-footer-list,
footer.wp-block-group .wp-block-list {
	list-style: none;
	padding-left: 0;
	margin-left: 0;
}

/* Liste de documents PDF -------------------------------------------------- */

.sop-doclist li {
	border-bottom: 1px solid var(--wp--preset--color--line);
	padding-block: 0.6rem;
	margin: 0;
}

.sop-doclist li:last-child {
	border-bottom: 0;
}

.sop-doclist a {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	font-size: var(--wp--preset--font-size--small);
}

.sop-doclist a::before {
	content: "";
	width: 16px;
	height: 20px;
	flex: none;
	background: currentColor;
	color: var(--wp--preset--color--accent);
	clip-path: polygon(0 0, 62% 0, 100% 30%, 100% 100%, 0 100%);
}

/* Pictogrammes des familles produits.

   Ce sont les tracés d'origine, en noir plein. Plutôt que d'en refaire six
   versions colorées, on les atténue : le gris obtenu est celui de l'ancien
   site, et il laisse le titre porter la couleur. */
.sop-famille-icone {
	display: block;
	width: 52px;
	height: 52px;
	margin-bottom: var(--wp--preset--spacing--20);
	opacity: 0.45;
}

/* Offres d'emploi et candidature spontanée dans la même rangée.

   La candidature spontanée ne peut pas entrer dans la boucle de requête, qui ne
   rend que des offres : on efface les conteneurs intermédiaires pour que les
   deux deviennent voisines.

   La rangée est en flex plutôt qu'en grille. Une grille laisse un trou quand la
   dernière ligne est incomplète — avec un seul poste ouvert, deux tiers de la
   largeur restaient vides. En flex, les cartes se partagent toute la largeur :
   ouvrir un poste rétrécit la candidature spontanée, et quand la ligne est
   pleine elle passe d'elle-même à la suivante, où elle s'étend. */
.wp-block-query.sop-offres {
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
	gap: var(--wp--preset--spacing--30);
}

.wp-block-query.sop-offres > .wp-block-post-template {
	display: contents;
}

/* WordPress espace les blocs d'un même flux par une marge haute. Ici l'écart
   est déjà donné par `gap` : la marge ne fait que décaler la candidature vers
   le bas, et l'empêche d'atteindre la hauteur de l'offre voisine. */
.wp-block-query.sop-offres > * {
	margin-block-start: 0;
	margin-block-end: 0;
}

/* `min()` évite que la base dépasse l'écran : sur un iPhone SE, 22 rem valent
   352 px pour 320 px de large, et la page se mettait à défiler horizontalement.
   `min-width: 0` autorise le rétrécissement, qu'un élément flex refuse par
   défaut dès que son contenu est plus large. */
.wp-block-query.sop-offres .wp-block-post-template > li,
.wp-block-query.sop-offres > .sop-candidature {
	flex: 1 1 min(22rem, 100%);
	min-width: 0;
}

/* Le message « aucun poste ouvert » n'a pas de voisin : il prend la ligne. */
.wp-block-query.sop-offres > .sop-card:not(.sop-candidature) {
	flex: 1 1 100%;
}

/* Le bouton se cale en bas, à la hauteur du « Voir l'annonce » des offres ;
   la mention de conservation des données reste en dessous. */
.sop-candidature .wp-block-buttons {
	margin-top: auto;
}

/* Logos des compteurs, repris de l'ancien site. */
.sop-stat-logo {
	display: block;
	width: 56px;
	height: 56px;
	margin-bottom: var(--wp--preset--spacing--20);
	opacity: 0.5;
}

/* Pictogrammes des quatre valeurs, même origine et même traitement. */
.sop-valeur-icone {
	display: block;
	width: 72px;
	height: 72px;
	margin-bottom: var(--wp--preset--spacing--30);
	/* Ces tracés sont des aplats pleins, bien plus denses que les icônes au
	   trait du thème : à pleine opacité ils écraseraient le titre qu'ils
	   annoncent. L'atténuation reproduit le gris de l'ancien site. */
	opacity: 0.55;
}

.sop-valeur-icone svg {
	display: block;
	width: 100%;
	height: 100%;
}

/* Cartes d'articles de hauteur égale.

   La grille donne déjà la même hauteur à chaque case, mais la carte qu'elle
   contient s'arrête à son texte : deux articles voisins n'ont pas le même
   nombre de lignes de résumé, et le cadre de l'un descend plus bas que l'autre.
   On étire donc la carte, et on repousse la date en pied pour que les rangées
   se lisent alignées. */
/* La règle ne vaut que si l'élément contient bien une carte. Sur la page de
   résultats de recherche, la boucle liste un titre et un extrait sans carte :
   `flex` les plaçait alors côte à côte, chaque titre poussant son extrait à une
   abscisse différente selon sa longueur. */
.wp-block-post-template > li:has(> .sop-card) {
	display: flex;
}

.wp-block-post-template > li > .sop-card {
	display: flex;
	flex: 1;
	flex-direction: column;

	/* Sans cela, la carte refuse de descendre sous la largeur naturelle de sa
	   photo : l'image déborde du cadre au lieu de s'y adapter. */
	min-width: 0;
}

/* `min-width: auto` est la valeur par défaut d'un enfant flex : il refuse de
   descendre sous la largeur naturelle de son contenu, et la photo déborde du
   cadre. Il faut le lever sur chaque enfant, pas seulement sur la carte. */
.wp-block-post-template > li > .sop-card > * {
	min-width: 0;
}

/* La photo suit la largeur de la carte plutôt que sa taille naturelle : sans
   cette contrainte, elle dépasse du cadre et recouvre les cartes voisines. */
.wp-block-post-template > li > .sop-card > .wp-block-post-featured-image,
.wp-block-post-template > li > .sop-card > .wp-block-post-featured-image img {
	width: 100%;
	flex: 0 0 auto;
}

/* Le cadrage est imposé ici plutôt que par l'attribut du bloc, qui n'était pas
   appliqué : une photo au format portrait doublait la hauteur de sa carte. */
.wp-block-post-template > li > .sop-card > .wp-block-post-featured-image img {
	height: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
}

.wp-block-post-template > li > .sop-card > .wp-block-post-date {
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--30);
}

/* Une page qui s'ouvre sur un visuel pleine largeur ne doit pas laisser de
   bande blanche sous l'en-tête : le bandeau se colle à la navigation. La règle
   ne s'applique qu'à ce cas précis — ailleurs, l'espacement reste. */
main:has(> .wp-block-post-content > .wp-block-cover.alignfull:first-child) {
	margin-top: 0;
}

/* Visuels ------------------------------------------------------------------ */

/* Blocs Image natifs : le client les remplace via « Remplacer » dans l'éditeur.
   Le recadrage est fait ici, pas dans le fichier : quelle que soit la photo
   déposée ensuite (portrait, panoramique, mal cadrée), la mise en page tient. */

.sop-media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--small);
}

/* Format panoramique : héros, visuel principal de fiche, cartes. */
.sop-media--wide img {
	aspect-ratio: 16 / 9;
}

/* Vignettes de galerie. */
.sop-media--thumb img {
	aspect-ratio: 4 / 3;
}

/* Galerie d'article.

   La galerie native répartit ses images à la proportion : une photo isolée en
   fin de rangée s'étire sur toute la largeur, et un portrait pris au téléphone
   se retrouve trois fois plus haut que ses voisines. Sur un reportage de
   chantier, cela donne une page en accordéon. On impose donc une grille et un
   recadrage uniforme — la photo garde son fichier d'origine, seul l'affichage
   est cadré. */
.wp-block-gallery.has-nested-images.columns-3 {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--30);
}

/* La règle native se protège par `:not(#individual-image)`, dont la spécificité
   d'identifiant l'emporterait sur un sélecteur de classes. On reprend le même
   garde pour rester à égalité. */
.wp-block-gallery.has-nested-images.columns-3 figure.wp-block-image:not(#individual-image) {
	width: auto;
	max-width: none;
	margin: 0;
	flex: none;
}

.wp-block-gallery.has-nested-images.columns-3 figure.wp-block-image:not(#individual-image) img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--small);
}

@media (max-width: 781px) {
	.wp-block-gallery.has-nested-images.columns-3 {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* Miniature de largeur fixe, dans une carte horizontale. */
.sop-media--mini {
	flex: none;
	width: 76px;
}

.sop-media--mini img {
	aspect-ratio: 4 / 3;
}

/* Coins plus marqués, hors carte. */
.sop-media--round img {
	border-radius: var(--wp--custom--radius--card);
}

/* Image affleurant les bords d'une carte : seuls les coins hauts sont arrondis. */
.sop-media--flush img {
	border-radius: var(--wp--custom--radius--card) var(--wp--custom--radius--card) 0 0;
}

/* Ces visuels sont livrés en 3/2, exactement le format d'affichage : aucun
   recadrage n'est donc nécessaire. Une hauteur plafonnée l'était pourtant, et
   coupait le produit en haut et en bas — ce que le cadrage d'origine avait
   justement évité. On laisse la proportion naturelle s'appliquer. */

/* Schéma technique : proportions d'origine, sans recadrage. Le format imposé
   par défaut sert à aligner des photos entre elles ; sur une figure cotée il
   rognerait la légende, c'est-à-dire la seule chose qui la rend lisible. */
.sop-media--schema img {
	aspect-ratio: auto;
	object-fit: contain;
	width: 100%;
	height: auto;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
}

/* Petit croquis coté : l'étirer sur toute la largeur du contenu ne l'agrandit
   pas, ça ne fait que l'interpoler. On le laisse à sa taille utile, centré. */
.sop-media--etroit img {
	display: block;
	max-width: 620px;
	margin-inline: auto;
}

/* Frise chronologique ------------------------------------------------------
   Une liste de dates, tenue par un filet vertical. Le repère est un
   pseudo-élément : rien à ajouter dans le balisage, donc rien que le client
   puisse casser en modifiant le texte d'une étape. */

.sop-frise {
	position: relative;
	padding-left: 2.25rem;
}

.sop-frise::before {
	content: "";
	position: absolute;
	top: 0.6rem;
	bottom: 0.6rem;
	left: 0.3rem;
	width: 2px;
	background: var(--wp--preset--color--line);
}

.sop-frise > .wp-block-group {
	position: relative;
}

.sop-frise > .wp-block-group::before {
	content: "";
	position: absolute;
	top: 0.55em;
	left: -2.25rem;
	width: 11px;
	height: 11px;
	border: 2px solid var(--wp--preset--color--accent);
	border-radius: 50%;
	background: var(--wp--preset--color--base);
}

/* La dernière étape, c'est aujourd'hui : on la marque d'un point plein. */
.sop-frise > .wp-block-group:last-child::before {
	background: var(--wp--preset--color--accent);
}

.sop-frise .sop-frise__date {
	color: var(--wp--preset--color--accent);
	font-weight: 800;
	letter-spacing: -0.01em;
}

/* Bloc de texte long ------------------------------------------------------ */

/* Largeur de lecture confortable. On limite les paragraphes plutôt que le
   conteneur : la mise en page « contrainte » de WordPress recentre tout bloc
   plus étroit que le contenu (margin auto !important), ce qui décalerait la
   section par rapport au reste de la page. */
.sop-prose > p {
	max-width: 80ch;
}

/* Surtitre de section ------------------------------------------------------ */

.sop-eyebrow {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	color: var(--wp--preset--color--accent);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

/* Petit carré plein, signature des sections. */
.sop-eyebrow::before {
	content: "";
	width: 0.6em;
	height: 0.6em;
	background: currentColor;
	flex: none;
}

/* Sur une couverture photo assombrie, le rouge devient illisible : on passe
   le surtitre en blanc. */
.wp-block-cover .sop-eyebrow {
	color: var(--wp--preset--color--base);
}

.sop-eyebrow.has-text-align-center {
	justify-content: center;
}

/* Boutons : pastille fléchée circulaire --------------------------------------
   Le libellé et la flèche sont séparés par une pastille ronde, à la manière
   des boutons de la maquette de référence. */

.sop-arrow .wp-block-button__link::after {
	content: "\2192";
	display: inline-grid;
	place-items: center;
	width: 1.7em;
	height: 1.7em;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.2);
	font-size: 0.8em;
	line-height: 1;
	transition: transform 0.15s ease;
}

/* Sur un bouton à contour, la pastille reprend le rouge très clair. */
.wp-block-button.is-style-sop-outline.sop-arrow .wp-block-button__link::after {
	background: var(--wp--preset--color--accent-soft);
	color: var(--wp--preset--color--accent);
}

/* Sur une couverture photo, le bouton à contour devient transparent et clair,
   pour ne pas faire deux pastilles blanches côte à côte. */
.wp-block-cover .wp-block-button.is-style-sop-outline .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--base);
	border-color: rgba(255, 255, 255, 0.55);
}

.wp-block-cover .wp-block-button.is-style-sop-outline .wp-block-button__link:hover {
	background: rgba(255, 255, 255, 0.12);
	color: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--base);
}

.wp-block-cover .wp-block-button.is-style-sop-outline.sop-arrow .wp-block-button__link::after {
	background: rgba(255, 255, 255, 0.22);
	color: var(--wp--preset--color--base);
}

.sop-arrow .wp-block-button__link:hover::after {
	transform: translateX(2px);
}

/* Listes à puces carrées ---------------------------------------------------- */

.sop-list-square {
	list-style: none;
	padding-left: 0;
	margin-left: 0;
}

.sop-list-square li {
	position: relative;
	padding-left: 1.4em;
	margin-bottom: 0.75rem;
}

.sop-list-square li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.5em;
	width: 0.5em;
	height: 0.5em;
	background: var(--wp--preset--color--accent);
}

/* Cartes de chiffres flottantes -------------------------------------------- */

/* Chiffre au-dessus, libellé en dessous. Côte à côte, la largeur du chiffre
   dictait celle du libellé : « 7 » lui laissait toute la carte, « + de 50 ans »
   le réduisait à une colonne de quatre mots. Empilés, les trois cartes se
   lisent pareil quelle que soit la longueur du nombre. */
.sop-stat-card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.35rem;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--preset--shadow--card);
	padding: 1.2rem 1.4rem;
}

.sop-stat-card p {
	margin: 0;
}

/* Les encarts de la page d'accueil portent un pictogramme. Posé au-dessus, il
   flottait seul sur sa ligne ; il passe à gauche du chiffre. Les encarts sans
   pictogramme — Qui sommes-nous, Nos valeurs — gardent leur empilement, d'où
   le `:has()` qui ne désigne que les premiers. */
.sop-stat-card:has(> .sop-stat-logo) {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	column-gap: 0.9rem;
}

.sop-stat-card > .sop-stat-logo {
	grid-column: 1;
	margin-bottom: 0;
}

.sop-stat-card:has(> .sop-stat-logo) > .sop-stat-number {
	grid-column: 2;
}

/* Une légende éventuelle reprend toute la largeur, sous les deux. */
.sop-stat-card:has(> .sop-stat-logo) > p:not(.sop-stat-number) {
	grid-column: 1 / -1;
}

/* Un décalage en escalier était appliqué aux deuxième et troisième encarts.
   Il n'a jamais eu l'effet visé : là où les cartes sont empilées, le cœur de
   WordPress impose `margin: auto !important` et l'annule ; là où elles sont en
   grille, la marge est prise sur la colonne et donnait trois largeurs
   différentes sur une même rangée. Retiré. */

/* Décor : trame de points et carré plein ------------------------------------ */

.sop-deco {
	position: relative;
}

/* Le contenu passe au-dessus du décor. Un `z-index: -1` sur les décors les
   ferait disparaître derrière le fond coloré de la section. */
.sop-deco > * {
	position: relative;
	z-index: 1;
}

.sop-deco::after {
	content: "";
	position: absolute;
	z-index: 0;
	top: 3rem;
	right: 1.5rem;
	width: 140px;
	height: 110px;
	background-image: radial-gradient(var(--wp--preset--color--line) 2px, transparent 2px);
	background-size: 14px 14px;
	pointer-events: none;
}

.sop-deco::before {
	content: "";
	position: absolute;
	z-index: 0;
	right: 4rem;
	bottom: 2.5rem;
	width: 64px;
	height: 64px;
	background: var(--wp--preset--color--accent);
	opacity: 0.9;
	pointer-events: none;
}

@media (max-width: 781px) {
	.sop-deco::before,
	.sop-deco::after {
		display: none;
	}
}

/* Collage d'images de la bannière ------------------------------------------ */

.sop-collage {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--wp--preset--spacing--30);
	align-items: start;
}

.sop-collage > * {
	margin: 0 !important;
}

@media (min-width: 782px) {
	.sop-collage > *:first-child {
		margin-top: 3.5rem !important;
	}
}

/* Chiffres clés ------------------------------------------------------------ */

.sop-stat-number {
	/* La ligne porte désormais le chiffre et ce qu'il mesure — « 7 sites de
	   production » plutôt que « 7 » suivi d'une légende. Elle est donc plus
	   longue, et la taille suit : un peu plus mesurée, et libre de passer à la
	   ligne. Le chiffre lui-même reste insécable grâce aux espaces insécables
	   posées dans le texte, sans quoi « 25 M€ » se couperait entre le nombre et
	   l'unité. */
	font-size: clamp(1.5rem, 2.6vw, 1.95rem);
	font-weight: 800;
	line-height: 1.15;
	letter-spacing: -0.02em;
	font-variant-numeric: tabular-nums;
	text-wrap: balance;
	flex: 0 0 auto;
}

/* Tuiles « métiers » ------------------------------------------------------- */

.sop-tile {
	overflow: hidden;
}

/* Sur fond photo assombri, l'icône passe en blanc. */
.sop-tile .sop-icon svg {
	color: var(--wp--preset--color--base);
}

.sop-tile .wp-block-cover__image-background {
	transition: transform 0.4s ease;
}

.sop-tile:hover .wp-block-cover__image-background {
	transform: scale(1.05);
}

/* Le voile passe à la couleur d'accent au survol. */
.sop-tile .wp-block-cover__background {
	transition: background-color 0.25s ease;
}

.sop-tile:hover .wp-block-cover__background.has-contrast-background-color {
	background-color: var(--wp--preset--color--accent);
}

/* Toute la tuile est cliquable, via l'unique lien qu'elle contient.
   Le conteneur interne d'une couverture est positionné : la surcouche s'y
   ancrerait et ne couvrirait que la zone de texte. On la déborde donc
   largement — `overflow: hidden` sur la tuile la rogne à ses bords. */
.sop-tile .wp-block-cover__inner-container a::before {
	content: "";
	position: absolute;
	inset: -1000px;
	z-index: 2;
}

/* Logos clients ------------------------------------------------------------ */

.sop-logo img {
	width: 100%;
	height: 60px;
	object-fit: contain;
	filter: grayscale(1);
	opacity: 0.65;
	transition: filter 0.2s ease, opacity 0.2s ease;
}

.sop-logo:hover img {
	filter: grayscale(0);
	opacity: 1;
}

/* Mur de logos clients ------------------------------------------------------

   Ils sont vingt-quatre. La grille du bloc les répartit d'après une largeur de
   colonne minimale, ce qui donne une colonne unique sur un téléphone : deux
   mille pixels de défilement pour la seule liste des clients. On impose donc un
   nombre de colonnes par palier, et une hauteur de logo qui suit.

   La spécificité est doublée volontairement : la mise en page du bloc est
   émise par WordPress avec une classe de même poids, et plus bas dans la page. */
.wp-block-group.sop-logos {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--40);
}

.sop-logos .sop-logo img {
	height: 40px;
}

@media (min-width: 48rem) {
	.wp-block-group.sop-logos {
		grid-template-columns: repeat(4, minmax(0, 1fr));
		gap: var(--wp--preset--spacing--50);
	}

	.sop-logos .sop-logo img {
		height: 52px;
	}
}

@media (min-width: 62rem) {
	.wp-block-group.sop-logos {
		grid-template-columns: repeat(6, minmax(0, 1fr));
	}

	.sop-logos .sop-logo img {
		height: 60px;
	}
}

/* Bandeau des références : défilement continu -------------------------------

   Le ruban glisse sans s'arrêter, à vitesse constante. Il est dupliqué une fois
   par le script : la translation s'arrête pile quand la seconde copie occupe la
   place de la première, si bien que la boucle ne montre aucune couture.

   La translation vaut la moitié de la largeur, plus la moitié d'une gouttière :
   les deux copies sont séparées par le même écart que deux logos voisins, et
   c'est cet écart-là qu'il faut rattraper pour que le raccord tombe juste.

   Tant que le script n'a pas pris la main — ou si l'on a demandé moins
   d'animations — la grille des vingt-quatre logos reste affichée en entier. */

.sop-carrousel {
	--sop-defile-ecart: var(--wp--preset--spacing--50);

	position: relative;
	overflow: hidden;
	margin-bottom: var(--wp--preset--spacing--80);
}

/* Aux deux bords, les logos étaient tranchés net. Un dégradé les fait entrer et
   sortir, ce qui donne au ruban une continuité au-delà du cadre. */
.sop-carrousel.est-actif {
	-webkit-mask-image: linear-gradient(
		to right,
		transparent,
		#000 4rem,
		#000 calc(100% - 4rem),
		transparent
	);
	mask-image: linear-gradient(
		to right,
		transparent,
		#000 4rem,
		#000 calc(100% - 4rem),
		transparent
	);
}

.sop-carrousel.est-actif .sop-carrousel__piste {
	display: flex;
	width: max-content;
	/* Le bloc Groupe est borné à la largeur du contenu ; sans cette levée, le
	   ruban resterait large de 1180 px et la translation, exprimée en
	   pourcentage, se serait calculée sur cette valeur-là. */
	max-width: none;
	gap: var(--sop-defile-ecart);
	grid-template-columns: none;
	margin-bottom: 0 !important;
	animation: sop-defile var(--sop-defile-duree, 120s) linear infinite;
	will-change: transform;
}

.sop-carrousel.est-actif .sop-carrousel__piste > .sop-logo {
	flex: 0 0 8rem;
	margin: 0;
}

/* Le survol suspend le ruban : c'est le seul moyen de s'arrêter sur un logo,
   et l'unique commande d'arrêt d'une animation qui, autrement, ne cesse
   jamais. Le focus clavier fait de même. */
.sop-carrousel.est-actif:hover .sop-carrousel__piste,
.sop-carrousel.est-actif:focus-within .sop-carrousel__piste {
	animation-play-state: paused;
}

/* La distance est posée en pixels par le script plutôt qu'en pourcentage : elle
   vaut la moitié du ruban plus la moitié d'une gouttière, et ne dépend ainsi
   d'aucune largeur intermédiaire. */
@keyframes sop-defile {
	to {
		transform: translateX(calc(-1 * var(--sop-defile-distance, 50%)));
	}
}

@media (min-width: 48rem) {
	.sop-carrousel.est-actif .sop-carrousel__piste > .sop-logo {
		flex: 0 0 10rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.sop-carrousel.est-actif .sop-carrousel__piste {
		animation: none;
	}
}

/* Valeurs : pictogramme à gauche du titre ---------------------------------

   Posé au-dessus, le pictogramme flottait seul sur sa ligne et éloignait le
   titre du bord haut de la carte. Il passe à sa gauche, centré sur lui ; la
   description et le lien reprennent toute la largeur en dessous. */
.sop-card:has(> .sop-valeur-icone) {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	column-gap: 1rem;
}

.sop-card > .sop-valeur-icone {
	grid-column: 1;
	margin-bottom: 0;
}

.sop-card:has(> .sop-valeur-icone) > h2,
.sop-card:has(> .sop-valeur-icone) > h3 {
	grid-column: 2;
	margin-top: 0;
}

.sop-card:has(> .sop-valeur-icone) > p {
	grid-column: 1 / -1;
}

/* Grilles de cartes sans rangée incomplète --------------------------------

   Le bloc Groupe répartit ses colonnes d'après une largeur minimale : le nombre
   de colonnes dépend de la place disponible, et rien ne garantit qu'il divise
   le nombre de cartes. D'où les rangées bancales — trois cartes puis une seule,
   quatre puis deux — et le trou qu'elles laissent.

   On fixe donc le nombre de colonnes par palier, en ne retenant que des
   diviseurs. La largeur minimale reste dans le bloc et sert de repli. */

.wp-block-group.sop-grille--duo {
	grid-template-columns: minmax(0, 1fr);
}

.wp-block-group.sop-grille--quatuor {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.wp-block-group.sop-grille--trio {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 48rem) {
	.wp-block-group.sop-grille--duo {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 62rem) {
	.wp-block-group.sop-grille--quatuor {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}

	.wp-block-group.sop-grille--trio {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* Bannière de consentement --------------------------------------------------

   Posée en bas, au-dessus du contenu sans le masquer : on peut lire la page et
   répondre ensuite. Les deux réponses ont le même poids visuel — rendre le
   refus plus discret que l'accord vicierait le consentement. */

.sop-consentement {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 100;
	padding: var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--base);
	border-top: 1px solid var(--wp--preset--color--line);
	box-shadow: 0 -10px 30px rgba(30, 25, 20, 0.12);
}

.sop-consentement[hidden] {
	display: none;
}

.sop-consentement__boite {
	display: grid;
	gap: var(--wp--preset--spacing--20);
	max-width: 1180px;
	margin: 0 auto;
}

.sop-consentement__titre {
	margin: 0;
	font-weight: 800;
	font-size: var(--wp--preset--font-size--medium);
}

.sop-consentement__texte {
	margin: 0;
	max-width: 62ch;
	color: var(--wp--preset--color--contrast-2);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
}

.sop-consentement__choix {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
}

.sop-consentement__bouton {
	flex: 0 0 auto;
	min-height: 2.75rem;
	padding: 0 1.6rem;
	border: 1px solid var(--wp--preset--color--accent);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--accent);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
	cursor: pointer;
	transition: background 0.2s ease, color 0.2s ease;
}

.sop-consentement__bouton[data-sop-mesure="oui"] {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--base);
}

.sop-consentement__bouton:hover {
	background: var(--wp--preset--color--contrast);
	border-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
}

@media (min-width: 48rem) {
	.sop-consentement__boite {
		grid-template-columns: 1fr auto;
		align-items: center;
		column-gap: var(--wp--preset--spacing--40);
	}

	.sop-consentement__titre,
	.sop-consentement__texte {
		grid-column: 1;
	}

	.sop-consentement__choix {
		grid-column: 2;
		grid-row: 1 / 3;
	}
}

/* Recherche du site --------------------------------------------------------

   Une loupe dans l'en-tête ouvre un bandeau sur toute la largeur, sur le modèle
   du méga-menu. Le formulaire seul suffit à chercher ; les suggestions qui
   s'affichent à la frappe viennent en plus. */

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

.sop-recherche {
	position: static;
	display: flex;
	align-items: center;
}

.sop-recherche__bouton {
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 50%;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--accent);
	cursor: pointer;
	transition: border-color 0.2s ease, background 0.2s ease;
}

.sop-recherche__bouton svg {
	width: 1.15rem;
	height: 1.15rem;
}

.sop-recherche__bouton:hover,
.sop-recherche.est-ouvert .sop-recherche__bouton {
	border-color: var(--wp--preset--color--accent);
	background: var(--wp--preset--color--base-2);
}

/* Le bandeau se cale sur l'en-tête, comme le panneau des produits. */
.sop-recherche__panneau {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	z-index: 30;
	padding: var(--wp--preset--spacing--40)
		max(var(--wp--preset--spacing--40), calc((100% - 1180px) / 2));
	background: var(--wp--preset--color--base);
	border-top: 1px solid var(--wp--preset--color--line);
	box-shadow: 0 18px 30px rgba(30, 25, 20, 0.1);
}

.sop-recherche__panneau[hidden] {
	display: none;
}

.sop-recherche__form {
	display: flex;
	gap: var(--wp--preset--spacing--20);
}

.sop-recherche__form input[type="search"] {
	flex: 1 1 auto;
	min-width: 0;
	padding: 0.85rem 1rem;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--medium);
}

.sop-recherche__form input[type="search"]:focus {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 1px;
	border-color: transparent;
}

.sop-recherche__envoyer {
	flex: 0 0 auto;
	padding: 0 1.4rem;
	border: 0;
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--base);
	font-weight: 700;
	cursor: pointer;
}

.sop-recherche__resultats {
	margin-top: var(--wp--preset--spacing--30);
}

/* Une liste verticale, sous le champ : c'est le geste attendu d'une
   suggestion. */
.sop-recherche__resultats ul {
	max-width: 42rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.sop-recherche__resultats a {
	display: block;
	padding: 0.4rem 0.5rem;
	border-radius: var(--wp--custom--radius--small);
	color: var(--wp--preset--color--contrast-2);
	text-decoration: none;
}

.sop-recherche__resultats a:hover,
.sop-recherche__resultats a:focus-visible {
	background: var(--wp--preset--color--base-2);
	color: var(--wp--preset--color--accent);
}

.sop-recherche__rien {
	margin: 0;
	color: var(--wp--preset--color--contrast-2);
	font-size: var(--wp--preset--font-size--small);
}

/* Formulaire (Fluent Forms) ------------------------------------------------
   L'extension apporte son propre habillage : on le ramène sur les jetons du
   thème pour que le formulaire ne soit pas un îlot visuel. */

/* Champs courts appairés : nom / société, e-mail / téléphone, code postal /
   ville. La classe est posée sur le champ dans Fluent Forms, le thème se
   contente de la mettre en page. */
@media (min-width: 700px) {
	.sop-form .ff-t-container:has(> .ff-t-cell) {
		display: block;
	}

	.sop-form .ff-el-group.ff-moitie {
		display: inline-block;
		width: calc(50% - 0.6rem);
		vertical-align: top;
	}

	.sop-form .ff-el-group.ff-moitie:nth-of-type(even) {
		margin-left: 1.2rem;
	}
}

/* Bulle d'aide de Fluent Forms : l'icône par défaut est d'un bleu vif qui ne
   figure nulle part dans la charte. */
.sop-form .ff-el-tooltip,
.sop-form .ff-el-tooltip svg {
	color: var(--wp--preset--color--contrast-2);
	fill: var(--wp--preset--color--contrast-2);
}

.sop-form .ff-el-tooltip:hover,
.sop-form .ff-el-tooltip:hover svg {
	color: var(--wp--preset--color--accent);
	fill: var(--wp--preset--color--accent);
}

.sop-form .ff-el-input--label label {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	color: var(--wp--preset--color--contrast);
	margin-bottom: 0.35rem;
}

.sop-form .ff-el-form-control {
	width: 100%;
	padding: 0.7rem 0.9rem;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	box-shadow: none;
	transition: border-color 0.15s ease;
}

.sop-form .ff-el-form-control:focus {
	border-color: var(--wp--preset--color--accent);
	outline: 2px solid var(--wp--preset--color--accent-soft);
	outline-offset: 0;
}

.sop-form .ff-el-form-control::placeholder {
	color: var(--wp--preset--color--contrast-2);
	opacity: 0.7;
}

.sop-form textarea.ff-el-form-control {
	min-height: 7rem;
	resize: vertical;
}

/* Case de consentement : la coche reste petite, le texte lisible. */
.sop-form .ff-el-form-check label {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--contrast-2);
	line-height: 1.5;
}

.sop-form .ff-el-form-check-input {
	accent-color: var(--wp--preset--color--accent);
	/* Mesurée à 13 px, la coche était plus petite que la cible tactile minimale
	   de 24 px recommandée par le WCAG (2.5.8). C'est la seule case du site, et
	   elle conditionne l'envoi : la manquer, c'est renvoyer une erreur à
	   quelqu'un qui a rempli tout le formulaire. */
	width: 1.15rem;
	height: 1.15rem;
	flex: 0 0 auto;
	margin-top: 0.1rem;
}

/* La zone cliquable de l'étiquette complète celle de la coche : le doigt vise
   la phrase entière, pas le carré. */
.sop-form .ff-el-form-check label {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
	min-height: 1.5rem;
	cursor: pointer;
}

/* Bouton d'envoi : identique aux autres boutons du site. */
.sop-form .ff-btn-submit {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--base);
	border: 0;
	border-radius: var(--wp--custom--radius--small);
	padding: 0.75rem 1.25rem;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	cursor: pointer;
	transition: background-color 0.15s ease;
}

.sop-form .ff-btn-submit:hover {
	background: var(--wp--preset--color--accent-dark);
}

.sop-form .text-danger,
.sop-form .error-text {
	color: var(--wp--preset--color--accent);
	font-size: var(--wp--preset--font-size--x-small);
}

.sop-form .ff-message-success {
	border: 1px solid var(--wp--preset--color--line);
	border-left: 3px solid var(--wp--preset--color--success);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base-2);
	padding: var(--wp--preset--spacing--40);
}

/* Fil d'Ariane ------------------------------------------------------------ */

.sop-breadcrumb {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--contrast-2);
}

.sop-breadcrumb strong {
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
}

/* Bloc « note de bas de tableau », mentions légères ------------------------ */

.sop-note {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--contrast-2);
}

/* Bouton secondaire (contour) --------------------------------------------- */

.wp-block-button.is-style-sop-outline .wp-block-button__link {
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	border: 1px solid var(--wp--preset--color--line);
}

.wp-block-button.is-style-sop-outline .wp-block-button__link:hover,
.wp-block-button.is-style-sop-outline .wp-block-button__link:focus {
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
}

/* Note de score (avis clients) -------------------------------------------- */

.sop-score {
	font-size: 2.5rem;
	font-weight: 800;
	line-height: 1;
}

.sop-stars {
	color: var(--wp--preset--color--accent);
	letter-spacing: 1px;
}

/* Accessibilité ----------------------------------------------------------- */

.sop-skip-link:focus {
	position: fixed;
	top: 0.5rem;
	left: 0.5rem;
	z-index: 1000;
	padding: 0.75rem 1rem;
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--small);
}

@media (prefers-reduced-motion: reduce) {
	.sop-card,
	.sop-arrow a::after,
	.sop-faq .wp-block-details summary::after {
		transition: none;
	}
}

/* Métiers : le volet roulant ------------------------------------------------

   Repris de l'ancien site, où l'effet était un « slide up » de 0,6 s en
   ease-in-out. La photo occupe toute la tuile ; un bandeau blanc en bas porte
   l'icône et le titre ; au survol ce bandeau remonte jusqu'en haut et découvre
   la description puis le lien.

   Le bandeau a une hauteur fixe, et le titre une place réservée de deux lignes :
   sans cela les six bandeaux se décaleraient dès qu'un libellé passe sur deux
   lignes, ce qui arrive en dessous de 1100 px.

   Tout est enfermé dans `@media (hover: hover)`. Sur un écran tactile il n'y a
   pas de survol : la carte y garde sa présentation d'origine, photo au-dessus et
   texte en dessous, plutôt qu'un contenu qu'un doigt ne pourrait pas atteindre. */

@media (hover: hover) and (pointer: fine) {

	.sop-volet {
		/* Le pictogramme et le titre partagent une ligne : la hauteur du bandeau
		   est celle du pictogramme (52 px) plus les marges internes. Avant, les
		   deux étaient empilés et il en fallait dix rem. */
		--sop-volet-bande: 6.5rem;

		position: relative;
		height: 25rem;
		overflow: hidden;
		/* La photo est posée derrière : le fond blanc de la carte la masquerait. */
		background: none !important;
	}

	/* La photo remplit la tuile. Un `z-index` négatif la place derrière les fonds
	   des éléments non positionnés — c'est ce qui permet au corps de rester
	   `static`, condition posée plus haut pour que la surcouche cliquable couvre
	   toute la carte et pas seulement le bandeau. */
	.sop-volet > .sop-media--flush {
		position: absolute;
		inset: 0;
		z-index: -1;
		margin: 0;
	}

	.sop-volet > .sop-media--flush img {
		width: 100%;
		height: 100%;
		object-fit: cover;
		border-radius: 0;
	}

	/* Sur une tuile presque carrée, une photo panoramique perd la moitié de sa
	   largeur, prise au centre. Deux d'entre elles ont leur sujet ailleurs : le
	   mur de stockage est au bord gauche, l'ouvrier de premier plan du chantier
	   de voirie un peu à gauche du centre. On déplace la fenêtre plutôt que de
	   recadrer les fichiers, qui restent ceux de la documentation marketing. */
	.sop-volet > .sop-media--sujet-gauche img {
		object-position: 32% center;
	}

	.sop-volet > .sop-media--sujet-bord img {
		object-position: 12% center;
	}

	/* Le corps est ancré en bas et animé en hauteur. `sop-card--stack` lui
	   demandait au contraire d'occuper toute la carte.

	   La surcouche cliquable n'est pas rognée par ce `overflow` : son bloc
	   conteneur est la carte, située hors du conteneur de débordement. */
	.sop-volet > .sop-card__body {
		/* Grille en deux colonnes : le pictogramme et le titre sur la même
		   ligne, la description en dessous sur toute la largeur. Empilés, le
		   pictogramme flottait seul au-dessus du titre. */
		display: grid;
		grid-template-columns: auto 1fr;
		align-items: center;
		align-content: start;
		column-gap: 0.85rem;
		flex: 0 0 auto;
		margin-top: auto;
		height: var(--sop-volet-bande);
		overflow: hidden;
		background: var(--wp--preset--color--base);
		/* 600 ms se voyaient traîner sous la souris, d'autant que la carte
		   quittée met le même temps à se refermer. Une courbe qui démarre vite
		   et s'achève en douceur donne le mouvement attendu d'un survol. */
		transition: height 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
	}

	.sop-volet > .sop-card__body > .sop-famille-icone {
		grid-column: 1;
		margin-bottom: 0;
	}

	.sop-volet > .sop-card__body > h3 {
		grid-column: 2;
		/* L'écart entre blocs posait une marge haute au titre, qui le décalait
		   de huit pixels sous le pictogramme. Sur une même ligne, c'est la
		   gouttière de la grille qui les sépare. */
		margin-top: 0;
	}

	.sop-volet > .sop-card__body > .sop-volet__cache {
		grid-column: 1 / -1;
		/* La description ne se contente pas de glisser hors du cadre rogné :
		   elle se révèle. Sans cela, on la voyait apparaître par tranches. */
		opacity: 0;
		transition: opacity 0.3s ease 0.05s;
	}

	/* `focus-within` ouvre le volet à la tabulation, faute de quoi le lien serait
	   atteignable au clavier mais invisible. */
	.sop-volet:hover > .sop-card__body,
	.sop-volet:focus-within > .sop-card__body {
		height: 100%;
		/* Le texte se centre une fois le panneau ouvert, plutôt que de flotter
		   en haut d'une surface deux fois trop grande pour lui. Volet fermé, il
		   ne faut surtout pas centrer : le contenu dépasse alors du bandeau et
		   déborderait aussi par le haut, découvrant la description.

		   Sur une grille, c'est `align-content` qui répartit dans la hauteur —
		   `justify-content` n'agirait que sur les colonnes. */
		align-content: center;
	}

	.sop-volet:hover > .sop-card__body > .sop-volet__cache,
	.sop-volet:focus-within > .sop-card__body > .sop-volet__cache {
		opacity: 1;
	}

	/* La place réservée au titre — deux lignes, toujours — servait à aligner les
	   six bandeaux entre eux quand un libellé passait sur deux lignes. C'est
	   désormais le pictogramme, de hauteur fixe, qui donne sa hauteur à la
	   ligne : la réserve ferait seulement flotter un titre court trop haut. */

	/* Le lien est poussé en bas de carte par `sop-card__body > .sop-arrow`, ce
	   qui l'éloignerait du texte pendant toute l'ouverture. Ici il suit la
	   description. */
	.sop-volet .sop-volet__cache > .sop-arrow {
		margin-top: var(--wp--preset--spacing--30);
	}

	@media (prefers-reduced-motion: reduce) {
		.sop-volet > .sop-card__body,
		.sop-volet > .sop-card__body > .sop-volet__cache {
			transition: none;
		}
	}
}

/* Liste sur plusieurs colonnes ---------------------------------------------

   Une énumération de communes tient sur une seule colonne étroite et allonge
   la page pour rien. `break-inside` empêche qu'un nom se coupe entre deux
   colonnes, ce que les navigateurs font volontiers sur les listes. */
.sop-colonnes {
	columns: 2;
	column-gap: var(--wp--preset--spacing--50);
}

.sop-colonnes li {
	break-inside: avoid;
}

@media (min-width: 50rem) {
	.sop-colonnes {
		columns: 3;
	}
}

/* Panneau du numéro de téléphone -------------------------------------------

   Le bouton de l'en-tête reste un lien `tel:`. Sur un ordinateur, où ce lien
   n'aboutit nulle part, un script l'intercepte et ouvre ce panneau : le numéro
   doit pouvoir être lu et recopié, pas seulement composé. */
.sop-tel {
	position: relative;
	display: inline-flex;
}

/* `hidden` doit l'emporter sur le `display: grid` ci-dessous : la règle du
   navigateur pour cet attribut a une spécificité nulle, n'importe quelle classe
   la neutralise, et le panneau restait ouvert au chargement. */
.sop-tel__panneau[hidden] {
	display: none;
}

.sop-tel__panneau {
	position: absolute;
	top: calc(100% + 0.75rem);
	right: 0;
	z-index: 60;
	display: grid;
	gap: var(--wp--preset--spacing--20);
	min-width: 15rem;
	padding: var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
	text-align: left;
}

/* La flèche rattache le panneau au bouton, sinon il flotte au-dessus du vide. */
.sop-tel__panneau::before {
	content: "";
	position: absolute;
	top: -6px;
	right: 16px;
	width: 10px;
	height: 10px;
	background: var(--wp--preset--color--base);
	border-left: 1px solid var(--wp--preset--color--line);
	border-top: 1px solid var(--wp--preset--color--line);
	transform: rotate(45deg);
}

.sop-tel__titre {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--contrast-2);
}

.sop-tel__numero {
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	/* Le numéro est fait pour être sélectionné à la souris. */
	user-select: all;
}

.sop-tel__numero:hover {
	color: var(--wp--preset--color--accent);
}

.sop-tel__copier {
	justify-self: start;
	padding: 0.35rem 0.75rem;
	font: inherit;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--contrast-2);
	background: var(--wp--preset--color--base-2);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--small);
	cursor: pointer;
}

.sop-tel__copier:hover {
	border-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent);
}

.sop-tel__lien {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--accent);
}


/* Répartition des marchés ---------------------------------------------------

   L'anneau et sa légende, côte à côte sur large écran, empilés en dessous. La
   légende porte le libellé et le chiffre de chaque part : le dessin ajoute la
   proportion, il ne la remplace pas. */
.sop-marches {
	display: grid;
	grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
	gap: var(--wp--preset--spacing--50);
	align-items: center;
	margin: var(--wp--preset--spacing--40) 0 0;
}

.sop-marches__dessin svg {
	display: block;
	width: 100%;
	height: auto;
}

.sop-marches__legende {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 0.55rem;
	/* Même corps que la liste voisine des types de clients, qui est en
	   « small » : la légende héritait du corps de texte et paraissait deux
	   points plus grosse à côté d'elle. */
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.55;
}

.sop-marches__ligne {
	display: grid;
	grid-template-columns: 0.75rem 1fr auto;
	gap: 0.75rem;
	align-items: baseline;
	padding-bottom: 0.55rem;
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.sop-marches__ligne:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

/* La pastille porte l'identité de la part ; le texte reste en couleur de texte,
   une teinte claire y serait illisible. */
.sop-marches__pastille {
	width: 0.75rem;
	height: 0.75rem;
	border-radius: 50%;
	align-self: center;
}

.sop-marches__libelle {
	color: var(--wp--preset--color--contrast);
}

.sop-marches__part {
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--contrast);
}

.sop-marches__legende-titre {
	grid-column: 1 / -1;
	margin: var(--wp--preset--spacing--20) 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--contrast-2);
	text-align: left;
}

@media (max-width: 47rem) {
	.sop-marches {
		grid-template-columns: 1fr;
		justify-items: center;
	}

	.sop-marches__dessin {
		max-width: 14rem;
	}

	.sop-marches__legende {
		width: 100%;
	}
}
