/* =========================================================================
   BESAFE SYSTEM — Feuille de styles principale
   Mobile-first, sans framework.

   CONCEPT : le site est un relevé technique.
   Le métier de Besafe n'est pas de vendre des caméras, c'est de venir sur
   place, relever les points faibles et dessiner un plan. Le site est ce plan.

   SIGNATURE : la boucle. Un circuit d'alarme est une boucle fermée — coupée,
   elle sonne. Un filet rouge pointillé part du héros, descend toute la page
   dans la marge technique en s'allumant section par section, et se referme
   sur un nœud plein au bandeau d'appel final.

   Charte imposée par le logo : marine / blanc / rouge. On n'ajoute aucune
   teinte, seulement de la profondeur.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. POLICES AUTO-HÉBERGÉES (RGPD : aucun appel à Google Fonts)
   Les .woff2 sont servis depuis assets/fonts/ du thème.
   ---------------------------------------------------------------------- */

/*
 * Titres ET corps — Inter (demande client). Elle remplace Archivo (titres) et
 * IBM Plex Sans (corps) : le site parle désormais d'une seule voix, du grand
 * titre du héros à la mention légale du pied.
 *
 * UN SEUL FICHIER, et c'est voulu : Inter est une police VARIABLE, ce fichier
 * couvre à lui seul toute la plage 100→900. Inutile d'en télécharger un par
 * graisse — Google en sert d'ailleurs le même octet pour 400, 600 et 700. 48 Ko
 * pour tout le site, contre 75 Ko pour les quatre fichiers statiques qu'il
 * remplace.
 *
 * ⚠️ Le « font-weight: 100 900 » n'est pas décoratif : sans cette PLAGE, le
 * navigateur croit tenir une police à graisse unique et synthétise le gras en
 * épaississant les contours (faux-bold). C'est ce qui distingue une variable
 * bien déclarée d'un rendu baveux.
 */
@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url('../fonts/inter-var.woff2') format('woff2');
}

/* Utilitaire — IBM Plex Mono : la police du relevé. Tags, métadonnées, cotes. */
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/plex-mono-500.woff2') format('woff2');
}

/* -------------------------------------------------------------------------
   2. VARIABLES
   ---------------------------------------------------------------------- */

:root {
	/* --- Couleurs de marque (imposées par le logo) --- */
	/* Plus AUCUN bleu (demande client) : les anciens marine/nuit deviennent des
	   NEUTRES (charbon). Seul le rouge reste comme couleur. Le nom des tokens
	   est conservé pour ne pas tout renommer. Valeurs bleues d'origine en commentaire. */
	--marine: #1C1C1C;      /* Charbon neutre (d'origine #102234, ex-#14293F). */
	--rouge: #E63727;       /* Rouge de marque (d'origine #EE2939). Seule couleur du site. */
	--blanc: #FFFFFF;

	/* --- Profondeurs dérivées (neutres) --- */
	--nuit: #121212;        /* Noir neutre profond (d'origine #0B1826). */
	--marine-clair: #2E2E2E; /* Gris foncé neutre (d'origine #1E3550). */
	--marine-ligne: rgba(255, 255, 255, 0.12); /* Filets sur fond sombre. */

	/*
	 * --- Fonds des grandes surfaces ---
	 * Le menu, le bandeau-CTA et le pied partageaient tous --nuit ; on leur donne
	 * chacun leur teinte.
	 * --fond-entete est passé en BLANC sur demande (d'origine --nuit, puis #14293F) :
	 * voir le bloc « EN-TÊTE BLANC » plus bas, qui bascule texte, burger et logo.
	 * Pour revenir à un menu sombre : remettre #14293F ici et retirer ce bloc.
	 */
	--fond-entete: #FFFFFF;
	--fond-bandeau: #1F1F1F; /* Neutre (d'origine #20242B). */
	--fond-pied: #1A1A1A;    /* Charbon (demande client ; avant #101010, d'origine #0D0F13). */

	/*
	 * Le rouge de marque (#E63727) ne passe pas AA en texte sur blanc (4,25:1)
	 * ni en fond de bouton sous du texte blanc. On le garde pour le graphisme,
	 * et on décline deux variantes conformes pour tout ce qui se lit.
	 */
	--rouge-cta: #CA3022;   /* Fond de bouton, décliné du nouveau rouge (d'origine #DA2130). Blanc dessus : 5,31:1 ✓ */
	--rouge-texte: #B32B1E; /* Rouge texte lisible sur fond clair (d'origine #C81F2D) : 6,40:1 sur blanc ✓ */
	--rouge-voile: rgba(230, 55, 39, 0.14); /* Voile du nouveau rouge (d'origine rgba(238,41,57,.14)). */

	/* --- Papier --- */
	--papier: #F5F7F9;      /* Gris clair des sections, unifié sur tout le site (avant #F2F2F2, d'origine #EDF0F3). */
	--trait: #DDDDDD;       /* Filets neutres sur fond clair (d'origine #D5DCE3). */
	--encre: #1C1C1C;       /* Charbon neutre, = --marine (d'origine #102234). */
	--encre-douce: #5C5C5C; /* Texte secondaire neutre — 6,7:1 sur blanc ✓ (d'origine #4B5C6E). */

	/* --- Typographie --- */
	/*
	 * Titres et corps partagent Inter : ce sont deux RÔLES, pas deux polices.
	 * On garde les deux jetons parce que ce qui les sépare (la graisse, la
	 * chasse négative des titres) reste réel, et qu'ils redeviendraient deux
	 * familles distinctes d'un seul changement ici.
	 */
	--font-titre: 'Inter', ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
	--font-corps: 'Inter', ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
	/*
	 * Le mono NE bouge PAS : c'est la signature du « relevé technique ». Les
	 * étiquettes (« QUESTION 2 SUR 4 », « VOTRE PLAN ») tiennent leur sens de
	 * leur chasse fixe — en Inter, le site cesserait de se lire comme un plan.
	 */
	--font-mono: 'IBM Plex Mono', ui-monospace, 'Cascadia Mono', 'Consolas', monospace;

	/* --- Rythme --- */
	/*
	 * Rayon des angles. Un seul jeton pilote tout : boutons, cartes, champs,
	 * encarts, filtres, pagination. Le changer ici change tout le site.
	 * Le schéma du héros, lui, reste anguleux : c'est un plan, pas de l'interface.
	 */
	--rayon: 8px;
	--rayon-sm: 4px;
	--ombre: 0 1px 2px rgba(17, 17, 17, 0.06), 0 8px 24px -12px rgba(17, 17, 17, 0.18);
	--ombre-forte: 0 2px 4px rgba(17, 17, 17, 0.08), 0 24px 48px -20px rgba(17, 17, 17, 0.32);
	--gouttiere: 1.5rem;
	--largeur-max: 1280px;
	--largeur-etroite: 760px;
	/* Le logo est un lockup sur deux lignes, presque carré : il lui faut de la
	   hauteur pour rester lisible, donc la barre est plus haute qu'un en-tête
	   à logo horizontal. */
	--entete-hauteur: 76px;   /* 100px avant : l'en-tete mangeait l'ecran (demande client). */
	/*
	 * La barre au défilement. 66px ne laissaient au logo que 46px de haut : sur
	 * un lockup à deux lignes (« BESAFE » / « SYSTEM »), la seconde ligne devenait
	 * illisible — le sigle survivait, pas la marque. 76px gardent le même rapport
	 * qu'au repos (logo = 76 % de la barre) et rendent au logo ses 58px.
	 */
	--entete-hauteur-defile: 64px; /* 76px avant : suit la barre amaigrie. */

	/*
	 * La RÉSERVE : la place gardée sous l'en-tête fixe, dans le flux.
	 *
	 * ⚠️ Elle est calée sur la hauteur RÉTRÉCIE, pas sur la hauteur initiale.
	 * Sinon, pendant les 34 premiers pixels de défilement — le temps que
	 * l'en-tête maigrisse — la réserve dépasse sous lui et on voit le fond blanc
	 * du body : une bande blanche entre l'en-tête et la première section.
	 *
	 * En contrepartie, à l'arrêt en haut de page, l'en-tête (100 px) recouvre les
	 * 34 premiers pixels de la première section. C'est sans conséquence : toutes
	 * les sections ont au moins 40 px de marge haute, donc aucun texte n'est
	 * masqué. Sur mobile l'en-tête ne rétrécit pas, la réserve vaut sa hauteur.
	 */
	--reserve-haut: var(--entete-hauteur);

	/*
	 * CE QUE L'EN-TÊTE RECOUVRE — la différence entre sa hauteur au repos et la
	 * réserve que le contenu lui laisse.
	 *
	 * La réserve est calée sur la hauteur RÉTRÉCIE de l'en-tête (voir plus bas) :
	 * au repos, l'en-tête est donc plus haut qu'elle et masque les premiers
	 * pixels du contenu. C'est voulu — l'alternative faisait apparaître une bande
	 * blanche pendant les premiers pixels de défilement.
	 *
	 * Mais un bloc qui commence par du texte doit connaître cette hauteur cachée
	 * pour la compenser. Sans quoi son padding est amputé d'autant : mesuré sur
	 * un écran de 1280 × 800, le surtitre des pages service arrivait à 15 px
	 * sous le menu, contre 59 sur les autres pages.
	 *
	 * Vaut 0 en dessous de 900 px, où l'en-tête ne rétrécit pas.
	 */
	--entete-cache: calc(var(--entete-hauteur) - var(--reserve-haut));

	/* Marge technique : la colonne de gauche où vit la boucle. Nulle en deçà
	   de 1100px, où la boucle n'est pas dessinée. */
	--piste-l: 0rem;
	--fond-noeud: var(--blanc);

	/*
	 * Hauteur de la barre d'action fixe du mobile. Calquée sur ce qui la
	 * fabrique : le min-height de ses liens (3,5rem) plus son filet supérieur.
	 * Le body s'en sert pour réserver sa place — et la réserve doit valoir la
	 * barre au pixel près, sinon le trop-plein se voit en bande blanche sous le
	 * pied de page (4,5rem réservés pour 57 px de barre = 15 px de blanc).
	 */
	--barre-action-hauteur: calc(3.5rem + 1px + env(safe-area-inset-bottom, 0px));

	--transition: 180ms cubic-bezier(0.4, 0, 0.2, 1);
	--transition-lente: 420ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* -------------------------------------------------------------------------
   3. RESET / BASE
   ---------------------------------------------------------------------- */

*,
*::before,
*::after {
	box-sizing: border-box;
}

/*
 * L'ATTRIBUT « hidden » DOIT TOUJOURS MASQUER.
 *
 * Le navigateur applique « [hidden] { display: none } » avec la plus faible
 * priorité qui soit : la moindre règle de mise en page la contredit. Or ce
 * thème pose des « display » sur presque tous ses composants — « .carte » est
 * en flex —, si bien qu'un élément marqué hidden en JavaScript restait
 * parfaitement visible. Le filtre des réalisations masquait ainsi des cartes
 * qui continuaient de s'afficher.
 *
 * Le thème rustinait le problème composant par composant (.hero__nav[hidden],
 * .panneau-rappel[hidden]…) : autant de règles à ne pas oublier au prochain
 * ajout. Cette règle-ci règle le cas une fois pour toutes.
 *
 * Le !important se justifie : « hidden » est une intention déclarée dans le
 * HTML, aucune règle de présentation ne doit pouvoir la contredire.
 */
[hidden] {
	display: none !important;
}

html {
	scroll-behavior: smooth;
	/* Compense le header sticky lors des sauts d'ancre. */
	scroll-padding-top: calc(var(--entete-hauteur) + 2rem);
}

body {
	margin: 0;
	font-family: var(--font-corps);
	font-size: 1.0625rem;
	line-height: 1.6;
	color: var(--encre);
	background: var(--blanc);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
	/*
	 * La place de la barre d'action fixe est réservée par le PIED DE PAGE, pas
	 * ici — voir « .pied » § 18. Une réserve posée sur le body est peinte en
	 * blanc, et il suffit d'un sous-pixel d'écart entre elle et la barre (0,2 px
	 * mesuré, la faute au filet de 1 px qui se rend à 0,8) pour qu'un cheveu
	 * blanc apparaisse sous un pied de page noir. Portée par le pied, la réserve
	 * est de la couleur du pied : l'écart, s'il subsiste, ne se voit plus.
	 */
}

/*
 * Les contrôles de formulaire n'héritent PAS de la police de la page : le
 * navigateur leur impose la sienne (Arial ici). Chaque composant s'en tirait en
 * redéclarant la famille dans son coin — et celui qui oubliait passait en Arial
 * sans que personne ne le voie. C'était le cas du bouton burger, en Arial sur
 * tout le site mobile.
 *
 * On règle donc la question une fois, à la racine. Uniquement la FAMILLE : le
 * corps et la graisse restent l'affaire de chaque composant.
 */
button,
input,
select,
textarea {
	font-family: inherit;
}

h1, h2, h3, h4 {
	font-family: var(--font-titre);
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.02em;
	margin: 0 0 0.6em;
	color: var(--marine);
	text-wrap: balance;
	/* Le français compose long : « Vidéosurveillance » seul débordait du titre
	   sur un écran de 320 px. Un titre qui casse un mot vaut mieux qu'une page
	   qui glisse latéralement. */
	overflow-wrap: break-word;
}

h1 {
	font-size: clamp(2.15rem, 4.6vw, 3.5rem);
	line-height: 1.04;
	letter-spacing: -0.03em;
}

h2 {
	font-size: clamp(1.65rem, 3vw, 2.35rem);
	line-height: 1.1;
}

h3 {
	font-size: 1.2rem;
	font-weight: 600;
	letter-spacing: -0.01em;
}

p { margin: 0 0 1rem; }

a {
	color: var(--marine);
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}

a:hover { color: var(--rouge-texte); }

img {
	max-width: 100%;
	height: auto;
	display: block;
}

ul, ol { margin: 0 0 1rem; padding-left: 1.2rem; }

/* Accessibilité : focus toujours visible, sur fond clair comme sur fond sombre. */
:focus-visible {
	outline: 2px solid var(--rouge);
	outline-offset: 3px;
	border-radius: 1px;
}

/* -------------------------------------------------------------------------
   4. UTILITAIRES
   ---------------------------------------------------------------------- */

.conteneur {
	width: 100%;
	max-width: var(--largeur-max);
	margin-inline: auto;
	/* La marge technique n'existe qu'à gauche : la mise en page est asymétrique,
	   comme un cartouche de plan. */
	padding-left: calc(var(--gouttiere) + var(--piste-l));
	padding-right: var(--gouttiere);
}

/*
 * Colonne de lecture étroite. On ne rétrécit PAS le conteneur — sinon il se
 * recentre dans la fenêtre et décroche de la marge technique, où vit la boucle.
 * On garde donc la boîte pleine largeur, calée à gauche comme tout le reste,
 * et on borne la mesure du texte lui-même.
 */
.conteneur--etroit > * { max-width: var(--largeur-etroite); }

/* Masqué visuellement mais lu par les lecteurs d'écran. */
.ecran-lecteur {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* Lien d'évitement (accessibilité clavier). */
.lien-evitement {
	position: absolute;
	top: -100px;
	left: 1rem;
	z-index: 999;
	padding: 0.75rem 1.25rem;
	background: var(--rouge-cta);
	color: var(--blanc);
	font-family: var(--font-titre);
	font-weight: 600;
	text-decoration: none;
	transition: top var(--transition);
}

.lien-evitement:focus {
	top: 0;
	color: var(--blanc);
}

/* Honeypot anti-spam : invisible pour l'humain, présent pour le robot. */
.pot-de-miel {
	position: absolute !important;
	left: -9999px;
	opacity: 0;
	height: 0;
	overflow: hidden;
}

.vide {
	padding: 2rem 0;
	color: var(--encre-douce);
	text-align: center;
}

/*
 * L'ÉTAT VIDE ILLUSTRÉ.
 *
 * Une liste vide n'est pas une panne : c'est un site qui vient d'ouvrir. Le
 * message le dit, et il ne laisse pas le visiteur sur une impasse. La mesure du
 * texte est bornée : centré et pleine largeur, il se lirait en travers de
 * l'écran.
 *
 * ⚠️ AUCUNE MARGE VERTICALE ICI, ET C'EST DÉLIBÉRÉ.
 *
 * Ce bloc vit dans une « .section », qui porte déjà 4 rem de padding (6 au
 * delà de 900 px). Le sien s'y ajoutait : 152 px au-dessus de l'émoji, 112 en
 * dessous — trop, et surtout dissymétrique, ce qui faisait flotter le message
 * trop haut. Un seul des deux doit espacer, et c'est la section : elle sait, en
 * plus, s'adapter à la largeur.
 */
.vide--illustre {
	padding-block: 0;
	max-width: 34rem;
	margin-inline: auto;
}

.vide__emoji {
	margin: 0 0 1rem;
	font-size: 2.75rem;
	line-height: 1;
}

/*
 * Le bouton Instagram : le rouge de la marque, pas celui d'Instagram. Un
 * dégradé mauve-orange au milieu d'une page qui n'en a aucun se lirait comme
 * un encart publicitaire collé après coup. Le picto suffit à dire où l'on va.
 */
.vide__insta .bouton__picto { opacity: 1; }

.vide__titre {
	margin: 0 0 0.75rem;
	font-family: var(--font-titre);
	font-size: clamp(1.35rem, 3.5vw, 1.75rem);
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--marine);
}

.vide__texte {
	margin: 0 0 2rem;
	line-height: 1.65;
}

/* Les deux boutons se centrent sous le texte, et s'empilent au besoin. */
.vide__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.75rem;
	margin: 0;
}

/*
 * LA SECTION QUI NE CONTIENT QUE CE MESSAGE.
 *
 * Elle est dimensionnée pour porter une grille de cartes ; seule avec quatre
 * lignes de texte, ses 6 rem de haut et de bas laissaient la page presque vide
 * et le message perdu au milieu. On resserre — symétriquement, pour que le
 * bloc soit posé et non suspendu.
 *
 * « :has() » plutôt qu'une classe posée dans le gabarit : la règle suit le
 * contenu, et vaut donc pour toute page qui affichera ce message demain sans
 * qu'on ait à y penser.
 */
.section:has(> .conteneur > .vide--illustre) {
	padding-block: 3.5rem;
}

@media (min-width: 900px) {
	.section:has(> .conteneur > .vide--illustre) {
		padding-block: 5rem;
	}
}

.icone { flex: none; }

/*
 * Surtitre — le tag du relevé. Mono, capitales, filet rouge en amorce.
 * Il nomme la nature de la section, il ne la numérote pas : ces sections ne
 * sont pas une séquence.
 */
.surtitre {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	margin: 0 0 1rem;
	font-family: var(--font-mono);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--rouge-texte);
}

.surtitre::before {
	content: '';
	flex: none;
	width: 1.75rem;
	height: 1px;
	background: var(--rouge);
}

/* Sur fond sombre, le rouge ne passe pas en petit corps : le texte devient
   blanc voilé, seul le filet reste rouge. */
.est-nuit .surtitre,
.hero .surtitre,
.bandeau-cta .surtitre {
	color: rgba(255, 255, 255, 0.72);
}

/* Étiquette de donnée : mono, discrète, pour les métadonnées de chantier. */
.donnee {
	font-family: var(--font-mono);
	font-size: 0.78rem;
	font-weight: 500;
	letter-spacing: 0.06em;
	color: var(--encre-douce);
}

/* -------------------------------------------------------------------------
   5. LA BOUCLE
   Le filet rouge qui descend la page. Dessinée seulement à partir de 1100px,
   là où la marge technique existe. En dessous, la page se resserre et la
   boucle disparaît : elle ne doit jamais voler de la place au contenu.
   ---------------------------------------------------------------------- */

@media (min-width: 1100px) {

	:root { --piste-l: 4.5rem; }

	.contenu-principal .hero,
	.contenu-principal .entete-page,
	.contenu-principal .service-hero,
	.contenu-principal .section,
	.contenu-principal .confiance,
	.contenu-principal .bandeau-cta {
		position: relative;
	}

	/*
	 * Le filet : pointillé, comme une limite de propriété sur un plan.
	 * Il est calé sur la marge technique du conteneur quelle que soit la
	 * largeur de la fenêtre — d'où le calcul, qui refait le centrage du
	 * conteneur pour retrouver son bord gauche.
	 */
	.contenu-principal .hero::before,
	.contenu-principal .entete-page::before,
	.contenu-principal .service-hero::before,
	.contenu-principal .section::before,
	.contenu-principal .confiance::before,
	.contenu-principal .bandeau-cta::before {
		content: '';
		position: absolute;
		top: 0;
		bottom: 0;
		left: calc(max(0px, (100% - var(--largeur-max)) / 2) + var(--gouttiere) + 1.5rem);
		width: 1px;
		z-index: 2;
		pointer-events: none;
		background: repeating-linear-gradient(
			180deg,
			var(--rouge) 0 5px,
			transparent 5px 11px
		);
		opacity: 0.4;
	}

	/*
	 * Le nœud est porté par l'étiquette de la section — surtitre, ou fil
	 * d'Ariane sur les pages qui en ont un. Il se pose donc exactement en face
	 * d'elle, quelle que soit la hauteur du bloc. L'étiquette commence au bord
	 * du contenu, soit 3rem à droite du filet.
	 */
	.contenu-principal .surtitre,
	.contenu-principal .entete-page .fil-ariane { position: relative; }

	.contenu-principal .surtitre::after,
	.contenu-principal .entete-page .fil-ariane::after {
		content: '';
		position: absolute;
		top: 50%;
		left: -3rem;
		width: 9px;
		height: 9px;
		margin: -4px 0 0 -4px;
		border: 1px solid var(--rouge);
		background: var(--fond-noeud);
		transform: rotate(45deg);
		transition: background-color var(--transition-lente), box-shadow var(--transition-lente);
		pointer-events: none;
	}

	/*
	 * Le capteur s'allume quand sa section entre dans le champ, et le reste.
	 * Il ne se contente plus de changer de couleur : il CLAQUE — une détonation
	 * brève, puis il tient. Un capteur qui se déclenche ne fond pas en douceur.
	 */
	.contenu-principal .est-vu .surtitre::after,
	.contenu-principal .est-vu .fil-ariane::after {
		background: var(--rouge);
		box-shadow: 0 0 0 5px var(--rouge-voile);
		animation: allume-capteur 700ms cubic-bezier(0.33, 1, 0.68, 1);
	}

	/* ⚠️ Garder le rotate(45deg) dans CHAQUE étape : une animation sur transform
	   remplace la transformation de base, elle ne s'y ajoute pas. Sans lui, le
	   losange redevient un carré le temps de l'animation. */
	@keyframes allume-capteur {
		0% {
			transform: rotate(45deg) scale(0.55);
			box-shadow: 0 0 0 0 rgba(230, 55, 39, 0.75);
		}
		45% {
			transform: rotate(45deg) scale(1.4);
			box-shadow: 0 0 0 9px rgba(230, 55, 39, 0.28);
		}
		100% {
			transform: rotate(45deg) scale(1);
			box-shadow: 0 0 0 5px var(--rouge-voile);
		}
	}

	/* ---------------------------------------------------------------------
	 * L'ARMEMENT — la boucle sous tension
	 *
	 * Le filet pointillé, c'est le circuit AU REPOS. Ce conducteur le remplit
	 * d'un rouge plein à mesure qu'on descend : la page s'arme. Il court sur
	 * exactement la même marge technique — d'où le calcul identique, à ne pas
	 * désynchroniser du filet.
	 *
	 * Hauteur posée par le JS (main.js § 9) : elle s'arrête au nœud de
	 * fermeture, pas au bas de la page.
	 * ------------------------------------------------------------------ */
	.contenu-principal { position: relative; }

	.armement {
		position: absolute;
		top: 0;
		left: calc(max(0px, (100% - var(--largeur-max)) / 2) + var(--gouttiere) + 1.5rem);
		width: 1px;
		/* Au-dessus du filet (z-index 2) : le conducteur le recouvre. */
		z-index: 3;
		pointer-events: none;
	}

	.armement__conducteur {
		display: block;
		position: relative;
		width: 100%;
		/* L'avancement est un ratio (0 → 1), posé au défilement. */
		height: calc(var(--avancement, 0) * 100%);
		background: var(--rouge);
		box-shadow: 0 0 9px 1px rgba(230, 55, 39, 0.55);
	}

	/*
	 * Pas de battement qui descend le fil : essayé (le pouls du logo en motif
	 * répété), retiré. Le conducteur qui se remplit et les capteurs qui claquent
	 * suffisent — le fil n'a pas besoin de s'agiter en plus pour qu'on comprenne
	 * qu'il est sous tension.
	 */

	/*
	 * LA FERMETURE. Le circuit claque : le nœud final s'embrase, une onde part.
	 * C'est la récompense du défilement, elle n'arrive qu'une fois.
	 */
	.contenu-principal.est-bouclee .bandeau-cta::after {
		box-shadow:
			0 0 0 6px var(--rouge-voile),
			0 0 26px 5px rgba(230, 55, 39, 0.55);
	}

	.bandeau-cta__onde {
		position: absolute;
		top: 50%;
		left: calc(max(0px, (100% - var(--largeur-max)) / 2) + var(--gouttiere) + 1.5rem);
		width: 13px;
		height: 13px;
		margin: -6px 0 0 -6px;
		z-index: 2;
		border: 1px solid var(--rouge);
		border-radius: 50%;
		opacity: 0;
		pointer-events: none;
	}

	.est-bouclee .bandeau-cta__onde {
		animation: onde 1.6s cubic-bezier(0.16, 1, 0.3, 1) 2;
	}

	@keyframes onde {
		from { opacity: 0.75; transform: scale(1); }
		to   { opacity: 0; transform: scale(7); }
	}

	/*
	 * Pas de mention écrite sous le nœud : le surtitre du bandeau dit déjà
	 * « Périmètre bouclé », à trois centimètres de là. Une annotation verticale
	 * y a été essayée puis retirée — elle sous-titrait sa propre image.
	 */

	/*
	 * La boucle se referme ici. Le filet s'arrête net au milieu du bandeau,
	 * sur un nœud plein : le circuit est bouclé, le périmètre est couvert.
	 */
	.contenu-principal .bandeau-cta::before {
		bottom: auto;
		height: 50%;
	}

	.contenu-principal .bandeau-cta::after {
		content: '';
		position: absolute;
		top: 50%;
		left: calc(max(0px, (100% - var(--largeur-max)) / 2) + var(--gouttiere) + 1.5rem);
		width: 13px;
		height: 13px;
		margin: -6px 0 0 -6px;
		z-index: 2;
		background: var(--rouge);
		box-shadow: 0 0 0 6px var(--rouge-voile);
		transform: rotate(45deg);
		pointer-events: none;
	}

	/* Le bandeau final porte le nœud de fermeture : son surtitre n'en pose pas. */
	.contenu-principal .bandeau-cta .surtitre::after { content: none; }

	/* Après la fermeture de la boucle, plus rien n'est tracé. */
	.contenu-principal .bandeau-cta ~ .section::before { content: none; }
	.contenu-principal .bandeau-cta ~ .section .surtitre::after { content: none; }

	/* Fond du nœud selon la section qu'il traverse. */
	.section--claire { --fond-noeud: var(--papier); }
	.hero { --fond-noeud: var(--nuit); }
	.entete-page { --fond-noeud: var(--papier); }
}

/* -------------------------------------------------------------------------
   6. BOUTONS
   Le rouge est réservé aux appels à l'action. Jamais d'aplat rouge massif.
   ---------------------------------------------------------------------- */

/*
 * Le picto de tête d'un bouton (le diagnostic, pour l'instant). Il se place
 * AVANT le libellé, là où la flèche se place après : l'un annonce de quoi il
 * s'agit, l'autre dit qu'on s'en va. Un peu plus petit que le corps du texte —
 * c'est un signe de reconnaissance, pas une illustration.
 */
.bouton__picto {
	flex: none;
	width: 18px;
	height: 18px;
	opacity: 0.9;
}

.bouton {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.6rem;
	padding: 0.75rem 1.35rem;
	font-family: var(--font-titre);
	font-size: 0.95rem;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: 0.005em;
	text-decoration: none;
	border: 1px solid transparent;
	border-radius: var(--rayon);
	cursor: pointer;
	transition: background-color var(--transition), border-color var(--transition), color var(--transition);
}

/* La flèche avance au survol : le bouton indique sa direction. */
.bouton__fleche {
	flex: none;
	transition: transform var(--transition);
}

.bouton:hover .bouton__fleche { transform: translateX(3px); }

.bouton--rouge {
	background: var(--rouge-cta);
	border-color: var(--rouge-cta);
	color: var(--blanc);
}

/* Au survol, le rouge de marque pur apparaît. */
.bouton--rouge:hover,
.bouton--rouge:focus {
	background: var(--rouge);
	border-color: var(--rouge);
	color: var(--blanc);
}

.bouton--marine {
	background: var(--marine);
	border-color: var(--marine);
	color: var(--blanc);
}

.bouton--marine:hover,
.bouton--marine:focus {
	background: var(--nuit);
	border-color: var(--nuit);
	color: var(--blanc);
}

/* Secondaire sur fond clair : filet seul. */
.bouton--trait {
	background: transparent;
	/* Bordure un peu plus présente que --trait, pour que le bouton secondaire
	   existe vraiment sur les sections claires. */
	border-color: rgba(28, 28, 28, 0.28);
	color: var(--marine);
}

/* Survol franc : le contour se remplit, le texte passe en blanc, la flèche
   glisse (animation .bouton__fleche déjà définie). */
.bouton--trait:hover,
.bouton--trait:focus {
	background: var(--marine);
	border-color: var(--marine);
	color: var(--blanc);
}

/* Secondaire sur fond sombre. */
.bouton--fantome {
	background: transparent;
	border-color: rgba(255, 255, 255, 0.35);
	color: var(--blanc);
}

.bouton--fantome:hover,
.bouton--fantome:focus {
	background: rgba(255, 255, 255, 0.08);
	border-color: var(--blanc);
	color: var(--blanc);
}

.bouton--grand {
	padding: 1rem 1.9rem;
	font-size: 1.05rem;
}

/* -------------------------------------------------------------------------
   7. EN-TÊTE
   ---------------------------------------------------------------------- */

/*
 * L'en-tête est FIXE, pas sticky.
 *
 * En sticky, il reste dans le flux du document : le rétrécir au défilement
 * changerait la hauteur de la page et ferait remonter tout le contenu d'un
 * coup. En fixe, il est hors flux — il peut donc maigrir sans rien bousculer.
 * La contrepartie est de lui réserver sa place, d'où le padding du contenu.
 */
.entete {
	position: fixed;
	top: 0;
	inset-inline: 0;
	z-index: 100;
	background: var(--fond-entete);
	transition: box-shadow var(--transition), background-color var(--transition);
}

/*
 * LA BARRE D'ADMINISTRATION.
 *
 * Connecté, WordPress pose « html { margin-top: 32px !important } » pour se
 * réserver sa barre. Le document descend donc de 32 px — mais pas l'en-tête,
 * qui est en position fixe et reste collé au bord de la fenêtre, donc SOUS la
 * barre. Résultat : l'en-tête perd 32 px de sa hauteur visible pendant que le
 * bandeau de page, lui, est bien descendu — d'où une bande blanche d'une
 * vingtaine de pixels entre les deux, visible sur toutes les pages.
 *
 * Invisible pour les visiteurs, qui ne sont jamais connectés. C'est ce qui la
 * rend traîtresse : seul l'administrateur du site la voit, et il la voit tout
 * le temps.
 *
 * ⚠️ En dessous de 783 px, la barre mesure 46 px ET n'est plus fixe : elle
 * défile avec la page. On l'accompagne donc au repos, puis on recolle l'en-tête
 * en haut dès que .est-defile apparaît — la classe que le JS pose déjà au
 * premier défilement, aucun script supplémentaire n'est nécessaire.
 */
.admin-bar .entete { top: 32px; }

@media screen and (max-width: 782px) {
	.admin-bar .entete { top: 46px; }
	.admin-bar .entete.est-defile { top: 0; }
}

.contenu-principal { padding-top: var(--reserve-haut); }

/*
 * Sur l'accueil, le héros passe SOUS l'en-tête, qui se fond en lui tant qu'on
 * n'a pas défilé. Dès le premier scroll, le JS pose .est-defile et le fond nuit
 * réapparaît.
 */
.a-header-transparent .contenu-principal { padding-top: 0; }

.a-header-transparent .entete:not(.est-defile):not(.est-ouvert) {
	background: transparent;
}

.entete.est-defile { box-shadow: var(--ombre-forte); }

.entete__inner {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-height: var(--entete-hauteur);
	transition: min-height var(--transition-lente);
}

/*
 * Au défilement, la barre se resserre et le logo maigrit : on rend de la
 * hauteur d'écran au contenu dès qu'on est entré dedans.
 */
.entete.est-defile .entete__inner { min-height: var(--entete-hauteur-defile); }

.entete.est-defile .site-logo__img { max-height: 48px; }

.entete.est-defile .bouton { padding-block: 0.6rem; }

.entete__logo {
	display: inline-flex;
	align-items: center;
	flex: none;
	text-decoration: none;
}

/*
 * Le logo est blanc et rouge : il n'existe que sur fond sombre. C'est le cas
 * partout où il est posé — en-tête et pied de page sont tous deux sur le nuit.
 */
.site-logo__img {
	max-height: 58px;   /* Suit la barre : 76px debordait des 76px de l'en-tete. */
	width: auto;
	transition: max-height var(--transition-lente);
}

/* Repli quand aucun logo n'est encore téléversé. */
.site-logo--texte {
	font-family: var(--font-titre);
	font-size: 1.25rem;
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--blanc);
}

.site-logo--texte:hover { color: var(--blanc); }

/* --- Menu burger (mobile) --- */

.burger {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: transparent;
	border: 1px solid rgba(255, 255, 255, 0.25);
	border-radius: var(--rayon);
	cursor: pointer;
}

.burger__barres,
.burger__barres::before,
.burger__barres::after {
	display: block;
	width: 18px;
	height: 1px;
	background: var(--blanc);
	transition: transform var(--transition), opacity var(--transition);
}

.burger__barres { position: relative; }

.burger__barres::before,
.burger__barres::after {
	content: '';
	position: absolute;
	left: 0;
}

.burger__barres::before { top: -6px; }
.burger__barres::after { top: 6px; }

/* Transformation en croix quand le menu est ouvert. */
.burger[aria-expanded="true"] .burger__barres { background: transparent; }
.burger[aria-expanded="true"] .burger__barres::before { transform: translateY(6px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__barres::after { transform: translateY(-6px) rotate(-45deg); }

/* --- Navigation --- */

/*
 * LE PANNEAU DOIT DÉFILER TOUT SEUL.
 *
 * Il est posé en absolu dans un en-tête FIXE : il est donc fixe lui aussi, et
 * défiler la page ne le fait pas monter d'un pixel. Or il mesure 1 193 px —
 * quatre entrées, cinq services, douze secteurs et le bouton de contact — pour
 * une fenêtre de 844. Tout ce qui dépassait était simplement inatteignable :
 * les derniers secteurs et « Parler à un technicien » n'existaient pas sur
 * téléphone. Pas coupés, pas masqués : hors d'atteinte, sans rien qui le dise.
 *
 * Il reçoit donc sa propre zone de défilement, bornée à la fenêtre moins la
 * hauteur de l'en-tête qu'il vient poser dessous. « dvh » plutôt que « vh » :
 * sur mobile, vh se cale sur la fenêtre barres d'outils RÉTRACTÉES, ce qui
 * redonnerait un panneau plus haut que l'écran au premier chargement.
 *
 * overscroll-behavior contient l'élan : arrivé en bas de la liste, on ne
 * repart pas dans la page derrière.
 */
.nav-principale {
	display: none;
	position: absolute;
	inset-inline: 0;
	top: 100%;
	/*
	 * Le panneau occupe TOUT ce qui reste : l'écran moins l'en-tête qu'il vient
	 * poser dessous, moins la barre d'action qui garde le bas. Il s'arrête donc
	 * pile sur « Appeler / Demander un devis », sans les recouvrir ni laisser
	 * voir un bout de page entre les deux.
	 *
	 * « height » et non « max-height » : à la seule hauteur de son contenu, le
	 * panneau flottait au milieu de l'écran une fois les sous-menus repliés —
	 * une boîte posée sur la page plutôt qu'un menu.
	 *
	 * « dvh » plutôt que « vh » : sur mobile, vh se cale sur la fenêtre barres
	 * d'outils RÉTRACTÉES, ce qui redonnerait un panneau plus haut que l'écran
	 * au premier chargement.
	 */
	height: calc(100vh - var(--entete-hauteur) - var(--barre-action-hauteur));
	height: calc(100dvh - var(--entete-hauteur) - var(--barre-action-hauteur));
	overflow-y: auto;
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
	padding: 1rem var(--gouttiere) 1.5rem;
	background: var(--fond-entete);
	border-top: 1px solid var(--marine-ligne);
}

.nav-principale.est-ouvert { display: block; }

/*
 * Les réseaux, en pied de menu. Réservés au panneau mobile : au-delà de 900 px
 * la nav est une barre horizontale, elle n'a pas de « bas » où les poser, et le
 * pied de page s'en charge déjà.
 */
.nav-reseaux,
.nav-pied { display: none; }

@media (max-width: 899px) {
	/*
	 * Le panneau est une colonne pleine hauteur : les réseaux prennent le
	 * blanc qui reste sous la liste et se posent en bas, au lieu de flotter
	 * juste sous la dernière entrée avec du vide dessous.
	 */
	.nav-principale {
		display: none;
		flex-direction: column;
	}

	.nav-principale.est-ouvert { display: flex; }

	/*
	 * ⚠️ LE BOUTON D'APPEL SORT DU MENU (demande client). Il faisait doublon
	 * avec « Appeler » de la barre d'action, qui est fixe en bas de l'écran et
	 * donc toujours à portée — deux fois le même geste à deux endroits, dont
	 * l'un oblige à ouvrir le menu pour y arriver. Le numéro reste partout
	 * ailleurs : barre d'action, héros, pied de page, page Contact.
	 *
	 * Ciblé sur le bouton d'appel et non sur « .entete__actions » : si le
	 * client active un jour « Être rappelé » (Personnaliser → En-tête), ce
	 * second bouton, lui, n'a pas de jumeau en bas d'écran et doit rester.
	 */
	.nav-principale .entete__appel { display: none; }

	/* La boîte d'actions vidée de son unique bouton ne doit pas garder ses
	   marges : sinon un blanc s'ouvre entre la liste et les réseaux. */
	.nav-principale .entete__actions:empty,
	.nav-principale .entete__actions:not(:has(> *:not(.entete__appel))) {
		display: none;
	}

	/*
	 * LES PROPORTIONS DU PANNEAU PLEIN ÉCRAN.
	 *
	 * Six entrées composées pour un menu déroulant de 300 px se retrouvaient
	 * tassées en haut d'un panneau de 710 : la liste occupait le tiers
	 * supérieur, et le reste était un blanc qui ressemblait à un oubli. Le
	 * problème n'était pas la hauteur mais l'échelle — un menu plein écran se
	 * compose en plein écran. La ligne passe donc de 45 à 62 px, ce qui la
	 * met au passage au-dessus des 44 px de cible tactile recommandés.
	 */
	/*
	 * La liste prend toute la place libre et la partage entre ses lignes. Une
	 * hauteur de ligne écrite en dur aurait bien rempli l'iPhone sur lequel on
	 * la règle, et débordé le premier écran plus court venu — six lignes de
	 * 76 px ne tiennent pas dans les 435 px utiles d'un 320 × 568. Ici, la
	 * ligne s'étire quand il y a de la place et se resserre quand il n'y en a
	 * plus, sans jamais passer sous la cible tactile de 3,5 rem.
	 */
	.menu {
		display: flex;
		flex-direction: column;
		flex: 1 1 auto;
		margin-bottom: 0;
	}

	.menu > li { flex: 1 1 auto; }

	.menu > li > a {
		display: flex;
		align-items: center;
		height: 100%;
		min-height: 3.5rem;
		padding-block: 0.5rem;
		font-size: 1.05rem;
	}

	/*
	 * Sauf quand un sous-menu est ouvert : la ligne doit alors reprendre sa
	 * hauteur naturelle, sinon le lien parent s'étire sur toute la colonne et
	 * pousse ses propres enfants hors de vue.
	 */
	.menu > .menu-item-has-children:not(.est-replie) { flex: 0 0 auto; }

	.menu > .menu-item-has-children:not(.est-replie) > a { height: auto; }

	/* Le sous-menu reste en retrait : c'est un second niveau, pas un premier. */
	.sub-menu a { padding-block: 0.8rem; }

	/*
	 * Le bas du menu tient en un bloc, poussé contre la barre d'action par
	 * « margin-top: auto ». Le blanc qui reste tombe alors ENTRE la navigation
	 * et lui — au même endroit qu'avant, mais il sépare deux choses au lieu de
	 * traîner après la dernière.
	 */
	.nav-pied {
		display: block;
		margin-top: auto;
		padding-top: 1.5rem;
		border-top: 1px solid rgba(0, 0, 0, 0.08);
	}

	.nav-pied__reperes {
		display: flex;
		flex-direction: column;
		gap: 0.2rem;
		margin: 0 0 1rem;
		font-family: var(--font-mono);
		font-size: 0.72rem;
		letter-spacing: 0.08em;
		text-transform: uppercase;
	}

	.nav-pied__zone { color: var(--encre-douce); }

	/* La disponibilité est l'argument, pas la mention : elle prend le rouge. */
	.nav-pied__dispo { color: var(--rouge-texte); }

	.nav-reseaux {
		display: flex;
		gap: 0.75rem;
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.nav-reseaux__lien {
		display: inline-flex;
		/* 44 px de cible tactile autour d'un glyphe de 24 : le glyphe se voit,
		   le doigt vise la zone. */
		align-items: center;
		justify-content: center;
		width: 44px;
		height: 44px;
		border-radius: 50%;
		opacity: 0.85;
		transition: opacity var(--transition);
	}

	.nav-reseaux__lien:hover,
	.nav-reseaux__lien:focus-visible { opacity: 1; }
}

/*
 * Pendant que le panneau est ouvert, la page derrière ne bouge plus. Sans ce
 * verrou, le doigt qui manque le panneau fait glisser le site sous un menu qui,
 * lui, reste collé à l'écran — on ne sait plus ce qu'on défile.
 *
 * « overflow: hidden » sur le body et non « position: fixed » : le premier
 * garde la position de lecture, le second la perd et renvoie en haut de page à
 * la fermeture.
 */
.a-menu-ouvert { overflow: hidden; }

.menu {
	margin: 0 0 1rem;
	padding: 0;
	list-style: none;
}

.menu li { position: relative; }

.menu a {
	display: block;
	padding: 0.7rem 0;
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 0.95rem;
	color: var(--blanc);
	text-decoration: none;
	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
	transition: color var(--transition);
}

.menu a:hover,
.menu .current-menu-item > a,
.menu .current_page_item > a {
	color: var(--rouge);
}

/*
 * Le chevron des entrées à sous-menu est posé plus bas, dans la version desktop
 * du menu : sur mobile, le sous-menu est déjà déplié sous « Services », il n'y
 * a donc rien à annoncer.
 */
.menu > .menu-item-has-children > a {
	display: flex;
	align-items: center;
	gap: 0.45rem;
}

/*
 * L'ACCORDÉON DES SOUS-MENUS (téléphone).
 *
 * « Services » et « Secteurs » arrivaient dépliés : dix-sept lignes déroulées
 * d'office, dont douze secteurs, pour quatre entrées de premier niveau. On ne
 * voyait plus le menu, seulement sa liste la plus longue — et « Contact »
 * tombait à 900 px du haut. Ils se replient donc, et le menu redevient ce
 * qu'il doit être : quatre choix, dont deux qu'on peut ouvrir.
 *
 * Le chevron est un BOUTON à part, posé à côté du lien et non à sa place :
 * l'entrée « Services » mène à quelque chose, et fusionner les deux rôles
 * forcerait à choisir entre y aller et déplier. Ici on peut faire les deux.
 *
 * ⚠️ Le repli est posé PAR LE SCRIPT (main.js § 1) et non en CSS. Sans
 * JavaScript, aucun bouton n'existerait pour rouvrir : les sous-menus restent
 * alors dépliés, comme avant, et rien n'est perdu.
 */
.menu__bascule {
	display: none;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	margin-left: auto;
	padding: 0;
	color: inherit;
	background: transparent;
	border: 0;
	cursor: pointer;
}

.menu__bascule svg {
	transition: transform var(--transition);
}

.menu__bascule[aria-expanded="true"] svg {
	transform: rotate(180deg);
}

@media (max-width: 899px) {
	.menu__bascule { display: inline-flex; }

	/*
	 * La ligne porte maintenant deux cibles : le lien à gauche, le chevron à
	 * droite. Le lien cesse donc de prendre toute la largeur, sinon le doigt
	 * qui vise le chevron atterrit dessus.
	 */
	.menu > .menu-item-has-children {
		display: flex;
		align-items: center;
		flex-wrap: wrap;
		border-bottom: 1px solid rgba(255, 255, 255, 0.08);
	}

	.menu > .menu-item-has-children > a {
		flex: 1;
		border-bottom: 0;
	}

	.menu > .menu-item-has-children > .sub-menu {
		flex-basis: 100%;
		padding-bottom: 0.4rem;
	}

	.menu > .menu-item-has-children.est-replie > .sub-menu { display: none; }
}

/* Sous-menu (Services) */
.sub-menu {
	margin: 0;
	padding-left: 1rem;
	list-style: none;
}

.sub-menu a {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	font-family: var(--font-corps);
	font-weight: 400;
	font-size: 0.95rem;
	color: rgba(255, 255, 255, 0.8);
}

/*
 * Icône du service dans le menu déroulé. Discrète au repos : elle sert à
 * distinguer les six prestations d'un coup d'œil, pas à décorer. Elle passe au
 * rouge de marque sur la ligne survolée ou courante — le même signal que
 * partout ailleurs.
 */
.menu__picto {
	flex: none;
	color: rgba(255, 255, 255, 0.45);
	transition: color var(--transition);
}

.sub-menu a:hover .menu__picto,
.sub-menu .current-menu-item > a .menu__picto {
	color: var(--rouge);
}

.menu__vide a { color: var(--blanc); }

.entete__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.85rem;
}

/*
 * Le bouton d'appel de l'en-tête. Il ne montre pas le numéro : il propose une
 * action. Le numéro reste dans le nom accessible du lien, donc annoncé par les
 * lecteurs d'écran, et affiché en clair là où on vient le chercher : le pied de
 * page, la page Contact et le bandeau d'appel.
 */
.entete__appel .icone { flex: none; }

/* ============================================================
 * EN-TÊTE BLANC (demande client)
 * Bascule l'en-tête sombre en en-tête blanc : fond (via --fond-entete),
 * texte du menu, burger, séparateurs — et le sous-menu déroulant desktop
 * passe lui aussi en blanc (voir le bloc jumeau dans la media query desktop).
 * Le logo noir est câblé côté PHP (besafe_logo_sombre_id + header.php).
 * POUR REVENIR À UN MENU SOMBRE : remettre --fond-entete: #14293F, puis
 * supprimer CE bloc ET son jumeau desktop (marqués « EN-TÊTE BLANC »).
 * ============================================================ */

/* Fond blanc plein dès le haut, y compris sur l'accueil (fin de la transparence). */
.a-header-transparent .entete:not(.est-defile):not(.est-ouvert) {
	background: var(--fond-entete);
}

/* Filet bas discret pour détacher l'en-tête du contenu clair. */
.entete { border-bottom: 1px solid var(--trait); }

/* Liens : encre au repos, rouge lisible (AA) au survol / page courante. */
.menu a { color: var(--encre); border-bottom-color: rgba(0, 0, 0, 0.08); }
.menu > li > a:hover,
.menu > .current-menu-item > a,
.menu > .current_page_item > a { color: var(--rouge-texte); }
.menu__vide a { color: var(--encre); }

/* Sous-menu : texte NOIR (panneau blanc, mobile comme desktop) — chaque lien
   des menus déroulés « Services » et « Secteurs » en encre pleine, pas en gris. */
.sub-menu a { color: var(--encre); }
.menu__picto { color: rgba(28, 28, 28, 0.45); }

/* Séparateur du panneau mobile, sur fond blanc. */
.nav-principale { border-top-color: rgba(0, 0, 0, 0.08); }

/* Le filet de la ligne à accordéon suit le même passage au clair : porté par
   le <li> et non par le <a>, il ne recevait pas la règle ci-dessus. */
.menu > .menu-item-has-children { border-bottom-color: rgba(0, 0, 0, 0.08); }
.menu__bascule { color: rgba(28, 28, 28, 0.55); }
.menu__bascule:hover,
.menu__bascule[aria-expanded="true"] { color: var(--rouge-texte); }

/* Burger foncé. */
.burger { border-color: rgba(0, 0, 0, 0.18); }
.burger__barres,
.burger__barres::before,
.burger__barres::after { background: var(--encre); }

/* --- Panneau « Être rappelé » --- */

.panneau-rappel {
	background: var(--marine);
	border-top: 1px solid var(--marine-ligne);
	padding-block: 1.75rem;
}

.panneau-rappel[hidden] { display: none; }

/* -------------------------------------------------------------------------
   8. HÉROS — LE PLAN
   Pas de photo obligatoire : un schéma d'implantation dessiné en SVG.
   Quand une photo existe, elle passe en calque duotone derrière le schéma.
   ---------------------------------------------------------------------- */

.hero {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: center;
	/*
	 * Le héros doit tenir EN ENTIER dans l'écran, onglets compris — sur un
	 * portable de 768 px de haut comme sur un grand écran. D'où ces marges
	 * serrées : 8,5rem suffisent à dégager l'en-tête (100 px) qui se superpose
	 * au héros sur l'accueil, les 11rem d'avant étaient du gaspillage.
	 */
	min-height: 82vh;
	/*
	 * ⚠️ Le retrait du HAUT vit sur .hero__slide, pas ici. Le visuel est posé en
	 * absolu DANS la diapositive : s'il restait sur .hero, l'image s'arrêterait
	 * net au bord du padding et laisserait un trait franc sous l'en-tête.
	 */
	padding-block: 0 1.5rem;
	background: var(--nuit);
	color: var(--blanc);
	overflow: hidden;
}

.hero--compact {
	min-height: 0;
	padding-block: 0 3.5rem;
}

/* Papier millimétré : le fond de plan. */
.hero::before,
.hero__grille {
	pointer-events: none;
}

.hero__grille {
	position: absolute;
	inset: 0;
	z-index: 0;
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
	background-size: 64px 64px;
	/* La grille s'efface vers la droite et le bas : on ne la remarque pas,
	   on la sent. */
	-webkit-mask-image: radial-gradient(120% 100% at 12% 0%, #000 0%, transparent 78%);
	mask-image: radial-gradient(120% 100% at 12% 0%, #000 0%, transparent 78%);
}

/*
 * « .hero__media » / « .hero__img » ont été retirés — le HTML ne les produit plus.
 *
 * C'était le fond global du héros : la photo de la page d'accueil, posée derrière
 * toutes les diapositives. Un fond global pour rien — les diapos de service
 * couvrent le héros de leur propre visuel pleine largeur, si bien que cette
 * photo-là ne se voyait jamais que sur la diapo de marque. Elle vit désormais
 * DANS cette diapo, en « .hero__visuel » (voir template-parts/section-hero.php),
 * et hérite du traitement des photos de service au lieu du sien.
 */

/* -------------------------------------------------------------------------
   LE CARROUSEL

   Une diapositive à la fois, en fondu. Pas de piste qui glisse : le contenu
   est dense (titre, accroche, points clés, deux boutons), et un glissement
   horizontal le rendrait illisible pendant la transition.

   Sans JavaScript, seule la première diapositive existe et la navigation reste
   masquée. Une flèche qui ne fait rien est pire que pas de flèche.
   ---------------------------------------------------------------------- */

/*
 * LES DIAPOSITIVES SONT EMPILÉES, PAS PERMUTÉES.
 *
 * Toutes occupent la MÊME cellule de grille. La hauteur de la piste est donc
 * celle de la plus haute, et elle ne bouge plus d'une diapositive à l'autre :
 * un titre sur deux lignes ou quatre pastilles au lieu de deux ne fait plus
 * sauter la page de 49 px à chaque changement.
 *
 * On masque avec « visibility », pas « display » : une diapositive cachée garde
 * sa place (c'est tout l'intérêt) mais sort du parcours clavier et de l'arbre
 * d'accessibilité — on ne tabule pas dans un bouton invisible.
 */
.hero__piste {
	position: relative;
	z-index: 1;
	display: grid;
	width: 100%;
	/*
	 * ⚠️ LA PISTE REMPLIT LE HÉROS — c'est elle qui portait la « bande bleue ».
	 *
	 * Le héros est un flex vertical centré, min-height 82vh. La piste, plus
	 * courte que lui, était donc centrée : il restait une frange de fond du
	 * héros au-dessus d'elle (23 px à 674 px de haut, 83 px à 1040 — elle
	 * grandit avec l'écran). Or la photo est posée sur la DIAPO, elle-même dans
	 * la piste : elle s'arrêtait à cette frange au lieu de monter jusqu'en haut.
	 *
	 * Sur le thème clair, cette frange est blanche sur fond blanc : invisible.
	 * Sur le bleu, elle est navy — c'est la bande qu'on voyait au-dessus du
	 * menu. Même défaut dans les deux thèmes, seule la couleur le trahit.
	 *
	 * « flex: 1 » lui fait prendre toute la hauteur laissée par les onglets :
	 * la photo part du haut du héros. Le texte, lui, reste centré (la diapo
	 * garde son « align-content: center »).
	 */
	flex: 1;
}

/*
 * Le contenu est CENTRÉ dans la cellule. Toutes les diapositives font désormais
 * la hauteur de la plus grande : sans ce centrage, les plus courtes laisseraient
 * un trou sous leur bouton avant la navigation. Centré, le vide se répartit
 * au-dessus et en dessous, et ne se voit plus.
 */
.hero__slide {
	grid-area: 1 / 1;
	display: grid;
	align-content: center;
	width: 100%;
	/*
	 * ⚠️ LA DIAPO PREND TOUTE LA HAUTEUR DU HÉROS, et ce n'est pas cosmétique.
	 *
	 * Le héros centre ses diapos (justify-content: center) et impose un
	 * min-height de 82vh. Une diapo plus courte que lui était donc centrée, en
	 * laissant une frange de son fond en haut et en bas — 23 px, mesurés. Or la
	 * photo est posée SUR la diapo (inset: 0) : elle s'arrêtait à ces 23 px.
	 *
	 * Sur le thème clair, cette frange est blanche sur une page blanche : elle
	 * ne se voit pas. Sur le bleu, elle est navy — c'est LA « bande bleue »
	 * au-dessus du menu. Le défaut est le même dans les deux thèmes, seule la
	 * couleur le révèle.
	 *
	 * La diapo remplit maintenant le héros : la photo va d'un bord à l'autre,
	 * en haut comme en bas. « align-content: center » garde le texte centré.
	 */
	height: 100%;
	/* Le dégagement de l'en-tête, qui se superpose au héros sur l'accueil. Il est
	   ICI et pas sur .hero pour que le visuel le couvre (voir la note plus haut). */
	/*
	 * Le dégagement de l'en-tête, qui se superpose au héros sur l'accueil.
	 * 5,5 rem (88 px) et non 8 : l'en-tête est passé de 100 à 77 px, ces
	 * 8 rem dataient de l'ancienne hauteur et repoussaient le bandeau
	 * « +20 ans » hors de l'écran. 88 px dégagent les 77 px de barre et
	 * laissent 11 px de respiration — en dessous, le texte passerait
	 * dessous.
	 */
	padding-top: 5.5rem;
	/*
	 * L'AIR SOUS LE DERNIER BOUTON.
	 *
	 * Sans lui, le bouton « Demander à être rappelé » touchait le bord bas de la
	 * diapo — mesuré à 0 px sur une fenêtre de 1515 × 698 (un 15 pouces). La diapo
	 * épouse son contenu : padding-top (116) + contenu (368) = 484, et rien ne
	 * réservait le bas. Le défaut est ancien ; il ne se voyait pas tant que la
	 * diapo de marque n'avait pas de photo, le bouton touchant alors du blanc sur
	 * du blanc. La photo a matérialisé ce bord, pas créé le défaut.
	 *
	 * Pourquoi un padding et pas un rabotage du titre : la diapo n'est PAS écrasée
	 * par une contrainte de hauteur (le min-height du héros est inactif, le contenu
	 * le dépasse déjà). Elle grandit donc simplement de ces 24 px — le contenu ne
	 * bouge pas d'un pixel, il n'y a rien à comprimer.
	 *
	 * Ce que ça coûte, mesuré : le bandeau « +20 ans » démarre 24 px plus bas et
	 * s'amorce sous le pli sur 42 px au lieu de 66. Il reste visible, donc il
	 * appelle toujours le défilement.
	 */
	padding-bottom: 1.5rem;
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--transition-lente), visibility var(--transition-lente);
}

.hero__slide.est-actif {
	opacity: 1;
	visibility: visible;
}

.hero__slide.est-actif > .hero__inner > .hero__contenu > * {
	animation: hero-entre 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/*
 * Le contenu entre en cascade, ligne à ligne. C'est ce décalage qui donne au
 * carrousel sa tenue : sans lui, tout apparaît d'un bloc et on dirait un
 * changement d'image, pas un changement de propos.
 */
.hero__slide.est-actif > .hero__inner > .hero__contenu > *:nth-child(1) { animation-delay: 0.05s; }
.hero__slide.est-actif > .hero__inner > .hero__contenu > *:nth-child(2) { animation-delay: 0.12s; }
.hero__slide.est-actif > .hero__inner > .hero__contenu > *:nth-child(3) { animation-delay: 0.19s; }
.hero__slide.est-actif > .hero__inner > .hero__contenu > *:nth-child(4) { animation-delay: 0.26s; }
.hero__slide.est-actif > .hero__inner > .hero__contenu > *:nth-child(5) { animation-delay: 0.33s; }

@keyframes hero-entre {
	from { opacity: 0; transform: translateY(14px); }
	to { opacity: 1; transform: translateY(0); }
}

/*
 * Le visuel du service. Il occupe la DROITE et se dissout vers la gauche : posé
 * en pleine largeur, il passait en fantôme derrière le texte, ce qui est pire
 * que pas d'image du tout. Il habille, il ne porte jamais le message.
 */
/*
 * LA PHOTO EST CANTONNÉE À LA DROITE.
 *
 * Étalée sur toute la largeur, elle passait sous le titre et les pastilles : le
 * détecteur d'alarme se lisait derrière « Sirène intérieure et extérieure ».
 * Voiler davantage l'aurait rendue invisible — c'est-à-dire inutile. On lui
 * donne donc SA moitié, et le texte garde la sienne. Le fondu ne sert plus qu'à
 * gommer son bord gauche, pas à masquer une erreur de mise en page.
 */
.hero__visuel {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	-webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 30%);
	mask-image: linear-gradient(90deg, transparent 0%, #000 30%);
}

@media (min-width: 900px) {
	.hero__visuel {
		/* Sa moitié. Le texte a la sienne. */
		left: 42%;
		-webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
		mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
	}
}

/*
 * Le traitement de l'image.
 *
 * Volontairement LÉGER : les photos produit fournies sont déjà sombres, avec le
 * matériel à droite et du vide à gauche. Un duotone gris à 55 % d'opacité — ce
 * qu'on appliquait tant qu'il n'y avait que des placeholders — les aurait
 * réduites en bouillie. On se contente de désaturer un peu et de refroidir : la
 * photo reste lisible, elle entre juste dans la palette du site.
 */
.hero__visuel-img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/*
	 * Le héros est bien plus large que haut : une photo produit en 4/3 s'y fait
	 * rogner d'un tiers en hauteur. Centrée, la coupe emporte le pied du matériel
	 * — les appareils flottent. On cale donc le cadrage vers le BAS, là où le
	 * matériel est posé.
	 */
	/* Le cadrage vertical est posé en style inline, service par service (champ
	   « Cadrage dans le carrousel »). Ici, seulement le repli. */
	object-position: center 50%;
	/* Juste ce qu'il faut pour entrer dans la palette du site. Au-delà, on ne
	   voit plus le matériel — et c'est lui qu'on est venu montrer. */
	filter: saturate(0.8) contrast(1.03);
	opacity: 1;
}

/*
 * Le voile. Il tombe de gauche (là où vit le texte) vers la droite (là où vit le
 * matériel) : le titre reste lisible sur n'importe quelle photo, et le produit
 * reste visible. C'est le dégradé qui fait tout le travail, pas l'opacité.
 */
/*
 * Le voile ne sert plus qu'à fondre les bords de la photo dans le nuit du
 * héros : haut, bas et gauche. Le centre reste net — c'est le matériel, et
 * c'est lui qu'on est venu montrer.
 */
.hero__visuel::after {
	content: '';
	position: absolute;
	inset: 0;
	background:
		linear-gradient(90deg, var(--nuit) 0%, rgba(17, 17, 17, 0) 32%),
		linear-gradient(0deg, var(--nuit) 0%, rgba(17, 17, 17, 0) 18%),
		linear-gradient(180deg, var(--nuit) 0%, rgba(17, 17, 17, 0) 14%);
}

@media (min-width: 900px) {
	/* Le contenu tient dans la moitié gauche : l'image a la droite pour elle. */
	.hero__inner--service { grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr); }
	.hero__inner--service .hero__contenu { grid-column: 1; }
}

/*
 * SUR MOBILE, LA PHOTO SE RETIRE — LE HÉROS RESTE BLANC. (demande client)
 *
 * Ce que ce bloc faisait avant, et pourquoi ça ne tenait pas. La photo était
 * gardée en fond d'ambiance : 32 % d'opacité, plus le masque du « héros clair »
 * qui l'efface sur son quart gauche et la rattrape à 58 %. Sur le fond nuit
 * d'origine, ce réglage se lisait comme une pénombre. Sur le fond BLANC, il ne
 * restait qu'un voile gris laiteux, net nulle part, et poussé vers la droite
 * par le masque — l'image paraissait décalée et floue au lieu d'être discrète.
 *
 * Un écran de 390 px ne laisse pas d'issue : il n'y a pas de « droite » où
 * reléguer la photo, et sous le titre, le sous-titre, trois pastilles et deux
 * boutons, tout traitement assez fort pour rendre le texte lisible détruit la
 * photo. On la retire donc franchement : le blanc du thème et sa grille
 * millimétrée portent le héros seuls, comme sur la diapo de marque qui n'a
 * jamais eu de photo. Le matériel garde ses vraies vitrines — pages service et
 * réalisations, où il est montré en grand et net.
 *
 * ⚠️ RÉVERSIBLE EN UNE LIGNE : rétablir « display: block » ici fait revenir la
 * photo. Elle est toujours produite dans le HTML (section-hero.php), elle n'est
 * pas montrée sur cette largeur.
 */
@media (max-width: 899px) {
	/*
	 * LA PHOTO REDEVIENT UNE PHOTO. (demande client)
	 *
	 * Elle a d'abord été un fond d'ambiance — 32 % d'opacité, masquée sur son
	 * quart gauche — ce qui donnait un voile gris décalé sur le blanc du thème,
	 * net nulle part. Puis on l'a retirée. Elle revient ici sous la seule forme
	 * qui tienne sur 390 px : un bloc, sous le texte, NET et opaque.
	 *
	 * Le fond de la diapo cesse d'être son support : plus de masque, plus de
	 * voile, plus d'opacité. Le texte garde le blanc pour lui, la photo garde
	 * ses pixels — personne ne marche sur personne, et c'est ce qui rendait
	 * l'ancien réglage impossible à régler.
	 *
	 * « order: 2 » parce que le HTML la place AVANT le texte : c'était l'ordre
	 * d'un calque de fond, ce n'est pas celui d'une illustration.
	 */
	/*
	 * ⚠️ SÉLECTEUR DOUBLÉ, ET CE N'EST PAS UN OUBLI DE MÉNAGE.
	 *
	 * Le masque en dégradé vient du bloc « HÉROS CLAIR », plus BAS dans le
	 * fichier et hors media query : à spécificité égale c'est lui qui gagne, et
	 * la photo revenait fondue au blanc sur son tiers gauche. « .hero__slide
	 * .hero__visuel » passe devant sans qu'on ait à déplacer quoi que ce soit.
	 */
	.hero__slide .hero__visuel {
		display: block;
		position: absolute;
		inset: 0;
		-webkit-mask-image: none;
		mask-image: none;
	}

	.hero__slide .hero__visuel-img {
		height: 100%;
		opacity: 1;
		object-fit: cover;
	}

	/*
	 * LE VOILE — vertical, et franchement appuyé.
	 *
	 * Sur grand écran, le voile tombe de la gauche vers la droite : le texte a
	 * sa moitié, le matériel garde la sienne. Sur 390 px, cette partition
	 * n'existe pas — le texte occupe toute la largeur, il passe forcément SUR
	 * la photo. Le voile devient donc vertical et couvre tout.
	 *
	 * Il est plus dense en bas qu'en haut : c'est là que vivent les pastilles
	 * et les boutons, et c'est là que les photos sont les plus claires (plans
	 * de comptoir, murs blancs). Le haut reste plus ouvert pour qu'on voie
	 * encore de quoi la photo parle.
	 */
	.hero__slide .hero__visuel::after {
		content: '';
		position: absolute;
		inset: 0;
		background: linear-gradient(
			180deg,
			rgba(10, 12, 14, 0.62) 0%,
			rgba(10, 12, 14, 0.78) 45%,
			rgba(10, 12, 14, 0.88) 100%
		);
	}

	/*
	 * Le texte repasse au blanc — sur les diapos QUI ONT une photo seulement.
	 * C'est la même règle que sur grand écran (« :has(.hero__visuel) »), pour
	 * la même raison : une diapo sans photo garde le héros blanc du thème.
	 */
	.hero__slide:has(.hero__visuel) .hero__titre,
	.hero__slide:has(.hero__visuel) .hero__sous-titre strong,
	.hero__slide:has(.hero__visuel) .hero__sous-titre b {
		color: var(--blanc);
	}

	.hero__slide:has(.hero__visuel) .hero__sous-titre,
	.hero__slide:has(.hero__visuel) .surtitre {
		color: rgba(255, 255, 255, 0.86);
	}

	/* Les pastilles de points clés : filet et fond translucides, sur la photo. */
	.hero__slide:has(.hero__visuel) .hero__point {
		color: var(--blanc);
		background: rgba(255, 255, 255, 0.12);
		border-color: rgba(255, 255, 255, 0.32);
	}

	/* Le bouton secondaire vit sur la photo : contour blanc, fond translucide. */
	.hero__slide:has(.hero__visuel) .bouton--fantome {
		color: var(--blanc);
		border-color: rgba(255, 255, 255, 0.55);
		background: rgba(255, 255, 255, 0.08);
	}

	/*
	 * LE BAS DU HÉROS : CINQ RECTANGLES EMPILÉS, C'EST QUATRE DE TROP.
	 *
	 * Trois pastilles chacune sur sa ligne, puis deux boutons de largeurs
	 * différentes : le bloc faisait 297 px de hauteur, tout en boîtes de même
	 * poids, et l'œil ne savait plus laquelle était l'action. On ne retire
	 * rien, on resserre et on hiérarchise.
	 *
	 * Les pastilles perdent 2 px de padding vertical et passent à 0,78 rem :
	 * « Caméras HD » et « Enregistrement sécurisé » tiennent alors sur la même
	 * ligne (295 px pour 327 disponibles), et le bloc tombe de trois lignes à
	 * deux. Ce sont des repères de lecture, pas des boutons : à cette taille
	 * ils cessent de rivaliser avec ce qui se clique.
	 */
	/* Sélecteurs préfixés par « .hero__slide » : les règles de base du composant
	   sont plus BAS dans le fichier, et une media query n'ajoute aucune
	   spécificité — sans ce préfixe, elles reprendraient la main. */
	.hero__slide .hero__points { gap: 0.45rem; margin-bottom: 1.4rem; }

	.hero__slide .hero__point {
		padding: 0.375rem 0.7rem;
		font-size: 0.78rem;
	}

	/*
	 * Les deux boutons prennent la pleine largeur. Ils faisaient 257 et 233 px,
	 * calés à gauche : deux bords droits différents, une colonne qui paraissait
	 * de travers. À pleine largeur ils forment une pile franche, et la cible
	 * tactile y gagne au passage.
	 */
	.hero__actions {
		gap: 0.75rem;
		align-items: stretch;
	}

	.hero__actions .bouton {
		width: 100%;
		justify-content: center;
	}

	/*
	 * LE MONITEUR SORT AUSSI — ET C'EST UNE QUESTION DE HAUTEUR, PAS DE GOÛT.
	 *
	 * Les six diapositives sont empilées dans la MÊME cellule de grille : la
	 * piste prend donc la hauteur de la plus haute, et toutes les autres s'y
	 * centrent. Or la diapo de marque portait seule le moniteur — 317 px, plus
	 * 48 de gouttière. Les cinq diapositives de service, qui n'ont que du
	 * texte, se retrouvaient donc posées au milieu d'une boîte de 1 031 px
	 * avec 430 px de vide réparti au-dessus et en dessous. Le titre flottait.
	 *
	 * Réduire le moniteur ne suffisait pas : même amputé de ses états, il
	 * laissait encore 288 px d'écart. Et faire suivre la hauteur à la diapo
	 * active est exclu — le carrousel défile tout seul, la page sauterait
	 * toutes les sept secondes.
	 *
	 * Sur téléphone, le héros porte donc les mots, et rien d'autre — c'est
	 * déjà le parti pris pour les photos, juste au-dessus. Les six diapos font
	 * enfin la même taille, et la page y gagne 365 px au passage.
	 */
	.moniteur { display: none; }

	.hero__inner { gap: 0; }

	/*
	 * Et le plancher de 82 vh tombe avec eux. Il existait pour qu'une photo ou
	 * le moniteur aient de quoi s'installer ; sans visuel, il ne fait plus que
	 * distendre une colonne de texte. Sur un iPhone la différence est nulle (le
	 * contenu dépasse déjà les 82 vh), mais sur une tablette en portrait il
	 * rouvrait 280 px de vide sous les mêmes six diapositives.
	 *
	 * Le héros mesure donc ce qu'il contient. Il occupe encore la quasi-totalité
	 * du premier écran sur téléphone — simplement, il ne l'invente plus.
	 */
	.hero { min-height: 0; }
}

/* L'icône du service, dans le surtitre. */
.hero__picto {
	flex: none;
	color: var(--rouge);
}

/* Les points clés, en pastilles. Ils viennent de la textarea du service :
   une ligne = une pastille. */
.hero__points {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin: 0 0 2rem;
	padding: 0;
	list-style: none;
}

.hero__point {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.5rem 0.9rem;
	font-family: var(--font-titre);
	font-size: 0.85rem;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.9);
	background: rgba(255, 255, 255, 0.05);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: var(--rayon);
}

.hero__point .icone { color: var(--rouge); }

/* --- La navigation --- */

/*
 * LE RAIL DU BAS — le jumeau de l'en-tête (demande client).
 *
 * Cette bande blanche n'était pas voulue : c'était le fond du héros qui restait
 * sous la photo. Blanche comme l'en-tête, mais sans rien de lui — 141 px contre
 * 77, pas de filet, pas de rythme. Elle se lisait comme un débord.
 *
 * Elle devient donc son pendant : même hauteur, même filet (le sien en bas,
 * celui-ci en HAUT — tous deux tournés vers la photo), et le contenu sur UNE
 * ligne comme l'en-tête aligne logo / menu / bouton. La photo est tenue entre
 * deux rails identiques : elle se lit comme une plaque cadrée, et les onglets
 * ne flottent plus dans du vide.
 *
 * Le « .conteneur » que porte déjà .hero__nav fait que ses onglets s'alignent
 * d'eux-mêmes sur le menu, en haut.
 */
.hero__nav {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	gap: 1.1rem;
	margin-top: 0;
	/*
	 * L'AIR AU-DESSUS DES FLÈCHES.
	 *
	 * Mesuré sur téléphone : 0 px entre le bas de la photo et les flèches, puis
	 * 18 px jusqu'aux onglets et 24 px jusqu'au bas du héros. La barre était
	 * collée en haut et respirait en bas — d'où l'impression qu'elle tombait de
	 * la photo. Elle reçoit au-dessus ce qu'elle avait déjà en dessous.
	 *
	 * PADDING et non marge : le filet est un pseudo-élément calé sur « top: 0 »
	 * de ce bloc. Une marge l'aurait fait descendre avec lui, à flotter au
	 * milieu du blanc ; le padding le laisse au contact de la photo, où il
	 * sépare — ce pour quoi il est là.
	 *
	 * Déclaré ICI et non dans une media query « max-width: 899px » : une fenêtre
	 * peut mesurer 899,33 px, et ni « max-width: 899 » ni « min-width: 900 » ne
	 * s'y appliquent — la barre y redevenait collée. Le palier ≥ 900 px, plus
	 * bas, redéfinit ce padding pour son propre compte ; aucun interstice
	 * possible entre les deux.
	 */
	padding-top: 1.5rem;
}

/*
 * Le filet, en pleine largeur. Il est posé en pseudo et non en « border-top »
 * parce que .hero__nav est un conteneur (1280 px) : sa bordure se serait
 * arrêtée au contenu, là où celle de l'en-tête traverse tout l'écran. Un rail
 * qui s'arrête en route n'est plus un rail.
 *
 * « width: 100% » sur un calque calé au bord du héros, et non « 100vw » : vw
 * compte l'ascenseur et aurait ajouté un débordement horizontal.
 */
.hero__nav::before {
	content: '';
	position: absolute;
	top: 0;
	left: calc(-1 * var(--gouttiere) - var(--piste-l));
	right: calc(-1 * var(--gouttiere));
	border-top: 1px solid var(--trait);
	pointer-events: none;
}

@media (min-width: 900px) {
	/*
	 * ⚠️ LE RAIL RESTE SUR DEUX LIGNES, et ce n'est pas un renoncement.
	 *
	 * Une seule ligne à la hauteur exacte de l'en-tête (76 px) a été essayée :
	 * le compteur et les six services demandent ~1350 px quand le conteneur en
	 * offre 1144. Les onglets se faisaient couper — « Maintenance » disparaissait
	 * purement et simplement. Un rail qui mange une entrée de menu ne vaut pas
	 * la symétrie qu'il achète.
	 *
	 * Ce qui fait le jumelage tient de toute façon aux trois autres traits : même
	 * blanc, même filet tourné vers la photo, même colonne (le .conteneur aligne
	 * les onglets sur le menu). La hauteur, elle, suit son contenu.
	 */
	.hero__nav {
		gap: 0.75rem;
		padding-block: 0.85rem;
	}

	.hero__onglets { padding-bottom: 0; }
}

.hero__nav[hidden] { display: none; }

.hero__nav-boutons {
	display: flex;
	align-items: center;
	gap: 1.25rem;
}

/*
 * Sous 360 px, deux ronds de 38 px, un compteur et sa jauge ne tiennent plus
 * dans la gouttière : la flèche « suivant » perdait 4 px sur sa droite, rognés
 * par le héros. On resserre les écarts plutôt que de rétrécir les boutons —
 * c'est de l'espacement qu'il faut prendre, pas de la cible tactile.
 */
@media (max-width: 359px) {
	.hero__nav-boutons { gap: 0.75rem; }
	.hero__compteur { gap: 0.5rem; }
}

/*
 * LES ONGLETS.
 *
 * Deux flèches ne suffisent pas : sur un carrousel de héros, presque personne
 * ne clique dessus. Sans ces noms, cinq services sur six resteraient invisibles
 * — le carrousel cacherait ce qu'il est censé montrer. Ici, on les lit tous.
 */
.hero__onglets {
	display: flex;
	gap: 0.5rem;
	margin: 0;
	padding: 0 0 0.5rem;
	list-style: none;
	/* Six noms de services ne tiennent pas dans un téléphone : on les fait
	   défiler plutôt que de les empiler sur quatre lignes. */
	overflow-x: auto;
	scrollbar-width: none;
}

.hero__onglets::-webkit-scrollbar { display: none; }

.hero__onglet {
	white-space: nowrap;
	padding: 0.5rem 0.9rem;
	font-family: var(--font-titre);
	font-size: 0.85rem;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.6);
	background: transparent;
	border: 1px solid rgba(255, 255, 255, 0.16);
	border-radius: var(--rayon);
	cursor: pointer;
	transition: color var(--transition), border-color var(--transition), background-color var(--transition);
}

.hero__onglet:hover {
	color: var(--blanc);
	border-color: rgba(255, 255, 255, 0.45);
}

.hero__onglet.est-actif {
	color: var(--blanc);
	background: rgba(230, 55, 39, 0.16);
	border-color: var(--rouge);
}


.hero__fleche {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 46px;
	height: 46px;
	padding: 0;
	color: var(--blanc);
	background: transparent;
	border: 1px solid rgba(255, 255, 255, 0.28);
	border-radius: 50%;
	cursor: pointer;
	transition: background-color var(--transition), border-color var(--transition);
}

.hero__fleche:hover {
	background: rgba(255, 255, 255, 0.08);
	border-color: var(--blanc);
}

/*
 * Le compteur. Ici, numéroter a un sens : un carrousel EST une séquence, et
 * savoir où l'on en est fait partie du contrat. La jauge dit la même chose
 * sans chiffre.
 */
.hero__compteur {
	display: flex;
	align-items: center;
	gap: 0.85rem;
	margin: 0;
	font-family: var(--font-mono);
	font-size: 0.8rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	color: var(--blanc);
}

.hero__compteur-total { color: rgba(255, 255, 255, 0.4); }

.hero__compteur-barre {
	display: block;
	width: 90px;
	height: 1px;
	background: rgba(255, 255, 255, 0.2);
}

.hero__compteur-barre > span {
	display: block;
	width: 0;
	height: 100%;
	background: var(--rouge);
	transition: width var(--transition-lente);
}

.hero__inner {
	position: relative;
	z-index: 1;
	display: grid;
	gap: 3rem;
	align-items: center;
	width: 100%;
	/* Même garde que le héros des services : sans minmax(0, …), la colonne se
	   cale sur le contenu le plus large et le héros, qui rogne, coupe le titre
	   en silence. Mesuré à 320 px : 46 px de texte perdus par la droite. */
	grid-template-columns: minmax(0, 1fr);
}

/*
 * Le plancher du clamp — 2,6 rem, soit ~42 px — a été calé sur « Protégez vos
 * locaux, vos biens et vos équipes », dont le mot le plus long fait 7 lettres.
 * Le titre porte désormais « Installateur de systèmes de sécurité » : à la même
 * taille, il tenait en SIX lignes sur un écran de 320 px et repoussait la
 * navigation du carrousel sous le pli. Sous 400 px, le plancher redescend —
 * le titre reste la plus grosse chose de l'écran, il cesse d'être l'écran.
 */
@media (max-width: 400px) {
	/* Sélecteur doublé : la règle de base est plus BAS dans le fichier et une
	   media query n'ajoute aucune spécificité. */
	.hero .hero__titre { font-size: clamp(1.85rem, 8vw, 2.6rem); }
}

.hero__titre {
	color: var(--blanc);
	font-size: clamp(2.6rem, 5.4vw, 4.3rem);
	/*
	 * L'INTERLIGNAGE DES CAPITALES ACCENTUÉES.
	 *
	 * Le h1 du site est à 1,04 — un interlignage calé sur des capitales SANS
	 * accent, où rien ne dépasse au-dessus de la hauteur de capitale. Ce titre-ci
	 * est le seul en capitales ACCENTUÉES sur plusieurs lignes, et il y prenait
	 * « LOCAUX, » au-dessus de « ÉQUIPES » : la virgule et l'accent aigu se
	 * touchaient, au point de se souder en un seul trait.
	 *
	 * Ce n'est pas un réglage à vue, les métriques d'Inter le donnent :
	 *   · la virgule descend de 0,215 em sous la ligne de base ;
	 *   · le « É » monte de 0,948 em au-dessus (dont 0,215 em pour l'accent seul).
	 * Il faut donc 1,164 em entre deux lignes de base pour un simple contact —
	 * 1,04 en laissait 0,124 em de trop peu (5,7 px mesurés à 46,4 px de corps).
	 *
	 * 1,2 dégage les glyphes et reste serré, comme il sied à un titre. Le seuil
	 * étant un RATIO, il vaut à toutes les tailles du clamp : rien à re-régler par
	 * palier. Le titre de SERVICE garde son 1,02 (une seule ligne, pas de contact
	 * possible) — sa règle passe après celle-ci.
	 */
	line-height: 1.2;
	margin-bottom: 1.5rem;
	text-transform: uppercase;
	text-wrap: balance;
}

/* Le trait : la signature typographique. Un segment rouge, rien de plus. */
.hero__titre::after {
	content: '';
	display: block;
	width: 4.5rem;
	height: 3px;
	margin-top: 1.5rem;
	background: var(--rouge);
}

/*
 * Le titre d'un service n'est pas un slogan : c'est un nom. On le laisse en
 * casse normale, et on lui retire le trait rouge — les pastilles des points
 * clés jouent déjà ce rôle de scansion juste en dessous.
 */
.hero__titre--service {
	text-transform: none;
	font-size: clamp(2.4rem, 4.9vw, 3.9rem);
	line-height: 1.02;
}

.hero__titre--service::after { content: none; }

/* Quand le surtitre porte l'icône du service, le tiret d'amorce ferait doublon. */
.surtitre:has(.hero__picto)::before { content: none; }

.hero__sous-titre {
	max-width: 46ch;
	font-size: 1.1rem;
	line-height: 1.6;
	margin-bottom: 2.25rem;
	color: rgba(255, 255, 255, 0.78);
}

/* Les mots clés balisés dans l'accroche : blanc plein sur le reste à 78 %. */
.hero__sous-titre strong,
.hero__sous-titre b {
	color: var(--blanc);
	font-weight: 700;
}

.hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1.25rem;
	margin: 0;
}

/* -------------------------------------------------------------------------
   LE TRACÉ — la diapositive de marque

   Le logo porte un pouls rouge ; on le prend au mot. Le héros montre le signal
   d'un site sous surveillance : la ligne bat, les trois états tiennent.

   Ce n'est plus le plan d'implantation qui était là avant, et c'est délibéré :
   le plan, le vrai, se dessine dans le pré-diagnostic au fil des réponses. Le
   montrer deux fois, c'était l'annoncer en petit avant de le tenir en grand.
   ---------------------------------------------------------------------- */

.moniteur {
	position: relative;
	width: 100%;
	max-width: 460px;
	margin-inline: auto;
	padding: 1.15rem 1.35rem 0.65rem;
	border: 1px solid var(--marine-ligne);
	border-radius: var(--rayon);
	background: linear-gradient(180deg, rgba(44, 44, 44, 0.55), rgba(17, 17, 17, 0.6));
	animation: apparait 0.8s ease both 0.35s;
}

@keyframes apparait {
	from { opacity: 0; }
	to { opacity: 1; }
}

.moniteur__entete {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin: 0 0 1rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.55);
}

.moniteur__nom { flex: 1; }
.moniteur__signe { color: rgba(255, 255, 255, 0.85); }

/* La LED. Une onde lente, pas un clignotant : le site va bien. */
.moniteur__voyant {
	width: 8px;
	height: 8px;
	flex: none;
	border-radius: 50%;
	background: var(--rouge);
	animation: pouls 2.6s ease-out infinite;
}

@keyframes pouls {
	0%        { box-shadow: 0 0 0 0 rgba(230, 55, 39, 0.55); }
	70%, 100% { box-shadow: 0 0 0 10px rgba(230, 55, 39, 0); }
}

/*
 * L'écran. Le quadrillage est celui du papier millimétré du héros, resserré :
 * un oscilloscope, pas un graphique de tableur.
 */
.moniteur__ecran {
	position: relative;
	height: clamp(88px, 13vh, 124px);
	margin-bottom: 0.6rem;
	border-radius: var(--rayon-sm);
	background-color: rgba(17, 17, 17, 0.55);
	background-image:
		repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 20px),
		repeating-linear-gradient(rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 20px);
	overflow: hidden;
	/* Le signal s'efface aux deux bords : il vient de loin et repart de même. */
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

.moniteur__signal-svg {
	display: block;
	width: 100%;
	height: 100%;
}

.moniteur__defile {
	animation: defile-signal 7s linear infinite;
}

/* Une période exactement : la seconde copie du tracé prend la place de la
   première, et la boucle ne se voit pas. */
@keyframes defile-signal {
	from { transform: translateX(0); }
	to   { transform: translateX(-240px); }
}

.moniteur__ligne {
	fill: none;
	stroke: var(--rouge);
	stroke-width: 1.6;
	stroke-linecap: round;
	stroke-linejoin: round;
	/* preserveAspectRatio="none" étire le repère : sans ceci, le trait s'épaissit
	   dans un sens et maigrit dans l'autre. */
	vector-effect: non-scaling-stroke;
	filter: drop-shadow(0 0 6px rgba(230, 55, 39, 0.45));
}

.moniteur__etats {
	margin: 0;
	padding: 0;
	list-style: none;
}

.moniteur__etats li {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	padding-block: 0.62rem;
	border-top: 1px solid var(--marine-ligne);
	font-size: 0.92rem;
	animation: apparait 0.6s ease both;
}

.moniteur__etats li:nth-child(1) { animation-delay: 0.8s; }
.moniteur__etats li:nth-child(2) { animation-delay: 0.95s; }
.moniteur__etats li:nth-child(3) { animation-delay: 1.1s; }

/* Le losange de la boucle, en petit : c'est le même capteur, partout. */
.moniteur__diode {
	width: 6px;
	height: 6px;
	flex: none;
	background: var(--rouge);
	transform: rotate(45deg);
}

.moniteur__libelle {
	flex: 1;
	color: rgba(255, 255, 255, 0.65);
}

.moniteur__valeur {
	font-family: var(--font-mono);
	font-size: 0.74rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--blanc);
}

/* ============================================================
 * HÉROS CLAIR (demande client) — le carrousel passe sur fond blanc.
 * Bloc GROUPÉ et RÉVERSIBLE : le supprimer en entier restaure le héros
 * sombre d'origine (aucune règle plus haut n'a été touchée).
 * Principe : fond blanc, texte encre, photos CONSERVÉES mais fondues dans
 * le blanc au lieu du nuit, et le moniteur devient une carte blanche dont
 * l'écran reste sombre (c'est un afficheur, il gagne à le rester).
 * ============================================================ */

.hero {
	background: var(--blanc);
	color: var(--encre);
	--fond-noeud: var(--blanc);
}

/* Grille millimétrée : filet sombre très discret (au lieu du blanc translucide). */
.hero__grille {
	background-image:
		linear-gradient(rgba(28, 28, 28, 0.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(28, 28, 28, 0.05) 1px, transparent 1px);
}

/*
 * La photo de la diapo 1 était ici « fondue dans le blanc » : 12 % d'opacité, en
 * niveaux de gris, sous un voile blanc opaque sur son quart gauche. Mesurée, elle
 * ressortait à #FFFFFF — blanc pur, d'un bord à l'autre du héros. Autrement dit
 * elle n'était pas discrète, elle était absente.
 *
 * Elle est maintenant un « .hero__visuel » comme les photos de service et suit
 * leurs règles, plus bas : pleine largeur, nette, ombrée à gauche, texte blanc.
 */

/* Photo de service (à droite) : CONSERVÉE. Les photos produit ont un fond
 * sombre ; les fondre dans le blanc avec des voiles blancs empilés créait une
 * zone grise « sale » sur les bords. On les remplace par un MASQUE en vignette
 * douce : la photo se dissout progressivement vers tous ses bords, sans halo.
 * Un léger éclaircissement évite le bloc trop lourd sur fond blanc. */
.hero__visuel {
	/* Fondu GAUCHE large et progressif (protège le texte sans bord franc) croisé
	   avec un feutrage HAUT/BAS : la photo se dissout dans le blanc de tous côtés,
	   sans voile gris ni transition brutale. */
	-webkit-mask-image:
		linear-gradient(90deg, transparent 24%, #000 58%),
		linear-gradient(180deg, transparent 0%, #000 12%, #000 82%, transparent 100%);
	-webkit-mask-composite: source-in;
	mask-image:
		linear-gradient(90deg, transparent 24%, #000 58%),
		linear-gradient(180deg, transparent 0%, #000 12%, #000 82%, transparent 100%);
	mask-composite: intersect;
}
.hero__visuel::after { content: none; }
/* Léger éclaircissement : les photos produit sont sombres, on les allège pour
   qu'elles ne pèsent pas comme un bloc noir sur le blanc. */
.hero__visuel-img { filter: saturate(0.95) brightness(1.07) contrast(0.98); }

/*
 * PHOTO PLEINE LARGEUR, SANS FONDU (demande client).
 *
 * La photo occupe le héros d'un bord à l'autre et reste nette partout : plus de
 * masque, plus de dissolution. C'est la demande, et elle est explicite.
 *
 * ⚠️ CE QUE ÇA COÛTE, pour qui passera ici plus tard. Le fondu n'était pas un
 * effet, c'était ce qui rendait le titre lisible : la photo a déjà été pleine
 * largeur par le passé, et avait été ramenée à « left: 42% » précisément parce
 * qu'elle passait sous le texte (voir le commentaire de « .hero__visuel » plus
 * haut). En le retirant, le titre revient sur la photo.
 *
 * D'où le bloc qui suit : sur une diapo qui porte une photo, le texte repasse en
 * BLANC. Ce n'est pas un caprice, c'est ce que les photos imposent — elles sont
 * sombres, avec le matériel à droite et du vide à gauche (voir plus haut) : ce
 * vide est fait pour du texte clair, pas pour de l'encre. La diapo de marque,
 * elle, n'a pas de photo et garde le héros blanc du thème.
 */
@media (min-width: 900px) {
	.hero__visuel {
		left: 0;
		-webkit-mask-image: none;
		mask-image: none;
	}

	/*
	 * L'OMBRE CÔTÉ TEXTE — et non un fondu.
	 *
	 * La nuance est tout l'objet : la photo n'est ni floutée, ni dissoute, ni
	 * rognée. Elle reste NETTE et pleine largeur d'un bord à l'autre. On pose
	 * seulement une ombre sur son tiers gauche, là où vit le texte, et elle a
	 * disparu avant la moitié — le matériel, lui, ne reçoit rien.
	 *
	 * Pourquoi c'est non négociable : la photo « Alarme » porte un détecteur
	 * BLANC exactement sous le titre. Mesuré sans ombre, le titre blanc y tombe à
	 * 1,1:1 — invisible. C'est mot pour mot ce que décrit le commentaire de
	 * « .hero__visuel » plus haut, qui avait fait reculer la photo à l'époque :
	 * « le détecteur d'alarme se lisait derrière "Sirène intérieure et
	 * extérieure" ». Le problème n'a pas changé de nature, seulement de remède :
	 * on assombrit au lieu de rogner.
	 */
	.hero__slide:has(.hero__visuel) .hero__visuel::after {
		content: '';
		position: absolute;
		inset: 0;
		pointer-events: none;
		/*
		 * Les bornes sont calées sur une mesure, pas sur un ressenti : le
		 * détecteur blanc de la photo « Alarme » (rgb 248) tombe vers 41 % de la
		 * largeur, juste sous la fin du titre. Il y faut 0,55 d'ombre pour que le
		 * blanc repasse au-dessus de 4,5:1 ; en deçà (0,28 essayé), le titre
		 * plafonnait à 2,5:1. L'ombre est éteinte à 62 %, donc le matériel — la
		 * moitié droite, ce qu'on est venu montrer — n'est pas touché.
		 */
		background: linear-gradient(
			90deg,
			rgba(8, 10, 12, 0.9) 0%,
			rgba(8, 10, 12, 0.78) 28%,
			rgba(8, 10, 12, 0.45) 46%,
			rgba(8, 10, 12, 0) 62%
		);
	}
}

/*
 * LE TEXTE SUR LA PHOTO.
 *
 * « :has(.hero__visuel) » ne cible que les diapositives qui ont réellement une
 * photo : la diapo de marque et tout service sans visuel gardent le héros clair,
 * sans qu'on ait à leur poser une classe à la main.
 *
 * L'ombre portée est SOUS le texte, pas sur la photo : elle détache les lettres
 * sans rien voiler. C'est ce qui remplace le fondu retiré.
 */
@media (min-width: 900px) {
	.hero__slide:has(.hero__visuel) .hero__titre,
	.hero__slide:has(.hero__visuel) .hero__sous-titre strong,
	.hero__slide:has(.hero__visuel) .hero__sous-titre b {
		color: var(--blanc);
		text-shadow: 0 1px 18px rgba(0, 0, 0, 0.55);
	}

	.hero__slide:has(.hero__visuel) .hero__sous-titre,
	.hero__slide:has(.hero__visuel) .surtitre {
		color: rgba(255, 255, 255, 0.86);
		text-shadow: 0 1px 14px rgba(0, 0, 0, 0.55);
	}

	/* Les pastilles de points clés : filet et fond translucides, sur le blanc. */
	.hero__slide:has(.hero__visuel) .hero__point {
		color: var(--blanc);
		background: rgba(255, 255, 255, 0.1);
		border-color: rgba(255, 255, 255, 0.3);
		backdrop-filter: blur(2px);
	}

	/* Le bouton secondaire : contour blanc, il vit sur la photo maintenant. */
	.hero__slide:has(.hero__visuel) .bouton--fantome {
		color: var(--blanc);
		border-color: rgba(255, 255, 255, 0.5);
	}

	.hero__slide:has(.hero__visuel) .bouton--fantome:hover,
	.hero__slide:has(.hero__visuel) .bouton--fantome:focus {
		color: var(--blanc);
		border-color: var(--blanc);
		background: rgba(255, 255, 255, 0.12);
	}
}

/* Titre & textes en encre ; les mots-clés gras passent en marine. */
.hero__titre { color: var(--marine); }
.hero .surtitre { color: var(--encre-douce); }
.hero__sous-titre { color: var(--encre-douce); }
.hero__sous-titre strong,
.hero__sous-titre b { color: var(--marine); }

/* Pastilles de points clés. */
.hero__point {
	color: var(--marine);
	background: rgba(28, 28, 28, 0.035);
	border-color: rgba(28, 28, 28, 0.14);
}

/* Bouton contour « Demander une étude ». */
.hero .bouton--fantome {
	color: var(--marine);
	border-color: rgba(28, 28, 28, 0.28);
}
.hero .bouton--fantome:hover,
.hero .bouton--fantome:focus {
	color: var(--marine);
	border-color: var(--marine);
	background: rgba(28, 28, 28, 0.04);
}

/* Onglets. */
.hero__onglet {
	color: var(--encre-douce);
	border-color: rgba(28, 28, 28, 0.18);
}
.hero__onglet:hover {
	color: var(--marine);
	border-color: rgba(28, 28, 28, 0.4);
}
.hero__onglet.est-actif {
	color: var(--marine);
	background: var(--rouge-voile);
	border-color: var(--rouge);
}

/* Flèches de navigation. */
.hero__fleche {
	color: var(--marine);
	border-color: rgba(28, 28, 28, 0.28);
}
.hero__fleche:hover {
	background: rgba(28, 28, 28, 0.05);
	border-color: var(--marine);
}

/* Compteur. */
.hero__compteur { color: var(--marine); }
.hero__compteur-total { color: rgba(28, 28, 28, 0.4); }
.hero__compteur-barre { background: rgba(28, 28, 28, 0.18); }

/* Le moniteur : carte blanche. */
.moniteur {
	background: #F6F8FA;
	border-color: var(--trait);
	box-shadow: 0 12px 32px rgba(28, 28, 28, 0.10);
}
.moniteur__entete { color: var(--encre-douce); }
.moniteur__signe { color: var(--marine); }
.moniteur__etats li { border-top-color: var(--trait); }
.moniteur__libelle { color: var(--encre-douce); }
.moniteur__valeur { color: var(--marine); }
/* Écran : plus de fond gris derrière la courbe (demande client). La courbe rouge
   repose directement sur la carte claire ; on garde un quadrillage très discret
   pour l'esprit oscilloscope. */
.moniteur__ecran {
	background-color: transparent;
	background-image:
		repeating-linear-gradient(90deg, rgba(28, 28, 28, 0.05) 0 1px, transparent 1px 20px),
		repeating-linear-gradient(rgba(28, 28, 28, 0.05) 0 1px, transparent 1px 20px);
}

/* -------------------------------------------------------------------------
   9. SECTIONS
   ---------------------------------------------------------------------- */

.section { padding-block: 4rem; }
.section--claire { background: var(--papier); }

/* ------------------------------------------------------------
 * ALTERNANCE BLANC/GRIS — ACCUEIL uniquement (demande client)
 * Le gris de marque --papier (#EDF0F3) est très proche du blanc et ne
 * marquait pas assez la séparation entre sections. On le fonce, MAIS
 * seulement sur l'accueil (classe body .a-header-transparent), pour ne pas
 * toucher les autres pages tant qu'on ne les traite pas.
 * POUR REVENIR EN ARRIÈRE : supprimer ce bloc (les sections reprennent
 * --papier), et remettre « section--claire » sur section-materiel.php.
 * ------------------------------------------------------------ */
.a-header-transparent .section--claire { background: #F5F7F9; }

.section__entete {
	max-width: 46rem;
	margin-bottom: 2.5rem;
}

/*
 * L'en-tête en deux colonnes : le titre à gauche, le chapô à droite. C'est le
 * motif qui structure toute la page d'accueil. Il donne au titre l'espace de
 * respirer, et le chapô ne vient plus l'alourdir juste en dessous.
 */
.section__entete--duo {
	max-width: none;
	display: grid;
	gap: 1.5rem;
	margin-bottom: 3.5rem;
}

.section__entete--duo .section__chapo { max-width: 46ch; }

.section__entete--centre {
	justify-items: center;
	text-align: center;
}

.section__entete--centre .surtitre { justify-content: center; }

/* Au centre, le tiret d'amorce du surtitre déséquilibre : on l'enlève. */
.section__entete--centre .surtitre::before { content: none; }

.section__entete--centre .section__chapo { max-width: 58ch; }

.section__titre { margin-bottom: 0.75rem; }

/* Le grand titre des sections en duo : celui qui porte le propos. */
.section__titre--grand {
	font-size: clamp(1.9rem, 3.6vw, 2.9rem);
	margin-bottom: 1.25rem;
	max-width: 18ch;
}

.section__chapo {
	font-size: 1.1rem;
	color: var(--encre-douce);
	margin: 0;
	max-width: 60ch;
}

.section__actions {
	margin-top: 2.5rem;
}

.section__actions--centre { text-align: center; }

@media (min-width: 900px) {
	.section__entete--duo {
		grid-template-columns: 1.25fr 1fr;
		gap: 4rem;
		align-items: end;
	}

	/* Centré, le chapô repasse sous le titre : deux colonnes centrées ne se
	   lisent pas. */
	.section__entete--centre {
		grid-template-columns: 1fr;
		gap: 1.25rem;
	}

	.section__entete--duo .section__titre {
		font-size: clamp(1.9rem, 3.4vw, 2.75rem);
		max-width: 16ch;
		margin-bottom: 0;
	}

	.section__entete--centre .section__titre {
		max-width: 20ch;
		margin-inline: auto;
	}
}

/* En-tête des pages internes : un cartouche, pas une bannière. */
.entete-page {
	padding-block: 3rem 2.5rem;
	background: var(--papier);
	border-bottom: 1px solid var(--trait);
}

.entete-page__titre { margin-bottom: 0.75rem; }

.entete-page__chapo {
	max-width: 62ch;
	margin: 0;
	font-size: 1.1rem;
	color: var(--encre-douce);
}

.fil-ariane {
	margin-bottom: 1rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--encre-douce);
}

.fil-ariane a {
	color: var(--encre-douce);
	text-decoration: none;
}

.fil-ariane a:hover { color: var(--rouge-texte); }

/* -------------------------------------------------------------------------
   10. BANDEAU CONFIANCE
   Trois faits vérifiables, sur le marine. Pas d'icônes décoratives.
   ---------------------------------------------------------------------- */

/*
 * UN RELEVÉ, PAS UNE LISTE À COCHER.
 *
 * Trois faits, chacun avec sa VALEUR en gros et son libellé en petit. « +10 ans »
 * se retient ; « ✓ +10 ans d'expérience » se lit comme n'importe quel site
 * d'artisan et s'oublie aussitôt. Les filets verticaux qui les séparent sont
 * ceux d'un tableau de relevé — la même grammaire que le reste du site.
 */
.confiance {
	position: relative;
	background: var(--marine);
	color: var(--blanc);
	/* 1,35 rem avant : le bandeau faisait 119 px et se faisait couper en bas
	   des petits écrans. Il en fait ~95 sans rien perdre de lisible. */
	padding-block: 0.9rem;
	border-block: 1px solid var(--marine-ligne);
}

.confiance__liste {
	display: grid;
	gap: 1px;
	margin: 0;
	padding: 0;
	/* Le fond fait office de filet : les cellules le laissent passer d'un pixel. */
	background: var(--marine-ligne);
}

.confiance__item {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.35rem;
	padding: 0.65rem 1.5rem;
	background: var(--marine);
}

/*
 * Les trois valeurs n'ont pas la même longueur (« +10 ans » contre « Paris + 8
 * départements »). On les borne : au-delà, la plus bavarde grossirait la ligne
 * et déséquilibrerait le relevé.
 */
.confiance__valeur {
	font-family: var(--font-titre);
	font-size: clamp(1.3rem, 1.9vw, 1.65rem);
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.02em;
	text-wrap: balance;
	color: var(--blanc);
}

/* Le libellé porte le nœud rouge de la boucle : c'est le même signe que les
   capteurs de la marge technique. */
.confiance__libelle {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin: 0;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.55);
}

.confiance__libelle::before {
	content: '';
	flex: none;
	width: 5px;
	height: 5px;
	background: var(--rouge);
	transform: rotate(45deg);
}

.icone--check { color: var(--rouge); }

/* -------------------------------------------------------------------------
   11. DUO (texte + média)
   ---------------------------------------------------------------------- */

.duo {
	display: grid;
	gap: 2.5rem;
	align-items: center;
}

/*
 * Une colonne de grille refuse par défaut de descendre sous la largeur
 * minimale de son contenu. Une galerie Gutenberg ou un tableau collé dans
 * l'éditeur écarte alors la colonne au-delà de l'écran. On rend la colonne
 * compressible : c'est au contenu de s'adapter, pas à la page de déborder.
 */
.duo > * { min-width: 0; }

.duo__media { position: relative; }

.duo__img {
	width: 100%;
	border-radius: var(--rayon);
}

/*
 * Équerre de cadrage : le coin d'un viseur. On ne l'ajoute qu'au média du duo
 * et aux vignettes de réalisation — c'est le seul ornement du thème.
 */
.duo__media::before,
.duo__media::after {
	content: '';
	position: absolute;
	width: 28px;
	height: 28px;
	border: 1px solid var(--rouge);
	pointer-events: none;
}

.duo__media::before {
	top: -8px;
	left: -8px;
	border-right: 0;
	border-bottom: 0;
}

.duo__media::after {
	right: -8px;
	bottom: -8px;
	border-left: 0;
	border-top: 0;
}

.media-large {
	margin: 0;
	padding-top: 2rem;
}

.media-large__img {
	width: 100%;
	border-radius: var(--rayon);
}

/* -------------------------------------------------------------------------
   12. GRILLES ET CARTES
   ---------------------------------------------------------------------- */

.grille {
	display: grid;
	gap: 1.5rem;
	grid-template-columns: 1fr;
}

.carte {
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--blanc);
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
	/* Indispensable dès que le rayon dépasse quelques pixels : sans ça, la
	   vignette carrée déborderait des angles arrondis de la carte. */
	overflow: hidden;
	transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition);
}

/*
 * Au survol, la bordure passe au ROUGE. Elle virait au marine, ce qui se lisait
 * comme un simple gris foncé : rien ne se passait. Le rouge est la couleur de
 * l'action sur ce site — la carte annonce qu'elle est cliquable, elle ne se
 * contente pas de changer de teinte.
 */
.carte:hover,
.carte:focus-within {
	transform: translateY(-2px);
	border-color: var(--rouge);
	box-shadow: var(--ombre);
}

/* Un filet rouge se tire en haut de la carte au survol : la carte est
   « sélectionnée », comme une ligne dans un relevé. */
.carte::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	z-index: 2;
	width: 0;
	height: 2px;
	background: var(--rouge);
	transition: width var(--transition-lente);
}

.carte:hover::before,
.carte:focus-within::before { width: 100%; }

.carte__lien-bloc {
	display: flex;
	flex-direction: column;
	height: 100%;
	color: inherit;
	text-decoration: none;
}

.carte__media {
	position: relative;
	aspect-ratio: 4 / 3;
	background: var(--marine);
	overflow: hidden;
}

.carte__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var(--transition-lente);
	/* THÈME CLAIR : les visuels de cartes/encarts fournis sont des placeholders
	   navy (bleu incrusté dans le fichier). On les désature pour qu'aucun bleu ne
	   subsiste et qu'ils entrent dans la palette neutre. Les vraies photos futures
	   passeront aussi en niveaux de gris — cohérent avec le charbon. Réversible :
	   retirer ce filtre (ici et sur .encart__img). */
	filter: grayscale(1);
}

.carte:hover .carte__img { transform: scale(1.03); }

/*
 * Vignette sans photo : plutôt qu'un rectangle gris, le fond de plan.
 * Le site doit être beau avant que le client n'ait fourni ses images.
 */
.carte__media--vide {
	background-color: var(--marine);
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
	background-size: 24px 24px;
}

.carte__media--vide::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	width: 18px;
	height: 18px;
	margin: -9px 0 0 -9px;
	border: 1px solid rgba(230, 55, 39, 0.7);
	transform: rotate(45deg);
}

/* Équerres de visée sur la vignette : elles se referment au survol. */
.carte__viseur {
	position: absolute;
	inset: 0;
	pointer-events: none;
	opacity: 0;
	transition: opacity var(--transition);
}

.carte:hover .carte__viseur,
.carte:focus-within .carte__viseur { opacity: 1; }

.carte__viseur::before,
.carte__viseur::after {
	content: '';
	position: absolute;
	width: 20px;
	height: 20px;
	border: 1px solid var(--rouge);
	transition: transform var(--transition-lente);
}

.carte__viseur::before {
	top: 10px;
	left: 10px;
	border-right: 0;
	border-bottom: 0;
	transform: translate(-6px, -6px);
}

.carte__viseur::after {
	right: 10px;
	bottom: 10px;
	border-left: 0;
	border-top: 0;
	transform: translate(6px, 6px);
}

.carte:hover .carte__viseur::before,
.carte:hover .carte__viseur::after,
.carte:focus-within .carte__viseur::before,
.carte:focus-within .carte__viseur::after {
	transform: translate(0, 0);
}

/*
 * L'icône, dans un carré rouge doux. Le rouge de marque n'y est qu'à 10 % : à
 * pleine puissance il ferait concurrence aux boutons, et le rouge du site ne
 * veut dire qu'une chose — « ici, on agit ».
 */
.carte__icone {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin-bottom: 1.5rem;
	color: var(--rouge-texte);
	background: rgba(230, 55, 39, 0.09);
	border-radius: var(--rayon);
	transition: background-color var(--transition), color var(--transition);
}

.carte__picto { width: 24px; height: 24px; }

.carte__icone-img {
	width: 26px;
	height: 26px;
	object-fit: contain;
}

/*
 * LA CARTE PHARE A ÉTÉ RETIRÉE (demande client).
 *
 * Elle mettait la première carte en fond nuit, au motif qu'« une grille où tout
 * a le même poids ne dit rien à personne ». L'argument se défend pour une offre
 * qui a une locomotive ; ici les cinq métiers se vendent, et la carte noire au
 * milieu de quatre blanches se lisait comme une réclame insérée dans la liste
 * plutôt que comme sa première entrée.
 *
 * Le drapeau « phare » de card-service.php reste accepté et ne fait plus rien :
 * archive-service.php le passe encore, et cette archive est désactivée. Le jour
 * où elle revient, elle n'aura pas de carte noire par surprise.
 */

/*
 * TOUTES LES RANGÉES À LA MÊME HAUTEUR.
 *
 * Les cartes s'alignaient déjà entre elles à l'intérieur d'une rangée — c'est
 * le « flex: 1 » de .carte__texte qui pousse le « Voir la solution » en bas.
 * Mais chaque rangée se dimensionne sur SON propre contenu : la première
 * faisait 280 px, la seconde 255, et la grille paraissait bancale d'une ligne
 * à l'autre.
 *
 * « grid-auto-rows: 1fr » aligne toutes les rangées sur la plus haute. Le
 * sélecteur vise les grilles qui contiennent des cartes de service — celle de
 * l'accueil comme celle des pages secteur — sans toucher aux grilles de
 * réalisations ou d'articles, dont les vignettes imposent déjà une hauteur.
 */
.grille:has(> .carte--service) { grid-auto-rows: 1fr; }

/*
 * LA DERNIÈRE RANGÉE SE CENTRE — cinq services sur trois colonnes.
 *
 * Trois cartes, puis deux calées à gauche : la grille avait un trou en bas à
 * droite, et l'ensemble penchait. Les deux dernières se centrent désormais sous
 * les trois premières.
 *
 * COMMENT. Une grille de trois colonnes ne sait pas centrer deux éléments : il
 * faudrait les démarrer à la « colonne 1,5 ». On passe donc à SIX pistes, chaque
 * carte en occupant deux — trois cartes par rangée, exactement comme avant — et
 * la quatrième démarre à la piste 2. Il reste alors une piste vide de chaque
 * côté : le centrage est exact, pas approché.
 *
 * La largeur des cartes ne bouge pas d'un pixel : 2 × (L − 5g)/6 + g se
 * simplifie en (L − 2g)/3, la formule des trois colonnes. Vérifiable au calcul
 * comme à la mesure.
 *
 * Le sélecteur ne se déclenche QUE sur une série de cinq — « quatrième depuis le
 * début ET deuxième depuis la fin ». Les pages secteur, qui affichent deux à
 * cinq services selon le secteur, gardent donc leur disposition normale dès
 * qu'elles n'en ont pas exactement cinq.
 */
/*
 * ⚠️ LES DEUX PALIERS NE SE CHEVAUCHENT PAS, ILS SE SUCCÈDENT — et ce n'est pas
 * un détail de style.
 *
 * Écrire « (min-width: 640px) and (max-width: 899px) » puis « (min-width: 900px) »
 * paraît couvrir tout l'intervalle. C'est faux : une fenêtre peut mesurer
 * 899,33 px — cela arrive au zoom, et sur certains appareils. Les DEUX requêtes
 * sont alors fausses, et la grille retombe sur la règle générale. Mesuré : à
 * 899 px, la dernière carte redevenait seule à gauche.
 *
 * Le second palier n'a donc pas de borne haute : il écrase simplement le
 * premier. Aucun interstice possible.
 */

/* Bande tablette : deux colonnes, donc QUATRE pistes. */
@media (min-width: 640px) {
	.grille--3:has(> .carte--service) {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}

	.grille--3:has(> .carte--service) > * { grid-column: span 2; }

	/*
	 * « dernière ET de rang impair » décrit exactement « seule sur sa rangée »
	 * dans une grille à deux colonnes — quel que soit le nombre de services
	 * rattachés au secteur.
	 */
	.grille--3:has(> .carte--service) > :nth-child(odd):last-child {
		grid-column: 2 / span 2;
	}
}

/* Grand écran : trois colonnes, donc SIX pistes. */
@media (min-width: 900px) {
	.grille--3:has(> .carte--service) {
		grid-template-columns: repeat(6, minmax(0, 1fr));
	}

	/*
	 * On annule d'abord la règle de la bande tablette : à trois colonnes, la
	 * dernière carte d'une série impaire n'est plus forcément seule — sur cinq
	 * services, elles sont deux. La laisser agir décalerait la quatrième.
	 */
	.grille--3:has(> .carte--service) > :nth-child(odd):last-child {
		grid-column: span 2;
	}

	.grille--3:has(> .carte--service) > :nth-child(4):nth-last-child(2) {
		grid-column: 2 / span 2;
	}
}

/* -------------------------------------------------------------------------
   LA CARTE DE SERVICE SUR TÉLÉPHONE

   Cinq cartes verticales, c'était 1 925 px de défilement pour une liste de
   cinq liens : la vignette, le titre, trois lignes d'accroche et un « Voir la
   solution » — empilés cinq fois. Le format vertical vaut quand les cartes
   sont côte à côte et se comparent d'un coup d'œil ; en colonne unique, il ne
   fait qu'allonger.

   Elles passent donc à l'horizontale, sur le modèle des tuiles de secteurs qui
   servent déjà ailleurs : l'icône tient la colonne de gauche sur toute la
   hauteur, le texte occupe le reste. Même contenu, un tiers de la hauteur.
   ---------------------------------------------------------------------- */
@media (max-width: 639px) {
	.carte--service .carte__corps {
		display: grid;
		grid-template-columns: 44px minmax(0, 1fr);
		column-gap: 1rem;
		row-gap: 0.3rem;
		padding: 1.25rem;
	}

	.carte--service .carte__icone {
		grid-column: 1;
		grid-row: span 3;
		align-self: start;
		width: 44px;
		height: 44px;
		margin-bottom: 0;
	}

	.carte--service .carte__picto { width: 21px; height: 21px; }

	.carte--service .carte__titre,
	.carte--service .carte__texte,
	.carte--service .carte__plus { grid-column: 2; }

	.carte--service .carte__titre { margin-bottom: 0; }

	/* « flex: 1 » poussait le « Voir la solution » en bas d'une carte étirée ;
	   en grille, il n'a plus lieu d'être. */
	.carte--service .carte__texte {
		flex: none;
		margin-bottom: 0.35rem;
		font-size: 0.92rem;
	}
}

.carte__corps {
	display: flex;
	flex-direction: column;
	flex: 1;
	padding: 1.75rem;
}

.carte__titre {
	font-size: 1.15rem;
	margin-bottom: 0.6rem;
}

.carte__lien {
	color: var(--marine);
	text-decoration: none;
}

/* Toute la carte devient cliquable, sans imbriquer de liens. */
.carte__lien::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
}

.carte__lien:hover { color: var(--rouge-texte); }

.carte__texte {
	color: var(--encre-douce);
	font-size: 0.98rem;
	margin-bottom: 1.25rem;
	flex: 1;
}

.carte__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	font-family: var(--font-mono);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--encre-douce);
	margin: 0;
}

/*
 * La date d'un article, en rouge. C'est le seul repère utile pour juger de la
 * fraîcheur d'un conseil — autant qu'il se voie.
 */
.carte__date {
	margin: 0 0 0.85rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--rouge-texte);
}

/* Les puces d'un chantier : où, et quand. */
.carte__puces {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin: 0 0 0.85rem;
}

.puce {
	display: inline-flex;
	align-items: center;
	padding: 0.25rem 0.6rem;
	font-family: var(--font-mono);
	font-size: 0.68rem;
	font-weight: 500;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--encre-douce);
	background: var(--papier);
	border-radius: var(--rayon-sm);
}

.section--claire .puce { background: var(--blanc); }

.puce--annee {
	color: var(--rouge-texte);
	background: rgba(230, 55, 39, 0.08);
}

/* Le lien « en savoir plus » est un signe, pas une phrase. */
.carte__plus {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 0.85rem;
	letter-spacing: 0.02em;
	color: var(--rouge-texte);
}

.carte__plus svg { transition: transform var(--transition); }

.carte:hover .carte__plus svg { transform: translateX(4px); }

/* Carte de secteur : pas de photo, une icône. Le secteur est une catégorie de
   terrain, pas un produit à montrer. */
.secteur__icone {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	margin-bottom: 1.25rem;
	color: var(--rouge-texte);
	background: var(--papier);
	border-radius: var(--rayon);
	transition: background-color var(--transition), color var(--transition);
}

.section--claire .secteur__icone { background: var(--blanc); }

.carte--secteur:hover .secteur__icone {
	background: var(--marine);
	color: var(--blanc);
}

.secteur__picto { width: 26px; height: 26px; }

.secteurs__texte { margin-top: 3.5rem; max-width: var(--largeur-etroite); }

/* Étiquette de prestation, posée SUR la vignette : c'est la première chose
   qu'on doit savoir d'un chantier — ce qu'on y a installé. */
.etiquette {
	position: absolute;
	left: 0.85rem;
	top: 0.85rem;
	z-index: 1;
	padding: 0.35rem 0.7rem;
	background: rgba(17, 17, 17, 0.9);
	backdrop-filter: blur(4px);
	color: var(--blanc);
	font-family: var(--font-mono);
	font-size: 0.68rem;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border-radius: var(--rayon-sm);
}

/* -------------------------------------------------------------------------
   12 bis. LES SECTIONS DE L'ACCUEIL

   Les motifs repris de la maquette : tuiles de secteurs, méthode numérotée,
   points forts du matériel, FAQ en accordéon, liens réseaux. Tous adaptés à la
   grammaire du site — charbon et rouge, Inter et Plex Mono, le trait technique.
   ---------------------------------------------------------------------- */

/* --- Les points forts du matériel --- */

.atouts {
	display: grid;
	gap: 1.5rem;
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
}

.atout {
	display: flex;
	align-items: flex-start;
	gap: 0.7rem;
}

.atout .icone {
	flex: none;
	margin-top: 0.25rem;
	color: var(--rouge);
}

.atout__titre {
	display: block;
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 1rem;
	color: var(--marine);
}

.atout__texte {
	display: block;
	margin-top: 0.15rem;
	font-size: 0.9rem;
	line-height: 1.5;
	color: var(--encre-douce);
}

/* --- Les tuiles de secteurs --- */

.grille-secteurs {
	display: grid;
	gap: 1rem;
	grid-template-columns: 1fr;
}

/*
 * CARROUSEL DES SECTEURS SUR TÉLÉPHONE.
 *
 * Douze tuiles empilées, c'est environ 1 500 px de défilement pour une section
 * qui n'est qu'un aiguillage — on scrollait à travers les secteurs au lieu de
 * les parcourir. Elles passent donc à l'horizontale, sur deux rangées : six
 * gestes au lieu de douze, et la section retombe à ~240 px de haut.
 *
 * Aucun JavaScript : scroll-snap fait le travail, et le geste est celui que le
 * téléphone connaît déjà. La tuile occupe 78 % de la largeur pour que la
 * suivante dépasse — c'est ce bout de carte qui dit qu'il y en a d'autres.
 *
 * Le débord négatif annule les marges du conteneur : la piste file d'un bord à
 * l'autre de l'écran, et le padding la remet en place à l'arrêt. Elle a son
 * propre overflow, donc elle ne fait pas glisser la page.
 */
/*
 * Les flèches de la piste. Même rond de 44 px que le héros, mais à l'encre :
 * la section est claire, le contour blanc du héros y serait invisible.
 *
 * Elles ne sont montrées que là où la piste défile — le script les dévoile
 * (§ 10 de main.js), la media query les remet sous clé au-delà du carrousel.
 * Un bouton visible qui ne fait rien est pire que pas de bouton.
 */
.secteurs-nav { display: none; }

@media (max-width: 639px) {
	.secteurs-nav:not([hidden]) {
		display: flex;
		justify-content: flex-end;
		gap: 0.5rem;
		margin-bottom: 1rem;
	}

	.secteurs-nav__fleche {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		flex: none;
		width: 44px;
		height: 44px;
		padding: 0;
		color: var(--marine);
		background: var(--blanc);
		border: 1px solid var(--trait);
		border-radius: 50%;
		cursor: pointer;
		transition: color var(--transition), border-color var(--transition), opacity var(--transition);
	}

	.secteurs-nav__fleche:hover,
	.secteurs-nav__fleche:focus-visible {
		color: var(--rouge-texte);
		border-color: var(--rouge);
	}

	/*
	 * En bout de piste, la flèche s'éteint sans disparaître : elle garde sa
	 * place, donc l'autre ne saute pas d'un cran quand on arrive au bout.
	 * « disabled » plutôt qu'un masquage : le lecteur d'écran l'annonce, et le
	 * clavier passe son tour.
	 */
	.secteurs-nav__fleche[disabled] {
		opacity: 0.3;
		cursor: default;
	}

	.grille-secteurs {
		grid-template-columns: none;
		grid-template-rows: repeat(2, auto);
		grid-auto-flow: column;
		grid-auto-columns: 78%;
		gap: 0.75rem;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x mandatory;
		scroll-padding-left: calc(var(--gouttiere) + var(--piste-l));
		margin-left: calc((var(--gouttiere) + var(--piste-l)) * -1);
		margin-right: calc(var(--gouttiere) * -1);
		padding-left: calc(var(--gouttiere) + var(--piste-l));
		padding-right: var(--gouttiere);
		padding-bottom: 0.25rem;
		/* La barre de défilement native ferait un trait gris sous la section :
		   le dépassement de la tuile suivante suffit à dire qu'on peut glisser. */
		scrollbar-width: none;
	}

	.grille-secteurs::-webkit-scrollbar { display: none; }

	.grille-secteurs .tuile {
		scroll-snap-align: start;
		/* Sans cette hauteur, deux tuiles de la même colonne se calent sur des
		   hauteurs différentes et la deuxième rangée ondule d'un cran à l'autre. */
		height: 100%;
	}
}

.tuile {
	position: relative;
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: 1.25rem;
	background: var(--blanc);
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
	text-decoration: none;
	transition: border-color var(--transition), transform var(--transition), box-shadow var(--transition);
}

.tuile:hover,
.tuile:focus-visible {
	transform: translateY(-2px);
	border-color: var(--rouge);
	box-shadow: var(--ombre);
}

.tuile__icone {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 44px;
	height: 44px;
	color: var(--rouge-texte);
	background: rgba(230, 55, 39, 0.09);
	border-radius: var(--rayon);
	transition: background-color var(--transition), color var(--transition);
}

.tuile:hover .tuile__icone {
	color: var(--blanc);
	background: var(--rouge-cta);
}

.tuile__icone .secteur__picto { width: 22px; height: 22px; }

.tuile__corps {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	min-width: 0;
	flex: 1;
}

.tuile__titre {
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 1rem;
	color: var(--marine);
}

/*
 * L'accroche est bornée à deux lignes : sans ça, une tuile bavarde déforme
 * toute la rangée, et la grille perd son alignement.
 */
.tuile__texte {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-size: 0.85rem;
	line-height: 1.45;
	color: var(--encre-douce);
}

.tuile__fleche {
	flex: none;
	color: var(--encre-douce);
	transition: transform var(--transition), color var(--transition);
}

.tuile:hover .tuile__fleche {
	transform: translateX(3px);
	color: var(--rouge-texte);
}

/* --- La méthode --- */

/*
 * LA MÉTHODE EST LA BOUCLE.
 *
 * Les cinq étapes sont posées sur le même filet rouge pointillé qui descend
 * toute la page, chacune sur son nœud. Le site raconte qu'on trace un périmètre
 * avant de le protéger : c'est ici que ce propos devient littéral.
 *
 * Fond nuit : après quatre sections claires d'affilée, la page a besoin d'un
 * point d'ancrage. Et c'est le seul endroit du site où l'on numérote — ici
 * l'ordre dit quelque chose de vrai.
 */
.methode-section {
	position: relative;
	background: var(--nuit);
	color: rgba(255, 255, 255, 0.72);
	overflow: hidden;
	--fond-noeud: var(--nuit);
}

.methode-section__grille {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
	background-size: 64px 64px;
	-webkit-mask-image: radial-gradient(120% 100% at 15% 0%, #000 0%, transparent 75%);
	mask-image: radial-gradient(120% 100% at 15% 0%, #000 0%, transparent 75%);
}

.methode-section__inner {
	position: relative;
	z-index: 1;
}

.methode-section .section__titre { color: var(--blanc); }

.methode-section .section__chapo { color: rgba(255, 255, 255, 0.72); }

.methode {
	display: grid;
	gap: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}

.methode__etape {
	position: relative;
	padding: 0 0 2.5rem 2.25rem;
}

.methode__etape:last-child { padding-bottom: 0; }

/*
 * Le filet. En colonne (mobile) il descend le long des étapes ; en rangée
 * (desktop) il les traverse. C'est le même pointillé que la boucle du site.
 */
.methode__etape::before {
	content: '';
	position: absolute;
	top: 5px;
	bottom: 0;
	left: 4px;
	width: 1px;
	background: repeating-linear-gradient(180deg, var(--rouge) 0 5px, transparent 5px 11px);
	opacity: 0.4;
}

.methode__etape:last-child::before { content: none; }

/* Le nœud : le même capteur que celui de la marge technique. */
.methode__noeud {
	position: absolute;
	top: 0;
	left: 0;
	width: 9px;
	height: 9px;
	border: 1px solid var(--rouge);
	background: var(--rouge);
	box-shadow: 0 0 0 5px var(--rouge-voile);
	transform: rotate(45deg);
	transition: box-shadow var(--transition-lente);
}

.methode__etape:hover .methode__noeud { box-shadow: 0 0 0 9px var(--rouge-voile); }

.methode__numero {
	display: block;
	margin-bottom: 0.5rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.14em;
	color: var(--rouge);
}

.methode__titre {
	font-size: 1.1rem;
	margin-bottom: 0.5rem;
	color: var(--blanc);
}

.methode__texte {
	margin: 0;
	font-size: 0.92rem;
	line-height: 1.55;
	color: rgba(255, 255, 255, 0.6);
}

/* --- La FAQ --- */

.faq {
	border-top: 1px solid var(--trait);
}

.faq__item { border-bottom: 1px solid var(--trait); }

/*
 * <details>/<summary> natifs : ouverture, fermeture, clavier et lecteurs
 * d'écran sont gérés par le navigateur. Pas une ligne de JavaScript.
 */
.faq__question {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 1.35rem 0;
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 1.02rem;
	color: var(--marine);
	cursor: pointer;
	list-style: none;
	transition: color var(--transition);
}

/* Le triangle par défaut du navigateur : on le retire, on met notre signe. */
.faq__question::-webkit-details-marker { display: none; }
.faq__question::marker { content: ''; }

.faq__question:hover { color: var(--rouge-texte); }

.faq__signe {
	position: relative;
	flex: none;
	width: 26px;
	height: 26px;
	border-radius: var(--rayon);
	background: rgba(230, 55, 39, 0.09);
	transition: background-color var(--transition);
}

/* Le « + » qui devient « × » : deux traits, l'un pivote. */
.faq__signe::before,
.faq__signe::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	width: 11px;
	height: 1.5px;
	margin: -0.75px 0 0 -5.5px;
	background: var(--rouge-texte);
	transition: transform var(--transition);
}

.faq__signe::after { transform: rotate(90deg); }

.faq__item[open] .faq__signe { background: var(--rouge-cta); }

.faq__item[open] .faq__signe::before,
.faq__item[open] .faq__signe::after { background: var(--blanc); }

.faq__item[open] .faq__signe::before { transform: rotate(45deg); }
.faq__item[open] .faq__signe::after { transform: rotate(-45deg); }

.faq__reponse {
	margin: 0;
	padding: 0 3rem 1.5rem 0;
	color: var(--encre-douce);
	animation: faq-ouvre 0.3s ease both;
}

@keyframes faq-ouvre {
	from { opacity: 0; transform: translateY(-4px); }
	to { opacity: 1; transform: translateY(0); }
}

/* --- Le lien-flèche, plus léger qu'un bouton --- */

.lien-fleche {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 0.95rem;
	color: var(--rouge-texte);
	text-decoration: none;
}

.lien-fleche svg { transition: transform var(--transition); }

.lien-fleche:hover svg { transform: translateX(4px); }

.duo__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
	margin: 2rem 0 0;
}

/* -------------------------------------------------------------------------
   13. FILTRES (archive des réalisations)
   ---------------------------------------------------------------------- */

.filtres {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 2.5rem;
}

.filtres__item {
	padding: 0.5rem 1rem;
	font-family: var(--font-mono);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--encre-douce);
	text-decoration: none;
	background: transparent;
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
	cursor: pointer;
	transition: background-color var(--transition), color var(--transition), border-color var(--transition);
}

.filtres__item:hover {
	border-color: var(--marine);
	color: var(--marine);
}

.filtres__item.est-actif {
	background: var(--marine);
	border-color: var(--marine);
	color: var(--blanc);
}

/* -------------------------------------------------------------------------
   14. ENCARTS ET LISTES
   ---------------------------------------------------------------------- */

.encart {
	padding: 1.75rem;
	background: var(--papier);
	border-radius: var(--rayon);
	border-left: 2px solid var(--rouge);
}

.section--claire .encart {
	background: var(--blanc);
	border: 1px solid var(--trait);
	border-left: 2px solid var(--rouge);
}

.encart__titre {
	font-size: 1.05rem;
	margin-bottom: 1rem;
}

.encart__media { margin-top: 1.5rem; }

.encart__img { border-radius: var(--rayon-sm); filter: grayscale(1); } /* THÈME CLAIR : neutralise le placeholder navy (cf. .carte__img). */

/* Liste à puces « check » — alimentée par une textarea, une ligne = une puce. */
.liste-check {
	margin: 0;
	padding: 0;
	list-style: none;
}

.liste-check li {
	position: relative;
	padding-left: 1.75rem;
	margin-bottom: 0.7rem;
}

.liste-check li::before {
	content: '';
	position: absolute;
	left: 0;
	top: 0.45em;
	width: 10px;
	height: 6px;
	border-left: 2px solid var(--rouge);
	border-bottom: 2px solid var(--rouge);
	transform: rotate(-45deg);
}

.liste-check--grande li {
	font-size: 1.05rem;
	margin-bottom: 1rem;
}

/* Fiche technique (réalisation) : un tableau de relevé. */
.fiche {
	margin: 0;
	border-top: 1px solid var(--trait);
}

/* Sur les très petits écrans, la valeur passe sous son libellé plutôt que de
   pousser la ligne hors de la fiche : « Copropriété — Saint-Maur-des-Fossés »
   ne tient pas à côté de « LIEU » en 320 px. */
.fiche__ligne {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: baseline;
	gap: 0.25rem 1rem;
	padding: 0.75rem 0;
	border-bottom: 1px solid var(--trait);
}

.fiche dt {
	flex: none;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--encre-douce);
}

.fiche dd {
	margin: 0;
	min-width: 0;
	overflow-wrap: break-word;
	text-align: right;
	font-family: var(--font-titre);
	font-weight: 600;
	color: var(--marine);
}

/* Chiffres clés (page À propos). */
.chiffres__liste {
	display: grid;
	gap: 1px;
	margin: 0;
	padding: 0;
	list-style: none;
	background: var(--marine-ligne);
	border: 1px solid var(--marine-ligne);
	border-radius: var(--rayon);
	overflow: hidden;
}

.chiffres__item {
	padding: 2.25rem 1.5rem;
	background: var(--marine);
	color: var(--blanc);
}

.chiffres__valeur {
	display: block;
	font-family: var(--font-titre);
	font-size: 3rem;
	font-weight: 700;
	line-height: 1;
	letter-spacing: -0.04em;
	color: var(--blanc);
}

.chiffres__libelle {
	display: block;
	margin-top: 0.75rem;
	font-family: var(--font-mono);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.7);
}

/* -------------------------------------------------------------------------
   15. BANDEAU CTA — LA FERMETURE DE LA BOUCLE
   ---------------------------------------------------------------------- */

.bandeau-cta {
	position: relative;
	padding-block: 4.5rem;
	background: var(--fond-bandeau);
	color: var(--blanc);
	overflow: hidden;
	--fond-noeud: var(--fond-bandeau);
}

.bandeau-cta__inner {
	position: relative;
	z-index: 1;
	display: grid;
	gap: 2rem;
	align-items: center;
}

.bandeau-cta__titre {
	color: var(--blanc);
	margin-bottom: 0.75rem;
}

.bandeau-cta__sous-titre {
	margin: 0;
	max-width: 52ch;
	color: rgba(255, 255, 255, 0.75);
}

.bandeau-cta__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
}

/* -------------------------------------------------------------------------
   16. CONTENU RÉDACTIONNEL (Gutenberg)
   ---------------------------------------------------------------------- */

.prose > *:first-child { margin-top: 0; }
.prose > *:last-child { margin-bottom: 0; }

/* Corps « relevé » (services + secteurs) : lecture aérée, le texte tient la
   hauteur de la colonne latérale (points clés). */
.duo--inverse .duo__texte.prose p { line-height: 1.8; margin-bottom: 1.85rem; }

.prose h2 { margin-top: 2.75rem; }
.prose h3 { margin-top: 2rem; }

.prose img,
.prose figure { border-radius: var(--rayon); }

.prose figure { margin: 2rem 0; }

.prose blockquote {
	margin: 2rem 0;
	padding: 0.5rem 0 0.5rem 1.5rem;
	border-left: 2px solid var(--rouge);
	background: transparent;
	font-family: var(--font-titre);
	font-size: 1.2rem;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: -0.01em;
	color: var(--marine);
}

.prose blockquote p:last-child { margin-bottom: 0; }

.prose a { color: var(--rouge-texte); }

/* Galerie native de Gutenberg = galerie photos des réalisations. */
.prose .wp-block-gallery img { border-radius: var(--rayon-sm); }

/*
 * Garde-fous du contenu éditorial. Ici le HTML vient de l'éditeur, pas du
 * thème : on ne maîtrise ni la longueur des mots (URL collée, référence
 * produit), ni la largeur des tableaux, ni les embarqués. Ces trois règles
 * garantissent qu'aucun article ne pourra faire déborder la page en mobile.
 */
.prose { overflow-wrap: break-word; }

.prose iframe,
.prose embed,
.prose object,
.prose video { max-width: 100%; }

/* Le tableau reste lisible : il défile dans sa propre boîte au lieu d'élargir
   la page. Le contour rappelle qu'il y a quelque chose à faire glisser. */
.prose table {
	display: block;
	width: fit-content;
	max-width: 100%;
	overflow-x: auto;
	border-collapse: collapse;
}

.prose :is(th, td) {
	padding: 0.6rem 0.9rem;
	border: 1px solid var(--trait);
	text-align: left;
}

/* -------------------------------------------------------------------------
   17. FORMULAIRES
   ---------------------------------------------------------------------- */

.formulaire__grille {
	display: grid;
	gap: 1.25rem;
	margin-bottom: 1.5rem;
}

.champ { margin: 0; }

.champ label {
	display: block;
	margin-bottom: 0.4rem;
	font-family: var(--font-mono);
	font-weight: 500;
	font-size: 0.72rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--encre-douce);
}

.champ input,
.champ select,
.champ textarea {
	width: 100%;
	padding: 0.75rem 0.9rem;
	font-family: var(--font-corps);
	font-size: 1rem;
	color: var(--encre);
	background: var(--blanc);
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
	transition: border-color var(--transition), box-shadow var(--transition);
}

.champ input:hover,
.champ select:hover,
.champ textarea:hover { border-color: var(--encre-douce); }

.champ input:focus,
.champ select:focus,
.champ textarea:focus {
	border-color: var(--marine);
	outline: 2px solid var(--rouge);
	outline-offset: 1px;
}

.champ textarea { resize: vertical; }

/* Case à cocher RGPD. */
.champ--case {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
}

.champ--case input {
	width: auto;
	margin-top: 0.3rem;
	flex: none;
	accent-color: var(--rouge-cta);
}

.champ--case label {
	margin: 0;
	font-family: var(--font-corps);
	font-weight: 400;
	font-size: 0.9rem;
	line-height: 1.5;
	letter-spacing: 0;
	text-transform: none;
	color: var(--encre-douce);
}

.requis { color: var(--rouge-texte); }

.formulaire__actions { margin: 0 0 0.75rem; }

.formulaire__mention {
	margin: 0;
	font-size: 0.85rem;
	color: var(--encre-douce);
}

/* -------------------------------------------------------------------------
   LE BADGE reCAPTCHA ET SA MENTION

   Google affiche par défaut un badge flottant en bas à droite. Ici, il se
   superposait à la barre d'action fixe du mobile — deux éléments flottants
   dans le même coin, dont l'un recouvrait « Demander un devis ».

   Les conditions de Google autorisent à le masquer, à une condition qu'elles
   énoncent explicitement : afficher à la place, dans le parcours, un texte
   renvoyant à leur politique de confidentialité ET à leurs conditions
   d'utilisation. C'est ce que fait besafe_captcha_mention(), sous chaque
   formulaire. Masquer le badge sans cette mention violerait les conditions.

   ⚠️ NE PAS SUPPRIMER L'UN SANS L'AUTRE. Retirer la mention oblige à
   réafficher le badge, et inversement.
   ---------------------------------------------------------------------- */
.grecaptcha-badge {
	visibility: hidden;
}

.formulaire__mention--captcha {
	margin-top: 0.5rem;
	font-size: 0.78rem;
	line-height: 1.5;
	opacity: 0.85;
}

.formulaire__mention--captcha a { color: inherit; }

.formulaire__mention--captcha a:hover,
.formulaire__mention--captcha a:focus-visible { color: var(--rouge-texte); }

/* Le formulaire de rappel et celui du diagnostic vivent sur fond sombre. */
.formulaire--rappel .formulaire__mention--captcha,
.diag .formulaire__mention--captcha {
	color: rgba(255, 255, 255, 0.55);
}

.formulaire__intro {
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 1.1rem;
	color: var(--blanc);
	margin-bottom: 1.25rem;
}

/* Le mini-formulaire de rappel vit sur fond marine (panneau de l'en-tête). */
.formulaire--rappel .champ label { color: rgba(255, 255, 255, 0.7); }
.formulaire--rappel .champ--case label { color: rgba(255, 255, 255, 0.75); }
.formulaire--rappel .champ--case label a { color: var(--blanc); }
.formulaire--rappel .formulaire__mention { color: rgba(255, 255, 255, 0.6); }

.formulaire--rappel .champ input,
.formulaire--rappel .champ select {
	background: var(--nuit);
	border-color: rgba(255, 255, 255, 0.2);
	color: var(--blanc);
}

.formulaire--rappel .champ input:hover,
.formulaire--rappel .champ select:hover { border-color: rgba(255, 255, 255, 0.45); }

.formulaire--rappel .formulaire__grille { grid-template-columns: 1fr; }

/* Messages de retour. */
.message {
	padding: 1rem 1.25rem;
	margin-bottom: 1.5rem;
	border-radius: var(--rayon);
	border-left: 3px solid;
	font-size: 0.98rem;
}

.message--succes {
	background: #E8F5EC;
	border-color: #1E7A43;
	color: #14532B;
}

.message--erreur {
	background: #FDECEE;
	border-color: var(--rouge-cta);
	color: #8C1520;
}

.message ul { margin: 0; padding-left: 1.2rem; }

/* -------------------------------------------------------------------------
   18. COORDONNÉES (page Contact)
   ---------------------------------------------------------------------- */

.coordonnees {
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid var(--trait);
}

.coordonnees li {
	padding: 1rem 0;
	border-bottom: 1px solid var(--trait);
}

.coordonnees__label {
	display: block;
	margin-bottom: 0.2rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	color: var(--encre-douce);
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.coordonnees__valeur {
	display: block;
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 1.05rem;
	color: var(--marine);
	text-decoration: none;
}

/* Une action, pas un numéro. Le numéro reste dans le lien tel:. */
.coordonnees__tel {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	font-size: 1.15rem;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--rouge-texte);
}

.coordonnees__tel:hover { color: var(--marine); }

/* -------------------------------------------------------------------------
   19. CARTE GOOGLE MAPS (chargée uniquement après consentement)
   ---------------------------------------------------------------------- */

.plan {
	position: relative;
	min-height: 320px;
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: var(--marine);
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
	background-size: 32px 32px;
	border-radius: var(--rayon);
	overflow: hidden;
}

.plan__consentement {
	padding: 2rem;
	text-align: center;
	max-width: 460px;
}

.plan__message {
	color: rgba(255, 255, 255, 0.85);
	margin-bottom: 1.25rem;
	font-size: 0.95rem;
}

.plan iframe {
	width: 100%;
	min-height: 420px;
	border: 0;
	display: block;
}

/* -------------------------------------------------------------------------
   20. BLOG
   ---------------------------------------------------------------------- */

.article__meta {
	font-family: var(--font-mono);
	color: var(--encre-douce);
	font-size: 0.75rem;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	margin: 0;
}

.article__separateur { margin-inline: 0.5rem; }

.navigation-article { padding-block: 2rem 3rem; }

.navigation-article .nav-links {
	display: grid;
	gap: 1rem;
}

.navigation-article a {
	display: block;
	padding: 1.25rem 1.5rem;
	background: var(--papier);
	border: 1px solid transparent;
	border-radius: var(--rayon);
	text-decoration: none;
	transition: border-color var(--transition), background-color var(--transition);
}

.navigation-article a:hover {
	background: var(--blanc);
	border-color: var(--marine);
}

.navigation-article__label {
	display: block;
	margin-bottom: 0.25rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	color: var(--encre-douce);
	text-transform: uppercase;
	letter-spacing: 0.1em;
}

.navigation-article__titre {
	display: block;
	font-family: var(--font-titre);
	font-weight: 600;
	color: var(--marine);
}

/* Pagination des archives. */
.pagination { margin-top: 3.5rem; }

.pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.4rem;
}

.pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 42px;
	height: 42px;
	padding-inline: 0.6rem;
	font-family: var(--font-mono);
	font-size: 0.85rem;
	font-weight: 500;
	color: var(--marine);
	text-decoration: none;
	background: transparent;
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
	transition: border-color var(--transition), background-color var(--transition);
}

.pagination .page-numbers:hover { border-color: var(--marine); }

.pagination .page-numbers.current {
	background: var(--marine);
	border-color: var(--marine);
	color: var(--blanc);
}

/* -------------------------------------------------------------------------
   21. COMMENTAIRES
   ---------------------------------------------------------------------- */

.commentaires { padding-block: 2rem 3rem; }

.commentaires__liste {
	margin: 0 0 2rem;
	padding: 0;
	list-style: none;
}

.commentaires__liste .children {
	list-style: none;
	padding-left: 1.5rem;
}

.commentaires__liste li {
	padding: 1.25rem 0;
	border-bottom: 1px solid var(--trait);
}

.comment-form { display: grid; gap: 1rem; }

.comment-form input[type="text"],
.comment-form input[type="email"],
.comment-form input[type="url"],
.comment-form textarea {
	width: 100%;
	padding: 0.75rem 0.9rem;
	font-family: var(--font-corps);
	font-size: 1rem;
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
}

/* -------------------------------------------------------------------------
   22. RECHERCHE ET 404
   ---------------------------------------------------------------------- */

.recherche {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	max-width: 520px;
}

/* Le champ garde une largeur utile mais accepte de rétrécir : sans min-width,
   la taille par défaut d'un input (20 caractères) pousse le bouton hors écran
   sur les petits mobiles. En dessous de ~19rem il passe à la ligne. */
.recherche__champ {
	flex: 1 1 12rem;
	min-width: 0;
	padding: 0.75rem 0.9rem;
	font-family: var(--font-corps);
	font-size: 1rem;
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
}

.recherche-repli { margin-block: 2rem; }

/* Le 404 parle le langage du site : un point du plan qui n'existe pas. */
.erreur-404__code {
	font-family: var(--font-mono);
	font-size: clamp(3rem, 12vw, 6rem);
	font-weight: 500;
	line-height: 1;
	letter-spacing: 0.02em;
	color: var(--trait);
	margin: 0 0 1rem;
}

.section--404 { padding-block: 4rem 5rem; }

/* -------------------------------------------------------------------------
   23. PIED DE PAGE
   ---------------------------------------------------------------------- */

.pied {
	background: var(--fond-pied);
	color: rgba(255, 255, 255, 0.72);
	padding-top: 4rem;
	/*
	 * Le pied porte la réserve de la barre d'action fixe du mobile (le body la
	 * portait avant : voir le commentaire là-bas). Il la peint donc de sa
	 * propre couleur, et la jonction avec la barre ne peut plus laisser filtrer
	 * de blanc. Au-delà de 900 px la barre n'existe pas et la variable est
	 * remise à zéro — le pied retrouve son padding normal.
	 */
	padding-bottom: var(--barre-action-hauteur);
	font-size: 0.95rem;
}

.pied__grille {
	display: grid;
	gap: 2.5rem;
	padding-bottom: 3rem;
}

.pied__logo { display: inline-block; margin-bottom: 1rem; }

.pied .site-logo__img {
	max-height: 96px;
	/* Logo ENTIÈREMENT blanc dans le pied (demande client) : on aplatit toute la
	   marque — y compris le pouls rouge — en une silhouette blanche pleine. */
	filter: brightness(0) invert(1);
}

.pied__baseline {
	margin: 0 0 1.25rem;
	max-width: 32ch;
}

.pied__titre {
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	color: rgba(255, 255, 255, 0.5);
	text-transform: uppercase;
	letter-spacing: 0.12em;
	margin-bottom: 1.25rem;
	padding-bottom: 0.75rem;
	border-bottom: 1px solid var(--marine-ligne);
}

.pied__liste {
	margin: 0;
	padding: 0;
	list-style: none;
}

.pied__liste li { margin-bottom: 0.6rem; }

/*
 * LE VOLET DES SECTEURS RESTANTS.
 *
 * Six secteurs sont visibles, les six autres attendent ici. Le <summary> doit
 * se lire comme une action, pas comme un titre de liste : c'est pour cela qu'il
 * porte le rouge de l'action et un chevron qui pivote — sans quoi on le prend
 * pour un intertitre et on ne clique jamais.
 */
.pied__volet { margin-top: 0.35rem; }

.pied__volet-bouton {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.35rem 0;
	font-size: 0.9rem;
	color: var(--rouge);
	cursor: pointer;
	/* Retire le triangle natif : on pose le nôtre, orientable. */
	list-style: none;
}

.pied__volet-bouton::-webkit-details-marker { display: none; }

.pied__volet-bouton::after {
	content: '';
	width: 7px;
	height: 7px;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg) translate(-2px, -2px);
	transition: transform var(--transition);
}

.pied__volet[open] .pied__volet-bouton::after {
	transform: rotate(-135deg) translate(-1px, -1px);
}

.pied__volet-bouton:hover { color: var(--blanc); }

/*
 * Un seul des deux libellés à la fois : « Voir les N autres » quand le volet
 * est fermé, « Réduire la liste » quand il est ouvert. La ligne ne coûte donc
 * jamais rien — elle sert toujours à quelque chose.
 */
.pied__volet-fermer,
.pied__volet[open] .pied__volet-ouvrir { display: none; }
.pied__volet[open] .pied__volet-fermer { display: inline; }

.pied__liste--volet { margin-top: 0.5rem; }

.pied__liste a,
.pied a {
	color: rgba(255, 255, 255, 0.72);
	text-decoration: none;
	transition: color var(--transition);
}

.pied__liste a:hover,
.pied a:hover { color: var(--rouge); }

/* Un appel à l'action, pas un numéro à recopier. */
.pied__tel {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: 0.35rem;
	font-family: var(--font-titre);
	font-size: 1.05rem;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--blanc) !important;
}

.pied__tel .icone { color: var(--rouge); }

.pied__tel:hover { color: var(--rouge) !important; }

.pied__reseaux {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Une pastille filaire, comme les flèches du carrousel : le pied de page n'a que
   du trait, un logo officiel plein y ferait une tache. */
.pied__reseau {
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border: 1px solid var(--marine-ligne);
	border-radius: var(--rayon);
	color: rgba(255, 255, 255, 0.72) !important;
	transition: color var(--transition), border-color var(--transition), background-color var(--transition), transform var(--transition);
}

.pied__reseau:hover,
.pied__reseau:focus-visible {
	border-color: var(--rouge);
	background-color: rgba(230, 55, 39, 0.1);
	color: var(--blanc) !important;
	transform: translateY(-2px);
}

/*
 * Réseaux sociaux : vrais logos officiels pleins (markup SVG dans footer.php),
 * chacun à ses couleurs de marque. La pastille devient un simple support : on
 * atténue son cadre au repos et on la relève au survol, sans teinter le logo.
 */
.pied__reseau[title="Facebook"],
.pied__reseau[title="LinkedIn"],
.pied__reseau[title="Instagram"] { border-color: transparent; }

.pied__reseau[title="Facebook"]:hover,
.pied__reseau[title="Facebook"]:focus-visible,
.pied__reseau[title="LinkedIn"]:hover,
.pied__reseau[title="LinkedIn"]:focus-visible,
.pied__reseau[title="Instagram"]:hover,
.pied__reseau[title="Instagram"]:focus-visible {
	border-color: rgba(255, 255, 255, 0.18);
	background-color: rgba(255, 255, 255, 0.06);
}

.pied__bas {
	border-top: 1px solid var(--marine-ligne);
	padding-block: 1.5rem;
}

.pied__bas-inner {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	align-items: center;
	text-align: center;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	letter-spacing: 0.05em;
	color: rgba(255, 255, 255, 0.5);
}

.pied__copyright { margin: 0; }

.pied__legal {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 1.25rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.pied__legal a { color: rgba(255, 255, 255, 0.5); }

/* -------------------------------------------------------------------------
   24. LE PRÉ-DIAGNOSTIC GUIDÉ

   Un formulaire en quatre questions, posé sur le bleu nuit, avec LE PLAN QUI SE
   DESSINE à côté au fil des réponses. C'est le seul endroit du site où l'on
   s'autorise ce niveau d'effet : c'est là que tout se joue.

   Sans JavaScript, les quatre étapes s'empilent et le formulaire s'envoie
   normalement. Tout ce qui suit et qui dépend de « est-guide » ne s'applique
   qu'une fois le JS en place.
   ---------------------------------------------------------------------- */

/*
 * La première question doit être visible d'entrée : on ne fait pas défiler
 * quelqu'un avant de lui demander quoi que ce soit. D'où le peu d'air en haut.
 *
 * ⚠️ PAS d'overflow: hidden ici. Un ancêtre qui rogne devient le conteneur de
 * défilement de tout élément sticky qu'il contient : le plan, à droite, ne
 * collerait plus au viewport et se retrouverait décalé vers le bas de la valeur
 * de son « top ». Le fond quadrillé est en inset: 0, il ne peut pas déborder :
 * rien à rogner.
 */
.diag {
	position: relative;
	padding-block: 2.5rem 4rem;
	background: var(--nuit);
	color: var(--blanc);
}

/* Papier millimétré, comme le héros : on est sur un plan. */
.diag::before {
	content: '';
	position: absolute;
	inset: 0;
	pointer-events: none;
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
	background-size: 64px 64px;
	-webkit-mask-image: radial-gradient(120% 100% at 10% 0%, #000 0%, transparent 75%);
	mask-image: radial-gradient(120% 100% at 10% 0%, #000 0%, transparent 75%);
}

.diag__inner {
	position: relative;
	z-index: 1;
	display: grid;
	gap: 3rem;
	align-items: start;
}

/* --- Amorce --- */

/* Volontairement plus sobre que le titre du héros : ici, la vedette c'est la
   question, pas le titre de la page. */
.diag__titre {
	margin-bottom: 0.6rem;
	font-size: clamp(1.7rem, 2.8vw, 2.2rem);
	color: var(--blanc);
}

.diag__baseline {
	margin: 0 0 1.75rem;
	max-width: 46ch;
	font-size: 0.98rem;
	color: rgba(255, 255, 255, 0.65);
}

/* --- La boucle de progression --- */

/* Colonnes automatiques : la boucle s'adapte au nombre d'étapes, on peut en
   ajouter une sans revenir ici. */
.diag__boucle {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	margin: 0 0 2.5rem;
	padding: 0;
	list-style: none;
}

.diag__noeud {
	position: relative;
	padding-top: 1.5rem;
	font-family: var(--font-mono);
	font-size: 0.68rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.35);
	transition: color var(--transition-lente);
}

/* Le filet qui relie les nœuds. */
.diag__noeud::before {
	content: '';
	position: absolute;
	top: 4px;
	left: 0;
	right: 0;
	height: 1px;
	background: repeating-linear-gradient(90deg, var(--rouge) 0 5px, transparent 5px 11px);
	opacity: 0.3;
}

/* Le nœud lui-même. */
.diag__noeud::after {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	width: 9px;
	height: 9px;
	border: 1px solid var(--rouge);
	background: var(--nuit);
	transform: rotate(45deg);
	transition: background-color var(--transition-lente), box-shadow var(--transition-lente);
}

.diag__noeud.est-actif { color: var(--blanc); }

.diag__noeud.est-actif::after,
.diag__noeud.est-fait::after {
	background: var(--rouge);
	box-shadow: 0 0 0 4px var(--rouge-voile);
}

.diag__noeud.est-fait { color: rgba(255, 255, 255, 0.6); }

.diag__noeud.est-fait::before { opacity: 0.9; }

/*
 * En mobile, cinq colonnes de ~65 px ne peuvent pas porter cinq libellés :
 * « L'EXISTANT » et « L'ÉCHÉANCE » se chevauchaient, illisibles. La boucle se
 * réduit alors à ce qu'elle a d'essentiel — le filet et les nœuds, qui disent
 * déjà où l'on en est. Le libellé de l'étape courante n'est pas perdu : le
 * titre « Question 1 sur 4 » le porte juste en dessous. Rien à réparer côté
 * accessibilité, la liste entière est en aria-hidden.
 */
@media (max-width: 699px) {
	.diag__noeud-label { display: none; }
	.diag__noeud { padding-top: 0.9rem; }
	.diag__boucle { margin-bottom: 2rem; }
}

/* --- Les étapes --- */

.diag__etape {
	margin: 0 0 2.5rem;
	padding: 0;
	border: 0;
}

/* En mode guidé, une seule étape à la fois, et elle entre par la droite. */
.est-guide .diag__etape {
	margin-bottom: 2rem;
	animation: diag-entre 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes diag-entre {
	from { opacity: 0; transform: translateX(16px); }
	to { opacity: 1; transform: translateX(0); }
}

.diag__question {
	display: block;
	padding: 0;
	margin-bottom: 1.5rem;
	font-family: var(--font-titre);
	font-size: clamp(1.5rem, 2.6vw, 2rem);
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1.15;
	color: var(--blanc);
}

/*
 * La question reçoit le focus au changement d'étape, pour être annoncée. Elle
 * n'est pas interactive : un anneau de focus n'y voudrait rien dire, il ne
 * ferait que polluer. Les vrais contrôles, eux, gardent le leur.
 */
.diag__question:focus { outline: none; }

.diag__compteur {
	display: block;
	margin-bottom: 0.75rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--rouge);
}

.diag__aide {
	display: block;
	margin-top: 0.5rem;
	font-family: var(--font-corps);
	font-size: 0.9rem;
	font-weight: 400;
	letter-spacing: 0;
	color: rgba(255, 255, 255, 0.55);
}

/* --- Les cartes de choix --- */

.diag__choix {
	display: grid;
	gap: 0.75rem;
}

.choix {
	position: relative;
	display: flex;
	align-items: center;
	gap: 0.9rem;
	padding: 1rem 1.1rem;
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid rgba(255, 255, 255, 0.12);
	border-radius: var(--rayon);
	cursor: pointer;
	transition: border-color var(--transition), background-color var(--transition), transform var(--transition);
}

.choix:hover {
	border-color: rgba(255, 255, 255, 0.35);
	background: rgba(255, 255, 255, 0.06);
}

/*
 * L'input reste dans le flux et reçoit le focus clavier — il est simplement
 * transparent et posé sur la carte. On ne le sort JAMAIS de l'écran : c'est ce
 * qui garde la navigation au clavier et les lecteurs d'écran intacts.
 */
.choix input {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}

.choix:has(input:focus-visible) {
	outline: 2px solid var(--rouge);
	outline-offset: 3px;
}

.choix:has(input:checked) {
	border-color: var(--rouge);
	background: rgba(230, 55, 39, 0.1);
}

.choix__picto {
	display: flex;
	flex: none;
	color: rgba(255, 255, 255, 0.45);
	transition: color var(--transition);
}

.choix:has(input:checked) .choix__picto { color: var(--rouge); }

.choix__corps {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
}

.choix__label {
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 1rem;
	color: var(--blanc);
}

.choix__indice {
	font-size: 0.85rem;
	color: rgba(255, 255, 255, 0.5);
}

/* La coche : un carré qui se remplit, pas une pastille de plus. */
.choix::after {
	content: '';
	position: absolute;
	top: 50%;
	right: 1.1rem;
	width: 16px;
	height: 16px;
	margin-top: -8px;
	border: 1px solid rgba(255, 255, 255, 0.25);
	border-radius: 2px;
	transition: border-color var(--transition), background-color var(--transition);
}

.choix:has(input:checked)::after {
	border-color: var(--rouge);
	background: var(--rouge) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 13 4 4L19 7'/%3E%3C/svg%3E") center / 11px no-repeat;
}

/* --- Champs de la dernière étape, sur fond sombre --- */

.diag .champ label { color: rgba(255, 255, 255, 0.6); }

.diag .champ input,
.diag .champ textarea {
	background: rgba(255, 255, 255, 0.04);
	border-color: rgba(255, 255, 255, 0.18);
	color: var(--blanc);
}

.diag .champ input:hover,
.diag .champ textarea:hover { border-color: rgba(255, 255, 255, 0.4); }

.diag .champ--case label {
	color: rgba(255, 255, 255, 0.7);
	text-transform: none;
	letter-spacing: 0;
}

.diag .champ--case label a { color: var(--blanc); }

.diag .message--erreur {
	background: rgba(230, 55, 39, 0.12);
	border-color: var(--rouge);
	color: #FFD7DA;
}

/* --- Actions --- */

.diag__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
	margin-bottom: 1.25rem;
}

.diag__actions [hidden] { display: none; }

.diag__mention {
	margin: 0;
	font-size: 0.85rem;
	color: rgba(255, 255, 255, 0.45);
}

/* --- Écran de fin --- */

.diag__fin { max-width: 46ch; }

.diag__fin-marque {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 76px;
	height: 76px;
	margin-bottom: 1.75rem;
	color: var(--rouge);
	border: 1px solid rgba(230, 55, 39, 0.4);
	border-radius: 50%;
	background: rgba(230, 55, 39, 0.08);
}

.diag__fin-titre {
	color: var(--blanc);
	margin-bottom: 1rem;
}

.diag__fin-texte {
	color: rgba(255, 255, 255, 0.72);
	margin-bottom: 0.75rem;
}

.diag__fin-texte a {
	color: var(--blanc);
	font-family: var(--font-titre);
	font-weight: 700;
}

/* --- LE PLAN VIVANT --- */

.diag__plan-cadre {
	padding: 1.5rem;
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: var(--rayon);
}

.diag__plan-titre {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: baseline;
	gap: 0.5rem;
	margin: 0 0 1rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.5);
}

.diag__plan-compteur { color: var(--rouge); }

.releve {
	width: 100%;
	height: auto;
	display: block;
}

.diag__plan-pied {
	margin: 1rem 0 0;
	font-size: 0.8rem;
	line-height: 1.5;
	color: rgba(255, 255, 255, 0.4);
}

/* --- Le trait du plan --- */

/* Le périmètre : la limite de propriété. Toujours là, même sans réponse. */
.releve__perimetre {
	fill: none;
	stroke: var(--rouge);
	stroke-width: 1.25;
	stroke-dasharray: 6 7;
	opacity: 0.75;
}

/* Le sol, puis les cloisons, puis les murs : on remplit avant de tracer. */
.releve__sol {
	fill: rgba(44, 44, 44, 0.55);
	stroke: none;
}

/*
 * Les murs porteurs sont épais, les cloisons fines : c'est la convention du
 * dessin d'architecte, et c'est ce qui rend le plan lisible d'un coup d'œil.
 * Les « trous » dans le tracé des murs SONT les ouvertures.
 */
.releve__murs {
	fill: none;
	stroke: rgba(255, 255, 255, 0.62);
	stroke-width: 6;
	stroke-linecap: square;
}

.releve__cloisons {
	fill: none;
	stroke: rgba(255, 255, 255, 0.3);
	stroke-width: 3;
	stroke-linecap: square;
}

/* Fenêtre : le double trait qui traverse le trou du mur. */
.releve__fenetre-fond {
	fill: none;
	stroke: rgba(255, 255, 255, 0.22);
	stroke-width: 6;
	stroke-linecap: butt;
}

.releve__fenetre {
	fill: none;
	stroke: rgba(255, 255, 255, 0.7);
	stroke-width: 1.5;
}

/* Porte : le vantail et son débattement. C'est ce détail qui fait « plan ». */
.releve__vantail {
	fill: none;
	stroke: rgba(255, 255, 255, 0.55);
	stroke-width: 2;
}

.releve__debattement {
	fill: none;
	stroke: rgba(255, 255, 255, 0.28);
	stroke-width: 1;
	stroke-dasharray: 3 3;
}

/*
 * Le texte d'un SVG suit l'échelle du viewBox : sur mobile, le plan est rendu
 * dans ~310 px au lieu de ~430, donc 9 px de viewBox ne font plus que 5,8 px à
 * l'écran — illisible. On grossit donc la police là où le plan rétrécit.
 */
.releve__piece {
	font-family: var(--font-mono);
	font-size: 16px;
	font-weight: 500;
	letter-spacing: 0.06em;
	fill: rgba(255, 255, 255, 0.55);
	text-transform: uppercase;
}

.releve__invite {
	font-family: var(--font-mono);
	font-size: 18px;
	font-weight: 500;
	letter-spacing: 0.1em;
	fill: rgba(255, 255, 255, 0.32);
	text-transform: uppercase;
}

@media (min-width: 900px) {
	.releve__piece { font-size: 10px; }
	.releve__invite { font-size: 12px; }
}

/* -------------------------------------------------------------------------
   LE BANDEAU COLLANT DU MOBILE

   Sur téléphone, le plan tombait sous le formulaire : il fallait défiler pour
   le voir se construire, donc on ne le voyait pas se construire. Il devient
   ici un bandeau fixe sous l'en-tête, qui reste sous les yeux pendant qu'on
   répond. Il n'apparaît qu'une fois le local choisi — avant, il n'aurait rien
   à montrer.
   ⚠️ SÉLECTEUR VOLONTAIREMENT PRÉFIXÉ PAR « .diag ». La vitrine de l'accueil
   réutilise la même carte (.diag__plan-cadre) pour MONTRER l'outil ; sans ce
   préfixe elle héritait du bandeau — donc position: fixed et translateY(-110%)
   — et le plan simulé disparaissait de l'accueil sur téléphone. Le bandeau
   n'a de sens que là où l'on répond aux questions : dans le formulaire.
   ---------------------------------------------------------------------- */

@media (max-width: 899px) {

	.diag .diag__plan-cadre {
		position: fixed;
		top: var(--entete-hauteur);
		left: 0;
		right: 0;
		z-index: 40;
		padding: 0.7rem var(--gouttiere) 0.85rem;
		/*
		 * ⚠️ PAPIER, PAS NUIT — et c'est la seule couleur possible ici.
		 *
		 * Ce bandeau datait du pré-diagnostic sombre : fond nuit, filet blanc.
		 * Le parcours est passé au clair depuis (bloc « PRÉ-DIAGNOSTIC CLAIR »)
		 * et le plan s'y dessine à l'ENCRE. Sur fond nuit, des traits d'encre
		 * sur du noir donnent un contraste de 1,02:1 : le plan existait, il ne
		 * se voyait simplement pas — pendant tout le parcours, sur mobile, et
		 * c'est pourtant là qu'il est censé se construire sous les yeux.
		 *
		 * La règle du bloc clair ne pouvait plus le corriger : ce sélecteur est
		 * préfixé par « .diag » (pour épargner la vitrine de l'accueil) et la
		 * bat donc en spécificité. Il porte lui-même sa couleur.
		 */
		background: var(--papier);
		border: 0;
		border-bottom: 1px solid var(--trait);
		border-radius: 0;
		box-shadow: var(--ombre-forte);
		/* Rangé au-dessus de l'écran tant qu'il n'y a rien à montrer. */
		transform: translateY(-110%);
		transition: transform var(--transition-lente);
	}

	.diag.a-plan .diag__plan-cadre { transform: translateY(0); }

	.diag .diag__plan-titre { margin-bottom: 0.5rem; }

	/*
	 * Hauteur fixe : le SVG se met à l'échelle tout seul (viewBox), et on garde
	 * ainsi la maîtrise de ce que le bandeau mange à l'écran. En dessous de
	 * 220 px, le plan devient trop petit et les noms de pièces illisibles.
	 */
	/* « svg.releve » : voir l'avertissement du § RELEVÉ DE CONFORMITÉ. Sans le
	   qualificatif, cette hauteur écrasait aussi la SECTION relevé des pages
	   service, qui a overflow: hidden — 1425 px de contenu passaient à la
	   trappe sur téléphone, sans le moindre signe extérieur. */
	svg.releve { height: 220px; }

	/* On réserve la place du bandeau, sinon il masquerait la question. */
	.diag.a-plan .diag__panneau { padding-top: 276px; }

	.diag__panneau { transition: padding-top var(--transition-lente); }

	/*
	 * ⚠️ L'en-tête ne rétrécit plus sur mobile : le bandeau est calé sur
	 * --entete-hauteur, et si l'en-tête maigrissait de 34 px au défilement, le
	 * bandeau flotterait dans le vide. On échange un effet contre une position
	 * juste — c'est le bon sens de l'échange.
	 */
	.entete.est-defile .entete__inner { min-height: var(--entete-hauteur); }
	.entete.est-defile .site-logo__img { max-height: 76px; }
}

/* --- Le matériel --- */

.releve__cone {
	fill: url(#plan-cone);
	stroke: rgba(255, 255, 255, 0.18);
	stroke-width: 0.75;
}

/*
 * Le matériel est blanc — c'est de l'équipement. Le ROUGE reste réservé à la
 * détection : détecteurs d'ouverture, de mouvement, sirène, centrale. C'est la
 * même grammaire que le reste du site, où le rouge dit « on surveille ».
 */
.releve__materiel {
	fill: none;
	stroke: rgba(255, 255, 255, 0.9);
	stroke-width: 1.4;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.releve__materiel--camera {
	fill: var(--blanc);
	stroke: var(--blanc);
}

/*
 * L'objectif, au CENTRE du dôme — c'est de ce point que part le champ de vision.
 * Il est creusé dans la couleur du plan, sans quoi il disparaîtrait dans le
 * blanc de la coupole.
 */
.releve__objectif {
	fill: var(--nuit);
	stroke: none;
}

/* La platine de fixation : le trait plat, côté mur. */
.releve__platine {
	fill: none;
	stroke: var(--blanc);
	stroke-width: 1.6;
}

.releve__materiel--contact,
.releve__materiel--pir,
.releve__materiel--sirene,
.releve__materiel--centrale {
	stroke: var(--rouge);
}

.releve__materiel--contact,
.releve__materiel--sirene { fill: var(--rouge); }

.releve__anneau {
	fill: none;
	stroke: var(--rouge);
	stroke-width: 1;
	stroke-dasharray: 4 4;
}

.releve__badge {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 500;
	fill: var(--rouge);
}

/*
 * Les calques. Éteints par défaut, ils s'allument quand le besoin correspondant
 * est coché — et le plan du local choisi est le seul affiché.
 */
.releve__local,
.releve__couche {
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--transition-lente), visibility var(--transition-lente);
}

.releve__local.est-actif,
.releve__couche.est-actif {
	opacity: 1;
	visibility: visible;
}

/*
 * L'invite est visible PAR DÉFAUT, et c'est le JS qui la masque une fois le
 * local choisi. L'inverse (l'afficher depuis le JS) laisserait le plan
 * totalement vide chez qui n'a pas de JavaScript.
 */
.releve__attente {
	opacity: 1;
	visibility: visible;
	transition: opacity var(--transition-lente), visibility var(--transition-lente);
}

.releve__attente.est-masque {
	opacity: 0;
	visibility: hidden;
}

/* Le matériel se pose : il ne surgit pas, il apparaît. */
.releve__couche {
	transform-box: fill-box;
	transform-origin: center;
	transform: scale(0.9);
	transition: opacity var(--transition-lente), visibility var(--transition-lente), transform var(--transition-lente);
}

.releve__couche.est-actif { transform: scale(1); }

/* --- La légende --- */

/*
 * Sans elle, le plan est joli mais muet. Elle ne liste que le matériel
 * réellement prévu : c'est la liste de ce qu'on viendrait poser.
 */
/*
 * Sept lignes empilées mangeaient un écran entier pour rien. En colonnes, la
 * légende tient en trois lignes — et elle se lit mieux : l'œil balaie une
 * grille, il ne descend pas une liste.
 */
.plan-legende {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: 0.6rem 1.25rem;
	margin: 1.25rem 0 0;
	padding: 1.25rem 0 0;
	list-style: none;
	border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.plan-legende:not(:has(li:not([hidden]))) {
	margin: 0;
	padding: 0;
	border-top: 0;
}

.plan-legende__item {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-size: 0.82rem;
	line-height: 1.3;
	color: rgba(255, 255, 255, 0.72);
}

.plan-legende__item[hidden] { display: none; }

.plan-legende__symbole {
	flex: none;
	width: 24px;
	height: 24px;
	fill: none;
	stroke: rgba(255, 255, 255, 0.9);
	stroke-width: 1.4;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.plan-legende__symbole--camera {
	fill: var(--blanc);
	stroke: var(--blanc);
}

.plan-legende__symbole--contact,
.plan-legende__symbole--pir,
.plan-legende__symbole--sirene,
.plan-legende__symbole--centrale {
	stroke: var(--rouge);
}

.plan-legende__symbole--contact,
.plan-legende__symbole--sirene { fill: var(--rouge); }

@media (min-width: 900px) {
	.diag { padding-block: 3rem 6rem; }

	.diag__inner {
		grid-template-columns: 1.15fr 0.85fr;
		gap: 4rem;
	}

	.diag__choix--2 { grid-template-columns: repeat(2, 1fr); }

	/* Le plan reste sous les yeux pendant qu'on répond : c'est la récompense. */
	.diag__plan {
		position: sticky;
		top: calc(var(--entete-hauteur) + 2rem);
	}
}

/* ============================================================
 * PRÉ-DIAGNOSTIC CLAIR (demande client) — le parcours passe sur fond blanc.
 * Bloc GROUPÉ et RÉVERSIBLE, sur le modèle du « HÉROS CLAIR » : le supprimer
 * en entier restaure le pré-diagnostic sombre d'origine (aucune règle plus
 * haut n'a été touchée). Il doit rester APRÈS les media queries de la section
 * 24, sinon celles-ci le recouvrent.
 *
 * Principe : on ne redessine rien, on inverse le support. Le plan cesse d'être
 * un écran de contrôle (traits blancs sur nuit) pour devenir CE QU'IL EST —
 * un tirage : traits d'encre sur papier. Le rouge ne bouge pas d'un pouce,
 * c'est lui qui porte encore le sens (détection, nœud actif, progression).
 * ============================================================ */

.diag {
	background: var(--blanc);
	color: var(--encre);
}

/* Papier millimétré : filet sombre très discret, comme le héros clair. */
.diag::before {
	background-image:
		linear-gradient(rgba(28, 28, 28, 0.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(28, 28, 28, 0.05) 1px, transparent 1px);
}

/* --- Amorce --- */

.diag__titre { color: var(--marine); }
.diag__baseline { color: var(--encre-douce); }

/* --- La boucle de progression --- */

.diag__noeud { color: rgba(28, 28, 28, 0.4); }
.diag__noeud::after { background: var(--blanc); }
.diag__noeud.est-actif { color: var(--marine); }
.diag__noeud.est-fait { color: var(--encre-douce); }

/* --- Les étapes --- */

.diag__question { color: var(--marine); }

/* Le rouge de marque ne passe pas AA en petit corps : le compteur prend la
   variante lisible, comme partout ailleurs sur fond clair. */
.diag__compteur { color: var(--rouge-texte); }
.diag__aide { color: var(--encre-douce); }

/* --- Les cartes de choix --- */

/* Sur le nuit, la carte s'éclaircissait pour exister ; sur le blanc, elle
   s'assombrit. Même geste, sens inverse. */
.choix {
	background: rgba(28, 28, 28, 0.02);
	border-color: rgba(28, 28, 28, 0.16);
}

.choix:hover {
	background: rgba(28, 28, 28, 0.05);
	border-color: rgba(28, 28, 28, 0.38);
}

/* L'état coché reste identique : c'est le repère du parcours, il ne change pas. */
.choix:has(input:checked) {
	border-color: var(--rouge);
	background: var(--rouge-voile);
}

.choix__picto { color: var(--encre-douce); }
.choix__label { color: var(--marine); }
.choix__indice { color: var(--encre-douce); }
.choix::after { border-color: rgba(28, 28, 28, 0.28); }

/* --- Champs de la dernière étape : ils redeviennent les champs du site --- */

.diag .champ label { color: var(--encre-douce); }

.diag .champ input,
.diag .champ textarea {
	background: var(--blanc);
	border-color: var(--trait);
	color: var(--encre);
}

.diag .champ input:hover,
.diag .champ textarea:hover { border-color: var(--encre-douce); }

.diag .champ--case label { color: var(--encre-douce); }
.diag .champ--case label a { color: var(--rouge-texte); }

.diag .message--erreur {
	background: #FDECEE;
	border-color: var(--rouge-cta);
	color: #8C1520;
}

/* --- Actions --- */

/* « Retour » est un bouton--fantome, dessiné pour le fond sombre. */
.diag .bouton--fantome {
	color: var(--marine);
	border-color: rgba(28, 28, 28, 0.28);
}

.diag .bouton--fantome:hover,
.diag .bouton--fantome:focus {
	color: var(--marine);
	border-color: var(--marine);
	background: rgba(28, 28, 28, 0.04);
}

.diag__mention { color: var(--encre-douce); }

/* --- Écran de fin --- */

.diag__fin-titre { color: var(--marine); }
.diag__fin-texte { color: var(--encre-douce); }
.diag__fin-texte a { color: var(--rouge-texte); }

/* --- LE PLAN VIVANT : le tirage --- */

.diag__plan-cadre {
	background: var(--papier);
	border-color: var(--trait);
}

/*
 * Le SVG du plan porte class="releve" et hérite donc du fond SOMBRE du
 * composant relevé — c'était la « boîte noire ». En mode clair on le rend
 * transparent : le papier du cadre passe dessous, et le plan se lit comme un
 * tirage sur calque. Scopé au cadre pour ne pas toucher les sections .releve.
 */
.diag__plan-cadre .releve { background: transparent; }

.diag__plan-titre { color: var(--encre-douce); }
.diag__plan-compteur { color: var(--rouge-texte); }
.diag__plan-pied { color: var(--encre-douce); }

/* Le sol : la surface bâtie, plus claire que le papier du cadre — sans quoi
   le plan se lirait en négatif. */
.releve__sol { fill: rgba(255, 255, 255, 0.9); }

/* Murs porteurs épais, cloisons fines : la hiérarchie du trait est conservée,
   seule son encre change. */
.releve__murs { stroke: rgba(28, 28, 28, 0.72); }
.releve__cloisons { stroke: rgba(28, 28, 28, 0.34); }

.releve__fenetre-fond { stroke: rgba(255, 255, 255, 0.95); }
.releve__fenetre { stroke: rgba(28, 28, 28, 0.6); }
.releve__vantail { stroke: rgba(28, 28, 28, 0.5); }
.releve__debattement { stroke: rgba(28, 28, 28, 0.3); }

.releve__piece { fill: rgba(28, 28, 28, 0.5); }
.releve__invite { fill: rgba(28, 28, 28, 0.32); }

/*
 * LE CHAMP DE VISION. Le dégradé du <defs> est blanc : sur le papier, il ne se
 * voit pas. Et en encre, il ne serait qu'une tache grise de plus sur un plan
 * déjà tout en gris — alors que c'est LE point de la page : voilà ce que la
 * caméra couvre.
 *
 * Il passe donc au rouge (gradient « plan-cone-clair », défini dans
 * template-parts/plan-diagnostic.php), avec son arête tracée : le champ a un
 * bord franc, comme une portée relevée au rapporteur. C'est la seule surface
 * colorée du plan — le regard y va sans qu'on ait rien à expliquer.
 */
.releve__cone {
	fill: url(#plan-cone-clair);
	/* L'arête tracée : c'est elle qui fait la portée « relevée au rapporteur »
	   plutôt qu'une tache. Elle tient le champ même là où l'aplat est le plus
	   ténu. */
	stroke: var(--rouge);
	stroke-width: 1.25;
	stroke-linejoin: round;
}

/*
 * Le matériel était blanc parce que le fond était noir : c'est « de
 * l'équipement », dessiné dans la couleur neutre du support. Sur le papier,
 * cette couleur est l'encre. Le ROUGE reste réservé à la détection.
 */
.releve__materiel { stroke: var(--marine); }

.releve__materiel--camera {
	fill: var(--marine);
	stroke: var(--marine);
}

/* L'objectif est creusé dans la coupole : il prend la couleur du support. */
.releve__objectif { fill: var(--papier); }

.releve__platine { stroke: var(--marine); }

/* --- La légende --- */

.plan-legende { border-top-color: var(--trait); }
.plan-legende__item { color: var(--encre-douce); }
.plan-legende__symbole { stroke: var(--marine); }

.plan-legende__symbole--camera {
	fill: var(--marine);
	stroke: var(--marine);
}

/* Le bandeau collant du mobile suit le même sort que le cadre. */
@media (max-width: 899px) {

	.diag__plan-cadre {
		background: var(--blanc);
		border-bottom: 1px solid var(--trait);
	}

	/* Sur blanc, l'ombre portée d'origine (calibrée pour le nuit) ne détache
	   plus rien : le bandeau a besoin d'un filet net et d'une ombre douce. */
	.diag__plan-cadre { box-shadow: 0 12px 24px rgba(28, 28, 28, 0.1); }

	/* Le cadre disparaît, le sol doit alors se détacher du blanc pur. */
	.releve__sol { fill: rgba(28, 28, 28, 0.03); }
	.releve__objectif { fill: var(--blanc); }
}

/* -------------------------------------------------------------------------
   24 bis. LE FORMULAIRE DU BAS DE L'ACCUEIL

   Il vient après le bandeau qui referme la boucle : la CSS ne trace donc plus
   rien à sa hauteur (voir « .bandeau-cta ~ .section » plus haut). Rien à faire
   de ce côté, c'était prévu.
   ---------------------------------------------------------------------- */

/*
 * Deux colonnes : le discours et les coordonnées à gauche, la fiche à droite.
 * Empilées sur mobile, la fiche en dernier — on lit pourquoi avant de remplir.
 *
 * « align-items: start » est indispensable : sans lui, la grille étire la fiche
 * sur toute la hauteur de la colonne de gauche et ses champs partent flotter au
 * milieu d'un cadre trop grand.
 */
.form-duo {
	display: grid;
	gap: 2.5rem;
	align-items: start;
}

.section--form .section__titre {
	margin-bottom: 1rem;
}

.section--form .section__chapo {
	max-width: 42ch;
	margin-bottom: 2rem;
}

@media (min-width: 900px) {
	/*
	 * La fiche prend la part la plus large : c'est elle qui porte l'action, et
	 * ses champs sur deux colonnes ont besoin de la place. Le rapport est
	 * l'inverse de « duo--contact » (page Contact), où le formulaire est à
	 * gauche : ici on argumente d'abord, on agit ensuite.
	 */
	.form-duo {
		grid-template-columns: 0.85fr 1.15fr;
		gap: 4rem;
	}
}

/*
 * LA FICHE — la sœur de la carte du plan (« .diag__plan-cadre »).
 * Mêmes cotes, volontairement : même gris, même filet, même rayon. Qui a vu le
 * pré-diagnostic reconnaît l'objet.
 */
/*
 * Fond uni. Le quadrillage millimétré du héros a été essayé ici puis retiré :
 * à 22 px, sur une surface aussi petite et déjà chargée de champs, la trame
 * salissait au lieu d'évoquer le papier. Elle fonctionne en grand, en fond de
 * page — pas sous un formulaire.
 */
.fiche {
	padding: 1.75rem;
	background: var(--papier);
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
}

/*
 * Le bandeau de la fiche : à gauche ce que c'est, à droite ce qu'il faut savoir
 * avant de signer. C'est la grammaire du bandeau du plan (« VOTRE PLAN » à
 * gauche, la valeur rouge à droite).
 */
.fiche__entete {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: baseline;
	gap: 0.5rem;
	margin: 0 0 1.75rem;
	padding-bottom: 1rem;
	border-bottom: 1px solid var(--trait);
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--encre-douce);
}

.fiche__valeur { color: var(--rouge-texte); }

/*
 * Les deux filets de la fiche ne décorent pas, ils découpent : au-dessus ce
 * qu'on remplit, en dessous ce qu'on envoie. Un imprimé a ces règles, et c'est
 * ce qui fait qu'on sait où on en est.
 */
.section--form .formulaire__actions {
	margin-top: 1.75rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--trait);
}

/* Les champs sont blancs : sur le gris de la fiche, ils se creusent au lieu de
   flotter — c'est là qu'on écrit. */
.section--form .champ input,
.section--form .champ select,
.section--form .champ textarea {
	background: var(--blanc);
}

@media (max-width: 599px) {
	/* La fiche garde ses filets mais rend la marge : sur 390 px, 1,75 rem de
	   chaque côté mangeaient la largeur utile des champs. */
	.fiche { padding: 1.25rem; }
}

/*
 * L'EN-TÊTE ÉTROIT (900 → 1080 px).
 *
 * Sur cette plage, le logo, les six entrées et le bouton d'appel ne tiennent
 * pas : il manque ~80 px. Avant, le menu étant hors du flux, il PASSAIT SOUS le
 * bouton — la collision ne se voyait pas dans le code, seulement à l'écran.
 * Remis dans le flux, il pousse au lieu de chevaucher : le débordement devient
 * visible, donc corrigeable.
 *
 * On resserre donc la pastille et l'écart juste sur cette plage. Le menu perd
 * ~107 px et tout rentre. Au-delà de 1080, il reprend ses aises.
 */
@media (min-width: 900px) and (max-width: 1080px) {
	.menu { gap: 0.15rem; }

	/*
	 * La chasse baisse aussi, pas seulement les marges : à 900 px la marge
	 * technique (72 px) ampute la zone utile, il ne reste que 744 px pour le
	 * logo, six entrées et le bouton. Les marges seules n'y suffisaient pas.
	 */
	.menu > li > a {
		padding-inline: 0.3rem;
		font-size: 0.8rem;
	}
}

/* -------------------------------------------------------------------------
   25. BARRE D'ACTION MOBILE
   Sur un site d'artisan, l'appel est la conversion. Sur mobile, il ne doit
   jamais être à plus d'un pouce de distance.
   ---------------------------------------------------------------------- */

.barre-action {
	position: fixed;
	inset-inline: 0;
	bottom: 0;
	z-index: 90;
	display: grid;
	grid-template-columns: 1fr 1fr;
	background: var(--nuit);
	border-top: 1px solid var(--marine-ligne);
	padding-bottom: env(safe-area-inset-bottom, 0);
}

.barre-action__lien {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	min-height: 3.5rem;
	padding: 0.5rem;
	font-family: var(--font-titre);
	font-weight: 600;
	font-size: 0.95rem;
	color: var(--blanc);
	text-decoration: none;
}

/*
 * En dessous de 360 px, « Demander à être rappelé » passait sur deux lignes et
 * la barre gagnait 8 px. Or le body réserve sa place à partir du min-height des
 * liens : la barre débordait donc de 8 px sur le pied de page. On resserre le
 * texte plutôt que la réserve — c'est le libellé qui déborde, pas la mesure qui
 * est fausse, et une réserve prise large rouvrirait la bande blanche.
 */
@media (max-width: 359px) {
	.barre-action__lien {
		gap: 0.35rem;
		padding-inline: 0.3rem;
		font-size: 0.85rem;
	}
}

.barre-action__lien--appel { border-right: 1px solid var(--marine-ligne); }

.barre-action__lien--devis {
	background: var(--rouge-cta);
	color: var(--blanc);
}

/*
 * Sur la page du pré-diagnostic, « Demander un devis » pointerait sur la page
 * où l'on se trouve déjà : c'est un cul-de-sac, et une distraction en plein
 * parcours de conversion. On ne garde que l'appel, en pleine largeur.
 */
.page-template-page-diagnostic .barre-action { grid-template-columns: 1fr; }
.page-template-page-diagnostic .barre-action__lien--devis { display: none; }
.page-template-page-diagnostic .barre-action__lien--appel { border-right: 0; }

/* =========================================================================
   RESPONSIVE
   ========================================================================= */

/*
 * BANDE TABLETTE (768–899 px). Tout est encore en une colonne alors que la
 * page, elle, est déjà large : le corps de texte des services et des secteurs
 * atteignait 139 caractères par ligne, contre ~82 sur le poste fixe une fois
 * les colonnes en place. L'œil perd sa ligne. On rend au texte la mesure que
 * le reste du site respecte. En dessous de ~736 px la règle ne mord plus :
 * l'écran est déjà plus étroit qu'elle.
 */
@media (max-width: 899px) {
	.prose,
	.releve__intro,
	.releve__corps,
	.faq__reponse { max-width: 46rem; }
}

@media (min-width: 640px) {
	.grille--3,
	.grille--4 { grid-template-columns: repeat(2, 1fr); }

	.grille-secteurs { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	.atouts { grid-template-columns: repeat(2, 1fr); }

	.confiance__liste { grid-template-columns: repeat(3, 1fr); }

	.chiffres__liste { grid-template-columns: repeat(3, 1fr); }

	.formulaire__grille { grid-template-columns: repeat(2, 1fr); }

	.champ--large { grid-column: 1 / -1; }

	.navigation-article .nav-links { grid-template-columns: repeat(2, 1fr); }

	.pied__bas-inner {
		flex-direction: row;
		justify-content: space-between;
		text-align: left;
	}
}

@media (min-width: 900px) {
	:root {
		--gouttiere: 2rem;
		/* L'en-tête rétrécit ici : la réserve suit sa hauteur RÉTRÉCIE (voir la
		   note sur --reserve-haut), sans quoi une bande blanche apparaît sous
		   l'en-tête pendant les premiers pixels de défilement. */
		--reserve-haut: var(--entete-hauteur-defile);
	}

	/* La barre d'action mobile disparaît : le téléphone est dans l'en-tête.
	   La réserve qu'elle imposait au pied de page tombe avec elle. */
	.barre-action { display: none; }
	:root { --barre-action-hauteur: 0px; }

	.section { padding-block: 6rem; }

	.entete-page { padding-block: 4.5rem 3.5rem; }

	.hero__inner { grid-template-columns: 1.05fr 0.95fr; gap: 4rem; }

	/* Le menu passe en barre horizontale : plus de burger. */
	.burger { display: none; }

	.nav-principale {
		display: flex;
		align-items: center;
		gap: 2rem;
		position: static;
		padding: 0;
		background: transparent;
		border: 0;
		/*
		 * ⚠️ Les deux lignes qui suivent ne sont pas décoratives. Le panneau
		 * mobile a sa propre zone de défilement (voir « LE PANNEAU DOIT DÉFILER
		 * TOUT SEUL ») ; laissée ici, elle ferait de la barre horizontale un
		 * conteneur de défilement, qui ROGNERAIT les sous-menus déroulants de
		 * Services et Secteurs au lieu de les laisser sortir.
		 */
		height: auto;
		max-height: none;
		overflow: visible;
	}

	/*
	 * LE MENU SE CENTRE ENTRE SES VOISINS, et non sur la page.
	 *
	 * Il était sorti du flux et centré sur l'en-tête, au motif que « le logo et
	 * le bouton d'appel n'ont pas la même largeur, un simple margin auto le
	 * décalerait de la moitié de leur différence ». C'est vrai — mais c'est
	 * précisément ce décalage qu'il FAUT, et l'inverse qui se voyait : centré sur
	 * la page, le menu laissait 113 px côté logo (115 px de large) et 66 px côté
	 * bouton (234 px de large). Il paraissait collé au bouton. Mesuré, pas
	 * supposé.
	 *
	 * Tant que le menu n'était que du texte, ça passait. La pastille lui a donné
	 * un bord net, et le déséquilibre a sauté aux yeux.
	 *
	 * Il revient donc dans le flux : « margin-inline: auto » partage à égalité
	 * l'espace libre de la nav. Le gap de la nav est aligné sur celui de
	 * l'en-tête (1 rem) pour que les deux blancs soient rigoureusement égaux —
	 * sans quoi le côté bouton hériterait des 2 rem de la nav en plus.
	 *
	 * Aucune largeur n'est écrite en dur : si le logo change ou si le bouton
	 * s'allonge, le centrage suit tout seul.
	 */
	.nav-principale {
		flex: 1;
		gap: 1rem;
	}

	.menu {
		display: flex;
		align-items: center;
		/*
		 * L'écart tombe de 2,75 rem à 0,75 rem, et ce n'est pas un resserrement :
		 * la pastille ajoute 0,8 rem de chaque côté du texte. C'est elle qui
		 * sépare désormais les entrées. À gap constant, le menu aurait gagné
		 * ~170 px et serait allé buter dans le logo et le bouton d'appel.
		 */
		gap: 0.75rem;
		/* ⚠️ EN DERNIER, et en une seule déclaration. Un « margin: 0 » traînait
		   ici : il écrasait les marges auto posées plus haut et le centrage ne
		   se faisait pas. */
		margin: 0 auto;
	}

	/*
	 * LA PASTILLE (demande client).
	 *
	 * Le lien n'avait aucune surface — « padding: 0.5rem 0 » : il n'y avait rien
	 * à colorier. On lui en donne une, arrondie au même rayon que les boutons et
	 * les cartes du site.
	 *
	 * Le voile rouge est un jeton qui existait déjà (--rouge-voile) : c'est le
	 * halo des nœuds de la boucle et le fond des cartes cochées du
	 * pré-diagnostic. La pastille n'invente donc pas une couleur, elle réutilise
	 * celle qui dit « ceci est actif » partout ailleurs.
	 */
	.menu > li > a {
		padding: 0.5rem 0.8rem;
		border-bottom: 0;
		border-radius: var(--rayon);
		transition: color var(--transition), background-color var(--transition);
	}

	/*
	 * Le survol et la page courante portent la MÊME pastille : l'un montre où
	 * l'on va, l'autre où l'on est. « :focus-visible » est là pour que la
	 * navigation au clavier voie exactement ce que voit la souris.
	 */
	.menu > li > a:hover,
	.menu > li > a:focus-visible,
	.menu > .current-menu-item > a,
	.menu > .current_page_item > a,
	.menu > .current-menu-ancestor > a,
	.menu > .current-menu-parent > a {
		background: var(--rouge-voile);
		color: var(--rouge-texte);
	}

	/*
	 * Chevron : sans lui, rien n'annonce que « Services » cache six pages.
	 * Il pivote vers le haut à l'ouverture — on lit l'état, pas seulement
	 * l'affordance.
	 */
	.menu > .menu-item-has-children > a::after {
		content: '';
		flex: none;
		width: 6px;
		height: 6px;
		margin-top: -3px;
		border-right: 1.5px solid currentColor;
		border-bottom: 1.5px solid currentColor;
		transform: rotate(45deg);
		transition: transform var(--transition), margin-top var(--transition);
	}

	.menu > .menu-item-has-children:hover > a::after,
	.menu > .menu-item-has-children:focus-within > a::after {
		margin-top: 2px;
		transform: rotate(-135deg);
	}

	/* Sous-menu déroulant au survol / focus. */
	.menu .sub-menu {
		position: absolute;
		top: 100%;
		left: 0;
		z-index: 20;
		min-width: 250px;
		padding: 0.5rem 0;
		background: var(--blanc); /* EN-TÊTE BLANC : sous-menu clair (d'origine var(--marine)). */
		border: 1px solid var(--trait);
		border-radius: var(--rayon);
		box-shadow: var(--ombre-forte);
		opacity: 0;
		visibility: hidden;
		transform: translateY(6px);
		transition: opacity var(--transition), transform var(--transition), visibility var(--transition);
	}

	.menu li:hover > .sub-menu,
	.menu li:focus-within > .sub-menu {
		opacity: 1;
		visibility: visible;
		transform: translateY(0);
	}

	.menu .sub-menu a {
		padding: 0.6rem 1.25rem;
		border-bottom: 0;
	}

	.menu .sub-menu a:hover { background: rgba(0, 0, 0, 0.05); } /* EN-TÊTE BLANC (d'origine rgba(255,255,255,.06)). */

	/* Menu « Secteurs » (12 entrées) : deux colonnes de 6, côte à côte.
	   Remplissage en colonne (1-6 à gauche, 7-12 à droite) pour garder
	   la lecture de haut en bas. Le menu Services (5 entrées) n’est pas visé. */
	.menu .colonnes-secteurs .sub-menu {
		display: grid;
		grid-template-columns: 1fr 1fr;
		grid-template-rows: repeat(6, auto);
		grid-auto-flow: column;
		min-width: 34rem;
		column-gap: 0.5rem;
	}

	.grille--3 { grid-template-columns: repeat(3, 1fr); }
	.grille--4 { grid-template-columns: repeat(4, 1fr); }

	/*
	 * Trois colonnes seulement à partir de 900 px : à quatre, la tuile n'offre
	 * plus que ~90 px au libellé une fois le picto et la flèche déduits, et
	 * « Collectivités & associations » s'y casse en quatre lignes. Le passage à
	 * quatre attend 1100 px (voir plus bas). minmax(0, 1fr) empêche la colonne
	 * de se caler sur la largeur minimale du contenu et de déborder de l'écran.
	 */
	.grille-secteurs { grid-template-columns: repeat(3, minmax(0, 1fr)); }

	/*
	 * La méthode passe en rangée : les cinq étapes se lisent alors comme un
	 * chemin — ce qu'elles sont. Le filet bascule à l'horizontale et les
	 * traverse, les nœuds s'alignent dessus.
	 */
	.methode {
		grid-template-columns: repeat(5, 1fr);
		margin-top: 1rem;
	}

	.methode__etape {
		padding: 2.25rem 1.75rem 0 0;
	}

	.methode__etape:last-child { padding-bottom: 0; }

	.methode__etape::before {
		top: 4px;
		bottom: auto;
		left: 0;
		right: 0;
		width: auto;
		height: 1px;
		background: repeating-linear-gradient(90deg, var(--rouge) 0 5px, transparent 5px 11px);
	}

	/* La dernière étape garde son filet : il file jusqu'au bord, la boucle ne
	   s'interrompt pas au milieu d'une phrase. */
	.methode__etape:last-child::before { content: ''; }

	.duo { grid-template-columns: 1fr 1fr; gap: 4rem; }

	/* Le texte prend la main sur ces trois-là : c'est lui qui porte l'argument,
	   l'image ne fait qu'accompagner. */
	.duo--materiel,
	.duo--maintenance { grid-template-columns: 1fr 1.05fr; align-items: center; }

	.duo--faq { grid-template-columns: 1fr 1.15fr; align-items: start; }


	/* Contenu large + colonne latérale (services, réalisations). */
	.duo--inverse {
		grid-template-columns: 1.8fr 1fr;
		align-items: start;
	}

	.duo--contact { grid-template-columns: 1.4fr 1fr; align-items: start; }

	.bandeau-cta__inner {
		grid-template-columns: 1fr auto;
		gap: 3rem;
	}

	.formulaire--rappel .formulaire__grille {
		grid-template-columns: repeat(3, 1fr);
		align-items: end;
	}

	.formulaire--rappel .champ--case { grid-column: 1 / -1; }

	/*
	 * Le pied est passé de quatre à CINQ colonnes : identité, contact, plan du
	 * site, services, secteurs. La première rétrécit — elle ne porte qu'un logo
	 * et trois icônes — et la dernière prend le double, parce qu'elle contient
	 * douze entrées qu'on met sur deux colonnes plutôt que sur douze lignes.
	 */
	.pied__grille { grid-template-columns: 1.3fr 1fr 0.9fr 1fr 1.4fr; }
}

@media (min-width: 1100px) {
	/* La place est là : les douze secteurs se lisent en trois rangées de quatre. */
	.grille-secteurs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* -------------------------------------------------------------------------
   ÉCRANS PEU HAUTS — LE HÉROS

   ⚠️ CES BLOCS DOIVENT RESTER ICI, APRÈS les règles de base du héros.
   Placés plus haut dans le fichier, ils avaient la même spécificité que
   .hero__titre et .hero__sous-titre définis plus bas : à spécificité égale,
   c'est la dernière règle qui gagne, et la base les écrasait en silence.
   ---------------------------------------------------------------------- */

/*
 * LE HÉROS S'ARRÊTE À LA LIGNE DE FLOTTAISON, BANDEAU COMPRIS.
 *
 * Sa hauteur, ce n'est pas une fraction arbitraire de l'écran : c'est l'écran
 * MOINS le bandeau de confiance (7,5rem ≈ 119 px) qui vient juste dessous. Le
 * héros et son bandeau finissent donc pile au pli, sur n'importe quelle
 * fenêtre. Avec les 82vh d'avant, un 15 pouces gardait 130 px de vide sous les
 * onglets pendant qu'un 12 pouces poussait le bandeau sous le pli.
 *
 * svh et pas vh : sur un portable dont la barre d'outils se rétracte, vh
 * compte une barre qui n'est pas là.
 *
 * :not(--compact) : les pages de service ont un héros court, il ne doit pas
 * se remettre à remplir l'écran par la bande.
 */
@media (min-width: 900px) {
	.hero:not(.hero--compact) {
		min-height: calc(100vh - 7.5rem);
		min-height: calc(100svh - 7.5rem);
	}
}

/*
 * Écrans peu HAUTS. La contrainte est la hauteur, pas la largeur : c'est donc
 * une media query sur la hauteur. On resserre le héros pour qu'il tienne en
 * entier, onglets compris — on ne demande à personne de deviner qu'il y a des
 * onglets sous la ligne de flottaison.
 *
 * ⚠️ LES SEUILS SE CALCULENT, ils ne se choisissent pas : un palier doit
 * s'enclencher exactement là où le palier du dessus ne rentre plus, sinon il
 * rapetisse pour rien. Hauteur du contenu + 7,5rem de bandeau = seuil.
 *   · pleine taille : 746 px de contenu → tient dès 865 px de fenêtre
 *   · resserré      : 623 px           → tient dès  746 px
 *   · très serré    : 516 px           → tient dès  635 px
 * Les 780/700 d'avant étaient posés à vue : entre 780 et 865 le héros
 * réclamait plus de place qu'il n'en avait (le bandeau passait sous le pli, ce
 * qu'on voyait sur un 15 pouces), et entre 700 et 746 il se ratatinait alors
 * qu'il restait de la marge.
 */
@media (max-height: 864px) and (min-width: 900px) {
	.hero {
		padding-block: 0 0.75rem;
	}

	/* Dégagement du menu, remonté depuis 6.75rem : le menu est devenu BLANC et
	   OPAQUE, il faut donc que le contenu du carrousel passe nettement dessous,
	   avec de l'air (menu = 101px). */
	.hero__slide { padding-top: 7.75rem; }

	.hero__titre { font-size: clamp(2.15rem, 4vw, 3.1rem); }

	/*
	 * ⚠️ Le titre de SERVICE doit être redit ici. Ce bloc arrive après
	 * .hero__titre--service dans le fichier, et à spécificité égale c'est la
	 * dernière règle qui gagne : sans cette ligne, le titre du carrousel
	 * retombait à la taille du titre de marque dès que la fenêtre passait sous
	 * 780 px de haut — c'est-à-dire chez presque tout le monde.
	 */
	.hero__titre--service { font-size: clamp(2.1rem, 4.2vw, 3.3rem); }

	.hero__titre::after { margin-top: 1rem; }

	.hero__sous-titre { margin-bottom: 1.5rem; }

	.hero__nav { margin-top: 1.5rem; }

	.moniteur { max-width: 400px; }
}

/*
 * Les écrans VRAIMENT bas : le 12 pouces (1280 × 800) et le 13 pouces Windows
 * (1366 × 768), dont la fenêtre ne fait plus que 640 à 650 px une fois la barre
 * du navigateur déduite. C'est le cas le plus contraint du parc, et il ne doit
 * pas être celui qui rate les onglets.
 */
@media (max-height: 745px) and (min-width: 900px) {
	.hero { padding-block: 0 0.75rem; }

	/* Idem : on dégage le menu opaque même sur les écrans les plus bas (menu 101px). */
	.hero__slide { padding-top: 7.25rem; }

	.hero .surtitre { margin-bottom: 0.6rem; }

	/*
	 * Cap relevé après nouvelle mesure sur la mise en page actuelle (le schéma
	 * SVG et le bandeau de confiance de l'ancien héros n'existent plus) : à
	 * 600–745 px de haut, le contenu de la diapo 1 s'arrête à ~365–520 px, soit
	 * 140 px+ de marge même titre à 48 px. L'ancien plafond de 2,05 rem était
	 * hérité d'une contrainte disparue. Le clamp en vw garde les fenêtres
	 * étroites à l'abri : le plafond n'est atteint qu'au-delà de ~1365 px de large.
	 */
	.hero__titre {
		font-size: clamp(1.9rem, 3.4vw, 2.9rem);
		margin-bottom: 1rem;
	}

	/*
	 * Même raison que plus haut : sans ce rappel, le titre de service serait
	 * écrasé par la règle générique.
	 *
	 * Et c'est bien le PLAFOND : un 12 pouces n'offre que 521 px sous l'en-tête,
	 * le contenu en occupe 517. Passer le titre à 48 px lui coûte deux lignes de
	 * plus (+25 px) et le bandeau de confiance repart sous le pli. Essayé, mesuré,
	 * annulé — inutile de le retenter.
	 */
	.hero__titre--service { font-size: clamp(1.9rem, 3.4vw, 2.7rem); }

	.hero__titre::after {
		width: 3.5rem;
		height: 2px;
		margin-top: 0.85rem;
	}

	.hero__sous-titre {
		font-size: 1rem;
		margin-bottom: 1.1rem;
	}

	.hero__actions .bouton--grand {
		padding: 0.7rem 1.4rem;
		font-size: 0.95rem;
	}

	.hero__nav {
		margin-top: 1rem;
		gap: 0.8rem;
	}

	.hero__fleche { width: 38px; height: 38px; }

	.moniteur { max-width: 340px; }
	.moniteur__ecran { height: 76px; }
	.moniteur__etats li { padding-block: 0.5rem; }
}

/* =========================================================================
   APPARITION AU DÉFILEMENT

   Chaque section monte de quelques pixels en se révélant, quand elle entre
   dans le champ. C'est le même signal que la boucle : l'observateur pose
   « est-vu » une fois pour toutes (main.js § 6), le capteur s'allume dans la
   marge et la section paraît — un seul geste, pas deux.

   ⚠️ Le préfixe .js n'est pas décoratif. C'est le CSS qui cache les sections ;
   sans le drapeau posé par header.php, un visiteur sans JavaScript aurait une
   page entièrement blanche, et le robot d'indexation aussi.

   ⚠️ NI LE HÉROS NI LE BANDEAU DE CONFIANCE. Ils sont déjà là au chargement :
   le héros a sa propre chorégraphie d'entrée, et le bandeau s'arrête pile à la
   ligne de flottaison — l'observateur n'allume une section qu'une fois son
   sommet remonté au-dessus des trois quarts de l'écran, si bien que le bandeau
   restait transparent tant qu'on n'avait pas défilé : une bande blanche sous le
   héros, au chargement, sur toutes les tailles d'écran. Mesuré, pas supposé.
   ========================================================================= */

/*
 * ⚠️ NI L'EN-TÊTE DE PAGE (« .entete-page ») — retiré de cette liste.
 *
 * C'est le bandeau gris qui porte le titre des pages listes et légales. Il est
 * le PREMIER élément de la page : il est donc déjà à l'écran au chargement, et
 * l'animer revenait à le faire entrer alors qu'il aurait dû être là. Le temps
 * du trajet — 40 px et 800 ms — il laissait une bande blanche entre le menu et
 * lui, à chaque ouverture de page.
 *
 * C'est exactement le raisonnement tenu deux lignes plus haut pour le héros et
 * le bandeau de confiance ; il s'appliquait à celui-ci aussi, on l'avait
 * simplement oublié. La règle vaut pour ce qu'on découvre en défilant, pas
 * pour ce qui est là quand la page s'ouvre.
 */
.js .contenu-principal .section,
.js .contenu-principal .bandeau-cta {
	opacity: 0;
	/*
	 * ⚠️ LA COURBE COMPTE PLUS QUE LA DISTANCE.
	 *
	 * Le fondu était invisible, et ce n'était pas une affaire de pixels : avec
	 * cubic-bezier(0.16, 1, 0.3, 1) — une exponentielle sortante —, 85 % du trajet
	 * étaient avalés dans les 60 premières millisecondes. La section était déjà
	 * posée avant qu'on ait eu le temps de la voir partir. Allonger la durée n'y
	 * aurait rien changé : elle aurait mis une seconde à parcourir ses trois
	 * derniers pixels.
	 *
	 * Une cubique sortante (0.33, 1, 0.68, 1) étale le mouvement : la moitié du
	 * trajet à 200 ms, la fin à 800. Elle décélère toujours — la section se pose,
	 * elle ne flotte pas — mais on la voit monter. Et 40px au lieu de 18 : à
	 * course visible, il faut une course qui existe.
	 */
	transform: translateY(40px);
	transition:
		opacity 800ms cubic-bezier(0.33, 1, 0.68, 1),
		transform 800ms cubic-bezier(0.33, 1, 0.68, 1);
}

.js .contenu-principal .section.est-vu,
.js .contenu-principal .bandeau-cta.est-vu {
	opacity: 1;
	transform: none;
}

/* =========================================================================
   MOUVEMENT RÉDUIT
   Le schéma reste dessiné, il ne s'anime simplement pas.
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }

	/*
	 * Les sections sont simplement LÀ. Neutraliser la transition ne suffirait
	 * pas : l'état de départ est opacity: 0, et une section jamais observée (la
	 * page ne défile pas, l'observateur ne se déclenche pas) resterait invisible.
	 */
	.js .contenu-principal .entete-page,
	.js .contenu-principal .section,
	.js .contenu-principal .bandeau-cta {
		opacity: 1 !important;
		transform: none !important;
	}

	/*
	 * Neutraliser la durée ne suffit pas : les entrées du moniteur sont
	 * construites sur des DÉLAIS. Sans les annuler aussi, ses trois états
	 * resteraient vides une seconde avant de surgir d'un coup — exactement ce
	 * qu'on cherche à éviter. On les met à zéro : le tracé est simplement là.
	 */
	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		animation-delay: 0s !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		transition-delay: 0s !important;
	}

	/*
	 * Le signal ne défile plus : la ligne est posée, pas immobilisée en pleine
	 * course. On la remet à l'origine, sans quoi la règle ci-dessus la laisserait
	 * figée sur son image de fin.
	 */
	.moniteur__defile { transform: none !important; }

	/* Le halo de la LED : une pulsation infinie n'a rien à faire ici. */
	.moniteur__voyant { box-shadow: none !important; }
}

/* =====================================================================
 * PAGE SERVICE — gabarit « relevé »
 * Bloc GROUPÉ et réversible. Réutilise les tokens et la signature du site
 * (mono, filet rouge, nœud losange). Classes préfixées pour ne rien
 * percuter. Voir single-service.php.
 * ===================================================================== */

/* ---- 1. HÉRO fiche technique ---- */
.service-hero {
	position: relative;
	background: var(--blanc);
	/*
	 * Le dégagement du menu fixe est DÉJÀ porté par .contenu-principal
	 * (padding-top: --reserve-haut). Ici on ne remet donc qu'un padding de
	 * respiration — sinon les deux se cumulent et le contenu descend trop bas.
	 *
	 * On y ajoute « --entete-cache » : la part que l'en-tête recouvre au repos,
	 * et qui serait autrement prise sur cette respiration.
	 */
	padding-top: calc(3rem + var(--entete-cache));
	padding-bottom: 4rem;
	overflow: hidden;
	--fond-noeud: var(--blanc);
}

/* La grille millimétrée, comme le héros d'accueil : le plan sous la page. */
.service-hero__grille {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background-image:
		linear-gradient(rgba(28, 28, 28, 0.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(28, 28, 28, 0.05) 1px, transparent 1px);
	background-size: 64px 64px;
	-webkit-mask-image: radial-gradient(120% 100% at 12% 0%, #000 0%, transparent 78%);
	mask-image: radial-gradient(120% 100% at 12% 0%, #000 0%, transparent 78%);
}

.service-hero__inner {
	position: relative;
	z-index: 1;
	display: grid;
	gap: 3rem;
	/*
	 * Aligné en HAUT, pas centré : l'image est plus grande que la colonne texte,
	 * et un centrage vertical ferait redescendre tout le texte sous le pli. En
	 * haut, l'image peut s'étendre sans pousser le titre ni les repères.
	 */
	align-items: start;
	/*
	 * ⚠️ minmax(0, 1fr) ET NON LA COLONNE PAR DÉFAUT.
	 *
	 * Une colonne de grille implicite refuse de descendre sous la largeur
	 * minimale de son contenu — ici, le mot le plus long du titre. « VIDÉO-
	 * SURVEILLANCE », en capitales à 38 px, mesure 401 px : la colonne s'y
	 * calait, dans un écran qui n'en offre que 327. Et comme le héros porte
	 * overflow: hidden, rien ne débordait — le titre, le chapô et l'intro
	 * étaient simplement COUPÉS au bord droit, sans barre de défilement pour
	 * le signaler. Un audit de débordement ne voit pas ce genre de perte.
	 */
	grid-template-columns: minmax(0, 1fr);
}

.service-hero .fil-ariane { margin-bottom: 1.25rem; }

.service-hero__picto { color: var(--rouge); }

/*
 * Le plancher du clamp valait 2,4 rem — 38 px — quelle que soit la largeur.
 * C'est confortable sur un portable, c'est trop pour un téléphone : le titre
 * le plus long du site y demandait 401 px. Le plancher devient donc relatif à
 * l'écran (7vw : 26 px à 375, 22 à 320), et 2,4 rem redevient ce qu'il aurait
 * toujours dû être — la taille de croisière, pas le minimum absolu.
 *
 * La coupure de mot posée sur les titres (§ 3) reste le filet de sécurité :
 * elle n'agit que si un mot dépasse malgré tout sa ligne.
 */
.service-hero__titre {
	font-size: clamp(1.75rem, 7vw, 3.9rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
	margin: 0 0 1.1rem;
	text-transform: uppercase;
	text-wrap: balance;
}

/*
 * LES PALIERS DU H1 — posés par PHP, pas par la fenêtre.
 *
 * Le H1 n'est plus forcément le nom court du service : il peut porter une
 * phrase écrite pour Google. Or un clamp() ne sait pas ce qu'il compose, il ne
 * connaît que la largeur de l'écran — il traiterait « Vidéosurveillance » et
 * « Installation de vidéosurveillance connectée à Paris » exactement pareil.
 * C'est besafe_h1() qui compte les caractères et pose la classe (inc/helpers.php).
 *
 * Ce qu'on corrige à chaque palier, et pourquoi :
 *   - la TAILLE, sinon un titre long occupe la moitié du premier écran et
 *     repousse l'accroche, les boutons et les repères sous le pli ;
 *   - l'INTERLIGNE, qui se resserre à mesure que les lignes se multiplient —
 *     1,05 va bien pour deux lignes, il aère trop à quatre ;
 *   - les CAPITALES, qui tombent au-delà de 48 caractères. Une phrase longue
 *     en capitales n'a plus de hampes ni de jambages : le mot perd sa forme et
 *     se déchiffre lettre à lettre. La signature du thème tient sur un ou deux
 *     mots, pas sur une phrase.
 */
.service-hero__titre--moyen {
	font-size: clamp(1.55rem, 5.4vw, 2.9rem);
	line-height: 1.1;
}

.service-hero__titre--long {
	font-size: clamp(1.4rem, 4.4vw, 2.3rem);
	line-height: 1.18;
	letter-spacing: -0.01em;
	text-transform: none;
}

/*
 * LES H1 SUR TÉLÉPHONE : PLUS GRANDS, ET ENFIN AÉRÉS.
 *
 * Deux corrections d'un coup, sur la même cause — ces titres ne tenaient plus
 * sur une ligne depuis qu'ils portent une phrase pour Google.
 *
 * 1. LA TAILLE. Les paliers avaient été calés au plus serré pour éviter le
 *    débordement, et le H1 tombait à 25 px sur un téléphone — plus petit que
 *    certains H2 de la même page. Le plancher vient maintenant du vw : il
 *    grandit avec l'écran au lieu d'être figé.
 *
 *    Les bornes ne sont pas au jugé. Le mot le plus long du site est
 *    « VIDÉOSURVEILLANCE » : 17 caractères, ~0,62 em de chasse chacun en
 *    capitales. Il lui faut donc 17 × 0,62 × corps ≤ largeur utile. À 390 px
 *    (327 utiles) cela plafonne le corps à 31 px ; à 320 px (272 utiles), à
 *    25,8 px. D'où 7,6vw, qui donne 29,6 px et 24,3 px — sous la limite dans
 *    les deux cas, sans marge inutile.
 *
 * 2. L'INTERLIGNAGE. Il valait 1,05 et 1,1, soit MOINS que le seuil de
 *    1,164 em établi plus haut pour les capitales accentuées (voir la note de
 *    .hero__titre : la virgule descend de 0,215 em, le « É » monte de
 *    0,948 em). Tant que ces titres tenaient sur une ligne, le seuil ne
 *    servait à rien. Sur trois lignes de « INSTALLATION D’ALARME ANTI-
 *    INTRUSION SANS FIL », il devient la différence entre un titre et un pâté.
 *
 *    Le palier long compose en bas de casse : pas d'accents en hauteur de
 *    capitale, mais des jambages — 1,3 lui va mieux que 1,2.
 */
@media (max-width: 899px) {
	.service-hero__titre {
		font-size: clamp(2rem, 8.5vw, 3rem);
		line-height: 1.2;
	}

	.service-hero__titre--moyen {
		font-size: clamp(1.55rem, 7.6vw, 2.6rem);
		line-height: 1.2;
	}

	.service-hero__titre--long {
		font-size: clamp(1.5rem, 6.4vw, 2.2rem);
		line-height: 1.3;
	}

	/* Les autres H1 du site (blog, contact, diagnostic, pages simples). Ils ne
	   sont pas en capitales, mais 1,04 reste un interlignage de titre à UNE
	   ligne — dès qu'il en faut deux sur un téléphone, il colle. */
	h1 { line-height: 1.15; }
}

.service-hero__chapo {
	max-width: 46ch;
	margin: 0 0 1.1rem;
	font-size: 1.18rem;
	line-height: 1.5;
	color: var(--encre-douce);
}

.service-hero__intro {
	max-width: 52ch;
	margin: 0 0 1.5rem;
}
.service-hero__intro p {
	margin: 0 0 0.7rem;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--encre-douce);
}
.service-hero__intro p:last-child { margin-bottom: 0; }
.service-hero__intro strong { color: var(--encre); font-weight: 700; }

.service-hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	margin: 0 0 1.75rem;
}

/*
 * Le bouton secondaire du héros vit sur fond BLANC ; le « fantôme » du thème est
 * blanc sur blanc (pensé pour les fonds sombres). On le repasse en encre sur
 * filet gris — lisible, discret à côté du bouton rouge.
 */
.service-hero__actions .bouton--fantome {
	color: var(--encre);
	border-color: var(--trait);
}
.service-hero__actions .bouton--fantome:hover,
.service-hero__actions .bouton--fantome:focus-visible {
	color: var(--encre);
	border-color: var(--encre);
	background: rgba(28, 28, 28, 0.04);
}

/*
 * L'image du héros ne vit PAS dans un cadre : elle se fond dans le papier.
 * Un feutrage sur les quatre bords — large à gauche (vers le texte) et en bas,
 * plus léger à droite et en haut — la fait émerger de la grille millimétrée au
 * lieu d'être une vignette posée dessus. Même parti pris que les visuels de
 * l'accueil : la photo habille, elle ne s'encadre pas.
 */
.service-hero__media {
	position: relative;
	margin: 0;
}

.service-hero__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	aspect-ratio: 16 / 10;
	/* Mobile : l'image est au-dessus du texte, on adoucit seulement le bas. */
	-webkit-mask-image: linear-gradient(0deg, transparent 0%, #000 14%, #000 100%);
	mask-image: linear-gradient(0deg, transparent 0%, #000 14%, #000 100%);
}

@media (min-width: 900px) {
	/*
	 * L'IMAGE DÉBORDE VERS LA GAUCHE, sous le texte, et se dissout dans le blanc.
	 *
	 * Elle n'est plus dans une colonne à droite : elle est posée en absolu sur la
	 * moitié droite du héros et s'étend vers la gauche, PAR-DESSOUS l'écriture
	 * (le texte repasse au-dessus, z-index). Un fondu gauche large et propre la
	 * fait disparaître dans le papier là où vivent le titre et l'accroche, si bien
	 * que l'encre reste parfaitement lisible. Elle ne colle pas au bord droit :
	 * elle s'arrête au bord du contenu, la gouttière du conteneur lui fait une
	 * marge.
	 */
	.service-hero__inner { display: block; position: relative; }

	.service-hero__texte {
		position: relative;
		z-index: 2;
		max-width: 52%;
	}

	.service-hero__media {
		position: absolute;
		top: 0;
		/*
		 * L'image occupe la MOITIÉ DROITE : son bord gauche s'arrête au bord droit
		 * du texte (52 % du conteneur), elle ne déborde plus sous l'écriture. Bord
		 * droit collé à la fenêtre (full-bleed). Comme elle ne passe jamais sous le
		 * texte, l'encre reste lisible à toutes les largeurs, sans calcul fragile.
		 */
		right: calc(-1 * (max(0px, (100vw - var(--largeur-max)) / 2) + var(--gouttiere)));
		left: 52%;
		width: auto;
		height: 100%;
		margin: 0;
		z-index: 1;
	}

	.service-hero__img {
		height: 100%;
		aspect-ratio: auto;
		object-position: center center;
		/*
		 * Le fondu doux d'origine : large et progressif sur le bord gauche, léger
		 * en haut et en bas pour ne pas trancher sur la grille. Le bord droit reste
		 * net (l'image sort de l'écran).
		 */
		-webkit-mask-image:
			linear-gradient(90deg, transparent 0%, #000 46%),
			linear-gradient(0deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
		-webkit-mask-composite: source-in;
		mask-image:
			linear-gradient(90deg, transparent 0%, #000 46%),
			linear-gradient(0deg, transparent 0%, #000 6%, #000 94%, transparent 100%);
		mask-composite: intersect;
	}
}

/* ---- Les repères ----
 *
 * La grammaire du thème est constante ailleurs : la VALEUR est en Inter gras
 * (voir .chiffres__valeur et .confiance__valeur), le LIBELLÉ en mono capitales.
 * Ces repères-ci faisaient l'inverse — une valeur en mono, à grande taille.
 * Sur une phrase comme « Paris - IDF - toute la France », le rendu tirait vers
 * le listing de code : chasse fixe, tirets isolés, rien de la voix du site.
 * On les réaligne sur la règle commune.
 */
.service-reperes {
	display: flex;
	flex-wrap: wrap;
	column-gap: 2.25rem;
	row-gap: 1rem;
	margin: 0;
	padding-top: 1.25rem;
	border-top: 1px solid var(--trait);
}
.service-reperes__item { margin: 0; }
.service-reperes__valeur {
	font-family: var(--font-titre);
	font-size: clamp(1.5rem, 2.4vw, 2rem);
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--encre);
	line-height: 1.1;
}

/*
 * LES CHIFFRES PASSENT AU ROUGE, avec un filet sous le nombre.
 *
 * Le rouge est la seule couleur du site : ne l'accorder qu'aux chiffres leur
 * donne le statut de preuve — « +20 ans », « 48 h » sont ce qui se retient.
 * Le filet est court et calé sur la largeur du nombre, pas de la colonne :
 * il souligne la valeur, il ne trace pas un séparateur de plus dans un bloc
 * qui en compte déjà deux (le filet plein en haut, le pointillé au milieu).
 *
 * ⚠️ Uniquement les repères CHIFFRÉS. Le repère en PHRASE (« Paris - IDF -
 * toute la France ») garde l'encre : tout mettre en rouge, c'est ne plus rien
 * mettre en avant.
 *
 * --rouge-texte et non --rouge : 6,40:1 sur fond clair, là où le rouge de
 * marque plafonne à 3,7:1 — insuffisant dès que la valeur descend en taille.
 */
.service-reperes__item:not(.service-reperes__item--texte) .service-reperes__valeur {
	display: inline-block;
	color: var(--rouge-texte);
}

.service-reperes__item:not(.service-reperes__item--texte) .service-reperes__valeur::after {
	content: '';
	display: block;
	width: 1.75rem;
	height: 3px;
	margin-top: 0.45rem;
	background: var(--rouge);
	border-radius: 2px;
}

/* Le filet occupant déjà l'espace, le libellé se recolle. */
.service-reperes__item:not(.service-reperes__item--texte) .service-reperes__libelle {
	margin-top: 0.3rem;
}

/*
 * Un repère peut porter une PHRASE plutôt qu'un chiffre (la zone d'intervention,
 * « Paris - IDF - toute la France »). En corps plein, elle ferait un pavé plus
 * gros que « +20 ans ». On la ramène à une taille de texte : lisible, alignée
 * sur les autres, et assez compacte pour tenir sur la ligne des repères.
 */
/* La phrase (zone d'intervention) prend sa propre ligne, sous les repères
   chiffrés : un layout net plutôt qu'un retour à la ligne au petit bonheur. */
.service-reperes__item--texte {
	flex-basis: 100%;
	padding-top: 0.9rem;
	border-top: 1px dashed var(--trait);
}
.service-reperes__item--texte .service-reperes__valeur {
	font-size: clamp(0.95rem, 1.2vw, 1.1rem);
	letter-spacing: 0;
	white-space: nowrap;
}
.service-reperes__item--texte .service-reperes__libelle { max-width: none; }
.service-reperes__libelle {
	margin: 0.4rem 0 0;
	font-size: 0.85rem;
	line-height: 1.35;
	color: var(--encre-douce);
	max-width: 18ch;
}

@media (min-width: 900px) {
	/*
	 * La colonne texte garde sa largeur confortable (sinon l'accroche et l'intro
	 * wrappent et le contenu déborde le pli). L'image, elle, s'étend par le bas
	 * du full-bleed : elle déborde jusqu'au bord de la fenêtre, donc reste grande
	 * sans voler de place au texte.
	 */
	.service-hero__inner { grid-template-columns: 1.05fr 0.95fr; gap: 3.5rem; }
}

/* ---- 2. DÉROULÉ (process) ---- */
.process {
	display: grid;
	gap: 0;
	margin: 2.5rem 0 0;
	padding: 0;
	list-style: none;
}
.process__etape {
	position: relative;
	padding: 0 0 2.5rem 2.25rem;
}
.process__etape:last-child { padding-bottom: 0; }
.process__etape::before {
	content: '';
	position: absolute;
	top: 6px;
	bottom: 0;
	left: 4px;
	width: 1px;
	background: repeating-linear-gradient(180deg, var(--rouge) 0 5px, transparent 5px 11px);
	opacity: 0.45;
}
.process__etape:last-child::before { content: none; }
.process__noeud {
	position: absolute;
	top: 0;
	left: 0;
	width: 9px;
	height: 9px;
	background: var(--rouge);
	box-shadow: 0 0 0 5px var(--rouge-voile);
	transform: rotate(45deg);
}
.process__numero {
	display: block;
	margin-bottom: 0.4rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.14em;
	color: var(--rouge-texte);
}
.process__titre { font-size: 1.15rem; margin: 0 0 0.4rem; }
.process__texte { margin: 0; color: var(--encre-douce); line-height: 1.6; max-width: 52ch; }

/* Sur large : les étapes en rangée, le filet les traverse à l'horizontale. */
@media (min-width: 800px) {
	.process {
		grid-auto-flow: column;
		grid-auto-columns: 1fr;
		gap: 2rem;
	}
	.process__etape { padding: 2rem 1.5rem 0 0; }
	.process__etape::before {
		top: 4px;
		bottom: auto;
		left: 0;
		right: 0;
		width: auto;
		height: 1px;
		background: repeating-linear-gradient(90deg, var(--rouge) 0 5px, transparent 5px 11px);
	}
	.process__etape:last-child::before { content: ''; }
	.process__noeud { top: 0; }
}

/* ---- 3. RELEVÉ DE CONFORMITÉ (signature) ---- */

/*
 * ⚠️ « section.releve » ET NON « .releve ». Le nom est déjà pris : le SVG du
 * plan de diagnostic s'appelle .releve lui aussi (§ 24). Sans le qualificatif
 * de balise, le padding de 4,5 rem s'appliquait AU SVG — qui, sur la vitrine
 * mobile de l'accueil, n'a que 220 px de haut : il ne restait que 76 px de
 * dessin, un timbre-poste au milieu d'une carte vide. Les deux .releve__*
 * ci-dessous ne se croisent pas, eux ; seule la racine était en conflit.
 */
section.releve {
	position: relative;
	background: var(--nuit);
	color: rgba(255, 255, 255, 0.72);
	padding-block: 4.5rem;
	overflow: hidden;
}
/* La grille millimétrée en blanc léger : le plan, version nuit. */
.releve__grille {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
	background-size: 64px 64px;
	-webkit-mask-image: radial-gradient(130% 120% at 85% 0%, #000 0%, transparent 72%);
	mask-image: radial-gradient(130% 120% at 85% 0%, #000 0%, transparent 72%);
}
.releve__inner { position: relative; z-index: 1; display: grid; gap: 2.5rem; }
.surtitre--clair { color: var(--rouge); }
/* Pas de nœud du filet global sur le relevé sombre : il flotterait sans ligne. */
.releve .surtitre::after { content: none !important; }
.releve__titre {
	font-size: clamp(1.8rem, 3.2vw, 2.6rem);
	line-height: 1.08;
	margin: 0 0 1rem;
	color: var(--blanc);
}
.releve__chapo { margin: 0; max-width: 42ch; line-height: 1.6; color: rgba(255, 255, 255, 0.66); }
.releve__source {
	margin: 1.25rem 0 0;
	font-family: var(--font-mono);
	font-size: 0.75rem;
	letter-spacing: 0.06em;
	color: rgba(255, 255, 255, 0.4);
}
.releve__liste { margin: 0; padding: 0; list-style: none; display: grid; gap: 1px; background: var(--marine-ligne); border: 1px solid var(--marine-ligne); border-radius: var(--rayon); overflow: hidden; }
.releve__item {
	position: relative;
	display: grid;
	/* La colonne centrale doit pouvoir se comprimer : « Référence ·
	   legifrance.gouv.fr » fixait sa largeur minimale, et la liste — qui rogne
	   pour tenir ses coins arrondis — mangeait 15 px de chaque point de
	   conformité en dessous de 340 px. */
	grid-template-columns: auto minmax(0, 1fr) auto;
	gap: 1.1rem;
	align-items: start;
	padding: 1.5rem;
	background: rgba(255, 255, 255, 0.02);
}
.releve__index {
	font-family: var(--font-mono);
	font-size: 0.8rem;
	font-weight: 500;
	color: var(--rouge);
	padding-top: 0.15rem;
}
.releve__point { margin: 0 0 0.35rem; font-size: 1.05rem; color: var(--blanc); }
.releve__texte { margin: 0; font-size: 0.95rem; line-height: 1.6; color: rgba(255, 255, 255, 0.62); }
.releve__coche { flex: none; color: var(--rouge); opacity: 0.9; }

/*
 * Sur téléphone, la marge latérale du point de conformité est prise deux fois :
 * une fois par la gouttière de la page, une fois par le padding de la carte.
 * 1,5 rem de chaque côté, plus l'index et la coche qui bordent la colonne, ne
 * laissaient que ~200 px au texte — soit 28 caractères par ligne, une colonne
 * de journal. On rend la largeur au contenu ; la respiration verticale, elle,
 * ne bouge pas : c'est elle qui sépare les points les uns des autres.
 */
@media (max-width: 899px) {
	.releve__item {
		padding-inline: 1rem;
		gap: 0.75rem;
	}
}

/* Le lien vers la source officielle : mono, discret, il affiche le domaine. */
.releve__lien {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	margin-top: 0.85rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	letter-spacing: 0.04em;
	color: rgba(255, 255, 255, 0.55);
	text-decoration: none;
	border-bottom: 1px solid transparent;
	padding-bottom: 1px;
	transition: color var(--transition), border-color var(--transition);
}
.releve__lien svg { flex: none; color: var(--rouge); }
.releve__lien:hover,
.releve__lien:focus-visible {
	color: var(--blanc);
	border-color: var(--rouge);
}

@media (min-width: 900px) {
	.releve__inner { grid-template-columns: 0.85fr 1.15fr; gap: 4rem; align-items: start; }
	.releve__intro { position: sticky; top: 6rem; }
}

/* ---- 5. SECTEURS (liens) ---- */
.secteurs-liens {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 1rem;
	margin: 2.5rem 0 0;
	padding: 0;
	list-style: none;
}
.secteur-lien {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.1rem 1.35rem;
	border: 1px solid var(--trait);
	border-radius: var(--rayon);
	background: var(--blanc);
	color: var(--encre);
	text-decoration: none;
	font-weight: 600;
	transition: border-color var(--transition), transform var(--transition), box-shadow var(--transition);
}
.secteur-lien:hover,
.secteur-lien:focus-visible {
	border-color: var(--rouge);
	transform: translateY(-2px);
	box-shadow: var(--ombre);
}
.secteur-lien__fleche { flex: none; color: var(--rouge-texte); transition: transform var(--transition); }
.secteur-lien:hover .secteur-lien__fleche { transform: translateX(3px); }

@media (min-width: 1100px) {
	.service-hero { padding-top: calc(3.5rem + var(--entete-cache)); padding-bottom: 4rem; }
}

/*
 * ÉCRANS COURTS (15 pouces et moins, ~700 px de haut). Le héros doit tenir en
 * entier au premier coup d'œil, jusqu'aux repères — sans quoi la promesse
 * (« 20 ans », « 48 h ») passe sous le pli. On resserre donc padding, titre et
 * interlignes. Sur les grands écrans, rien ne change : la place ne manque pas.
 */
@media (min-width: 900px) and (max-height: 860px) {
	.service-hero { padding-top: calc(1.75rem + var(--entete-cache)); padding-bottom: 2.25rem; }
	/*
	 * Titre bridé pour que même le plus long (« Alarme intrusion connectée »)
	 * tienne sur UNE ligne : deux lignes de titre poussaient les repères sous le
	 * pli. Sur ces écrans courts, tous les services restent visibles d'un coup.
	 */
	.service-hero__titre { font-size: clamp(1.7rem, 2.5vw, 2.1rem); margin-bottom: 0.8rem; }
	.service-hero .surtitre { margin-bottom: 0.6rem; }
	.service-hero__chapo { font-size: 1.02rem; line-height: 1.45; margin-bottom: 0.8rem; }
	.service-hero__intro { margin-bottom: 1rem; }
	.service-hero__intro p { font-size: 0.92rem; line-height: 1.5; margin-bottom: 0.5rem; }
	.service-hero__actions { margin-bottom: 1.1rem; }
	.service-reperes { padding-top: 0.9rem; }
	.service-reperes__valeur { font-size: clamp(1.3rem, 1.9vw, 1.6rem); }
	.service-reperes__item--texte { padding-top: 0.7rem; }
}

@media (max-width: 640px) {
	.service-hero { padding-top: calc(2rem + var(--entete-cache)); padding-bottom: 3rem; }
	.service-reperes { gap: 1.5rem; }
}

/* =========================================================================
 * LE HÉROS DES SERVICES ET DES SECTEURS SUR TÉLÉPHONE
 *
 * Même traitement que le carrousel de l'accueil, pour la même raison : sur
 * 390 px il n'y a pas de « moitié droite » où reléguer la photo. Elle passe
 * donc en fond plein, sous un voile vertical, et le texte repasse au blanc.
 *
 * Avant, elle était posée SOUS le texte, en vignette de 16/10 : le héros
 * faisait 1 079 px de haut pour dire une prestation, et la photo arrivait
 * après les boutons — donc après la décision. En fond, elle accompagne la
 * lecture au lieu de l'allonger.
 *
 * Le « :has(.service-hero__media) » n'est pas un ornement : un service sans
 * photo doit garder le héros blanc du thème, texte à l'encre. Sans lui, on
 * aurait du blanc sur blanc.
 * ========================================================================= */
@media (max-width: 899px) {
	/*
	 * ⚠️ LE CONTENEUR REPASSE EN STATIQUE, ET C'EST LUI QUI COMPTE.
	 *
	 * « inset: 0 » se mesure depuis la boîte de padding du plus proche ancêtre
	 * POSITIONNÉ. Or « .service-hero__inner » est en relative : la photo se
	 * calait sur lui, donc SOUS les 2 rem de padding haut du héros — d'où une
	 * bande blanche entre le menu et la photo, et la même en bas. En rendant le
	 * conteneur statique, l'ancêtre positionné redevient « .service-hero » et
	 * la photo couvre le héros entier, padding compris.
	 *
	 * Son z-index tombe avec sa position : c'est « .service-hero__texte » qui
	 * porte l'empilement (voir plus bas), pas lui.
	 */
	.service-hero:has(.service-hero__media) .service-hero__inner {
		position: static;
	}

	.service-hero:has(.service-hero__media) .service-hero__media {
		position: absolute;
		inset: 0;
		z-index: 0;
		margin: 0;
	}

	.service-hero:has(.service-hero__media) .service-hero__img {
		height: 100%;
		aspect-ratio: auto;
		object-fit: cover;
		-webkit-mask-image: none;
		mask-image: none;
	}

	/* Le voile : plus dense en bas, là où vivent les repères et les boutons —
	   et là où ces photos d'équipement sont les plus claires. */
	.service-hero:has(.service-hero__media) .service-hero__media::after {
		content: '';
		position: absolute;
		inset: 0;
		background: linear-gradient(
			180deg,
			rgba(10, 12, 14, 0.66) 0%,
			rgba(10, 12, 14, 0.8) 45%,
			rgba(10, 12, 14, 0.9) 100%
		);
	}

	/*
	 * ⚠️ C'est le TEXTE qu'il faut élever, pas son conteneur. La photo est son
	 * FRÈRE et vient après lui dans le HTML : à z-index égal, c'est le dernier
	 * peint qui gagne, et le titre disparaissait sous la photo. Monter le
	 * conteneur commun n'y change rien — les deux sont dedans. C'est déjà ce
	 * que fait la règle desktop, pour la même raison.
	 */
	.service-hero:has(.service-hero__media) .service-hero__texte {
		position: relative;
		z-index: 1;
	}

	/* --- Le texte passe au blanc --- */
	.service-hero:has(.service-hero__media) .service-hero__titre,
	.service-hero:has(.service-hero__media) .service-hero__intro strong,
	.service-hero:has(.service-hero__media) .service-hero__intro b,
	.service-hero:has(.service-hero__media) .service-reperes__valeur {
		color: var(--blanc);
	}

	/*
	 * Sur la photo, les chiffres restent rouges — mais en --rouge de marque et
	 * non en --rouge-texte : ce dernier est calibré pour le fond clair et vire
	 * au brun dès qu'on le pose sur du sombre.
	 */
	.service-hero:has(.service-hero__media) .service-reperes__item:not(.service-reperes__item--texte) .service-reperes__valeur {
		color: var(--rouge);
	}

	.service-hero:has(.service-hero__media) .service-hero__chapo,
	.service-hero:has(.service-hero__media) .service-hero__intro p,
	.service-hero:has(.service-hero__media) .surtitre,
	.service-hero:has(.service-hero__media) .service-reperes__libelle,
	.service-hero:has(.service-hero__media) .fil-ariane a {
		color: rgba(255, 255, 255, 0.86);
	}

	/* Les filets du bloc repères, sur la photo. */
	.service-hero:has(.service-hero__media) .service-reperes,
	.service-hero:has(.service-hero__media) .service-reperes__item--texte {
		border-color: rgba(255, 255, 255, 0.28);
	}

	/* --- Les repères se resserrent --- */
	/* Ils tiennent le rôle des pastilles de l'accueil : des repères de lecture.
	   À leur taille d'origine ils pesaient autant que les boutons. */
	.service-hero .service-reperes { padding-top: 1rem; column-gap: 1.75rem; row-gap: 0.75rem; }

	/*
	 * ⚠️ Seuls les repères CHIFFRÉS. Un repère peut porter une phrase (« Paris ·
	 * IDF · toute la France ») : celui-là est en white-space: nowrap et compose
	 * déjà à une taille de texte. Lui appliquer 1,35 rem le faisait dépasser du
	 * héros — qui rogne, donc la phrase était coupée sans bruit.
	 */
	.service-hero .service-reperes__item:not(.service-reperes__item--texte) .service-reperes__valeur {
		font-size: 1.35rem;
	}

	/* Le héros compact rogne : le filet s'affine pour ne pas coûter de hauteur. */
	.service-hero .service-reperes__item:not(.service-reperes__item--texte) .service-reperes__valeur::after {
		width: 1.4rem;
		height: 2px;
		margin-top: 0.35rem;
	}

	.service-hero .service-reperes__libelle { font-size: 0.8rem; margin-top: 0.25rem; }

	/* --- Les boutons prennent la pleine largeur --- */
	.service-hero__actions {
		display: flex;
		flex-direction: column;
		align-items: stretch;
		gap: 0.75rem;
	}

	.service-hero__actions .bouton {
		width: 100%;
		justify-content: center;
	}

	.service-hero:has(.service-hero__media) .service-hero__actions .bouton--fantome {
		color: var(--blanc);
		border-color: rgba(255, 255, 255, 0.55);
		background: rgba(255, 255, 255, 0.08);
	}

	/* La grille millimétrée n'a plus de papier à quadriller : la photo occupe
	   le fond, le quadrillage la salirait. */
	.service-hero:has(.service-hero__media) .service-hero__grille { display: none; }
}


/* =========================================================================
 * VITRINE DU DIAGNOSTIC (accueil) — on MONTRE l'outil au lieu de le lier.
 * ========================================================================= */
.diag-vitrine__points { margin: 1.4rem 0 1.9rem; }
.diag-vitrine__chapo strong { color: var(--encre); font-weight: 700; }

.diag-vitrine__apercu { margin: 0; }
.diag-vitrine__entete {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	margin-bottom: 0.9rem;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}
.diag-vitrine__label { color: var(--encre-douce); }
.diag-vitrine__tag { color: var(--rouge-texte); }
.diag-vitrine__legende {
	margin: 0.85rem 0 0;
	font-family: var(--font-mono);
	font-size: 0.72rem;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--encre-douce);
}

/*
 * PRÉ-ALLUMAGE DU PLAN DE LA VITRINE — boutique, et TOUT l'équipement.
 *
 * Sans JavaScript : le module du diagnostic est gardé par « if (diagForm) », et
 * il n'y a pas de formulaire ici. C'est donc le CSS qui allume les calques.
 *
 * Seule la vidéosurveillance l'était — deux caméras et leurs cônes. La section
 * annonce pourtant « votre plan de sécurité » et vend un outil qui couvre les
 * cinq métiers : la vitrine montrait le cinquième de ce qu'elle promet. Tous
 * les calques sont désormais allumés — caméras, détecteurs d'ouverture et de
 * mouvement, sirène, centrale, contrôle d'accès, réseau, et l'anneau 24/7 —
 * soit onze repères au lieu de deux. C'est ce que le visiteur obtiendra s'il
 * coche tout, donc c'est une promesse tenable, pas une vitrine gonflée.
 *
 * Le sélecteur ne nomme plus les calques un par un : celui qu'on ajoutera au
 * plan demain s'allumera ici sans qu'on ait à y repenser.
 */
.diag-vitrine .releve__local[data-local="commerce"],
.diag-vitrine .releve__couche {
	opacity: 1;
	visibility: visible;
	transform: none;
}
.diag-vitrine .releve__attente { opacity: 0; visibility: hidden; }

@media (min-width: 900px) {
	.duo--diag { align-items: center; gap: 3.5rem; }
}
