/* ------------------------- Variables globales -------------------------- */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');

:root {
	/* Valeur de repli, identique à la valeur "neutre" posée sur .site-header
	   (cf. plus bas) : garantit que les widgets HUD (nav/compte/couleur/
	   langue/footer, tous position:fixed en dehors du DOM de .site-header)
	   résolvent toujours --header-accent, même sur une page sans classe
	   d'accent explicite sur <body> (cf. .accent-* plus bas, qui la
	   surchargent avec la vraie couleur active). */
	/* Bleu par défaut assombri (demande explicite : "uniquement pour la
	   couleur bleu, il faut choisir un autre bleu plus sombre" — suite au
	   nouvel habillage "nébuleuse" de .btn-account--primary, l'ancien bleu
	   #0b6efd/(11,110,253) ressortait trop clair/plat à côté des étoiles
	   blanches). Ancienne valeur #0b6efd / (11,110,253) → nouvelle #0a58ca /
	   (10,88,202), même teinte (ratio R:G:B conservé) juste réduite en
	   luminosité. Répercuté partout où CETTE valeur précise apparaît
	   (--title-accent plus bas, .site-header/.site-footer, la pastille
	   "Bleu" du sélecteur Mon profil) pour rester cohérent, mais SANS toucher
	   aux 5 autres couleurs ni au bleu FIXE #3b82f6/(59,130,246) utilisé par
	   ailleurs sur les pages vitrine (choix "Bleu" explicite dans Mon profil,
	   hors périmètre de cette demande). */
	--header-accent: 10, 88, 202;
	--brand-color: #0a58ca;
	--brand-color-soft: rgba(var(--header-accent), 0.15);
	--brand-color-glow: rgba(var(--header-accent), 0.35);
	/* Couleur de texte/icône à poser SUR un fond plein var(--brand-color)
	   (cf. .btn-account, .profile-avatar-initials, .review-avatar,
	   .comment-item--admin .comment-avatar, etc. — tous couplés à
	   "color: var(--brand-color-contrast, #fff)" plutôt qu'un blanc en dur).
	   #fff convient à toutes les teintes saturées existantes (bleu/ambre/
	   émeraude/violet/rouge) ; seule .user-accent-cyan (devenue "Blanc", cf.
	   Mon profil) la repasse en sombre, sans quoi le texte blanc deviendrait
	   illisible sur un fond blanc. */
	--brand-color-contrast: #fff;
	/* Accent du "prompt" terminal des titres h1/h2 (cf. règles h1::before,
	   h1::after, h2::before, h2{} plus bas) : par défaut identique au bleu
	   de marque, mais recoloré par les classes .accent-* posées sur <body>
	   (cf. partials/header.php / $bodyAccentCls) pour suivre l'accent de la
	   page active / de la préférence utilisateur, comme le header et le
	   footer. --title-accent-soft reprend séparément la teinte historique du
	   fond de h2 (légèrement différente du bleu de marque) pour ne rien
	   changer par défaut sur les pages sans accent dédié. */
	--title-accent: 10, 88, 202;
	--title-accent-soft: 59, 130, 246;
	/* Paire de couleurs "harmonisantes" par accent (demande explicite,
	   spécifiée littéralement pour chaque choix : bleu -> bleu/blanc,
	   blanc -> blanc/gris, orange -> jaune/orange, rouge -> rouge/noir,
	   vert -> vert/doré (2e teinte laissée à mon choix), violet ->
	   violet/rose (2e teinte laissée à mon choix) — recalculé pour chacune
	   des 6 couleurs via .accent-* ci-dessous. Sert aux CTA qui doivent
	   suivre la préférence choisie sans reprendre l'accent brut tel quel
	   (cf. .livre-dor-cta-btn plus bas). Valeur par défaut ici = paire pour
	   le bleu (couleur de base du site). */
	--accent-harmony-1: 59, 130, 246;
	--accent-harmony-2: 226, 232, 240;
	/* 3ème teinte (demande explicite, PRÉCISÉE depuis : "il faut que cela
	   soit du ton de la couleur principale sélectionnée donc un ton bleu
	   qui est une variante du bleu utilisé" — corrige un 1er essai qui
	   partait sur une teinte totalement différente, ex. violet pour le
	   bleu) : sert de couleur d'accent à .btn-accueil (cf. plus bas dans ce
	   fichier) à la place de --accent-harmony-2 — une VARIANTE (plus
	   sombre/plus claire) de la même famille de teinte que la couleur
	   principale (--header-accent/--accent-harmony-1), jamais une teinte
	   différente. Valeur par défaut ici = bleu plus profond (pour le thème
	   bleu de base, --accent-harmony-1 ci-dessus = 59,130,246). */
	--accent-harmony-3: 29, 78, 216;
	/* Couleur de texte à poser sur le dégradé --accent-harmony-1/-2 (cf.
	   .livre-dor-cta-btn) : blanc par défaut, repassé en sombre par les
	   paires trop claires (blanc/gris, jaune/orange) où un texte blanc
	   deviendrait illisible — même principe que --brand-color-contrast. */
	--accent-harmony-contrast: #fff;
	--text-color: #ffffff;
	--text-muted: rgba(255,255,255,0.75);
	--background: #070a12;
	--muted: rgba(255,255,255,0.75);
	--radius: 14px;
	--gap: 1rem;
    --font-body: "Inter", system-ui, sans-serif;
	--font-title: "JetBrains Mono", "Fira Code", monospace;
	--font-title-classic: "Space Grotesk", sans-serif;
	/* Fond spatial générique "bgsiteindex" (starfield), repris tel quel dans
	   des dizaines de sections partout sur le site (index.php, offres-site.php,
	   sitevitrine/pro/surmesure, hm.php, conseilaccompagnement.php, plusieurs
	   sections d'accueil.php...). Variable plutôt qu'un url() en dur dans
	   chacune de ces règles : une seule origine à recolorer pour suivre la
	   couleur choisie en Mon profil (cf. .img-accent-* plus bas et
	   $_imgAccentColor dans partials/header.php), sans toucher aux autres
	   calques (gradients/overlays) de chaque règle. Pas de variante "bleu"
	   dédiée : ce fichier neutre EST déjà le bleu par défaut. */
	--space-bg: url("../image/bgsiteindex.png");
	/* --cockpit-bg RETIRÉE (demande explicite : tous les fichiers
	   cockpit_*.png/grandcockpit.png ont été supprimés du dossier image) —
	   le hero d'accueil.php (seul utilisateur de cette variable, cf. main
	   .hero plus bas) réutilise désormais --space-bg ci-dessus. */
}

.site-main {
	position: relative;
	overflow: clip;
}

/* ─── BACKGROUND FIXE : accueil.php (même logique que le reste du site,
   cf. .page-offers::before / .page-vitrine::before / etc.) : bgsite.png
   en fond fixe sur toute la page plutôt qu'un visuel dédié à l'accueil. */
.site-main::before {
	content: "";
	position: fixed;
	inset: 0;
	/* var(--space-bg) plutôt que bgsite.png en dur (même image de base,
	   juste un cadrage légèrement différent) : cette couche générique est
	   celle qui couvre notamment les dashboards (compte-*.php/admin-*.php,
	   qui n'ont pas de hero dédié) — elle doit donc suivre la couleur
	   choisie en Mon profil comme le reste du site (cf. .img-accent-*). */
	background:
		linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
		var(--space-bg) center / cover no-repeat;
	z-index: 0;
}
.site-main > * {
	position: relative;
	z-index: 1;
}

/* ─── Espace réservé en bas de page pour le footer flottant ───
   Le footer flottant a depuis été nettement simplifié/réduit (widgets
   consolidés, contenu recentré, cf. historique des demandes explicites sur
   .site-footer) — l'ancienne valeur (480/680/980px) datait d'une version
   bien plus haute et laissait un vide excessif en fin de page partout sur
   le site (demande explicite : "il n'y a plus besoin du global... ou alors
   il faut le diminuer"). Valeur réduite pour coller à la hauteur réelle du
   footer actuel, avec une marge de sécurité raisonnable ; certaines pages
   (register.php ci-dessous) gardent un override local si leur dernière
   section a besoin d'un peu plus de marge. */
:root {
	--footer-clearance: 260px;
}

@media (max-width: 992px) {
	:root { --footer-clearance: 360px; }
}

@media (max-width: 480px) {
	:root { --footer-clearance: 520px; }
}

/* register.php (demande explicite "diminue légèrement l'écart avec le
   footer") : la valeur globale ci-dessus a depuis été réduite, mais
   .register-split (via var(--footer-clearance) en padding-bottom, cf. plus
   bas dans ce fichier) a besoin d'un peu plus de marge que les autres pages
   pour éviter que le footer flottant ne recouvre le formulaire — override
   local conservé pour cette page uniquement. */
.site-main[data-page="register.php"] {
	--footer-clearance: 380px;
}
@media (max-width: 992px) {
	.site-main[data-page="register.php"] { --footer-clearance: 560px; }
}
@media (max-width: 480px) {
	.site-main[data-page="register.php"] { --footer-clearance: 820px; }
}

*, *::before, *::after {
  box-sizing: border-box;
}

/* font-size fixe (demande explicite : nav "travail" du compte client trop
   grande sur Chrome par rapport à Edge). Cause identifiée : tout le site est
   dimensionné en `rem`, or aucune règle ne fixait jusqu'ici la taille de
   référence (1rem) — elle dépendait donc entièrement du réglage "Taille de
   police" du navigateur (chrome://settings/fonts, distinct du zoom Ctrl+/-),
   qui peut différer d'un navigateur à l'autre sur une même machine même sans
   action volontaire de l'utilisateur. En la fixant ici à 16px (valeur par
   défaut standard), tous les `rem` du site deviennent identiques sur
   Chrome/Edge/Firefox quel que soit ce réglage — le zoom navigateur
   (Ctrl+/-, pincer-zoomer) continue lui de fonctionner normalement pour
   l'accessibilité, seul ce réglage de "taille par défaut" est neutralisé. */
html{
	font-size: 16px;
	/* overflow-x: clip -> hidden (correctif) : "clip" sur <html> a un effet
	   de bord documenté sur Android Chrome — au-delà d'empêcher le
	   débordement horizontal DE LA PAGE (effet recherché ici, contre le
	   débordement d'éléments décoratifs), certaines versions du moteur
	   propagent cette restriction à la logique de routage des gestes
	   tactiles pour TOUTE LA PAGE, y compris des conteneurs enfants ayant
	   pourtant leur propre overflow-x:auto indépendant (ex. les bandes de
	   nav du dashboard, .account-sidenav-links) — le swipe horizontal n'y
	   fonctionne alors plus DU TOUT, malgré un CSS par ailleurs correct sur
	   l'élément lui-même. "hidden" empêche exactement le même débordement
	   de page sans ce comportement de bord touch-spécifique. */
	overflow-x: hidden;
}

html, body {
	scroll-behavior: smooth;
	height: auto;
	margin: 0;
	padding: 0;
	color: var(--text-color);
	background: #070a12;
    font-family: var(--font-body);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;


}

body {
	/* Même filet que ci-dessus, posé aussi sur body (pattern robuste
	   habituel : html+body ensemble plutôt que html seul) — inoffensif si
	   déjà couvert par html, mais évite de dépendre d'un seul point pour
	   contenir un débordement horizontal décoratif. */
	overflow-x: hidden;
}


h1, h2, h3 {
	font-family: var(--font-title);
}

/* Les h3 (sous-titres de cartes, labels) gardent la typo "classique" :
   le traitement "terminal" (police mono + prompt + curseur) ne s'applique
   qu'aux h1 et aux titres de section (h2), pas aux sous-titres h3. */
h3 {
	font-family: var(--font-title-classic);
}

h2{
	background: rgba(var(--title-accent-soft), 0.10);
	box-shadow: 0 0 14px rgba(var(--title-accent-soft), 0.15);
	transition: background-color .4s ease, box-shadow .4s ease;
}

/* ─── Titres "tech" / terminal ───
   h1 = titre de page/hero avec curseur clignotant ; h2 = titre de section
   avec un prompt discret. Les pseudo-éléments ne récupèrent pas le
   background-clip:text du parent : couleur explicite nécessaire. */
h1 {
	position: relative;
}

h1::before {
	content: "> ";
	color: rgb(var(--title-accent));
	-webkit-text-fill-color: rgb(var(--title-accent));
	font-weight: 700;
	transition: color .4s ease;
}

h1::after {
	content: "";
	display: inline-block;
	width: 0.5em;
	height: 0.85em;
	margin-left: 0.12em;
	background: rgb(var(--title-accent));
	vertical-align: -0.1em;
	animation: title-cursor-blink 1s step-end infinite;
	transition: background-color .4s ease;
}

@keyframes title-cursor-blink {
	50%, 100% { opacity: 0; }
	0%, 49% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	h1::after {
		animation: none;
	}
}

h2::before {
	content: "// ";
	color: rgb(var(--title-accent));
	-webkit-text-fill-color: rgb(var(--title-accent));
	opacity: 0.65;
	font-weight: 600;
	font-size: 0.85em;
	transition: color .4s ease;
}

/* ─── Titres "planète de la page" (sitevitrine.php / sitepro.php / surmesure.php)
   Remplace le préfixe générique "// " par l'icône planète propre à chaque
   offre (même planète que le hero de la page : planet-eau pour Essentiel,
   planet-mars pour Business, planet-terre pour Sur-mesure) sur les titres
   "Modules disponibles", "À quoi ressemble un site…"/"Chaque projet
   sur-mesure…" et le h2 du CTA final. L'icône est un <img> inséré en tout
   premier enfant du h2 (donc en dehors des nœuds de texte parcourus par
   l'effet machine à écrire de main.js, qui ne touche que le texte et
   laisse l'image intacte). */
.h2-planet-title::before {
	content: none;
}
.h2-planet-icon {
	width: 1.05em;
	height: 1.05em;
	object-fit: contain;
	vertical-align: -0.18em;
	margin-right: 0.3em;
	display: inline-block;
}

/* ─── Planètes de fond des hero "titres" (refonte.php / audit-site.php /
   conseil.php / accompagnement.php / hebergement.php / maintenance.php /
   programmation.php / bot-discord.php) — Même logique que les planètes
   ci-dessus, mais en fond du hero (juste après la nav inter-pages
   .hmg-nav) plutôt qu'en icône de h2. Léger (opacity) pour ne pas nuire à
   la lisibilité du texte par-dessus, qui passe naturellement au-dessus
   car ::before est toujours peint en premier (aucun z-index dédié requis
   sur .cw-hero-inner / etc.). Les pages "hub" (offres-site.php, hm.php)
   reçoivent la même illustration-galaxie que les bulles de titre de
   offres-site.php (cf. .section-title--essentiel plus bas dans ce
   fichier), pour marquer visuellement un point d'entrée vers plusieurs
   offres plutôt qu'une offre unique — sauf conseilaccompagnement.php, qui
   reprend plutôt la planète de catégorie (cf. plus bas). */
.page-refonte .cw-hero,
.page-conseil .cw-hero,
.page-accomp .cw-hero,
.page-heberg .heberg-hero,
.page-maint .maint-hero,
.page-hm .hm-hero,
.page-programmation .cw-hero {
	position: relative;
}
.page-refonte .cw-hero::before,
.page-conseil .cw-hero::before,
.page-accomp .cw-hero::before,
.page-heberg .heberg-hero::before,
.page-maint .maint-hero::before,
.page-hm .hm-hero::before,
.page-programmation .cw-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	background-repeat: no-repeat;
	background-position: center;
	background-size: cover;
	opacity: .2;
	z-index: 0;
	pointer-events: none;
}

/* offres-site.php : la galaxie couvre tout .offer-intro-block (hero +
   .offer-levels), pas seulement le hero — sur cette page le fond doit
   courir jusqu'au premier divider (.divider-to-table), qui suit
   immédiatement .offer-intro-block dans le markup. */
.page-offers .offer-intro-block {
	position: relative;
}
/* TEST : galaxie retirée de .offer-intro-block (elle prenait trop de
   place, concentrée sur cette seule section) et déplacée en fond de
   PAGE entier — cf. .page-offers::before plus bas dans ce fichier.
   content:none supprime proprement ce pseudo-élément (plus de calque à
   cet endroit). Ancienne version (image + vignette anti-bord déchiqueté
   dans cette section) : à restaurer si le test page entière ne convainc
   pas. */
.page-offers .offer-intro-block::before {
	content: none;
}

/* TEST : planètes de refonte.php / audit-site.php retirées du hero (trop
   concentrées/imposantes sur cette seule section, même constat que pour
   offres-site.php/hm.php ci-dessus) et déplacées en fond de PAGE entier —
   cf. .page-refonte::before/::after plus bas dans ce fichier. Chaque page
   garde SA planète dédiée (magma pour refonte.php, business pour
   audit-site.php), juste affichée en plein fond désormais au lieu d'être
   cantonnée au hero. background-image:none neutralise juste l'image (comme
   pour .page-hm .hm-hero::before), le reste de la règle partagée plus haut
   (opacity, cover...) ne sert donc plus mais reste inoffensif. */
.page-refonte:not(.page-audit-site) .cw-hero::before {
	background-image: none;
}
.page-audit-site .cw-hero::before {
	background-image: none;
}

/* Conseil, Accompagnement, Programmation, Hébergement, Maintenance :
   planètes de hero retirées (même traitement que refonte.php/audit-site.php/
   hm.php ci-dessus — trop concentrées/imposantes sur cette seule section).
   background-image:none neutralise juste l'image, le reste de la règle
   partagée plus haut (opacity, cover...) reste inoffensif. */
.page-conseil-hub .cw-hero::before,
.page-conseil:not(.page-conseil-hub) .cw-hero::before,
.page-accomp .cw-hero::before,
.page-programmation:not(.page-bot-discord) .cw-hero::before,
.page-bot-discord .cw-hero::before,
.page-heberg .heberg-hero::before,
.page-maint .maint-hero::before {
	background-image: none;
}

/* TEST : galaxie retirée de .hm-hero (trop concentrée/imposante sur cette
   seule section) et déplacée en fond de PAGE entier — cf. .page-hm::before
   plus bas dans ce fichier. La règle partagée plus haut (opacity .2,
   cover, etc.) reste posée sur .hm-hero::before mais sans image à
   afficher : background-image:none neutralise juste l'image (au lieu de
   content:none) pour rester cohérent avec l'usage de background-image
   comme SEULE propriété redéfinie par page dans ce bloc. */
.page-hm .hm-hero::before {
	background-image: none;
}

/* ─── Effet machine à écrire ───
   Le texte des h1/h2 est révélé caractère par caractère par main.js quand
   le titre entre dans le viewport (le préfixe "> "/"// " et, pour le h1,
   le curseur clignotant restent gérés en CSS pur, inchangés). Pendant la
   frappe (.typing-run), le h2 reçoit lui aussi un curseur clignotant
   temporaire pour renforcer l'effet terminal ; il disparaît une fois le
   titre entièrement affiché (.typing-done), comme dans un vrai terminal. */
h2.typing-run::after {
	content: "";
	display: inline-block;
	width: 0.45em;
	height: 0.8em;
	margin-left: 0.12em;
	background: rgb(var(--title-accent));
	vertical-align: -0.05em;
	animation: title-cursor-blink 1s step-end infinite;
}

@media (prefers-reduced-motion: reduce) {
	h2.typing-run::after {
		animation: none;
	}
}

/* ─── Accent des titres (prompt terminal h1/h2) selon la page active /
   préférence utilisateur ─── posé sur <body> par partials/header.php
   ($bodyAccentCls), en miroir des classes .site-header--x / .site-footer--x.
   Les deux variables sont recolorées ensemble : plus de distinction entre
   le "bleu de marque" et le "bleu tint par défaut" une fois un accent dédié
   actif. */
.accent-amber    { --title-accent: 245, 158, 11;  --title-accent-soft: 245, 158, 11;  --header-accent: 245, 158, 11; --accent-harmony-1: 250, 204, 21;  --accent-harmony-2: 249, 115, 22; --accent-harmony-3: 194, 65, 12;   --accent-harmony-contrast: #0f172a; --offer-tint-dim: 162, 75, 14;   --offer-tint-mid: 249, 115, 22;  --offer-tint-neon: 255, 205, 14; }
.accent-emerald  { --title-accent: 16, 185, 129;  --title-accent-soft: 16, 185, 129;  --header-accent: 16, 185, 129; --accent-harmony-1: 34, 197, 94;   --accent-harmony-2: 163, 230, 53; --accent-harmony-3: 5, 150, 105;   --accent-harmony-contrast: #0f172a; --offer-tint-dim: 106, 150, 34;  --offer-tint-mid: 163, 230, 53;  --offer-tint-neon: 21, 241, 168; }
/* --brand-color-contrast ajoutée ici (bug réel signalé : "langue active" et
   "effet page active" de CroisierWeb illisibles — texte blanc sur fond
   devenu quasi blanc) — jusqu'ici seules .user-accent-cyan/.page-accent-cyan
   (préférence EXPLICITE de couleur, cf. plus bas) la repassaient en sombre ;
   .accent-cyan, elle, est posée sur <body> dans TOUS les cas où "Blanc" est
   la couleur active (y compris l'accent PAR DÉFAUT d'une page, ex.
   hebergement.php/maintenance.php, SANS choix explicite du visiteur — cf.
   partials/header.php, $bodyAccentCls), donc le seul endroit garantissant
   une correction dans TOUS les cas, pas seulement la préférence explicite. */
.accent-cyan     { --title-accent: 232, 237, 245; --title-accent-soft: 232, 237, 245; --header-accent: 232, 237, 245; --accent-harmony-1: 241, 245, 249; --accent-harmony-2: 100, 116, 139; --accent-harmony-3: 219, 234, 254; --accent-harmony-contrast: #0f172a; --brand-color-contrast: #0f172a; --offer-tint-dim: 65, 75, 90;    --offer-tint-mid: 100, 116, 139; --offer-tint-neon: 255, 255, 255; }
.accent-gold     { --title-accent: 185, 28, 28;  --title-accent-soft: 185, 28, 28;  --header-accent: 185, 28, 28; --accent-harmony-1: 239, 68, 68;   --accent-harmony-2: 30, 30, 30; --accent-harmony-3: 127, 29, 29;   --accent-harmony-contrast: #fff; --offer-tint-dim: 20, 20, 20;    --offer-tint-mid: 30, 30, 30;    --offer-tint-neon: 241, 36, 36; }
.accent-blue     { --title-accent: 59, 130, 246;  --title-accent-soft: 59, 130, 246;  --header-accent: 59, 130, 246; --accent-harmony-1: 59, 130, 246;  --accent-harmony-2: 226, 232, 240; --accent-harmony-3: 29, 78, 216;   --accent-harmony-contrast: #fff; --offer-tint-dim: 147, 151, 156; --offer-tint-mid: 226, 232, 240; --offer-tint-neon: 77, 169, 255; }
/* Violet : demande explicite "inverse, violet pour Premium et Essentiel et
   rose pour Business" — seul thème où -mid/-neon ne suivent pas la règle
   générale (mid=secondaire/harmony-2, neon=principale boostée, cf.
   commentaire détaillé plus bas) : -mid vaut ici la couleur PRINCIPALE
   (violet, = --header-accent) et -neon la couleur SECONDAIRE (rose, =
   --accent-harmony-2), toutes deux non boostées, littéralement échangées
   par rapport aux 5 autres thèmes. */
.accent-violet   { --title-accent: 139, 92, 246;  --title-accent-soft: 139, 92, 246;  --header-accent: 139, 92, 246; --accent-harmony-1: 139, 92, 246;  --accent-harmony-2: 236, 72, 153; --accent-harmony-3: 109, 40, 217;  --accent-harmony-contrast: #fff; --offer-tint-dim: 153, 47, 99;   --offer-tint-mid: 139, 92, 246;  --offer-tint-neon: 236, 72, 153; }
/* --offer-tint-dim/-mid/-neon (ci-dessus, sur chaque .accent-*) : demande
   explicite (2e passe, remplace la 1ère version basée sur la couleur
   secondaire pour -neon) "essaie avec les mêmes teintes pour Essentiel et
   Premium, et une teinte néon (de la couleur PRINCIPALE) pour Business" :
   -mid = --accent-harmony-2 (couleur secondaire) telle quelle, utilisée à
   la fois par Essentiel ET Premium (même teinte pour les deux désormais,
   cf. .rocketv-sas--1/--3 et .pricing-card--1/--3 plus bas) ; -neon = une
   version éclaircie/boostée de --header-accent (couleur PRINCIPALE, pas la
   secondaire), calculée uniformément pour les 6 couleurs par un simple
   ×1.3 (canal par canal, plafonné à 255) — fonctionne aussi bien sur les
   teintes déjà vives (amber/emerald/gold/blue/violet, qui gagnent en
   luminosité tout en gardant leur saturation) que sur la teinte cyan/blanc
   déjà très claire (qui plafonne naturellement vers un blanc pur
   255,255,255, une lueur "néon blanche" cohérente pour ce thème pâle).
   -dim reste défini (assombri ~65% de -mid) mais n'est plus consommé par
   cette section pour l'instant (Premium utilise désormais -mid comme
   Essentiel) — conservé au cas où. Seule la section "3 trajectoires de
   lancement" d'accueil.php (.rocketv-sas--1/-2/-3, .pricing-card--1/-2/-3,
   cf. plus bas) les consomme pour l'instant : services.php et les pages
   offres (sitevitrine/sitepro/surmesure) seront adaptées plus tard
   (demande explicite). */
/* --accent-harmony-1/-2 (ci-dessus, sur chaque .accent-*) : paires
   spécifiées littéralement par choix (demande explicite, confirmées/
   revérifiées) — bleu: bleu/blanc, blanc(cyan): blanc/gris, orange(amber):
   jaune/orange, rouge(gold): rouge/noir, vert(emerald): vert/citron,
   violet: violet/rose. Remplace le schéma split-complémentaire calculé du
   tour précédent. */
/* --header-accent ci-dessus dupliqué depuis .site-header--x (cf. plus bas
   dans ce fichier) plutôt que fusionné avec --title-accent : "gold" a
   volontairement 2 teintes différentes selon le système (251,191,36 ambré
   pour le titre, 185,28,28 rouge-noir/magma pour le header) — distinction
   déjà en place avant ce widget, conservée ici à l'identique. Cette
   duplication rend --header-accent disponible sur <body> (donc sur TOUT
   élément position:fixed hors du DOM de .site-header, ex. les widgets HUD
   nav/compte/couleur/langue/footer) sans dépendre de la présence réelle de
   l'élément <header> dans la page. */

/* ─── Images d'identité (logo/fond spatial "bgsiteindex") selon la couleur
   choisie en Mon profil (cf. $_imgAccentColor dans partials/header.php) —
   posées pour les 6 couleurs SANS exception, y compris "bleu"
   (contrairement à .user-accent-* / .accent-* plus haut, qui traitent le
   bleu comme "pas de préférence").
   --space-bg RETIRÉ de ces 5 règles (demande explicite : "j'ai supprimé
   tout les bgsiteindex de couleur") — les fichiers bgsiteindex_violet/
   orange/rouge/vert/blanc.png ont été supprimés du disque, seul le fichier
   neutre bgsiteindex.png (valeur par défaut tout en haut du fichier)
   subsiste désormais. Sans override ici, TOUTES les couleurs retombent
   proprement sur ce même fond neutre (plus aucune référence à un fichier
   inexistant, donc plus de fond cassé/manquant selon la couleur choisie).
   --cockpit-bg et ses 5 variantes RETIRÉS de ce fichier (demande explicite :
   "j'ai supprimé du dossier image toutes les images cockpit et cockpit de
   couleur") — les fichiers cockpit_*.png/grandcockpit.png ont tous été
   supprimés du disque ; le hero de accueil.php (seule page à les utiliser,
   cf. main .hero plus bas) retombe désormais sur --space-bg comme le reste
   du site, plus aucune référence à un fichier inexistant. */

/* ─── Trou noir (halo/lueur + bande horizontale) d'index.php et accueil.php
   selon la couleur choisie en Mon profil ─── 5 teintes réutilisables
   (--hole-light/-mid/-soft/-base/-glow, triplets "R, G, B" sans rgba() pour
   pouvoir être recombinés à différentes opacités) partagées par les DEUX
   pages via rgba(var(--hole-x, repli-couleur-de-la-page), alpha) : chaque
   page fournit son PROPRE repli (bleu pour index.php, ambre pour
   accueil.php, cf. .index-hero-black-hole/.home-hero-halo plus bas) —
   quand une préférence explicite est active ici, elle prend le dessus sur
   CES DEUX replis à la fois puisque c'est la même variable. Pas de règle
   .img-accent-blue avant ce point (le bleu n'avait besoin d'aucun autre
   override) : ajoutée ici uniquement pour ces 5 teintes, nécessaire pour
   qu'un choix explicite "Bleu" recolore aussi le trou noir d'accueil.php
   (ambre par défaut). */
/* Recolorées (demande explicite : "adapter les trous noirs aux couleurs
   bleu/blanc, blanc/gris, vert/citron, violet/rose, rouge/noir,
   orange/jaune") pour que chaque disque d'accrétion affiche VRAIMENT les 2
   teintes nommées de la paire --accent-harmony-1/-2 (cf. .accent-* tout en
   haut de ce fichier), pas juste un dégrédé de nuances d'une seule couleur
   comme avant (ex. émeraude/violet/rouge ne montraient jusqu'ici aucune
   trace de leur 2e teinte citron/rose/noir). Convention gardée identique
   pour les 6 : --hole-base = la teinte la plus saturée/sombre de la paire
   (anneau principal), --hole-light = la teinte la plus claire de la paire
   (anneau le plus lumineux), --hole-mid/-soft = paliers intermédiaires
   entre les 2, --hole-glow = teinte du halo (box-shadow), assez lumineuse
   pour rester visible sur fond noir même quand --hole-base est très sombre
   (cas "rouge/noir" ci-dessous). */
.img-accent-blue    { --hole-light: 226,232,240; --hole-mid: 130,175,248; --hole-soft: 80,150,246;  --hole-base: 59,130,246;  --hole-glow: 90,160,255; }
.img-accent-violet  { --hole-light: 255,200,225; --hole-mid: 200,130,220; --hole-soft: 170,110,235; --hole-base: 139,92,246;  --hole-glow: 220,120,200; }
.img-accent-amber   { --hole-light: 255,230,120; --hole-mid: 255,190,70;  --hole-soft: 255,165,50;  --hole-base: 250,140,30;  --hole-glow: 255,170,60; }
.img-accent-gold    { --hole-light: 255,110,100; --hole-mid: 150,50,45;   --hole-soft: 70,25,25;    --hole-base: 35,25,25;    --hole-glow: 220,50,45; }
.img-accent-emerald { --hole-light: 210,245,120; --hole-mid: 120,225,75;  --hole-soft: 60,205,90;   --hole-base: 34,197,94;   --hole-glow: 140,225,70; }
.img-accent-cyan    { --hole-light: 255,255,255; --hole-mid: 200,210,225; --hole-soft: 150,165,185; --hole-base: 100,116,139; --hole-glow: 210,218,230; }

/* ─── Couleur de header choisie par le client (Mon profil) : propagée aux
   boutons/liens/badges de TOUT le site ─── posée en PLUS de .accent-* (qui ne
   recolore que le "prompt" des titres) uniquement quand la couleur vient
   d'une préférence utilisateur explicite (jamais pour l'accent par défaut
   d'une page publique, pour ne pas changer le rendu vu par un visiteur
   anonyme). --brand-color/-soft/-glow pilotent la quasi-totalité des boutons,
   liens et badges du site (cf. usages de var(--brand-color) dans ce fichier). */
.user-accent-amber    { --brand-color: #f59e0b; --brand-color-soft: rgba(245,158,11,.15); --brand-color-glow: rgba(245,158,11,.35); }
.user-accent-emerald  { --brand-color: #10b981; --brand-color-soft: rgba(16,185,129,.15); --brand-color-glow: rgba(16,185,129,.35); }
.user-accent-cyan     { --brand-color: #e8edf5; --brand-color-soft: rgba(232,237,245,.15); --brand-color-glow: rgba(232,237,245,.35); --brand-color-contrast: #0f172a; }
/* #b91c1c (rouge), pas #fbbf24 (ambre) : "gold" est le nom interne du choix
   affiché "Rouge" dans le widget couleur (cf. --header-accent: 185,28,28
   plus haut, .accent-gold) — --brand-color pilote la quasi-totalité des
   boutons/liens du site (highlights inclus, cf. .site_description .highlight
   plus bas) et doit suivre la même teinte rouge, pas l'ancien ambre "gold"
   d'origine. Bug réel remonté explicitement ("pourquoi les highlights sont
   en jaune pour le rouge ?"), pas juste esthétique. */
.user-accent-gold     { --brand-color: #b91c1c; --brand-color-soft: rgba(185,28,28,.15); --brand-color-glow: rgba(185,28,28,.35); }
.user-accent-violet   { --brand-color: #8b5cf6; --brand-color-soft: rgba(139,92,246,.15); --brand-color-glow: rgba(139,92,246,.35); }

/* Formulaire de devis (partials/order-form.php, sitevitrine/sitepro/surmesure) :
   les boutons et accents du formulaire reprennent la couleur de la page active
   (cyan / gold), sans effet sur le reste du site (portée limitée à la section). */
.page-accent-cyan { --brand-color: #e8edf5; --brand-color-soft: rgba(232,237,245,.15); --brand-color-glow: rgba(232,237,245,.35); --brand-color-contrast: #0f172a; }
/* #b91c1c (rouge), pas #fbbf24 (ambre) : même bug/correctif que
   .user-accent-gold plus haut (cf. son commentaire) — "gold" = "Rouge"
   partout dans le système de couleurs, cette règle-ci avait été oubliée
   lors du renommage, laissant le formulaire de devis de sitepro.php
   afficher l'ancien jaune/ambre "gold" au lieu du rouge attendu (demande
   explicite, "la logique n'est pas respectée"). */
.page-accent-gold { --brand-color: #b91c1c; --brand-color-soft: rgba(185,28,28,.15); --brand-color-glow: rgba(185,28,28,.35); }
.order-form-section .account-checkbox-label input[type="checkbox"]:hover { border-color: var(--brand-color); }
.order-form-section .account-module-card:has(input[type="checkbox"]:checked) { border-color: var(--brand-color); background: var(--brand-color-soft); }
.order-form-section .module-tier-badge--standard { border-color: var(--brand-color-soft); }
.order-form-section .account-request-details summary:hover { border-color: var(--brand-color); }



/* ------------------------- Accessiblité-- */

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

/* ========================= séparateur section ========================= */

.section-divider {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 10px;
    z-index: 3;
}

/* ─── BULLE DU DIVIDER ───
   Avant : un pill quasi invisible (padding 5-8px) autour d'une icône de
   64px — le fond bleu très pâle ne formait pas vraiment une "bulle"
   lisible. Désormais un vrai badge rond avec halo, cohérent avec le reste
   des composants circulaires du site (ex. photo de about.php). */
.divider-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 62px;
    height: 62px;
    padding: 0;
    border-radius: 50%;
    background: radial-gradient(circle at 50% 35%, rgba(var(--header-accent),.24) 0%, rgba(var(--header-accent),.12) 62%, rgba(var(--header-accent),.07) 100%);
    border: 1px solid rgba(var(--header-accent),.32);
    box-shadow: 0 8px 26px rgba(var(--header-accent),.16), inset 0 1px 0 rgba(255,255,255,.08);
    color: #fdfdfd;
    text-decoration: none;
    position: relative;
    cursor: pointer;
    transition: background .3s ease, border-color .3s ease, box-shadow .3s ease, color .3s ease;
    animation: floatUpDown 1.0s infinite;
}

/* ─── TEXTE DU DIVIDER ───
   Avant : un pill quasi noir (fond rgba(7,10,18,.85)) posé juste sous la
   bulle bleue, sans lien visuel avec elle. Désormais une étiquette dans la
   même famille bleue que la bulle, pour lire "bulle + texte" comme un seul
   composant plutôt que deux éléments disjoints. */
.divider-action::after {
    content: attr(data-tooltip);
    position: absolute;
    top: calc(100% + 14px);
    left: 50%;
    transform: translateX(-50%);

    background: rgba(var(--header-accent),.10);
    color: rgba(255,255,255,.72);
    padding: 6px 16px;
    border-radius: 999px;
    font-size: .70rem;
    font-weight: 700;
    white-space: nowrap;
    letter-spacing: .07em;
    text-transform: uppercase;

    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(var(--header-accent),.20);

    pointer-events: none;
    transition: background .25s ease, border-color .25s ease, color .25s ease;
}

.divider-action:hover::after {
    background: rgba(var(--header-accent),.20);
    border-color: rgba(var(--header-accent),.42);
    color: #ffffff;
}

/* Étiquette "En savoir plus" du tout premier divider (section hero
   d'accueil.php, cible #solution) remontée très légèrement — scopé à
   .hero pour ne pas déplacer l'étiquette des 7 autres dividers de la
   page (ni celles des autres pages), qui réutilisent .divider-action. */
.hero .divider-action::after {
    top: calc(100% + 8px);
}

.divider-action:hover {
    color: rgb(var(--header-accent));
    background: radial-gradient(circle at 50% 35%, rgba(var(--header-accent),.34) 0%, rgba(var(--header-accent),.18) 62%, rgba(var(--header-accent),.09) 100%);
    border-color: rgba(var(--header-accent),.55);
    box-shadow: 0 15px 40px rgba(var(--header-accent),0.28), inset 0 1px 0 rgba(255,255,255,.12);
}

.divider-action .rocket-icon {
    width: 40px;
    height: 40px;
    transform: rotate(180deg) scale(0.8);
    transition: transform 0.2s ease;
}

.divider-action:hover .rocket-inner {
    animation: shakeSoft 0.5s infinite;
}

.section-divider .rocket-wrapper.launch.down,
.hero .rocket-wrapper.launch.down,
.scroll-bottom-banner .rocket-wrapper.launch.down {
    filter: drop-shadow(0 10px 20px rgba(0,0,0,0.2));
    animation: rocketLaunchDown 2s ease-in forwards;
    will-change: transform;
}

/* ─── DIVIDERS COLORÉS SELON LA SECTION DE DESTINATION ───
   Historique : le divider de #why-target menait autrefois à #new-hebergement
   (thème cyan/bleu fixe rgba(59,130,246), d'où l'override ci-dessous). Depuis
   la relocalisation de "De l'idée à la mise en orbite" (#method-heading)
   entre #why-target et le livre d'or (demande explicite, cf. reorder de
   cette session), ce divider mène désormais à #method-heading — une
   section sans thème de couleur dédié — et affiche le tooltip "Prêt à
   commencer ?". Override bleu fixe retiré (demande explicite : "le divider
   [...] ne s'adapte pas à la couleur sélectionnée") : retombe sur le bleu
   PAR DÉFAUT accent-aware de .divider-action (comme les autres dividers
   génériques de la page), au lieu d'un bleu figé indépendant du sélecteur.
   Même principe déjà appliqué juste en dessous pour le divider de
   #new-hebergement quand SA destination a perdu son thème dédié. */

/* Le divider de #new-hebergement menait autrefois à #new-refonte (thème
   ambre/orange) — depuis la fusion des 4 services dans cette même section,
   il mène directement à #reviews-heading (pas de thème dédié) : override
   orange retiré, retombe sur le bleu par défaut de .divider-action. */

.home-service-section--refonte .section-divider .divider-action {
    background: radial-gradient(circle at 50% 35%, rgba(16,185,129,.24) 0%, rgba(16,185,129,.12) 62%, rgba(16,185,129,.07) 100%);
    border-color: rgba(16,185,129,.32);
    box-shadow: 0 8px 26px rgba(16,185,129,.16), inset 0 1px 0 rgba(255,255,255,.08);
}

.home-service-section--refonte .section-divider .divider-action::after {
    background: rgba(16,185,129,.10);
    border-color: rgba(16,185,129,.20);
}

.home-service-section--refonte .section-divider .divider-action:hover::after {
    background: rgba(16,185,129,.20);
    border-color: rgba(16,185,129,.42);
    color: #ffffff;
}

.home-service-section--refonte .section-divider .divider-action:hover {
    color: #10b981;
    background: radial-gradient(circle at 50% 35%, rgba(16,185,129,.34) 0%, rgba(16,185,129,.18) 62%, rgba(16,185,129,.09) 100%);
    border-color: rgba(16,185,129,.55);
    box-shadow: 0 15px 40px rgba(16,185,129,.28), inset 0 1px 0 rgba(255,255,255,.12);
}

.home-service-section--refonte .section-divider .divider-line {
    background: linear-gradient(90deg, transparent, rgba(16,185,129,.55), transparent);
}

/* ─── accueil.php : bulle de fond des dividers entièrement retirée ───
   Le réglage "invisible seulement au survol" ne fonctionnait pas (demande
   explicite : "ça ne marche pas, enlève complètement le bleu, c'est plus
   simple") — remplacé par un retrait total, repos ET survol : plus aucun
   fond/bordure/ombre, quelle que soit la variante colorée (.why-target/
   .home-service-section--refonte/base) ni l'état. Seule la rockette (qui
   continue de shake au survol via .divider-action:hover .rocket-inner)
   reste visible. Scopé à accueil.php via data-page (même technique que
   .site-header/.site-footer plus haut) : services.php (dividers colorés
   par href juste en dessous) n'est pas concerné. Sélecteur pesé à
   l'identique des variantes colorées ci-dessus (3 unités de spécificité
   pour l'état repos) et placé APRÈS elles dans le fichier pour gagner par
   ordre de source en cas d'égalité. */
body:has([data-page="accueil.php"]) .section-divider .divider-action,
body:has([data-page="accueil.php"]) .section-divider .divider-action:hover {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
}

/* ─── SERVICES.PHP : dividers colorés selon la section de destination ───
   Même principe qu'accueil.php, mais ici les 5 dividers ne sont pas
   imbriqués dans la section qui les précède/suit (ils sont entre deux
   <section> dans le flux) : on cible donc directement le lien de chaque
   divider via son href (#refonte, #hebergement, #programmation, #conseil),
   qui correspond déjà aux couleurs des capsules du hero de la page
   (.service-capsule--refonte/--cloud/--programmation/--conseil). Le
   divider vers #section-offers reste bleu (couleur par défaut = couleur
   de .service-capsule--featured), donc pas de règle dédiée nécessaire. */
.divider-action[href="#refonte"] {
    background: radial-gradient(circle at 50% 35%, rgba(245,158,11,.24) 0%, rgba(245,158,11,.12) 62%, rgba(245,158,11,.07) 100%);
    border-color: rgba(245,158,11,.32);
    box-shadow: 0 8px 26px rgba(245,158,11,.16), inset 0 1px 0 rgba(255,255,255,.08);
}
.divider-action[href="#refonte"]::after {
    background: rgba(245,158,11,.10);
    border-color: rgba(245,158,11,.20);
}
.divider-action[href="#refonte"]:hover::after {
    background: rgba(245,158,11,.20);
    border-color: rgba(245,158,11,.42);
    color: #ffffff;
}
.divider-action[href="#refonte"]:hover {
    color: #f59e0b;
    background: radial-gradient(circle at 50% 35%, rgba(245,158,11,.34) 0%, rgba(245,158,11,.18) 62%, rgba(245,158,11,.09) 100%);
    border-color: rgba(245,158,11,.55);
    box-shadow: 0 15px 40px rgba(245,158,11,.28), inset 0 1px 0 rgba(255,255,255,.12);
}

.divider-action[href="#hebergement"] {
    background: radial-gradient(circle at 50% 35%, rgba(59,130,246,.24) 0%, rgba(59,130,246,.12) 62%, rgba(59,130,246,.07) 100%);
    border-color: rgba(59,130,246,.32);
    box-shadow: 0 8px 26px rgba(59,130,246,.16), inset 0 1px 0 rgba(255,255,255,.08);
}
.divider-action[href="#hebergement"]::after {
    background: rgba(59,130,246,.10);
    border-color: rgba(59,130,246,.20);
}
.divider-action[href="#hebergement"]:hover::after {
    background: rgba(59,130,246,.20);
    border-color: rgba(59,130,246,.42);
    color: #ffffff;
}
.divider-action[href="#hebergement"]:hover {
    color: #3b82f6;
    background: radial-gradient(circle at 50% 35%, rgba(59,130,246,.34) 0%, rgba(59,130,246,.18) 62%, rgba(59,130,246,.09) 100%);
    border-color: rgba(59,130,246,.55);
    box-shadow: 0 15px 40px rgba(59,130,246,.28), inset 0 1px 0 rgba(255,255,255,.12);
}

.divider-action[href="#programmation"] {
    background: radial-gradient(circle at 50% 35%, rgba(16,185,129,.24) 0%, rgba(16,185,129,.12) 62%, rgba(16,185,129,.07) 100%);
    border-color: rgba(16,185,129,.32);
    box-shadow: 0 8px 26px rgba(16,185,129,.16), inset 0 1px 0 rgba(255,255,255,.08);
}
.divider-action[href="#programmation"]::after {
    background: rgba(16,185,129,.10);
    border-color: rgba(16,185,129,.20);
}
.divider-action[href="#programmation"]:hover::after {
    background: rgba(16,185,129,.20);
    border-color: rgba(16,185,129,.42);
    color: #ffffff;
}
.divider-action[href="#programmation"]:hover {
    color: #10b981;
    background: radial-gradient(circle at 50% 35%, rgba(16,185,129,.34) 0%, rgba(16,185,129,.18) 62%, rgba(16,185,129,.09) 100%);
    border-color: rgba(16,185,129,.55);
    box-shadow: 0 15px 40px rgba(16,185,129,.28), inset 0 1px 0 rgba(255,255,255,.12);
}

.divider-action[href="#conseil"] {
    background: radial-gradient(circle at 50% 35%, rgba(139,92,246,.24) 0%, rgba(139,92,246,.12) 62%, rgba(139,92,246,.07) 100%);
    border-color: rgba(139,92,246,.32);
    box-shadow: 0 8px 26px rgba(139,92,246,.16), inset 0 1px 0 rgba(255,255,255,.08);
}
.divider-action[href="#conseil"]::after {
    background: rgba(139,92,246,.10);
    border-color: rgba(139,92,246,.20);
}
.divider-action[href="#conseil"]:hover::after {
    background: rgba(139,92,246,.20);
    border-color: rgba(139,92,246,.42);
    color: #ffffff;
}
.divider-action[href="#conseil"]:hover {
    color: #8b5cf6;
    background: radial-gradient(circle at 50% 35%, rgba(139,92,246,.34) 0%, rgba(139,92,246,.18) 62%, rgba(139,92,246,.09) 100%);
    border-color: rgba(139,92,246,.55);
    box-shadow: 0 15px 40px rgba(139,92,246,.28), inset 0 1px 0 rgba(255,255,255,.12);
}

/* La barre horizontale (.divider-line) suit la même couleur que la bulle
   ci-dessus, mais comme elle n'est pas une descendante de .divider-action
   (c'est une sœur de .rocket-wrapper dans .section-divider), un sélecteur
   [href=...] ne l'atteint pas — d'où ces classes modificatrices posées
   directement sur .section-divider dans services.php. Sélecteur composé
   (.section-divider.section-divider--x, 2 classes sur le même élément)
   plutôt que descendant simple : la règle de base .section-divider
   .divider-line est définie plus loin dans le fichier avec la même
   spécificité (0,2,0), et gagnerait sinon par ordre de source. */
.section-divider.section-divider--refonte .divider-line {
    background: linear-gradient(90deg, transparent, rgba(245,158,11,.55), transparent);
}
.section-divider.section-divider--pro .divider-line {
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.55), transparent);
}
.section-divider.section-divider--programmation .divider-line {
    background: linear-gradient(90deg, transparent, rgba(16,185,129,.55), transparent);
}
.section-divider.section-divider--surmesure .divider-line {
    background: linear-gradient(90deg, transparent, rgba(139,92,246,.55), transparent);
}

/* ─── services.php : divider "trou noir" mobile uniquement (rocket blanche,
   teinte neutre/monochrome façon horizon des événements, plutôt qu'une des
   couleurs de section ci-dessus) — cf. .services-mobile-void-divider dans
   responsive.css pour la visibilité (mobile only) et le gap énorme. Masqué
   par défaut ici (desktop) : la règle qui le réaffiche est scopée mobile
   dans responsive.css. ─── */
.services-mobile-void-divider {
    display: none;
}
.divider-action[href="#services-cta"] {
    background: radial-gradient(circle at 50% 35%, rgba(255,255,255,.20) 0%, rgba(255,255,255,.08) 62%, rgba(0,0,0,.06) 100%);
    border-color: rgba(255,255,255,.35);
    box-shadow: 0 8px 26px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.14);
    color: #ffffff;
}
.divider-action[href="#services-cta"]::after {
    background: rgba(255,255,255,.08);
    border-color: rgba(255,255,255,.22);
}
.divider-action[href="#services-cta"]:hover::after {
    background: rgba(255,255,255,.16);
    border-color: rgba(255,255,255,.4);
    color: #ffffff;
}
.divider-action[href="#services-cta"]:hover {
    color: #ffffff;
    background: radial-gradient(circle at 50% 35%, rgba(255,255,255,.32) 0%, rgba(255,255,255,.16) 62%, rgba(0,0,0,.1) 100%);
    border-color: rgba(255,255,255,.55);
    box-shadow: 0 15px 40px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.18);
}
.section-divider.section-divider--void .divider-line {
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.5), transparent);
}

/* ─── offres-site.php UNIQUEMENT : bannière flottante "aller en bas de
   page", rockette blanche même teinte monochrome que le divider "trou noir"
   ci-dessus (réutilise .rocket-wrapper/.divider-action, pas .section-divider
   ni sa grande ligne verticale — juste la bulle). Affichée/masquée par
   assets/js/main.js (scroll vers le bas -> visible 2s -> disparaît ;
   définitivement masquée après la moitié de la page parcourue). ─── */
.scroll-bottom-banner {
    position: fixed;
    left: 50%;
    bottom: 34px;
    transform: translateX(-50%) translateY(12px);
    z-index: 500;
    opacity: 0;
    pointer-events: none;
    transition: opacity .35s ease, transform .35s ease;
}
.scroll-bottom-banner.is-visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
}
.scroll-bottom-banner .rocket-wrapper {
    padding: 8px;
}
.scroll-bottom-banner .divider-action {
    width: 52px;
    height: 52px;
    background: radial-gradient(circle at 50% 35%, rgba(255,255,255,.20) 0%, rgba(255,255,255,.08) 62%, rgba(0,0,0,.06) 100%);
    border-color: rgba(255,255,255,.35);
    box-shadow: 0 8px 26px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.14);
    color: #ffffff;
}
.scroll-bottom-banner .divider-action .rocket-icon {
    width: 32px;
    height: 32px;
}
.scroll-bottom-banner .divider-action::after {
    background: rgba(255,255,255,.08);
    border-color: rgba(255,255,255,.22);
}
.scroll-bottom-banner .divider-action:hover::after {
    background: rgba(255,255,255,.16);
    border-color: rgba(255,255,255,.4);
    color: #ffffff;
}
.scroll-bottom-banner .divider-action:hover {
    color: #ffffff;
    background: radial-gradient(circle at 50% 35%, rgba(255,255,255,.32) 0%, rgba(255,255,255,.16) 62%, rgba(0,0,0,.1) 100%);
    border-color: rgba(255,255,255,.55);
    box-shadow: 0 15px 40px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.18);
}

.section-divider .rocket-wrapper.launch.down::before,
.hero .rocket-wrapper.launch.down::before,
.scroll-bottom-banner .rocket-wrapper.launch.down::before {
    content: "";
    position: absolute;
    left: 50%;
    top: -10px;
    width: 10px;
    height: 18px;
    transform: translateX(-50%);
    background: linear-gradient(to top, #fff, transparent);
    border-radius: 50%;
    animation: flameBurst 1.5s ease-out forwards;
    pointer-events: none;
}

.section-divider .rocket-wrapper.launch.down::after,
.hero .rocket-wrapper.launch.down::after,
.scroll-bottom-banner .rocket-wrapper.launch.down::after {
    content: "";
    position: absolute;
    left: 50%;
    top: -20px;
    width: 4px;
    height: 40px;
    transform: translateX(-50%);
    background: linear-gradient(to top, #fff, transparent);
    animation: smokeTrail 1.5s ease-out forwards;
    pointer-events: none;
}

/* ========================= Back to Top = */

.back-to-top {
    position: fixed;
    top: 18px;
    left: 48.55%;
    padding-top: 100px;
	z-index: 3;
    filter: blur(2px);
   
   

    display: inline-flex;
    align-items: center;
    gap: 8px;

    padding: 4px 8px;
    color: rgba(255,255,255,0.85);
    text-decoration: none;

    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.08);
    backdrop-filter: blur(10px);
    border-radius: 999px;

    box-shadow: 0 10px 30px rgba(0,0,0,0.25);

    opacity: 0;
    visibility: hidden;
    pointer-events: none;

    transition: opacity 0.25s ease, transform 0.35s ease, filter 0.35s ease;
}
/* Taille alignée sur les rockettes de divider (.divider-action .rocket-icon)
   — le rocket-icon par défaut (64px) était trop imposant pour ce bouton. */
.back-to-top .rocket-icon {
    width: 40px;
    height: 40px;
}

.back-to-top:hover .tooltip-text {
    opacity: 1;
    visibility: visible;
    top: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
}
.back-to-top.visible {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    filter: blur(0);
	transform: scale(0.8);
    
}

@media (hover: hover) and (pointer: fine) {
    .back-to-top:hover {
        background: rgba(var(--header-accent),0.12);
        border-color: rgba(var(--header-accent),0.35);
        color: rgb(var(--header-accent));
        box-shadow: 0 15px 40px rgba(var(--header-accent),0.15);
        animation: shakeSoft 0.6s infinite;
    }
}

.back-to-top::before,
.back-to-top::after {
    content: "";
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    opacity: 0;
    pointer-events: none;
}

.back-to-top::before {
    bottom: -14px;
    width: 10px;
    height: 18px;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.15) 40%, rgba(255,100,0,0) 70%);
    border-radius: 50%;
    filter: blur(1px);
}

.back-to-top::after {
    bottom: -40px;
    width: 4px;
    height: 40px;
    background: linear-gradient(to top, rgba(255, 255, 255, 0.15), transparent);
}

.back-to-top.launching::before {
    opacity: 1;
    animation: flame 0.4s ease-out forwards;
}

.back-to-top.launching::after {
    opacity: 1;
    animation: smokeTrail 0.5s ease-out forwards;
}


/* ========================= boutons = */

.btn-primary {
    display: inline-block;
    position: relative;
    padding: 12px 28px;

    background: rgba(0, 1, 2, 0.418);
    border: 1px solid rgba(1, 8, 17, 0.3);
    border-radius: 14px;

    color: #ffffff;
    font-weight: 600;
    font-size: 1.1rem;
    text-decoration: none;

    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);

    box-shadow:
        0 0 20px rgba(var(--header-accent), 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);

    pointer-events: auto;
    cursor: pointer;

    transition:
        transform 0.25s ease,
        background 0.25s ease,
        box-shadow 0.25s ease,
        border-color 0.25s ease;
}

.btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 14px;
    background: radial-gradient(circle at 50% 0%, rgba(var(--header-accent), 0.25), transparent 70%);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.btn-primary:hover {
    transform: translateY(-2px);
    background: rgba(var(--header-accent), 0.22);
    border-color: rgba(var(--header-accent), 0.55);
    box-shadow:
        0 12px 32px rgba(var(--header-accent), 0.22),
        inset 0 1px 0 rgba(255, 255, 255, 0.10);
}

.btn-primary:hover::before {
    opacity: 1;
}

.btn-primary:active {
    transform: translateY(0) scale(0.97);
    box-shadow: 0 4px 12px rgba(var(--header-accent), 0.15);
}

/* ─── CTA secondaire (hero accueil.php) ───
   Volontairement en retrait par rapport à .btn-primary : contour fin,
   fond quasi transparent, pas de halo — pour proposer un second chemin
   ("comment ça marche ?") sans concurrencer le CTA principal. ─── */
.btn-secondary {
    display: inline-block;
    padding: 12px 26px;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 14px;
    color: rgba(255, 255, 255, 0.82);
    font-weight: 600;
    font-size: 1.02rem;
    text-decoration: none;
    transition: color 0.25s ease, background 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}

.btn-secondary:hover {
    color: #ffffff;
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.4);
    transform: translateY(-2px);
}

.btn-secondary:active {
    transform: translateY(0);
}

.hero-cta-row {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 14px;
}

/* Les 2 CTA à la même taille (demande explicite, style de chacun inchangé) :
   min-width commun calé sur le libellé le plus long des 4 langues
   ("Website erstellen"/"Create a website"), text-align:center pour garder
   le texte centré dans les boutons plus larges que leur contenu. */
.hero-cta-row .btn-primary,
.hero-cta-row .btn-secondary {
    min-width: 210px;
    text-align: center;
}

/* ─── CTA du hero accueil.php ───
   "Découvrir ma méthode" reprend le registre "fonctionnel" déjà utilisé
   ailleurs sur le site (.btn-account--functional dans l'espace client,
   .footer-cta dans le footer) : bordure à la teinte de marque, typo
   monospace/majuscules — plutôt qu'un CTA marketing à dégradé façon
   .btn-account--cta. MAIS il reste le CTA principal de la hero (à côté
   du CTA secondaire "Explorer") : sa version initiale, trop proche en
   contraste de .btn-secondary (même opacité de fond, bordure plus fine,
   texte teinté donc moins lisible qu'un blanc pur, police plus petite),
   se faisait passer pour LE bouton secondaire alors qu'il ne l'est pas.
   Fond teinté marque + bordure pleine + texte blanc + poids de police
   plus fort lui redonnent la primauté visuelle sans basculer dans le
   dégradé marketing. Le CTA secondaire ("Explorer") garde son style en
   retrait pour ne pas concurrencer le premier. */
.hero-cta-row .btn-primary {
    background: color-mix(in srgb, var(--brand-color) 18%, rgba(255,255,255,.05));
    border: 1.5px solid color-mix(in srgb, var(--brand-color) 75%, rgba(255,255,255,.16));
    color: #ffffff;
    border-radius: 8px;
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    box-shadow: 0 4px 18px color-mix(in srgb, var(--brand-color) 30%, transparent);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.hero-cta-row .btn-primary::before {
    display: none;
}

.hero-cta-row .btn-primary:hover {
    background: color-mix(in srgb, var(--brand-color) 32%, rgba(255,255,255,.05));
    border-color: var(--brand-color);
    color: #fff;
    transform: translateY(-2px);
    box-shadow: 0 8px 28px color-mix(in srgb, var(--brand-color) 42%, transparent);
}

.hero-cta-row .btn-secondary {
    background: rgba(255,255,255,.05);
    border-color: rgba(255,255,255,.32);
    color: rgba(255,255,255,.92);
}

.hero-cta-row .btn-secondary:hover {
    background: rgba(255,255,255,.10);
    border-color: rgba(255,255,255,.55);
}


/* ------------------------- Header -------------------------- */

.site-header {
    --header-accent: 10, 88, 202;
    position: fixed;
    top: 20px;
    left: 50%;
    transform: translateX(-50%) translateY(0);
    width: min(1200px, calc(100% - 40px));
    height: 64px;
    box-sizing: border-box;
    z-index: 100;
    background: rgba(20, 22, 30, 0.62);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-top-color: rgba(var(--header-accent), .30);
    border-radius: 18px;
    box-shadow:
        0 10px 40px rgba(0, 0, 0, 0.45),
        inset 0 1px 0 rgba(255,255,255,.06);
    overflow: visible;
    transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.35s ease, border-top-color .4s ease;
}

/* ─── Accent du header adapté à la page active (refonte, programmation,
   bot-discord, audit-site, et les 3 offres de création de site) ─── */
.site-header--amber    { --header-accent: 245, 158, 11; }
.site-header--emerald  { --header-accent: 16, 185, 129; }
.site-header--cyan     { --header-accent: 232, 237, 245; }
/* "Gold" recoloré en rouge-noir façon "Magma" (demande explicite : sa teinte
   d'origine était trop proche d'"Amber"/Mars). */
.site-header--gold     { --header-accent: 185, 28, 28; }
.site-header--blue     { --header-accent: 59, 130, 246; }
.site-header--violet   { --header-accent: 139, 92, 246; }

.site-header.hidden {
    transform: translateX(-50%) translateY(-120px);
    opacity: 0;
}

/* ─── services.php + dashboards admin/compte : header masqué à l'arrivée ───
   Contrairement au reste du site (header visible par défaut, masqué
   seulement au scroll vers le bas, cf. main.js bloc HEADER), ici le header
   reste invisible tant qu'on n'a pas commencé à défiler — demande
   explicite, étendue de services.php à TOUTES les pages admin-*.php/
   compte-*.php (classe partagée .account-page, cf. main.js). :not(.visible)
   plutôt que .hidden : au chargement, l'élément n'a encore NI l'une NI
   l'autre classe (JS pas encore exécuté / avant le premier scroll), donc
   cibler uniquement .hidden laisserait passer un flash "visible par
   défaut" le temps que le script tourne ; :not(.visible) couvre aussi cet
   état neutre initial. */
body:has(main.page-service, main.account-page, [data-page="index.php"]) .site-header:not(.visible) {
    transform: translateX(-50%) translateY(-120px);
    opacity: 0;
    pointer-events: none;
}

/* La tentative précédente d'ajouter un masquage supplémentaire lié à
   .is-all-landed sur services.php (règle retirée ici) provoquait un bug
   signalé explicitement : au premier scroll vers le bas, le header
   apparaissait brièvement puis se refermait. Retour à la même logique
   simple qu'index.php (demande explicite "applique cette même logique à
   services.php") : uniquement la règle partagée :not(.visible)
   ci-dessus, qui suffit et se comporte correctement. */

.site-header.visible {
    transform: translateX(-50%) translateY(0);
    opacity: 1;
}

/* ─── index.php : header masqué au chargement, comportement normal ensuite
   (demande explicite, remplace l'ancienne auto-révélation) ─── Auparavant,
   le header réapparaissait automatiquement à la fin de l'intro
   (indexHeaderReveal calé sur var(--reveal-delay)) : retour explicite "ne
   pas le faire apparaître au chargement". index.php est donc désormais
   ajouté au sélecteur partagé ci-dessus (body:has(..., [data-page="index.php"])
   .site-header:not(.visible)) : comme services.php/les dashboards compte,
   le header reste invisible tant que .visible n'a pas été ajouté par
   main.js (donc tant qu'on n'a pas commencé à défiler), puis suit
   exactement le même comportement normal de hide-on-scroll que le reste
   du site. */

.site-header::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: repeating-linear-gradient(
        135deg,
        rgba(255,255,255,0.02) 0,
        rgba(255,255,255,0.02) 1px,
        transparent 1px,
        transparent 12px
    );
    opacity: 0.25;
    animation: stripes 12s linear infinite;
    pointer-events: none;
}

.site-header::after {
    content: "";
    position: absolute;
    inset: -2px;
    background: radial-gradient(circle at 50% 0%, rgba(var(--header-accent),0.15), transparent 60%);
    pointer-events: none;
    transition: background .4s ease;
}

.site-header .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0; 
    height: 100%;
}

/* Grid (et non flex) pour que #main-nav soit VRAIMENT centré (colonne du
   milieu, largeur "auto") indépendamment de la largeur du logo à gauche ou
   du bloc langue/compte à droite (colonnes 1fr de chaque côté) — un simple
   "justify-content: space-between" en flex ne centre pas exactement le bloc
   du milieu si les 2 extrémités n'ont pas la même largeur, ce qu'aucun
   réglage en pourcentage ne pouvait corriger de façon fiable. Sans effet sur
   mobile : @media (max-width: 992px) redéfinit entièrement .header-inner
   (cf. responsive.css) pour la mise en page hamburger. */
.header-inner {
    height: 100%;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 1rem;
    padding: 0 24px;
    box-sizing: border-box;
}
.nav-left  { justify-self: start; }
.main-nav  { justify-self: center; }
.nav-right { justify-self: end; }

.brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
    color: inherit;
}

.brand-logo {
    width: 120px;
    height: 44px; 
    object-fit: contain;
}

.brand-text {
    font-weight: 700;
    font-size: 1.125rem;
}

.main-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    gap: 1rem;
    align-items: center;
}

.main-nav a {
    position: relative;
    padding: 0.5rem 0.9rem;
    border-radius: 10px;
    text-decoration: none;
    color: var(--muted);
    font-weight: 600;
    letter-spacing: .01em;
    transition: color 0.25s, background 0.25s;
    white-space: nowrap;
}

.main-nav a:hover {
    background: rgba(255,255,255,0.06);
    color: var(--brand-color);
}

.main-nav .active > a {
    /* Suit l'accent du header actif (page ou préférence utilisateur) au lieu
       d'un bleu fixe, cf. rgb(var(--header-accent)) plus bas pour le sous-menu. */
    background: rgba(var(--header-accent),0.12);
    border: 1px solid rgba(var(--header-accent),0.25);
    border-radius: 10px;
}

/* ── « Services » mis en avant : reste à sa place normale dans le menu,
   mais avec un visuel de bouton "spatial" (nébuleuse + étoiles + lueur
   pulsée, cohérent avec le reste du site) plutôt qu'un simple lien texte,
   pour attirer l'œil sur la rubrique phare du site. Les lueurs de nébuleuse,
   l'ombre et l'icône suivent --header-accent (posée sur .site-header, cf.
   plus bas dans ce fichier) pour rester assorties à la couleur active ;
   animation dédiée (navServicesPulse, pas galaxyPulseBlue qui est partagé
   avec .title-bubble ailleurs sur le site et ne doit pas changer). ── */
.main-nav .nav-services-featured > a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px 20px;
    font-size: 0.94rem;
    font-weight: 700;
    color: #ffffff;
    /* Semis d'étoiles (au-dessus, neutres) + lueurs de nébuleuse (teintées
       accent) + dégradé de base (en-dessous) — le tout en arrière-plan de
       l'élément, donc toujours derrière l'icône et le texte, sans
       complication d'empilement. */
    background:
        radial-gradient(1px 1px at 18% 28%, rgba(255,255,255,.85), transparent 100%),
        radial-gradient(1px 1px at 38% 72%, rgba(255,255,255,.60), transparent 100%),
        radial-gradient(1.5px 1.5px at 58% 22%, rgba(255,255,255,.8), transparent 100%),
        radial-gradient(1px 1px at 76% 62%, rgba(255,255,255,.55), transparent 100%),
        radial-gradient(1px 1px at 90% 32%, rgba(255,255,255,.75), transparent 100%),
        radial-gradient(1px 1px at 8% 62%, rgba(255,255,255,.45), transparent 100%),
        radial-gradient(circle at 25% 20%, rgba(var(--header-accent),.26), transparent 55%),
        radial-gradient(circle at 80% 75%, rgba(var(--header-accent),.20), transparent 55%),
        linear-gradient(135deg, #04070f, #0d2a5c 55%, #1f0f3d 130%);
    border: 1px solid rgba(255,255,255,.12);
    border-radius: 999px;
    box-shadow: 0 0 14px rgba(var(--header-accent),.14), 0 0 28px rgba(var(--header-accent),.07), inset 0 1px 0 rgba(255,255,255,.08);
    animation: navServicesPulse 9s ease-in-out infinite;
    transition: transform .25s ease, background .4s ease, border-color .25s ease, box-shadow .4s ease;
}

@keyframes navServicesPulse {
    0%, 100% { box-shadow: 0 0 14px rgba(var(--header-accent),.14), 0 0 28px rgba(var(--header-accent),.07), inset 0 1px 0 rgba(255,255,255,.08); }
    50%      { box-shadow: 0 0 22px rgba(var(--header-accent),.24), 0 0 44px rgba(var(--header-accent),.12), inset 0 1px 0 rgba(255,255,255,.08); }
}

.nav-services-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    filter: drop-shadow(0 0 3px rgba(var(--header-accent),.55));
    transition: transform .25s ease, filter .4s ease;
}

/* Petite fusée qui « s'allume » au survol du bouton, comme les fusées des
   dividers (même animation shakeSoft, cf. animation.css). */
.main-nav .nav-services-featured > a:hover .nav-services-icon {
    transform: translateY(-2px);
    animation: shakeSoft .5s infinite;
}

.main-nav .nav-services-featured > a:hover,
.main-nav .nav-services-featured.active > a {
    background:
        radial-gradient(1px 1px at 18% 28%, rgba(255,255,255,.95), transparent 100%),
        radial-gradient(1px 1px at 38% 72%, rgba(255,255,255,.70), transparent 100%),
        radial-gradient(1.5px 1.5px at 58% 22%, rgba(255,255,255,.9), transparent 100%),
        radial-gradient(1px 1px at 76% 62%, rgba(255,255,255,.65), transparent 100%),
        radial-gradient(1px 1px at 90% 32%, rgba(255,255,255,.85), transparent 100%),
        radial-gradient(1px 1px at 8% 62%, rgba(255,255,255,.55), transparent 100%),
        radial-gradient(circle at 25% 20%, rgba(var(--header-accent),.34), transparent 55%),
        radial-gradient(circle at 80% 75%, rgba(var(--header-accent),.26), transparent 55%),
        linear-gradient(135deg, #060d24, #123a7a 55%, #291552 130%);
    border-color: rgba(255,255,255,.20);
    transform: translateY(-2px);
}

/* Flèche "▾" (cf. .has-submenu > a::after plus bas) supprimée pour "Services"
   et "À propos" (demande explicite) — spécificité plus élevée que la règle
   générique, donc gagne sans dépendre de l'ordre dans la feuille de style. */
.main-nav .nav-services-featured > a::after,
.main-nav .nav-presentation > a::after {
    display: none;
}

/* Bouton central "Mon espace" (nav business) : les tentatives précédentes de
   décalage individuel (margin, puis position relative) modifiaient toujours
   l'écart entre "Accueil"/"Mon espace"/"Support" — indésirable. La demande
   finale est de décaler tout le BLOC (Accueil, Mon espace, Support) d'un
   coup, ce qui centre mieux "Mon espace" sans toucher aux écarts internes
   (ils bougent ensemble). .nav-business-link n'a donc plus besoin de règle
   spécifique ici. */

/* Centrage de #main-nav désormais géré directement par la grille de
   .header-inner (grid-template-columns: 1fr auto 1fr + justify-self: center,
   cf. plus haut dans ce fichier) — vraiment "pile au milieu" quelle que soit
   la largeur du logo ou du bloc langue/compte, contrairement aux essais
   précédents en pourcentage/margin-left qui approchaient le centre sans
   jamais le toucher exactement. Plus besoin de règle ici. */

.has-submenu > a::after {
    content: "▾";
    margin-left: 6px;
    font-size: 0.7em;
    opacity: 0.6;
    transition: transform 0.2s ease;
}

.has-submenu.submenu-open > a::after {
    transform: rotate(180deg);
}

.main-nav .has-submenu {
    position: relative;
}

/* "Services" et "À propos" doivent ouvrir leur sous-menu au MÊME endroit
   (demande explicite : "pile en dessous de services"), pas chacun centré
   sous son propre bouton — or les 2 déclencheurs n'occupent pas la même
   position horizontale dans la liste. Solution : leur sous-menu (left:50% +
   translateX(-50%), cf. plus bas) n'est plus positionné par rapport à sa
   propre <li> (on lui retire son rôle de repère ci-dessous, position:static)
   mais par rapport à la RANGÉE ENTIÈRE de nav (.main-nav > ul, repère commun
   ajouté ici) : le "50%" se calcule alors sur la largeur de tout le bloc de
   nav, centré sur le header depuis le passage de .header-inner en grille
   (cf. plus haut) — donc pile sous "Services", qui en occupe le centre. */
.main-nav > ul {
    position: relative;
}
.main-nav .nav-services-featured,
.main-nav .nav-presentation {
    position: static;
}

.main-nav .submenu {
    display: grid;
    grid-template-columns: repeat(2, minmax(260px, 1fr));
    gap: 4px 10px;
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 14px;
    padding: 0.6rem;
    background: rgba(17, 19, 27, 0.96);
    backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-top: 2px solid rgba(var(--header-accent),.45);
    border-radius: 14px;
    box-shadow:
        0 20px 50px rgba(0, 0, 0, 0.5),
        inset 0 1px 0 rgba(255,255,255,.05);
    min-width: 260px;
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
    transition: opacity 0.12s ease, transform 0.12s ease;
}

/* Dernier item resté seul sur sa ligne (nombre impair d'items) : pleine largeur */
.main-nav .submenu li:only-child,
.main-nav .submenu li:nth-child(odd):last-child {
    grid-column: 1 / -1;
}

/* Sous-menu "À propos" : 5 items répartis en 2 colonnes fixes en desktop
   (Présentation / Partenaires / Livre d'or / Contact / Projets à suivre —
   Contact rejoint ce sous-menu uniquement en desktop, cf. .submenu-contact
   et le markup de partials/header.php ; sur mobile il reste un item de
   premier niveau séparé, donc ce sous-menu n'y compte que 4 items) plutôt
   que la règle générique ci-dessus qui étirerait le 5ᵉ item (Projets à
   suivre) sur toute la largeur — ici il doit rester seul en bas de la
   colonne 1. */
.nav-presentation .submenu li:nth-child(odd):last-child {
    grid-column: 1;
}

/* Sous-menu "Services" : même principe — 5 items en 2 colonnes fixes
   (Création Site Web / Refonte / Programmation / Hébergement / Conseil et
   Accompagnement, cf. l'ordre du markup dans partials/header.php), le 5ᵉ
   (Conseil et Accompagnement) doit rester seul en colonne 1 plutôt que de
   s'étirer sur toute la largeur. */
.nav-services-featured .submenu li:nth-child(odd):last-child {
    grid-column: 1;
}

/* Sous-menu à un seul item par ligne (ex : Présentation) : pas de grille 2 colonnes */
.main-nav .submenu.submenu--single {
    grid-template-columns: 1fr;
}

/* Ancrage horizontal : évite que 2 sous-menus voisins se chevauchent quand
   l'un d'eux est large (2 colonnes). Le sous-menu s'accroche par son bord
   droit à son déclencheur au lieu de déborder vers la droite. */
.main-nav .submenu.submenu--align-right {
    left: auto;
    right: -24px;
}

.main-nav .submenu.submenu--align-left {
    left: 8px;
}

/* Sous-menus "Services" et "À propos" : centrés PILE sous leur déclencheur
   (demande explicite), quelle que soit sa largeur ou celle du sous-menu —
   "left: 50%" + "translateX(-50%)" plutôt qu'un simple décalage en left/right
   (l'ancrage à droite précédent faisait déborder le sous-menu très loin vers
   la gauche du déclencheur). Les DEUX sous-menus utilisent le même centrage
   (demande explicite : "au même endroit") — même largeur de base par
   ailleurs (cf. .main-nav .submenu, grid-template-columns identique pour les
   deux). translateY(-6px) reprend l'état "fermé" de la règle générique
   .main-nav .submenu ; l'état "ouvert" est réaffirmé plus bas (cf. règles
   après .has-submenu.submenu-open > .submenu) pour ne pas perdre le
   translateX(-50%) à l'ouverture. Sans effet sur mobile : le sous-menu y
   passe en position:static (cf. responsive.css). */
.main-nav .nav-services-featured .submenu.submenu--align-right,
.main-nav .nav-presentation .submenu.submenu--align-right {
    left: 50%;
    right: auto;
    transform: translateX(-50%) translateY(-6px);
}
/* Nuance de 1px vers la gauche pour "Services" uniquement ("c'est bon, ou
   1px à gauche si tu veux") — placé après la règle partagée ci-dessus pour
   gagner sur "À propos" qui reste pile centré. */
.main-nav .nav-services-featured .submenu.submenu--align-right {
    transform: translateX(calc(-50% - 1px)) translateY(-6px);
}

/* Alignement vertical : les décalages différenciés qui existaient ici (28px
   pour "À propos", 22px pour "Services") n'ont plus lieu d'être depuis que
   les deux sous-menus partagent le même repère de positionnement
   (.main-nav > ul, cf. règle plus haut) — ils héritent naturellement de la
   même ligne de base. On les décale malgré tout un peu plus bas que le 14px
   par défaut (demande explicite), à l'identique pour les deux puisqu'ils
   doivent rester alignés l'un sur l'autre. Le pont de survol (::before) est
   agrandi en conséquence pour garder le survol actif pendant la traversée de
   cet espace plus grand. */
.main-nav .nav-services-featured .submenu,
.main-nav .nav-presentation .submenu {
    margin-top: 22px;
}
.main-nav .nav-services-featured .submenu::before,
.main-nav .nav-presentation .submenu::before {
    top: -22px;
    height: 22px;
}

/* Contact rejoint le sous-menu "À propos" en desktop (cf. .submenu-contact
   dans partials/header.php) : l'item de premier niveau d'origine n'a donc
   plus lieu d'être ici. Sur mobile, le header doit rester inchangé — cette
   règle est donc annulée dans responsive.css (Contact redevient un item de
   premier niveau, et .submenu-contact est masqué à la place).
   :has(.nav-presentation) : en mode "business" (header dashboard client),
   le sous-menu "À propos" n'existe pas du tout dans le DOM (cf.
   partials/header.php) — Contact doit alors rester visible ici, seul
   moyen de l'afficher dans ce mode. */
.main-nav > ul:has(.nav-presentation) > li.nav-contact {
    display: none;
}

/* "Mon compte" : item ajouté après Contact uniquement pour la pile de nav
   mobile (cf. partials/header.php) — en desktop, l'icône
   .account-menu-trigger / .account-header-link dans .nav-right remplit
   déjà ce rôle, donc masqué ici par défaut ; réactivé uniquement sous
   992px (cf. responsive.css). */
.main-nav .nav-account {
    display: none;
}

.main-nav .submenu::before {
    content: "";
    position: absolute;
    top: -14px;
    left: -10px;
    right: -10px;
    height: 14px;
}

/* Révélation :hover pure CSS (secours sans JS) — exclut désormais "Services"
   ET "À propos" (.nav-services-featured / .nav-presentation) : ces deux
   déclencheurs partagent maintenant le même délai de survol (1s avant
   ouverture, cf. main.js) avant ouverture, entièrement piloté par la classe
   JS submenu-open (demande explicite : "appliquer la même règle que pour
   services" à "À propos"). S'ils restaient couverts ici, ce :hover pur (qui
   ignore tout délai, ne dépendant que de la position du curseur) ouvrirait
   le sous-menu instantanément et court-circuiterait le délai. Les autres
   déclencheurs imbriqués gardent leur propre logique (clic uniquement, cf.
   plus haut). */
@media (hover: hover) and (pointer: fine) {
    .main-nav .has-submenu:not(.nav-services-featured):not(.nav-presentation):hover > .submenu {
        opacity: 1;
        transform: translateY(0);
        pointer-events: auto;
        transition: opacity 0.18s ease 0.06s, transform 0.18s ease 0.06s;
    }

    .main-nav .has-submenu:not(.nav-services-featured):not(.nav-presentation):hover > a::after {
        transform: rotate(180deg);
    }
}


.has-submenu.submenu-open > .submenu {
    visibility: visible;
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
    transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0s;
}

/* Réaffirme le centrage (translateX(-50%), cf. règle plus haut) pour
   "Services" et "À propos" à l'ouverture : sans ceci, les règles génériques
   ci-dessus/ci-dessous ("transform: translateY(0)", même spécificité mais
   sans translateX) écraseraient le centrage et le sous-menu retomberait
   collé à gauche. Sélecteurs construits pour égaler la spécificité des
   règles qu'ils remplacent, placés juste après elles. */
.nav-services-featured.submenu-open > .submenu,
.nav-presentation.submenu-open > .submenu {
    transform: translateX(-50%) translateY(0);
}
/* Même nuance de 1px pour "Services" qu'à l'état fermé (cf. règle plus
   haut) — placé après pour gagner sur la règle partagée juste au-dessus. */
.nav-services-featured.submenu-open > .submenu {
    transform: translateX(calc(-50% - 1px)) translateY(0);
}

.main-nav .submenu li a {
    position: relative;
    display: block;
    padding: 0.62rem 1.5rem 0.62rem 1.4rem;
    font-weight: 500;
    font-size: 1rem;
    /* Plus lumineux que --muted (utilisé ailleurs sur le site) pour rester
       lisible même quand la page n'est pas active : le blanc à 88% associé
       au poids 500 se distingue nettement du fond sombre du dropdown. */
    color: rgba(255,255,255,.88);
    border-radius: 8px;
    white-space: nowrap;
    transition: color .2s ease, background .2s ease, padding-left .2s ease;
}

/* ─── Repère d'état : liséré vertical, façon indicateur de menu technique ─── */
.main-nav .submenu li a::before {
    content: "";
    position: absolute;
    left: 0;
    top: 8px;
    bottom: 8px;
    width: 2px;
    /* Liséré d'état assorti à l'accent du header actif plutôt qu'à une
       couleur de marque fixe, pour rester cohérent avec la page/le sous-menu
       actifs (cf. rgb(var(--header-accent)) posé sur .site-header). */
    background: rgb(var(--header-accent));
    transform: scaleY(0);
    transform-origin: center;
    transition: transform .2s ease;
}

.main-nav .submenu li a:hover,
.main-nav .submenu li.active > a {
    color: #fff;
    background: rgba(var(--header-accent),.08);
    padding-left: 1.7rem;
}

.main-nav .submenu li a:hover::before,
.main-nav .submenu li.active > a::before {
    transform: scaleY(1);
}

/* ─── Voyant lumineux (page active dans un sous-menu) ───
   Petit point à gauche du libellé, visible pour tous les items (gris discret
   par défaut) et allumé à la couleur d'accent du header pour la page
   actuellement affichée. Positionné avec assez de marge avant le texte
   (cf. padding-left du lien ci-dessus/ci-dessous) pour ne pas coller au mot
   qui suit. */
.main-nav .submenu li > a::after {
    content: "";
    position: absolute;
    left: 7px;
    top: 50%;
    transform: translateY(-50%);
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255,255,255,.22);
    box-shadow: none;
    transition: background .2s ease, box-shadow .2s ease;
}

.main-nav .submenu li.active > a::after {
    background: rgb(var(--header-accent));
    box-shadow: 0 0 6px rgba(var(--header-accent), .75), 0 0 2px rgba(var(--header-accent), .9);
}

/* ─── Sous-sous-menus (Programmation, Création de site, Conseil et
   Accompagnement ont eux-mêmes un sous-menu à l'intérieur du menu
   "Services") ───
   Ces triggers utilisent un ".submenu-caret" en span réel (et non le
   chevron générique ".has-submenu > a::after", qui de toute façon perd
   contre la règle plus spécifique du voyant lumineux ci-dessus) : le
   ::after reste donc disponible pour le point, qui s'affiche ici comme sur
   n'importe quel autre item du sous-menu. */

.submenu-caret {
    display: inline-block;
    margin-left: 6px;
    font-size: .8em;
    opacity: .5;
    transition: transform .2s ease;
}

.main-nav .submenu li.submenu-nested.submenu-open > a .submenu-caret {
    transform: rotate(90deg);
}

/* Sous-sous-menu : révélé au CLIC uniquement (1 clic ouvre, 1 clic ferme —
   cf. main.js), sur tous les écrans, pas au survol. Le survol s'est avéré
   peu fiable ici (fermetures intempestives, notamment sur "Programmation"),
   le clic supprime totalement ce problème.
   Sur desktop, affiché en overlay (position absolute) ANCRÉ à son item
   plutôt qu'en flux normal, pour ne jamais faire grandir la cellule de la
   grille (et donc ne jamais décaler les items voisins). Largeur calée sur
   celle de son item (min 100%) : il reste dans la colonne de la grille,
   jamais de débordement latéral hors écran.
   Volontairement SANS la classe générique ".submenu" (cf. markup dans
   partials/header.php) : cette classe porte tout le système du dropdown de
   premier niveau (position absolute avec ses propres offsets, opacity/
   pointer-events à 0 par défaut, grid 2 colonnes, et sur mobile un
   max-height:0 + overflow:hidden en responsive.css) qui créait des conflits
   de spécificité imprévisibles avec un panneau imbriqué. ".submenu--nested"
   définit donc son propre comportement. */
.main-nav .submenu li.submenu-nested {
    position: relative;
}

/* Tous les items du menu "Services" ouvrent désormais un sous-sous-menu :
   plus besoin de les distinguer des liens simples par un style permanent
   (fond teinté + bordure + gras au repos). Au repos, un trigger a donc
   exactement le même aspect qu'un item de sous-menu classique — seuls le
   survol et l'ouverture (ci-dessous) le mettent en avant. */
.main-nav .submenu li.submenu-nested > a.submenu-trigger:hover,
.main-nav .submenu li.submenu-nested.submenu-open > a.submenu-trigger {
    background: linear-gradient(90deg, rgba(var(--header-accent),.34), rgba(var(--header-accent),.06) 75%);
    border-left: 3px solid rgba(var(--header-accent),.95);
}

.main-nav .submenu li.submenu-nested > a.submenu-trigger .submenu-caret {
    opacity: .85;
    font-size: 1em;
    color: rgb(var(--header-accent));
}

.main-nav .submenu--nested {
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    list-style: none;
    z-index: 6;
}

.main-nav .submenu li.submenu-nested.submenu-open > .submenu--nested {
    display: flex;
}

.main-nav .submenu--nested li a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: .92rem;
    padding: 0.5rem 1.1rem 0.5rem 1.2rem;
    color: rgba(255,255,255,.88);
}

/* .submenu-price/--cyan/--gold/--blue retirés (demande explicite : "enlève
   les prix à côté des offres" dans le sous-menu Création de site) — plus
   aucun usage dans le HTML. */

/* Neutralise le décalage de padding-left au survol/actif hérité de la règle
   générique ".main-nav .submenu li a:hover" (pensée pour le liséré du menu
   de premier niveau) : sur les triggers imbriqués et les items du
   sous-sous-menu, ce décalage donnait l'impression que le texte "sautait"
   au survol. */
.main-nav .submenu li.submenu-nested > a:hover,
.main-nav .submenu li.submenu-nested.active > a,
.main-nav .submenu--nested li a:hover,
.main-nav .submenu--nested li.active > a {
    padding-left: 1.4rem;
}

.main-nav .submenu--nested li a:hover,
.main-nav .submenu--nested li.active > a {
    padding-left: 1.2rem;
}

@media (hover: hover) and (pointer: fine) {
    /* Desktop uniquement : overlay ancré sous l'item, largeur propre plutôt
       qu'héritée du flux (cf. commentaire plus haut). Ouverture au clic
       (cf. main.js), donc plus aucun souci de survol/reflow entre les
       cellules de la grille du menu "Services". */
    .main-nav .submenu--nested {
        position: absolute;
        top: 100%;
        left: 0;
        min-width: 100%;
        margin-top: 4px;
        padding: 6px;
        background: rgba(17, 19, 27, 0.98);
        backdrop-filter: blur(16px);
        -webkit-backdrop-filter: blur(16px);
        border: 1px solid rgba(255,255,255,.08);
        border-radius: 10px;
        box-shadow: 0 16px 36px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.05);
    }
}

@media (max-width: 992px), (hover: none), (pointer: coarse) {
    /* Mobile / tactile : accordéon en flux normal, pas d'overlay (pas de
       survol continu, donc pas de risque de reflow-pendant-le-hover). */
    .main-nav .submenu--nested {
        margin: 2px 0 6px;
        padding: 2px 0 2px 14px;
        border-left: 2px solid rgba(255,255,255,.08);
    }

    .main-nav .submenu--nested li a {
        padding: 0.65rem 1rem;
        font-size: .95rem;
        white-space: normal;
    }
}

.lang-switcher {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.lang {
    padding: 0.4rem 0.6rem;
    border-radius: 6px;
    text-decoration: none;
    font-weight: 700;
    color: var(--muted);
    border: 1px solid transparent;
    transition: color 0.25s, border-color 0.25s; 
    white-space: nowrap;
}

.lang:hover {
    /* rgb(var(--header-accent)) plutôt que --brand-color : le "reflet" de la
       langue sélectionnée (et son survol) suit l'accent du header actif
       (page ou préférence utilisateur, cf. .site-header--* dans ce fichier). */
    color: rgb(var(--header-accent));
}

.lang.active {
    color: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),0.12);
}

.nav-right {
    display: flex;
    align-items: center;
    gap: 14px;
}

.nav-right-sep {
    width: 1px;
    height: 22px;
    background: rgba(255,255,255,.12);
    flex-shrink: 0;
}

.account-header-link {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    color: var(--text-muted);
    border: 1px solid rgba(255,255,255,.1);
    background: none;
    cursor: pointer;
    transition: color .2s, border-color .2s, background .2s;
    flex-shrink: 0;
}

.account-header-link svg { width: 17px; height: 17px; }

.account-header-link:hover {
    color: #fff;
    border-color: rgba(var(--header-accent),.35);
    background: var(--brand-color-soft);
}

.account-menu {
    position: relative;
    flex-shrink: 0;
}

.account-menu-trigger {
    width: auto;
    height: 36px;
    border-radius: 999px;
    padding: 0 10px;
    gap: 6px;
    font: inherit;
}

.account-menu-caret {
    width: 12px !important;
    height: 12px !important;
    transition: transform .2s ease;
}

.account-menu.menu-open .account-menu-trigger,
.account-menu-trigger[aria-expanded="true"] {
    color: #fff;
    border-color: rgba(var(--header-accent),.35);
    background: var(--brand-color-soft);
}

.account-menu.menu-open .account-menu-caret {
    transform: rotate(180deg);
}

.account-menu-dropdown {
    position: absolute;
    top: calc(100% + 12px);
    right: 0;
    min-width: 200px;
    background: #0c1220;
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 12px;
    padding: 6px;
    box-shadow: 0 18px 40px rgba(0,0,0,.45);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity .18s ease, transform .18s ease, visibility 0s linear .18s;
    z-index: 60;
}

.account-menu.menu-open .account-menu-dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity .18s ease, transform .18s ease, visibility 0s linear 0s;
}

.account-menu-dropdown a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    color: var(--text-color);
    font-size: .88rem;
    font-weight: 600;
    text-decoration: none;
    transition: background .15s ease, color .15s ease;
    white-space: nowrap;
}

.account-menu-dropdown a svg { width: 16px; height: 16px; flex-shrink: 0; opacity: .8; }

.account-menu-dropdown a:hover {
    background: rgba(var(--header-accent),.14);
    color: #fff;
}

.account-menu-dropdown .account-menu-logout {
    margin-top: 4px;
    border-top: 1px solid rgba(255,255,255,.08);
    padding-top: 12px;
    color: #ff9d9d;
}

.account-menu-dropdown .account-menu-logout:hover {
    background: rgba(255,80,80,.14);
    color: #ffc2c2;
}

@media (max-width: 992px) {
    .account-menu-dropdown { right: -6px; }
}

.nav-toggle {
    display: none;
    background: none;
    border: 0;
    width: 40px;
    height: 40px;
}

.hamburger {
    width: 18px;
    height: 2px;
    background: var(--text-color);
    position: relative;
    transition: background 0.25s ease; 
}

.hamburger::before,
.hamburger::after {
    content: "";
    position: absolute;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--text-color);
    transition: transform 0.25s ease; 
}

.hamburger::before { top: -6px; }
.hamburger::after  { top:  6px; }

.nav-left a {
    color: var(--muted);
    font-weight: 600;
    text-decoration: none;
    position: relative;
    transition: color 0.25s;
    white-space: nowrap;
}

.nav-left a.active {
    color: var(--brand-color);
}

.nav-left a.active::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: -2px;
    width: 100%;
    height: 2px;
    background: var(--brand-color);
}

/* ========================= FOOTER ========================= */

/* Footer flottant compact (demande explicite, cf. partials/footer.php) :
   même hauteur/habillage que les widgets .hud-widget (padding, blur, coins
   en équerre .hud-corner ajoutés en markup), positionné dans la MÊME
   rangée que .hud-widget--color (gauche) et .hud-widget--lang (droite) —
   d'où max-width contenu plutôt que min(1200px,...) comme avant, pour ne
   jamais chevaucher ces 2 widgets sur desktop. Comportement d'apparition
   (position fixed/bottom/translateX/.visible) VOLONTAIREMENT inchangé —
   seules taille/habillage/disposition interne changent. */
.site-footer {
	--footer-accent: 10, 88, 202;
	position: fixed;
	bottom: 20px;
	left: 50%;
    pointer-events: none;
	transform: translateX(-50%) translateY(120px);
	opacity: 0;
	width: auto;
	/* Plafond relevé (880px -> 1040px, bug réel constaté en capture d'écran
	   PC : "Navigation/Services/A propos/Légal" retombait sur sa PROPRE
	   ligne, au-dessus du logo/copyright/réseaux, même sur un écran large)
	   — la rangée logo(64px, largeur variable selon le fichier réel) +
	   copyright + réseaux sociaux EN LIGNE (redemandé au tour précédent) a
	   fait grandir le contenu total au point de dépasser régulièrement
	   l'ancien plafond de 880px, ce qui déclenchait le retour à la ligne de
	   .footer-inner (flex-wrap:wrap, cf. plus bas) même en plein écran. */
	max-width: min(1040px, calc(100% - 460px));
	/* z-index aligné sur .hud-widget (480, cf. plus bas) : à 2 comme
	   auparavant, son propre sous-menu déroulant (#footer-mini-nav .submenu,
	   z-index:490) restait plafonné à ce niveau très bas dans le contexte
	   d'empilement global (.site-footer crée son propre contexte via
	   position+z-index) — n'importe quel autre élément de la page avec un
	   z-index plus élevé pouvait alors le recouvrir intégralement, rendant
	   son ouverture invisible malgré un état DOM correct ("le sous-menu ne
	   s'ouvre pas du tout"). Bug réel de contexte d'empilement, pas un
	   simple choix esthétique. */
	z-index: 480;
	background: rgba(6, 10, 20, .78);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
	border: 1px solid rgba(var(--footer-accent), .45);
	border-radius: 4px;
	box-shadow:
        0 0 0 1px rgba(0,0,0,.4),
        0 8px 30px rgba(0,0,0,.5),
        0 0 24px rgba(var(--footer-accent), .18);
	/* padding symétrique (37px/16px -> 20px/20px, demande explicite
	   "centrer le contenu du footer, là collé en bas") : l'écart asymétrique
	   d'origine compensait l'étiquette des widgets couleur/langue (cf.
	   .hud-widget-label) pour matcher leur hauteur totale — mais depuis
	   l'agrandissement du logo (20px -> 64px, cf. .footer-logo plus bas),
	   le contenu de ce footer dépasse de toute façon largement cette
	   hauteur de référence ; l'excès de padding-top ci-dessus ne faisait
	   plus que pousser visuellement tout le contenu vers le bas de la
	   boîte au lieu de le centrer. */
	padding: 20px 20px;
	overflow: visible;
	transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.35s ease, border-bottom-color .4s ease;
}

/* ─── Accent du footer aligné sur l'accent du header actif (page ou
   préférence utilisateur, cf. partials/header.php / $footerAccentCls) ─── */
.site-footer--amber    { --footer-accent: 245, 158, 11; }
.site-footer--emerald  { --footer-accent: 16, 185, 129; }
.site-footer--cyan     { --footer-accent: 232, 237, 245; }
.site-footer--gold     { --footer-accent: 185, 28, 28; }
.site-footer--blue     { --footer-accent: 59, 130, 246; }
.site-footer--violet   { --footer-accent: 139, 92, 246; }

.site-footer.visible {
	transform: translateX(-50%) translateY(0);
    pointer-events: auto;
	opacity: 1;
}

.site-footer::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image: repeating-linear-gradient( 135deg, rgba(255,255,255,0.02) 0, rgba(255,255,255,0.02) 1px, transparent 1px, transparent 12px );
	opacity: 0.25;
	pointer-events: none;
}

.site-footer::after {
	content: "";
	position: absolute;
	inset:-2px;
	background: radial-gradient( circle at 50% 100%, rgba(var(--footer-accent),0.15), transparent 60% );
	transition: background .4s ease;
	pointer-events: none;
}

.footer-inner {
	position: relative;
	max-width: 1200px;
	margin: 0 auto;
	/* Filet de sécurité : sur les petits écrans, le sitemap en colonnes peut
	   rendre le footer plus haut que la fenêtre elle-même. On autorise un
	   défilement interne plutôt que de laisser une partie du contenu
	   inaccessible en haut du panneau. */
	max-height: calc(100dvh - 140px);
	overflow-y: auto;
	overflow-x: hidden;
	-webkit-overflow-scrolling: touch;
}

/* ─── TOP: BRAND + CTA ─── */
.footer-top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	padding-bottom: 22px;
	margin-bottom: 26px;
	border-bottom: 1px solid rgba(255,255,255,.08);
}

.footer-brand {
	display: flex;
	align-items: center;
	gap: 10px;
	text-decoration: none;
	color: inherit;
}

.footer-brand:hover {
    transform: scale(1.05);
}

.footer-brand img {
	width: 170px;
	height: 58px;
	/* Marge verticale négative : compense la hausse de hauteur (42px → 58px)
	   pour que la boîte de l'image (donc la ligne .footer-top) garde le
	   même encombrement qu'avant — seul le logo grandit visuellement,
	   la hauteur globale du footer ne bouge pas. */
	margin: -8px 0;
	object-fit: contain;
	opacity: 0.85;
}

.footer-text {
	font-weight: 700;
	font-size: 1.05rem;
	color: rgba(255,255,255,0.85);
}

/* ─── Boutons du footer — style "fonctionnel" (même logique que
   .btn-account--functional dans l'espace client : sobre, bordure fine,
   fond quasi transparent, typo monospace/majuscules) plutôt qu'un CTA
   marketing (fond plein, ombre portée, pulsation). "Mon compte" garde
   juste une bordure plus marquée pour rester le bouton le plus visible
   des 3, sans reprendre le traitement "CTA". ─── */
.footer-cta {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 11px 18px;
	border-radius: 8px;
	background: rgba(var(--footer-accent), .08);
	border: 1px solid rgba(var(--footer-accent), .55);
	color: #fff;
	font-family: var(--font-title);
	font-weight: 600;
	font-size: .8rem;
	text-transform: uppercase;
	letter-spacing: .05em;
	text-decoration: none;
	transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
}

.footer-cta:hover {
	background: rgba(var(--footer-accent), .18);
	border-color: rgb(var(--footer-accent));
	transform: translateY(-1px);
}

.footer-cta:active {
	transform: none;
}

/* ─── Bouton "Mon compte" du header (cf. partials/header.php, nav-right) :
   copie exacte de .footer-cta ci-dessus (même demande explicite), seule la
   variable d'accent change (--header-accent, posée sur .site-header, plutôt
   que --footer-accent) puisqu'il vit désormais dans le header. Remplace
   l'ancien sélecteur de langue FR/EN/DE à cet emplacement (déplacé dans le
   nouveau widget flottant bas-droite). ─── */
.header-cta {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 9px 16px;
	border-radius: 8px;
	background: rgba(var(--header-accent), .08);
	border: 1px solid rgba(var(--header-accent), .55);
	color: #fff;
	font-family: var(--font-title);
	font-weight: 600;
	font-size: .78rem;
	text-transform: uppercase;
	letter-spacing: .05em;
	text-decoration: none;
	transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
}

.header-cta:hover {
	background: rgba(var(--header-accent), .18);
	border-color: rgb(var(--header-accent));
	transform: translateY(-1px);
}

.header-cta:active {
	transform: none;
}

/* ═══════════════════════════════════════════════════════════════════
   WIDGETS FLOTTANTS "HUD" (Navigation haut-gauche, Mon compte haut-droite,
   couleur bas-gauche, langue bas-droite)
   ═══════════════════════════════════════════════════════════════════
   Demande explicite : présents sur TOUTES les pages (cf. partials/footer.php,
   posés hors de $_isDashboardPage — compte-*.php ET admin-*.php), assez
   grands pour être bien visibles, habillage "vaisseau spatial"/tech façon
   panneau de contrôle (coins en équerre façon .cockpit-corner déjà utilisé
   ailleurs sur le site, fond vitré, liseré lumineux qui suit
   --header-accent, désormais disponible sur <body> — cf. .accent-* plus
   haut — donc résolu correctement même si aucun de ces widgets n'est
   descendant d'un <header>). Masqués pendant tout scroll (haut ou bas) et
   réaffichés 2s après l'arrêt (cf. .is-scroll-hidden, basculée par main.js)
   — demande explicite, remplace l'ancien couplage "repli near-bottom du
   footer" pour couleur/langue. z-index élevé mais sous les bannières
   cookies/traduction. */
.hud-widget {
    position: fixed;
    bottom: 22px;
    z-index: 480;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 18px 16px;
    /* Vignette (demande explicite "j'aimerais également appliquer ce style
       de vignette à navigation/mon compte/couleur/langue") : même
       quadrillage que .service-capsule::before sur services.php (et que
       .site_description .highlight, cf. plus haut), posé ici en 2e/3e
       couches de background-image plutôt qu'en pseudo-élément — les 4
       widgets utilisent déjà ::before/::after ailleurs (cf. .hud-corner,
       markup dédié) pour les coins en équerre, donc pas de pseudo-élément
       libre. Fond/flou/bordure/lueur eux-mêmes inchangés (couleur
       d'accent conservée, cf. .hud-corner et le glow ci-dessous — demande
       explicite passée "les coins doivent suivre la couleur choisie"). */
    background-image:
        linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
    background-size: 16px 16px;
    background-color: rgba(6, 10, 20, .78);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(var(--header-accent), .45);
    border-radius: 10px;
    box-shadow: 0 0 0 1px rgba(0,0,0,.4), 0 8px 30px rgba(0,0,0,.5), 0 0 24px rgba(var(--header-accent), .18);
    transition: transform .5s cubic-bezier(.16,1,.3,1), opacity .4s ease;
}

.hud-widget--color { left: 22px; }
.hud-widget--lang   { right: 22px; }

/* Widgets haut de page (remplacent l'ancienne barre <header>) : ancrés en
   haut, pas en bas — bottom:auto annule la valeur de base ci-dessus. */
.hud-widget--nav,
.hud-widget--account {
    top: 22px;
    bottom: auto;
}
.hud-widget--nav     { left: 22px; }
.hud-widget--account { right: 22px; }

/* Plus de place pour Navigation (demande explicite) : depuis le retrait de
   l'alignement forcé de largeur avec Couleur (cf. main.js,
   syncHudWidgetPairWidths retiré), ce widget reprend sa largeur naturelle —
   ce padding latéral supplémentaire + le flex-wrap:nowrap ci-dessous (sur
   #main-nav > ul) évitent qu'un utilisateur connecté ("Tableau de bord" +
   "Support", plus long que "Accueil"/"CroisierWeb"/"A propos") ne voie
   "Support" repoussé sur une 2e ligne faute de place. */
.hud-widget--nav {
    padding: 14px 26px 16px;
}
#main-nav > ul {
    flex-wrap: nowrap;
}

/* Replié/cache : glisse hors de l'écran plutôt qu'un simple fondu, pour
   renforcer la sensation "panneau qui se rétracte". Les widgets ancrés en
   BAS glissent vers le bas (hors écran par en-dessous) ; ceux ancrés en
   HAUT glissent vers le haut (hors écran par au-dessus) — sinon ils
   glisseraient vers le centre de la page au lieu de sortir du viewport. */
.hud-widget--color.is-collapsed,
.hud-widget--lang.is-collapsed,
.hud-widget--color.is-pending,
.hud-widget--lang.is-pending {
    opacity: 0;
    pointer-events: none;
    transform: translateY(calc(100% + 40px));
}
.hud-widget--nav.is-collapsed,
.hud-widget--account.is-collapsed,
.hud-widget--nav.is-pending,
.hud-widget--account.is-pending {
    opacity: 0;
    pointer-events: none;
    transform: translateY(calc(-100% - 40px));
}

/* Nouveau comportement unifié (demande explicite) : les 4 widgets corner
   (nav/compte/couleur/langue — PAS le mini-footer, cf. plus bas, qui garde
   son propre comportement d'apparition près du bas de page) deviennent
   invisibles pendant tout scroll actif, quel que soit le sens, et
   réapparaissent seulement 2s après l'arrêt du scroll (cf. main.js). Même
   traitement visuel que .is-collapsed/.is-pending ci-dessus (regroupés dans
   les mêmes règles directionnelles au-dessus plutôt que dupliqués ici). */
.hud-widget--color.is-scroll-hidden,
.hud-widget--lang.is-scroll-hidden {
    opacity: 0;
    pointer-events: none;
    transform: translateY(calc(100% + 40px));
}
.hud-widget--nav.is-scroll-hidden,
.hud-widget--account.is-scroll-hidden {
    opacity: 0;
    pointer-events: none;
    transform: translateY(calc(-100% - 40px));
}

/* "Pop" du widget Navigation à l'arrivée en haut de page (demande explicite,
   en plus de son comportement scroll existant ci-dessus) : cf. main.js, qui
   force la réapparition IMMÉDIATE (sans attendre les 2s d'inactivité) dès
   que scrollY repasse proche de 0, et ajoute cette classe le temps d'un
   petit rebond d'accroche.
   opacity AJOUTÉE au keyframe (bug signalé : "coupure" dans l'animation
   d'apparition) : main.js retire .is-scroll-hidden (opacity:0, hors écran)
   et ajoute .is-top-pop dans le même tick. Une animation prend TOUJOURS le
   pas sur une transition pour une même propriété — le "transform" ci-dessous
   était donc déjà entièrement piloté par ce keyframe, mais PAS l'opacity :
   comme ce keyframe ne la mentionnait pas, elle restait gérée par la
   transition générique de .hud-widget (opacity .4s ease, cf. plus haut),
   sur son propre timing/easing, différent de celui du rebond (.5s,
   cubic-bezier distinct). Le fondu (opacity) finissait donc AVANT la fin du
   petit rebond (transform) : le widget apparaissait déjà pleinement opaque
   pendant qu'il continuait de bouger légèrement derrière — 2 mouvements
   perçus comme désynchronisés au lieu d'un seul, d'où la "coupure"
   signalée. Piloter opacity ICI, sur exactement le même timing que
   transform, supprime ce décalage : un seul mouvement continu (fondu +
   rebond terminent ensemble). */
@keyframes hudNavTopPop {
    0%   { transform: translateY(-6px) scale(.94); opacity: 0; }
    55%  { transform: translateY(2px) scale(1.04); opacity: 1; }
    100% { transform: translateY(0) scale(1); opacity: 1; }
}
.hud-widget--nav.is-top-pop,
.hud-widget--account.is-top-pop {
    animation: hudNavTopPop .5s cubic-bezier(.16,1,.3,1) both;
}

/* ─── (Ancienne animation d'apparition au chargement — SUPPRIMÉE, cf.
   main.js.) Gardait Navigation/Mon compte invisibles 1.2s à chaque
   chargement de page avant un fondu de .6s : bug d'apparition signalé sur
   mobile, en contradiction avec la règle plus récente qui impose que ces
   2 widgets soient visibles immédiatement dès le rendu serveur, sans délai. */

/* Coins en équerre lumineux (même esprit que .cockpit-corner sur
   accueil.php) : 2 bordures perpendiculaires par coin, façon viseur HUD. */
.hud-corner {
    position: absolute;
    width: 14px;
    height: 14px;
    border-color: rgba(var(--header-accent), .85);
    pointer-events: none;
}
/* border-top/-left/-right/-bottom en LONGHAND width+style (pas le raccourci
   "border-top: 2px solid") : ce raccourci, sans couleur précisée, réinitialise
   border-*-color à currentColor — ce qui écrasait silencieusement la couleur
   d'accent posée juste au-dessus et faisait apparaître les coins blancs (ou
   couleur du texte) au lieu de suivre --header-accent. Bug réel, pas un
   simple choix esthétique à ajuster. */
.hud-corner--tl {
    top: -1px; left: -1px;
    border-top-width: 2px; border-top-style: solid;
    border-left-width: 2px; border-left-style: solid;
}
.hud-corner--tr {
    top: -1px; right: -1px;
    border-top-width: 2px; border-top-style: solid;
    border-right-width: 2px; border-right-style: solid;
}
.hud-corner--bl {
    bottom: -1px; left: -1px;
    border-bottom-width: 2px; border-bottom-style: solid;
    border-left-width: 2px; border-left-style: solid;
}
.hud-corner--br {
    bottom: -1px; right: -1px;
    border-bottom-width: 2px; border-bottom-style: solid;
    border-right-width: 2px; border-right-style: solid;
}

.hud-widget-label {
    font-family: var(--font-title);
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .16em;
    color: rgba(var(--header-accent), .9);
    text-shadow: 0 0 8px rgba(var(--header-accent), .5);
}

/* Bouton "roquette" repli/déploiement : posé SUR LE CÔTÉ du widget, PAS
   dedans (demande explicite) — absolute par rapport à .hud-widget (déjà
   position:fixed, sert donc de bloc englobant sans changement
   supplémentaire). Le widget couleur est ancré à GAUCHE de l'écran : la
   roquette dépasse sur SA droite (vers le centre) ; le widget langue est
   ancré à DROITE : elle dépasse sur SA gauche (vers le centre aussi) —
   jamais vers le bord d'écran où il n'y a pas de place. */
.hud-widget-toggle {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    overflow: visible;
    border-radius: 50%;
    border: 1px solid rgba(var(--header-accent), .4);
    background: rgba(6, 10, 20, .92);
    color: rgba(var(--header-accent), .95);
    cursor: pointer;
    z-index: 2;
    transition: background-color .2s ease, border-color .2s ease;
}
.hud-widget--color .hud-widget-toggle { right: -15px; }
.hud-widget--lang  .hud-widget-toggle { left: -15px; }
.hud-widget-toggle:hover {
    background: rgba(var(--header-accent), .26);
    border-color: rgb(var(--header-accent));
}
/* Roquette HORIZONTALE, pas diagonale (demande explicite, simplification :
   "place la rockette horizontalement et ne la fait pas tourner. Elle se
   tourne à l'arrivée pour se placer dans le bon sens") : l'ancien schéma
   (-45deg déployée / 135deg repliée) pointait en diagonale alors que la
   traînée ci-dessous est purement HORIZONTALE (scaleX) — la traînée ne
   suivait donc jamais vraiment l'axe de la roquette. Ici, la roquette
   pointe désormais dans le MÊME axe que sa traînée (90deg = vers la
   droite, -90deg = vers la gauche selon le widget, cf. règles par widget
   ci-dessous) et ne pivote qu'UNE fois, au moment bascule ouverture/
   fermeture (demi-tour de 180°), jamais en continu. */
.hud-widget-toggle-icon {
    position: relative;
    z-index: 1;
    width: 14px;
    height: 14px;
    /* >=1.5s (demande explicite : "il ne faut pas que la fermeture soit
       instantanée mais d'au moins 1.5s") — la rotation de la roquette est
       l'animation d'ouverture/fermeture elle-même, pas un simple changement
       d'icône. */
    transition: transform 1.6s cubic-bezier(.65, 0, .35, 1);
}
/* Couleur : traînée à gauche du bouton, qui grandit vers la DROITE
   (transform-origin: left center plus bas) — la roquette pointe donc vers
   la droite au repos (déployée), et vers la gauche une fois repliée (demi-
   tour), pour rester alignée sur cet axe dans les 2 états. */
/* Sens inversé (demande explicite : "tourne les de 180 degré, elles sont
   dans le mauvais sens") — les 2 états sont simplement permutés par
   rapport à la version précédente (90deg/-90deg -> -90deg/90deg pour la
   couleur, et inversement pour la langue), toujours dans le même axe que
   la traînée (cf. .hud-widget-toggle-trail plus bas, transform-origin
   inchangé). */
.hud-widget--color .hud-widget-toggle-icon { transform: rotate(-90deg); }
.hud-widget--color.is-widget-collapsed .hud-widget-toggle-icon { transform: rotate(90deg); }
/* Langue : traînée à droite du bouton, qui grandit vers la GAUCHE
   (transform-origin: right center plus bas) — axe inversé par rapport au
   widget couleur. */
.hud-widget--lang .hud-widget-toggle-icon { transform: rotate(90deg); }
.hud-widget--lang.is-widget-collapsed .hud-widget-toggle-icon { transform: rotate(-90deg); }

/* Traînée derrière la roquette (demande explicite) : rejouée à chaque
   bascule (ouverture ET fermeture) via .is-toggling, posée temporairement
   par main.js — une classe d'état pure comme .is-widget-collapsed ne se
   "rejouerait" pas en sens inverse au redéploiement, il faut un déclencheur
   à chaque clic. Durée alignée sur la rotation de l'icône ci-dessus (1.6s).
   Le sens (transform-origin) part du bouton vers l'EXTÉRIEUR du widget
   (même côté que sa position en dehors de la boîte, cf. ci-dessus). */
.hud-widget-toggle-trail {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 3px;
    height: 3px;
    border-radius: 999px;
    background: linear-gradient(90deg, rgba(var(--header-accent), 0), rgba(var(--header-accent), .95));
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, -50%) scaleX(0);
}
.hud-widget--color .hud-widget-toggle-trail { transform-origin: left center; }
.hud-widget--lang  .hud-widget-toggle-trail { transform-origin: right center; }
.hud-widget-toggle.is-toggling .hud-widget-toggle-trail {
    animation: hudRocketTrail 1.6s ease-out;
}
@keyframes hudRocketTrail {
    0%   { opacity: 0;   transform: translate(-50%, -50%) scaleX(0); }
    12%  { opacity: .95; }
    65%  { opacity: .5;  transform: translate(-50%, -50%) scaleX(20); }
    100% { opacity: 0;   transform: translate(-50%, -50%) scaleX(26); }
}

.hud-widget-options {
    display: flex;
    align-items: center;
    gap: 10px;
    /* Anime l'espacement en même temps que le repli des options (demande
       explicite "l'animation n'est absolument pas fluide") : sans cela, le
       "gap" fixe entre 2 options restait figé pendant que l'une d'elles
       rétrécissait à 0 (max-width), créant un blanc résiduel qui sautait
       d'un coup à la fin de la transition plutôt que de se refermer en
       douceur. */
    transition: gap 1.6s ease;
}

/* ─── Repli manuel/auto des widgets couleur/langue (demande explicite) :
   déployé par défaut (toutes les options visibles), seul le choix
   actuellement sélectionné (.is-active) reste visible une fois replié —
   les autres options rétrécissent à 0 (max-width/opacity) plutôt qu'un
   display:none brutal. La transition réelle est fusionnée directement DANS
   .hud-color-option/.hud-lang-option plus bas dans ce fichier (pas ici) :
   une règle séparée à spécificité égale mais déclarée AVANT celles-ci
   aurait été intégralement écrasée par leur "transition: ..." plus simple
   (shorthand qui remplace tout, ne fusionne pas) — bug réel qui rendait le
   repli/déploiement instantané malgré cette règle. ─── */
.hud-widget--color.is-widget-collapsed .hud-color-option:not(.is-active) {
    opacity: 0;
    max-width: 0;
    /* min-width:0 ajouté (bug réel trouvé, cf. .hud-lang-option ci-dessous
       qui l'avait déjà) : un item flex a par défaut un min-width "auto" qui
       reprend la taille intrinsèque de son contenu (le disque de 40px) —
       cette valeur automatique passe AVANT max-width dans le calcul de la
       largeur utilisée, donc sans ce min-width:0 explicite, l'option ne
       pouvait JAMAIS réellement descendre sous ~40px de large malgré
       "max-width:0", seule son opacity s'animait (repli qui semblait
       "sauter" plutôt que se refermer). */
    min-width: 0;
    margin: 0;
    pointer-events: none;
}
.hud-widget--lang.is-widget-collapsed .hud-lang-option:not(.is-active) {
    opacity: 0;
    max-width: 0;
    min-width: 0;
    padding: 0;
    margin: 0;
    border-width: 0;
    pointer-events: none;
}
/* Le "gap" flex (10px de base) reste appliqué entre CHAQUE paire d'items
   même quand ils sont réduits à une largeur de 0 (comportement normal de
   flexbox : gap ignore la taille réelle des enfants) — sans cette règle,
   replié, le widget gardait tout l'espacement des options masquées (ex.
   6 x 10px de "trous" invisibles autour de la seule option active), qui la
   décalait au lieu de la centrer parfaitement dans la vignette repliée.
   Transition déjà posée sur "gap" dans .hud-widget-options de base. */
.hud-widget--color.is-widget-collapsed .hud-widget-options--color,
.hud-widget--lang.is-widget-collapsed .hud-widget-options--lang {
    gap: 0;
}


/* ─── Widget langue ─── */
.hud-lang-option {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 46px;
    /* max-width EXPLICITE et fini (demande explicite "l'animation n'est
       absolument pas fluide") : bug réel trouvé ici — sans cette valeur,
       le max-width de repos vaut "none" (mot-clé, pas une longueur), or
       une transition CSS ne peut PAS interpoler entre "none" et une
       longueur (0px lors du repli) ; le navigateur "saute" directement à
       la valeur finale au lieu d'animer, pendant que les AUTRES propriétés
       (opacity, padding...) transitionnent normalement sur 1.6s — d'où
       l'impression d'un repli non fluide/instantané malgré la durée
       déclarée plus bas. Valeur choisie confortablement au-dessus du
       min-width + padding ci-dessus pour ne jamais tronquer "FR"/"EN"/
       "DE"/"IT". */
    max-width: 70px;
    height: 40px;
    padding: 0 10px;
    border-radius: 4px;
    border: 1px solid rgba(255,255,255,.18);
    background: rgba(255,255,255,.04);
    color: rgba(255,255,255,.75);
    font-family: var(--font-title);
    font-weight: 700;
    font-size: .85rem;
    letter-spacing: .04em;
    text-decoration: none;
    overflow: hidden;
    /* Propriétés de repli (opacity/max-width/min-width/padding/margin/
       border-width) à 1.6s — demande explicite ("pas instantané, au moins
       1.5s"). Bug réel corrigé ici : une règle séparée déclarée PLUS HAUT
       dans ce fichier posait déjà ces durées, mais cette redéclaration-ci
       (même sélecteur, même spécificité, plus bas donc gagnante) la
       remplaçait ENTIÈREMENT avec un simple "transition: ...15s/.2s" — un
       shorthand ne fusionne jamais avec un autre, il l'écrase, d'où le
       repli qui restait instantané malgré la règle plus haut. */
    transition: background-color .2s ease, border-color .2s ease, color .2s ease, transform .15s ease,
        opacity 1.6s ease, max-width 1.6s ease, min-width 1.6s ease,
        padding 1.6s ease, margin 1.6s ease, border-width 1.6s ease;
}
.hud-lang-option:hover {
    border-color: rgba(var(--header-accent), .7);
    color: #fff;
    transform: translateY(-2px);
}
.hud-lang-option.is-active {
    background: rgb(var(--header-accent));
    border-color: rgb(var(--header-accent));
    /* --accent-harmony-contrast en repli intermédiaire (avant #fff) : même
       filet de sécurité que #main-nav > ul > li.active > a plus bas — le
       vrai correctif de lisibilité "Blanc" (pastille de langue active
       illisible) est sur .accent-cyan lui-même, cf. plus haut. */
    color: var(--brand-color-contrast, var(--accent-harmony-contrast, #fff));
}

/* ─── Widget couleur ─── */
.hud-color-option {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 0;
    border-radius: 50%;
    /* overflow:hidden RETIRÉ (bug réel constaté : tooltip invisible) — le
       disque lui-même (.color-swatch-dot, span enfant) a déjà son propre
       border-radius:50% qui suffit à garder SON fond rond ; l'overflow:hidden
       posé ICI, sur .hud-color-option (le lien, qui sert d'ancrage de
       position:relative au tooltip [data-tooltip]::after ci-dessous),
       rognait le tooltip car un pseudo-élément d'un élément fait partie de
       SA PROPRE zone de clipping — il ne peut pas s'en échapper même
       positionné en dehors de la boîte visuelle (contrairement à ce que
       supposait le commentaire précédent). */
    /* max-width explicite et fini : même correctif/raison que .hud-lang-
       option ci-dessus (48px, confortable au-dessus des 40px du disque
       .color-swatch-dot). */
    max-width: 48px;
    /* position:relative : ancrage du tooltip [data-tooltip]::after
       ci-dessous (demande explicite "au hover sur les planètes du
       sélecteur, indique les 2 couleurs"). */
    position: relative;
    /* Même correctif/raison que .hud-lang-option ci-dessus. */
    transition: transform .15s ease, opacity 1.6s ease, max-width 1.6s ease,
        min-width 1.6s ease, padding 1.6s ease, margin 1.6s ease, border-width 1.6s ease;
}
.hud-color-option:hover { transform: scale(1.1); }

/* Tooltip "2 couleurs" (demande explicite) : remplace l'ancien "title"
   natif du navigateur (un seul mot, non stylable) par un vrai tooltip CSS,
   même technique que [data-tooltip]::after sur les highlights d'index.php
   mais celui-ci reste bien caché hors survol/focus (pas de version
   "toujours visible" ici, le widget couleur n'a pas cette demande). */
.hud-color-option[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    width: max-content;
    max-width: 160px;
    background: rgba(10, 14, 30, .97);
    border: 1px solid rgba(255, 255, 255, .12);
    color: #fff;
    border-radius: 8px;
    font-size: .78rem;
    font-weight: 500;
    line-height: 1.3;
    text-align: center;
    white-space: nowrap;
    padding: 6px 10px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .2s ease, visibility .2s ease, transform .2s cubic-bezier(.16,1,.3,1);
    z-index: 20;
}
.hud-color-option[data-tooltip]:hover::after,
.hud-color-option[data-tooltip]:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}
.hud-color-option .color-swatch-dot {
    width: 40px;
    height: 40px;
}
.hud-color-option.is-active .color-swatch-dot {
    border-color: #fff;
    box-shadow: 0 2px 8px rgba(0,0,0,.5), inset -8px -8px 16px rgba(0,0,0,.55), 0 0 0 3px rgba(255,255,255,.3), 0 0 16px rgba(255,255,255,.4);
}

/* ─── Widget "Navigation" (haut-gauche) — remplace l'ancienne barre
   <header>. Reprend le moteur JS générique de main.js (.main-nav
   .has-submenu, survol avec délai sur nav-services-featured/nav-presentation,
   clic pour les sous-sous-menus imbriqués) : seul l'habillage change ici,
   entièrement scopé sous .hud-widget--nav pour ne jamais dépendre des
   anciennes règles .main-nav/.submenu (toujours présentes plus haut dans ce
   fichier mais désormais sans effet, plus aucun élément ne les cible —
   conservées telles quelles, dead code inoffensif). ─── */
/* Sélecteurs préfixés #main-nav (pas juste .main-nav) volontairement : cf.
   assets/css/responsive.css, qui contient de nombreuses règles ".main-nav
   ..."/".main-nav .nav-services-featured ..." dans son @media(max-width:992px)
   (héritées de l'ancien hamburger mobile). Ce fichier étant chargé APRÈS
   celui-ci, une règle de MÊME spécificité y gagnerait sur mobile. #main-nav
   (id posé sur ce <nav>, cf. partials/footer.php) a une spécificité
   supérieure à n'importe quelle combinaison de classes et gagne donc dans
   tous les cas, sans avoir à auditer/modifier responsive.css. */
#main-nav { display: block; }
#main-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
/* Rangée horizontale (demande explicite, remplace la colonne d'origine) —
   seul le NIVEAU 1 (Accueil/CroisierWeb/A propos) passe en ligne ; la règle
   générique ci-dessus reste en colonne pour les sous-menus (#main-nav
   .submenu la réaffirme de toute façon explicitement). */
#main-nav > ul {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: stretch;
    min-width: 0;
    gap: 8px;
}
#main-nav li { position: relative; }

#main-nav a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 9px 12px;
    border-radius: 4px;
    border: 1px solid rgba(255,255,255,.14);
    background: rgba(255,255,255,.04);
    color: rgba(255,255,255,.82);
    font-family: var(--font-title);
    font-weight: 600;
    font-size: .82rem;
    letter-spacing: .02em;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}
#main-nav > ul > li > a:hover,
#main-nav > ul > li.submenu-open > a {
    border-color: rgba(var(--header-accent), .7);
    color: #fff;
    background: rgba(var(--header-accent), .12);
}
#main-nav > ul > li.active > a {
    background: rgb(var(--header-accent));
    border-color: rgb(var(--header-accent));
    /* Cette règle (spécificité ID) est celle qui s'applique réellement à
       l'état "page active" de CroisierWeb/Accueil/A propos — elle l'emporte
       sur le fond nébuleuse de .main-nav .nav-services-featured.active > a
       plus haut dans ce fichier, qui n'est donc JAMAIS rendu à l'écran (bug
       de spécificité CSS distinct, sans impact visuel puisque cette règle-ci
       le masque entièrement). --accent-harmony-contrast ajouté en repli
       intermédiaire (avant #fff) : filet de sécurité pour toute future
       couleur d'accent dont le texte sur fond plein --header-accent
       nécessiterait du sombre sans qu'on pense à dupliquer
       --brand-color-contrast dessus (cf. .user-accent-cyan) — le vrai
       correctif de lisibilité "Blanc" est sur .accent-cyan lui-même, cf.
       plus haut dans ce fichier. */
    color: var(--brand-color-contrast, var(--accent-harmony-contrast, #fff));
}

/* Bouton "CroisierWeb" mis en valeur (demande explicite) : plus large,
   accent dès l'état de repos (pas seulement au survol/actif) — c'est le
   principal point d'entrée vers l'offre, il doit se distinguer d'Accueil/
   A propos. */
#main-nav .nav-services-featured > a {
    background: rgba(var(--header-accent), .16);
    border-color: rgba(var(--header-accent), .55);
    color: #fff;
    font-weight: 700;
    padding: 9px 16px;
}
#main-nav .nav-services-featured > a:hover,
#main-nav .nav-services-featured.submenu-open > a {
    background: rgb(var(--header-accent));
    border-color: rgb(var(--header-accent));
    /* Ajouté (bug réel : sans cette ligne le texte restait figé à la valeur
       de repos #fff, cf. #main-nav .nav-services-featured > a plus haut) —
       illisible en blanc sur un fond devenu plein au survol/sous-menu ouvert
       quand "Blanc" est la couleur active. Même repli en 2 temps que
       #main-nav > ul > li.active > a ci-dessus. */
    color: var(--brand-color-contrast, var(--accent-harmony-contrast, #fff));
}

/* Chevron discret sur les 2 déclencheurs de sous-menu (CroisierWeb/A propos)
   — scopé ici pour ignorer proprement l'ancienne règle générique
   ".has-submenu > a::after" (plus haut dans ce fichier, non retirée mais
   sans élément cible désormais) sans avoir à la modifier.
   :not(.submenu-nested) (demande explicite, "il y a une flèche de couleur
   et une grise, enlève la grise") : les 5 déclencheurs du sous-menu
   CroisierWeb (Création de sites/Refonte-Audit/...) ont TOUS .has-submenu
   ET .submenu-nested à la fois — sans cette exclusion, ce ::after
   générique (gris, opacity .55) s'affichait EN PLUS de leur propre
   .submenu-caret (span réel, coloré à l'accent), d'où les 2 flèches. */
#main-nav .has-submenu:not(.submenu-nested) > a::after {
    content: '›';
    font-size: 1rem;
    line-height: 1;
    opacity: .55;
    transform: none;
    position: static;
}
#main-nav .has-submenu.submenu-open:not(.submenu-nested) > a::after { opacity: .9; }

/* Sous-menu 1er niveau (CroisierWeb / A propos) : déploiement EN DESSOUS du
   déclencheur (demande explicite, "le premier sous menu se déploie en
   dessous du déclencheur"), comme un dropdown classique — plutôt que
   l'ancien flyout latéral à droite du widget. Le sous-sous-menu imbriqué
   (.submenu--nested, cf. plus bas) continue lui de s'ouvrir À DROITE de
   son propre déclencheur, à l'intérieur de ce dropdown. */
#main-nav .submenu {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    /* width:max-content (demande explicite) : ce flyout est un calque
       flottant qui se pose PAR-DESSUS le contenu de la page (z-index 490,
       jamais poussé dans le flux) — il n'a donc aucune raison d'être
       contraint à une largeur fixe étroite, ni à une hauteur maximale avec
       défilement interne (retiré : demande explicite, "utilise l'espace
       disponible, ne les restreins pas à une petite box" — la barre de
       défilement latérale ÉTAIT justement le max-height/overflow-y:auto
       posé ici au tour précédent, pas une contrainte utile). Seul
       max-width reste, comme pur garde-fou contre un débordement du
       VIEWPORT lui-même sur un écran très étroit (jamais une contrainte de
       design) — la bascule .submenu-flip-h/-v (main.js) gère le cas où
       même ainsi il déborderait. */
    width: max-content;
    min-width: 220px;
    max-width: min(420px, calc(100vw - 20px));
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 10px;
    list-style: none;
    background: rgba(6, 10, 20, .94);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(var(--header-accent), .4);
    border-radius: 6px;
    box-shadow: 0 8px 30px rgba(0,0,0,.5);
    opacity: 0;
    pointer-events: none;
    /* translateY (pas translateX) : le dropdown descend désormais depuis le
       déclencheur au lieu de glisser depuis le côté. */
    transform: translateY(-8px);
    transition: opacity .2s ease, transform .2s ease;
    z-index: 490;
}
#main-nav .has-submenu.submenu-open > .submenu {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}
/* Bascule dynamique (mesurée par main.js, clampSubmenuToViewport) quand le
   flyout déborde du viewport une fois réellement rendu — corrige le cas
   "sous-menu hors écran/hors champ visible" au lieu de le laisser se faire
   rogner silencieusement par overflow-x:clip (cf. html {} plus haut).
   Le dropdown de 1er niveau (#main-nav .submenu, s'ouvre EN DESSOUS) et le
   sous-sous-menu imbriqué (#main-nav .submenu--nested, s'ouvre À DROITE)
   n'ont pas le même axe de débordement à corriger : le 1er reste aligné à
   gauche mais bascule à droite (right:0) s'il déborde, le 2e bascule
   complètement de l'autre côté de son déclencheur (comme avant). */
#main-nav .submenu.submenu-flip-h {
    left: auto;
    right: 0;
}
#main-nav .submenu--nested.submenu-flip-h {
    left: auto;
    right: calc(100% + 10px);
}
#main-nav .submenu.submenu-flip-v,
#main-nav .submenu--nested.submenu-flip-v {
    top: auto;
    bottom: 0;
}

/* ─── Sous-menus "CroisierWeb" et "A propos" centrés sous TOUTE la vignette
   Navigation, PC et mobile (demande explicite) — pas seulement sous leur
   déclencheur respectif (qui n'occupe qu'une partie de la largeur du
   widget, cf. #main-nav .submenu plus haut, "left:0" ancré sur le <li>).
   Technique : #main-nav li est position:relative en général (cf. règle
   plus bas) — ce qui fait du <li> lui-même le bloc de référence de son
   ".submenu" (position:absolute). En repassant CES 2 <li> précis en
   position:static, leur ".submenu" remonte chercher l'ancêtre positionné
   suivant : .hud-widget--nav (position:fixed), qui englobe le widget
   ENTIER (étiquette + liste complète) — "top:100%"/"left:50%" se calculent
   donc désormais sur toute sa hauteur/largeur, pas sur la seule ligne du
   déclencheur. Placé APRÈS les règles .submenu-flip-h/-v ci-dessus (même
   spécificité si les 2 s'appliquaient en même temps, mais un centrage sous
   un widget borné rend un débordement bien plus rare). ─── */
#main-nav .nav-services-featured,
#main-nav .nav-presentation {
    position: static;
}
#main-nav .nav-services-featured .submenu,
#main-nav .nav-presentation .submenu {
    left: 50%;
    right: auto;
    transform: translateX(-50%) translateY(-8px);
}
#main-nav .nav-services-featured.submenu-open > .submenu,
#main-nav .nav-presentation.submenu-open > .submenu {
    transform: translateX(-50%) translateY(0);
}
/* align-self:stretch + width:100%/border-box explicites (pas seulement le
   align-items:stretch par défaut du parent flex) : garantit que CHAQUE
   ligne occupe la pleine largeur du sous-menu (lui-même dimensionné sur
   son contenu le plus large, cf. #main-nav .submenu width:max-content plus
   haut) — condition nécessaire pour que .submenu-trigger-label en flex:1
   pousse réellement la planète au même x sur les 5 lignes (demande
   explicite, "les items ne sont pas alignés verticalement"). */
#main-nav .submenu li {
    position: relative;
    align-self: stretch;
}
#main-nav .submenu li a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    box-sizing: border-box;
    /* padding-left agrandi à 22px (demande explicite, "les points lumineux
       [...] se superpose[nt]" avec le texte) : le voyant lumineux (cf.
       .main-nav .submenu li > a::after plus bas, point de 6px posé à
       left:7px) chevauchait le texte, qui ne commençait qu'à 10px. */
    padding: 7px 10px 7px 22px;
    border-radius: 4px;
    border: none;
    background: transparent;
    color: rgba(255,255,255,.78);
    font-family: var(--font-body, inherit);
    font-weight: 500;
    font-size: .8rem;
    white-space: nowrap;
}
#main-nav .submenu li a:hover,
#main-nav .submenu li.active > a {
    background: rgba(var(--header-accent), .16);
    color: #fff;
}

/* 2 colonnes (demande explicite "colonne 1 texte, colonne 2 planète") sur
   les 5 déclencheurs du sous-menu CroisierWeb (Création de sites/Refonte-
   Audit/Programmation/Hébergement/Conseil et accompagnement) : mêmes 5
   planètes que les highlights d'index.php (cf. data-planet,
   .site_description .highlight plus haut). Le libellé (colonne 1) est
   mis en "flex:1" : il grandit pour occuper toute la largeur restante de
   la ligne, texte callé à gauche — la planète (colonne 2) se retrouve
   ainsi TOUJOURS juste après lui, au même x pour les 5 lignes (elles
   partagent déjà la même largeur totale, cf. #main-nav .submenu width:
   max-content plus haut, qui dimensionne tout le menu sur son contenu le
   plus large) : un vrai alignement en colonnes sans grille/subgrid. */
#main-nav .submenu li.submenu-nested > a.submenu-trigger {
    text-align: left;
}
.submenu-trigger-label {
    flex: 1 1 auto;
    text-align: left;
}
.submenu-planet-icon {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background-image: var(--submenu-planet-img);
    background-size: cover;
    background-position: center;
    box-shadow: 0 0 0 1px rgba(255,255,255,.18), inset -3px -3px 6px rgba(0,0,0,.45);
}
.submenu-planet-icon[data-planet="eau"]      { --submenu-planet-img: url('../image/planet-bleu.webp'); }
.submenu-planet-icon[data-planet="orange"]   { --submenu-planet-img: url('../image/planet-orange.webp'); }
.submenu-planet-icon[data-planet="blanc"]     { --submenu-planet-img: url('../image/planet-blanc.webp'); }
.submenu-planet-icon[data-planet="vert"]      { --submenu-planet-img: url('../image/planet-vert.webp'); }
.submenu-planet-icon[data-planet="violette"]  { --submenu-planet-img: url('../image/planet-violet.webp'); }

/* Icônes terre/lune/galaxie/soleil du sous-menu "À propos" retirées (demande
   explicite : "enlever les planètes/galaxies dans le sous-menu A propos, ne
   garder que le texte") — plus aucun usage dans le HTML. Les variantes
   eau/orange/blanc/vert/violette juste au-dessus restent : toujours
   utilisées par le sous-menu "CroisierWeb". */

/* Sous-sous-menu imbriqué (ex. "Création de sites" dans CroisierWeb) :
   flyout encore plus à droite, ouvert au clic (cf. main.js, isNested). */
#main-nav .submenu--nested {
    position: absolute;
    top: 0;
    left: calc(100% + 8px);
    /* width:max-content (même logique que #main-nav .submenu plus haut) :
       flyout de 2e niveau, lui aussi purement superposé au-dessus du
       contenu de page — se dimensionne sur ses entrées (libellés + badges
       prix Essentiel/Business/Premium) sans jamais wrapper/déborder, la
       bascule .submenu-flip-h gère le débordement du VIEWPORT si besoin. */
    width: max-content;
    min-width: 200px;
    max-width: min(380px, calc(100vw - 20px));
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    padding: 8px;
    list-style: none;
    background: rgba(4, 7, 16, .97);
    border: 1px solid rgba(var(--header-accent), .35);
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0,0,0,.5);
    opacity: 0;
    pointer-events: none;
    transform: translateX(-6px);
    transition: opacity .2s ease, transform .2s ease;
    z-index: 491;
}
#main-nav .submenu li.submenu-nested.submenu-open > .submenu--nested {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(0);
}

/* ─── Widget "Mon compte" (haut-droite) ─── */
/* Alignement en ligne (demande explicite, remplace l'empilement en colonne) :
   bouton principal + liens secondaires côte à côte plutôt que superposés,
   pour rester compact malgré l'ancrage en haut de page. */
.hud-widget-options--account {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 12px;
    min-width: 0;
}
.hud-account-primary {
    display: block;
    text-align: center;
    padding: 10px 16px;
    border-radius: 4px;
    border: 1px solid rgba(var(--header-accent), .55);
    background: rgba(var(--header-accent), .16);
    color: #fff;
    font-family: var(--font-title);
    font-weight: 700;
    font-size: .84rem;
    letter-spacing: .02em;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .2s ease, border-color .2s ease, transform .15s ease;
}
.hud-account-primary:hover {
    background: rgb(var(--header-accent));
    border-color: rgb(var(--header-accent));
    transform: translateY(-1px);
}
.hud-account-secondary {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    font-size: .74rem;
    white-space: nowrap;
}
.hud-account-secondary a {
    color: rgba(255,255,255,.6);
    text-decoration: none;
    transition: color .2s ease;
}
.hud-account-secondary a:hover { color: #fff; }
.hud-account-secondary a.hud-account-logout:hover { color: rgba(248, 113, 113, .9); }

/* ─── Tablette / petit laptop (bug réel trouvé : responsive.css forçait
   encore .main-nav en position:fixed + opacity:0/visibility:hidden en
   dessous de 992px — cf. commentaire de suppression dans responsive.css —
   ce qui rendait le widget "Navigation" et la nav du vrai footer
   invisibles/inutilisables sur toute la plage 641-992px, en plus de
   641-992px n'ayant de toute façon jamais eu SA PROPRE règle ici, la seule
   existante étant celle à 640px plus bas). Resserre juste assez pour éviter
   tout débordement (padding réduit, "Navigation" autorisé à passer à la
   ligne) sans reprendre l'ancien habillage "pile verticale" — ce dernier
   reste réservé à la règle 640px ci-dessous, pensée pour des écrans bien
   plus étroits. ─── */
@media (max-width: 992px) {
    .hud-widget--nav     { top: 16px; left: 14px; bottom: auto; padding: 12px 20px 14px; }
    .hud-widget--account { top: 16px; right: 14px; bottom: auto; }
    #main-nav > ul {
        flex-wrap: wrap;
        row-gap: 6px;
    }
}

@media (max-width: 640px) {
    .hud-widget {
        bottom: 12px;
        padding: 10px 12px 12px;
        gap: 6px;
    }
    .hud-widget--color { left: 10px; }
    .hud-widget--lang   { right: 10px; }
    /* bottom:auto EXPLICITE ici (bug réel trouvé, "Navigation/Mon compte
       remplissent tout l'écran") : la règle générique ".hud-widget"
       ci-dessus pose "bottom:12px" — .hud-widget--nav/--account portent
       AUSSI la classe "hud-widget" et n'annulaient plus "bottom" à cette
       largeur (seule la règle de base, tout en haut de ce fichier, posait
       "bottom:auto", mais à spécificité égale (1 classe) c'est la règle la
       PLUS TARDIVE dans le fichier qui gagne — donc CE bloc-ci). Avec
       "top" ET "bottom" tous deux définis (position:fixed + height:auto),
       le panneau s'étire pour remplir tout l'espace entre les deux, soit
       la quasi-totalité de la hauteur de l'écran. */
    /* "Meilleure idée" (demande explicite, remplace l'ancien empilement
       Navigation/Mon compte l'un sous l'autre) : seule "Navigation" reste
       centrée en haut de page. "Mon compte" descend rejoindre la même
       rangée que Couleur/Langue, entre les deux (cf. .hud-widget--account
       plus bas, ancrée en bas comme eux au lieu du haut). */
    .hud-widget--nav {
        left: 50%;
        right: auto;
        bottom: auto;
        top: 12px;
        transform: translateX(-50%);
        width: calc(100% - 20px);
        max-width: 420px;
        /* Contenu centré (demande explicite : "centre le contenu (titre +
           bouton) au centre de leur vignette pour Navigation et mon
           compte") : align-items:center centre le libellé ET la nav (tous
           deux flex children de .hud-widget--nav) horizontalement dans la
           carte ; text-align:center couvre le texte du libellé lui-même
           (qui, en flex-item stretché, remplissait toute la largeur de la
           carte mais restait affiché à gauche dans cette boîte). */
        align-items: center;
        text-align: center;
    }
    #main-nav > ul {
        justify-content: center;
    }
    /* "Mon compte" entre Couleur (gauche) et Langue (droite), même rangée
       (même valeur de "bottom" que .hud-widget--color/--lang ci-dessous,
       cf. règle plus bas dans ce bloc) — centré horizontalement, largeur
       plafonnée pour ne pas chevaucher les 2 widgets voisins.
       bottom:12px = position par défaut, IDENTIQUE au bas de page normal
       (demande explicite : "remettre en bas de page dans les autres cas") —
       la remontée (près du footer) est posée à part, cf.
       "body.footer-revealed .hud-widget--account" plus bas dans ce même
       bloc, activée par la classe déjà posée par main.js
       (handleFooterVisibility -> document.body.classList.toggle
       ('footer-revealed', nearBottom)) exactement quand le footer flottant
       apparaît — aucun nouveau JS nécessaire. */
    .hud-widget--account {
        top: auto;
        bottom: 12px;
        left: 50%;
        right: auto;
        transform: translateX(-50%);
        width: auto;
        max-width: 150px;
        /* Contenu centré (demande explicite, cf. .hud-widget--nav ci-dessus
           pour le détail) : le libellé "MON COMPTE" restait affiché à
           gauche dans sa boîte stretchée malgré le bouton/liens déjà
           centrés (cf. .hud-widget-options--account plus bas). */
        align-items: center;
        text-align: center;
    }

    /* ─── Vrai conflit trouvé (bug persistant malgré le fix opacity
       précédent, "coupure" toujours signalée en mobile) : Navigation/Mon
       compte sont centrés horizontalement ICI via "left:50%;
       transform:translateX(-50%)" (règles juste au-dessus). Mais
       .is-collapsed/.is-pending/.is-scroll-hidden (hors media query, plus
       haut dans ce fichier) ET l'animation .is-top-pop (@keyframes
       hudNavTopPop) redéfinissent TOUS "transform" avec uniquement un
       translateY/scale, SANS le translateX(-50%) — un seul "transform" ne
       peut porter qu'une valeur à la fois, donc dès que l'une de ces
       classes s'applique (masquage au scroll, "pop" en haut de page...),
       le widget perd instantanément son centrage horizontal et saute d'un
       demi-widget vers la gauche pendant tout le masquage/l'animation, puis
       re-saute au centre en revenant à l'état normal. C'est CE saut
       horizontal (pas l'opacity, déjà corrigée) qui est la "coupure" —
       invisible sur desktop (ces widgets n'y sont pas centrés par
       transform), donc jamais repéré avant ce signalement mobile répété.
       Surcharge : recompose translateX(-50%) + le translateY d'origine
       dans un seul transform, pour CETTE largeur d'écran uniquement. */
    .hud-widget--nav.is-collapsed,
    .hud-widget--nav.is-pending,
    .hud-widget--nav.is-scroll-hidden {
        transform: translateX(-50%) translateY(calc(-100% - 40px));
    }
    /* "Mon compte" a en plus changé d'ancrage sur cette largeur (bottom:12px
       au lieu de top, cf. règle .hud-widget--account ci-dessus) : le
       masquer vers le HAUT (comme Navigation, resté ancré en haut) le
       ferait glisser DANS le contenu de la page au lieu de sortir de
       l'écran par le bas — direction recalée en conséquence, même principe
       que .hud-widget--color/--lang (ancrés en bas eux aussi, cf. plus haut
       dans ce fichier). */
    .hud-widget--account.is-collapsed,
    .hud-widget--account.is-pending,
    .hud-widget--account.is-scroll-hidden {
        transform: translateX(-50%) translateY(calc(100% + 40px));
    }
    /* Même conflit pour le "pop" (.is-top-pop, cf. @keyframes hudNavTopPop
       plus haut) : une animation prend le pas sur toute valeur "transform"
       statique, donc une simple surcharge de "transform" ici n'aurait aucun
       effet — il faut un keyframe dédié qui inclut translateX(-50%) à
       chaque étape, substitué seulement pour cette largeur d'écran
       (animation-name seul, les autres réglages — durée/timing/fill-mode —
       restent hérités de la règle de base). Navigation reste ancrée en
       haut (même sens que sur desktop) ; Mon compte, ancré en bas ici,
       rebondit dans le sens opposé pour rester cohérent avec sa position
       réelle. */
    @keyframes hudNavTopPopMobile {
        0%   { transform: translateX(-50%) translateY(-6px) scale(.94); opacity: 0; }
        55%  { transform: translateX(-50%) translateY(2px) scale(1.04); opacity: 1; }
        100% { transform: translateX(-50%) translateY(0) scale(1); opacity: 1; }
    }
    .hud-widget--nav.is-top-pop {
        animation-name: hudNavTopPopMobile;
    }
    @keyframes hudAccountTopPopMobile {
        0%   { transform: translateX(-50%) translateY(6px) scale(.94); opacity: 0; }
        45%  { transform: translateX(-50%) translateY(-2px) scale(1.04); opacity: 1; }
        100% { transform: translateX(-50%) translateY(0) scale(1); opacity: 1; }
    }
    .hud-widget--account.is-top-pop {
        animation-name: hudAccountTopPopMobile;
    }

    /* Compact + empilé en colonne (au lieu de la disposition en ligne par
       défaut, cf. .hud-widget-options--account plus haut) : le widget
       n'a que 150px de large ici (cf. max-width ci-dessus), pas assez pour
       "Tableau de bord"/"S'inscrire" + les liens secondaires côte à côte. */
    .hud-widget--account .hud-widget-options--account {
        flex-direction: column;
        align-items: center;
        gap: 4px;
    }
    .hud-widget--account .hud-account-primary {
        padding: 6px 10px;
        font-size: .68rem;
        text-align: center;
        white-space: normal;
    }
    .hud-widget--account .hud-account-secondary {
        flex-direction: column;
        font-size: .62rem;
        gap: 2px;
        white-space: normal;
    }
    .hud-widget-options { gap: 6px; }
    .hud-lang-option { min-width: 38px; height: 34px; font-size: .75rem; }
    .hud-color-option .color-swatch-dot { width: 32px; height: 32px; }
    .hud-widget-label { font-size: .6rem; letter-spacing: .1em; }
    /* Roquette un peu plus petite + moins débordante sur petit écran, pour
       ne pas risquer de sortir du viewport (widgets déjà collés aux bords
       à 10px ci-dessus). */
    .hud-widget-toggle { width: 26px; height: 26px; }
    .hud-widget--color .hud-widget-toggle { right: -12px; }
    .hud-widget--lang  .hud-widget-toggle { left: -12px; }
    /* Traînée de la roquette retirée en responsive (demande explicite) :
       l'accordéon couleur/langue s'ouvre désormais à la verticale sur
       mobile (cf. plus bas) — la traînée, purement horizontale (scaleX),
       n'a plus de sens visuel dans cet axe. La rotation de l'icône
       elle-même (ouverture/fermeture) est conservée, seule la traînée
       disparaît. */
    .hud-widget-toggle.is-toggling .hud-widget-toggle-trail {
        animation: none;
    }
    .hud-widget-toggle-trail {
        display: none;
    }
    /* flex-wrap repassé en "wrap" ici (annule le nowrap desktop ci-dessus) :
       sur écran étroit, le widget lui-même est bien plus contraint (padding
       réduit ci-dessus, collé au bord à 10px) — le nowrap desktop ferait
       déborder la rangée hors du widget plutôt que de l'aider. */
    #main-nav > ul { min-width: 132px; flex-wrap: wrap; }
    #main-nav a { padding: 7px 9px; font-size: .74rem; }
    /* Écran étroit : plus assez de place à droite pour un flyout — les
       sous-menus s'ouvrent plutôt EN DESSOUS de leur déclencheur (pleine
       largeur disponible du widget), pas sur le côté. #main-nav (pas
       .hud-widget--nav .submenu) pour gagner face à responsive.css, cf.
       commentaire plus haut. */
    #main-nav .submenu {
        left: 0;
        top: calc(100% + 8px);
        min-width: 190px;
        max-width: calc(100vw - 40px);
    }
    #main-nav .submenu li.submenu-nested > .submenu--nested {
        left: 0;
        top: calc(100% + 6px);
        min-width: 170px;
        max-width: calc(100vw - 56px);
    }
    .hud-widget-options--account { flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; }
    .hud-account-primary { padding: 8px 12px; font-size: .76rem; }
    /* Plus de remontée conditionnelle (demande explicite, "meilleure idée" :
       "mon compte couleur et langue toujours en bas de page... rajouter un
       padding sur le footer et pas sur les vignettes") : "Mon compte" reste
       à sa position basse normale (12px, cf. règle plus haut) en toute
       circonstance — c'est désormais .site-footer qui monte pour se placer
       au-dessus de cette rangée quand il apparaît (cf. règle plus bas dans
       ce même bloc 640px). */
}

/* ─── Conteneur "Accueil" + "Mon compte" + "S'inscrire" en mobile, cf.
   responsive.css ─── */
.footer-top-actions {
	display: inline-flex;
	align-items: center;
	gap: 12px;
}

/* Deux copies de ce conteneur existent dans le markup (cf. partials/footer.php) :
   ".footer-top-actions--desktop" dans .footer-top (à côté du logo) et
   ".footer-top-actions--mobile" juste au-dessus du sitemap. Sur desktop,
   seule la 1ère est utile — la 2ᵉ est masquée par défaut ; responsive.css
   inverse ça en mobile. */
.footer-top-actions--mobile {
	display: none;
}

/* "Accueil" n'a de sens qu'en mobile, une fois le logo masqué (cf.
   responsive.css) : sur desktop le logo fait déjà office de lien vers
   l'accueil. Masqué ici par défaut, réaffiché uniquement en mobile.
   "S'inscrire", lui, reste affiché sur desktop comme bouton secondaire
   à gauche de "Mon compte" (cf. règle dédiée juste après). Style
   volontairement en retrait (secondaire) par rapport à ".footer-cta"
   ("Mon compte"), qui doit rester le bouton mis en avant. */
.footer-home-btn,
.footer-register-btn {
	display: none;
	align-items: center;
	padding: 11px 18px;
	border-radius: 8px;
	color: rgba(255,255,255,.7);
	font-family: var(--font-title);
	font-weight: 600;
	font-size: .8rem;
	text-transform: uppercase;
	letter-spacing: .05em;
	text-decoration: none;
	background: rgba(255,255,255,.03);
	border: 1px solid rgba(255,255,255,.14);
	transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
}

.footer-register-btn {
	display: inline-flex;
}

.footer-home-btn:hover,
.footer-register-btn:hover {
	color: #fff;
	background: rgba(255,255,255,.07);
	border-color: rgba(255,255,255,.28);
	transform: translateY(-1px);
}

.footer-home-btn:active,
.footer-register-btn:active {
	transform: none;
}

/* ─── SITEMAP (colonnes) ─── */
.footer-sitemap {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 24px;
	padding-bottom: 22px;
	margin-bottom: 22px;
	border-bottom: 1px solid rgba(255,255,255,.08);
}

.footer-col-title {
	display: flex;
	align-items: baseline;
	gap: 8px;
	margin: 0 0 14px;
	font-size: .72rem;
	font-weight: 700;
	letter-spacing: .09em;
	text-transform: uppercase;
	/* Suit --footer-accent (posée sur .site-footer) plutôt qu'un bleu fixe :
	   les 4 titres de colonne (Navigation/Services/Entreprise/Légal) restent
	   assortis à l'accent du header/footer actif. */
	color: rgba(var(--footer-accent),.85);
	transition: color .4s ease;
}

.footer-col-title-link {
	display: flex;
	align-items: baseline;
	gap: 8px;
	color: inherit;
	text-decoration: none;
	transition: opacity .2s ease;
}

.footer-col-title-link:hover {
	opacity: .78;
	text-decoration: underline;
	text-decoration-color: rgba(var(--footer-accent),.5);
}

.footer-col-index {
	font-family: monospace;
	font-size: .72rem;
	font-weight: 400;
	letter-spacing: 0;
	color: rgba(var(--footer-accent),.45);
	transition: color .4s ease;
}

.footer-col-links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.footer-col-links a {
	position: relative;
	display: inline-block;
	padding: 5px 0 5px 12px;
	text-decoration: none;
	color: rgba(255,255,255,0.6);
	font-size: .92rem;
	font-weight: 500;
	transition: color 0.2s ease, padding-left 0.2s ease;
}

.footer-col-links a::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: 5px;
	height: 1px;
	background: rgba(var(--footer-accent),.55);
	transform: translateY(-50%) scaleX(0);
	transform-origin: left;
	transition: transform .2s ease, width .2s ease;
}

.footer-col-links a:hover {
	/* Suit --footer-accent (posée sur .site-footer selon la page active,
	   cf. partials/header.php / $footerAccentCls) plutôt qu'un bleu fixe,
	   comme le reste des éléments du footer (titres de colonne, CTA...). */
	color: rgb(var(--footer-accent));
	padding-left: 16px;
}

.footer-col-links a:hover::before {
	transform: translateY(-50%) scaleX(1);
	width: 9px;
}

/* ─── BOTTOM: COPYRIGHT + SOCIAUX ─── */
.footer-bottom {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	flex-wrap: wrap;
}

.footer-copy {
	margin: 0;
	text-align: left;
	font-size: 0.85rem;
	color: rgba(255,255,255,0.5);
}

.footer-socials {
	display: flex;
	align-items: center;
	gap: 10px;
}

.footer-social-link {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	color: rgba(255,255,255,.6);
	border: 1px solid rgba(255,255,255,.12);
	background: rgba(255,255,255,.03);
	transition: color .2s ease, border-color .2s ease, background .2s ease, transform .2s ease;
}

.footer-social-link svg {
	width: 16px;
	height: 16px;
}

.footer-social-link:hover {
	color: #fff;
	border-color: rgba(var(--header-accent),.5);
	background: rgba(var(--header-accent),.14);
	transform: translateY(-2px);
	box-shadow: 0 6px 16px rgba(var(--header-accent),.25);
}

/* ─── Footer flottant compact : disposition interne en une seule rangée
   (mini-menus déroulants + copyright/réseaux), cf. partials/footer.php.
   Redéclare .footer-inner/.footer-bottom/.footer-social-link en overrides
   ciblés plutôt que d'éditer leurs règles d'origine plus haut (toujours
   utilisées telles quelles par d'autres composants du site). ─── */
.site-footer .footer-inner {
	max-width: none;
	max-height: none;
	overflow: visible;
	/* Grille à 3 colonnes (nav | logo+copyright | réseaux sociaux), demande
	   explicite "le logo doit être bien centré au centre du footer" : avec
	   un simple flex space-between, le bloc logo+copyright se centrait au
	   mieux dans l'espace restant à DROITE de la nav, jamais au centre réel
	   de toute la barre. 2 colonnes latérales égales (1fr) garantissent que
	   la colonne du milieu (largeur "auto", cf. .footer-bottom) tombe bien
	   au centre mathématique du footer, quelle que soit la largeur propre
	   de la nav à gauche et des réseaux sociaux à droite. */
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 18px;
	/* wrap (pas nowrap) : filet de sécurité — si le contenu dépasse malgré
	   tout la largeur disponible sur un viewport intermédiaire, il passe
	   sur une 2e ligne DANS la boîte au lieu de déborder par-dessus/à côté
	   (bug remonté explicitement, "beaucoup d'élément hors box"). */
	row-gap: 8px;
}
#footer-mini-nav { justify-self: start; }
.site-footer .footer-bottom { justify-self: center; }
.site-footer .footer-socials { justify-self: end; }
.site-footer .footer-bottom {
	display: flex;
	align-items: center;
	padding-left: 14px;
	border-left: 1px solid rgba(255,255,255,.12);
}
/* Rangée logo + copyright (demande explicite "placer le logo a gauche") :
   logo (lien cliquable vers index.php) + barre grise de séparation +
   copyright, alignés sur une seule ligne. */
.site-footer .footer-brand-row {
	display: flex;
	align-items: center;
	gap: 14px;
}
.site-footer .footer-logo-link {
	display: block;
	line-height: 0;
	flex: 0 0 auto;
	border-radius: 10px;
	transition: opacity .2s ease;
}
.site-footer .footer-logo-link:hover {
	opacity: .85;
}
.site-footer .footer-logo {
	/* Agrandi fortement (20px -> 64px de haut, demande explicite "il faut
	   grandement agrandir le logo") : le footer flottant garde une hauteur
	   libre (cf. .footer-inner ci-dessus, pas de height fixe), il peut donc
	   grandir sans rien casser autour. */
	display: block;
	height: 64px;
	width: auto;
	border-radius: 10px;
}
/* Barre grise verticale entre le logo et le copyright (demande explicite
   "rajoutes une barre grise à droite du logo"). */
.site-footer .footer-brand-divider {
	width: 1px;
	height: 34px;
	flex: 0 0 auto;
	background: rgba(255,255,255,.18);
}
.site-footer .footer-copy {
	font-size: .72rem;
	white-space: nowrap;
}
/* Réseaux sociaux sur 1 ligne, 3e colonne de la grille .footer-inner
   ci-dessus (demande explicite : garder discord/linkedin tout à droite,
   en ligne). */
.site-footer .footer-socials {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 10px;
}
.site-footer .footer-social-link {
	width: 26px;
	height: 26px;
	flex: 0 0 auto;
}
.site-footer .footer-social-link svg { width: 13px; height: 13px; }

/* Mini-nav du footer : même moteur JS générique que le widget Navigation
   (.main-nav .has-submenu dans main.js) mais présenté en rangée horizontale
   de 4 déclencheurs, avec un flyout qui s'ouvre VERS LE HAUT (le footer est
   ancré en bas d'écran, contrairement au widget Navigation en haut). */
/* Déclencheurs sur 2 lignes fixes (demande explicite : "ligne 1 : Navigation,
   Services / ligne 2 : A propos, légal") : grille 2 colonnes plutôt qu'un
   simple flex-wrap qui dépendait de la largeur disponible — l'ordre du DOM
   (Navigation, Services, Entreprise/"A propos", Légal, cf. les 4 <li> plus
   haut) correspond déjà exactement à l'ordre de remplissage par défaut d'une
   grille (ligne par ligne), donc aucun changement de markup nécessaire.
   justify-content:start (pas center, hérité de .footer-inner) : demande
   explicite "alignés à gauche". */
#footer-mini-nav ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(2, max-content);
	justify-content: start;
	/* justify-items:start (au lieu du "stretch" par défaut d'une grille) :
	   chaque bouton ne s'étire plus à la largeur de son voisin de colonne
	   (ex. "A propos" ne s'étirait plus discrètement à la largeur de
	   "Navigation" au-dessus) — chacun ne prend que sa propre largeur de
	   texte, avec un espacement réellement uniforme entre eux (cf. gap
	   ci-dessous). */
	justify-items: start;
	/* Espacement agrandi (8px -> 14px/18px, demande explicite "rajoute de
	   l'espace entre les 4 boutons... ils sont trop serrés"). */
	row-gap: 14px;
	column-gap: 18px;
}
#footer-mini-nav li { position: relative; }
#footer-mini-nav > ul > li > a {
	display: block;
	/* Largeur fixe + texte centré (demande explicite "les 4 boutons de
	   navigation doivent être de la même taille") : avant, chaque bouton ne
	   prenait que la largeur de son propre texte (Navigation/Services/A
	   propos/Légal ont des longueurs différentes), donc 4 tailles
	   différentes malgré le padding identique. 118px couvre confortablement
	   le plus long label ("Navigation") dans toutes les langues du site. */
	width: 118px;
	box-sizing: border-box;
	padding: 8px 12px;
	text-align: center;
	border-radius: 4px;
	border: 1px solid rgba(255,255,255,.14);
	background: rgba(255,255,255,.04);
	color: rgba(255,255,255,.8);
	font-family: var(--font-title);
	font-weight: 600;
	font-size: .72rem;
	letter-spacing: .03em;
	text-decoration: none;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}
#footer-mini-nav > ul > li > a:hover,
#footer-mini-nav > ul > li.submenu-open > a {
	border-color: rgba(var(--footer-accent), .7);
	color: #fff;
	background: rgba(var(--footer-accent), .12);
}
#footer-mini-nav .submenu {
	position: absolute;
	/* top:auto EXPLICITE (bug réel trouvé, "s'ouvre toujours en dessous et
	   en ligne au lieu d'une colonne") : l'ancienne règle générique
	   ".main-nav .submenu" (encore présente plus haut dans ce fichier,
	   posée pour le widget Navigation avec ses items nav-services-featured/
	   nav-presentation, cf. commentaire à côté) fixe "top: 100%" sur TOUT
	   ".submenu" imbriqué dans un ancêtre ".main-nav" — or #footer-mini-nav
	   porte AUSSI la classe "main-nav" (moteur JS de sous-menus partagé).
	   Cette règle-ci ne posait jusqu'ici QUE "bottom", jamais "top" : les 2
	   valeurs ("top:100%" hérité + "bottom:calc(100%+10px)" posé ici)
	   s'appliquaient donc SIMULTANÉMENT (2 propriétés distinctes, aucun
	   conflit de spécificité entre elles) — avec position:absolute et
	   height:auto, top ET bottom tous deux définis force le navigateur à
	   ÉTIRER la boîte entre les deux (le classique "top:0;bottom:0" qui
	   remplit tout l'espace dispo), donnant une hauteur quasi nulle/négative
	   ici vu la faible hauteur du déclencheur — d'où le rendu cassé
	   (ouverture en dessous, mise en page en ligne). "top: auto" ici annule
	   l'héritage et ne laisse plus QUE "bottom" pilote la position. */
	top: auto;
	bottom: calc(100% + 10px);
	left: 0;
	/* width:max-content (même logique que #main-nav plus haut) : flyout
	   posé au-dessus du contenu de page, se dimensionne sur ses libellés
	   plutôt que d'être contraint à une petite boîte fixe. */
	width: max-content;
	min-width: 190px;
	max-width: min(360px, calc(100vw - 20px));
	display: flex;
	flex-direction: column;
	gap: 2px;
	margin: 0;
	padding: 8px;
	list-style: none;
	background: rgba(6, 10, 20, .94);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
	border: 1px solid rgba(var(--footer-accent), .4);
	border-radius: 6px;
	box-shadow: 0 8px 30px rgba(0,0,0,.5);
	opacity: 0;
	pointer-events: none;
	transform: translateY(6px);
	transition: opacity .2s ease, transform .2s ease;
	z-index: 490;
}
#footer-mini-nav li.has-submenu.submenu-open > .submenu {
	opacity: 1;
	pointer-events: auto;
	transform: translateY(0);
}
/* Bascule dynamique (mesurée par main.js, cf. #main-nav plus haut pour le
   détail) : si le flyout déborderait à droite du viewport une fois ouvert,
   il s'ancre à droite de son déclencheur au lieu de la gauche. */
#footer-mini-nav .submenu.submenu-flip-h {
	left: auto;
	right: 0;
}
/* text-align:left répété à 3 niveaux (submenu, li, a) + !important sur le
   lien (demande explicite répétée : "le texte des liens est toujours
   centré") : malgré la règle déjà posée sur le lien lui-même (ID-scopée,
   donc normalement prioritaire sur tout le CSS partagé "main-nav"), le
   texte restait rapporté centré — sécurité supplémentaire à 3 niveaux pour
   ne plus dépendre d'un seul point de défaillance/héritage, quelle qu'en
   soit la cause exacte (feuille non rechargée côté navigateur, etc.). */
#footer-mini-nav .submenu,
#footer-mini-nav .submenu li {
	text-align: left;
}
/* align-self:stretch (demande explicite répétée, confirmée par capture
   d'écran : chaque ligne du sous-menu flottait à une position horizontale
   différente selon la longueur de son texte, comme si le groupe entier
   était centré plutôt que chaque ligne étirée sur toute la largeur) :
   qu'une source d'"align-items" concurrente existe quelque part dans le
   CSS partagé "main-nav" ou non, "align-self" posé DIRECTEMENT sur l'enfant
   l'emporte toujours sur la valeur d'"align-items" du parent flex — un
   correctif définitif qui ne dépend plus de trouver la règle fautive
   exacte. width:100% en complément, pour que la boîte de chaque lien
   corresponde réellement à cette largeur étirée. */
#footer-mini-nav .submenu li {
	align-self: stretch;
	width: 100%;
	box-sizing: border-box;
}
#footer-mini-nav .submenu li a {
	display: block;
	width: 100%;
	box-sizing: border-box;
	/* padding-left porté à 22px (bug réel trouvé, demande explicite "le
	   point visuel est placé sous le texte, il faut créer un décalage") :
	   ce lien partage le même point/pastille (.main-nav .submenu li >
	   a::after, 6px, posé à left:7px) que le widget Navigation — mais
	   contrairement à lui (#main-nav .submenu li a, déjà en padding-left:
	   22px), CE lien-ci était resté à 9px, faisant chevaucher la pastille
	   (7-13px) et le début du texte (dès 9px). Même valeur que le widget
	   Navigation pour un espacement cohérent sur tout le site.
	   text-align:left en !important (demande explicite répétée "je veux
	   que le tout soit alignés à gauche" / "le texte est toujours
	   centré") : dernier recours après plusieurs tentatives sans
	   !important restées sans effet visible signalé par l'utilisateur. */
	padding: 6px 9px 6px 22px;
	text-align: left !important;
	border-radius: 4px;
	color: rgba(255,255,255,.78);
	font-size: .78rem;
	font-weight: 500;
	white-space: nowrap;
	text-decoration: none;
}
#footer-mini-nav .submenu li a:hover { background: rgba(var(--footer-accent), .16); color: #fff; }
/* Dernier menu ("Légal") : son flyout s'alignerait hors de l'écran à droite
   si ancré à gauche comme les autres — ancré à droite à la place. */
#footer-mini-nav > ul > li:last-child > .submenu { left: auto; right: 0; }

/* ─── Petits écrans (demande explicite) : plus assez de place pour loger le
   footer ENTRE couleur (gauche) et langue (droite) sur la même rangée — il
   passe pleine largeur, juste EN DESSOUS d'elles. Seuil à 900px (plus large
   que celui des widgets eux-mêmes, 640px) : la formule
   max-width:min(880px, calc(100% - 460px)) du footer desktop deviendrait
   négative bien avant 640px, ce nouveau seuil la neutralise à temps. ─── */
@media (max-width: 900px) {
    /* max-width + flex-wrap (bug réel trouvé, "couleur et langue se
       chevauchent") : les 2 widgets sont ancrés chacun à un bord opposé
       (left/right) avec une largeur basée sur leur contenu (7 pastilles
       couleur dont "Automatique", 4 langues) — sans plafond, rien
       n'empêchait leur rangée de s'étendre jusqu'à se recouvrir au milieu
       de l'écran sur les largeurs les plus étroites. Plafonné à la moitié
       de l'écran chacun (avec la marge des 22px/14px d'ancrage déduite) :
       au-delà, les pastilles/langues passent à la ligne (flex-wrap) en
       filet de sécurité plutôt que de continuer à pousser horizontalement
       vers l'autre widget.
       bottom : plus de remontée conditionnelle (demande explicite,
       "meilleure idée" : "mon compte couleur et langue toujours en bas de
       page. Le footer se place au dessus donc rajouter un padding sur le
       footer et pas sur les vignettes") — couleur/langue restent à leur
       position basse normale (22px, cf. règle générique .hud-widget tout en
       haut de ce fichier, aucune surcharge nécessaire ici) EN
       PERMANENCE. C'est désormais le footer flottant (.site-footer
       ci-dessous) qui remonte pour se placer AU-DESSUS d'elles quand il
       apparaît, plutôt que l'inverse — plus simple, un seul élément mobile
       au lieu de 3.
       Pastilles couleur resserrées à 30px/6px de gap dès ce seuil (au lieu
       d'attendre 640px) : sur cette plage 641-900px, les 7 pastilles à leur
       taille desktop (40px) dépassaient la largeur plafonnée ci-dessus et
       repassaient à la ligne — rendant ce widget plus haut que celui de
       langue (jamais que 4 items, toujours sur une ligne). Demande
       explicite "même hauteur" : en tenant les 2 sur une seule ligne dans
       tous les cas, les 2 widgets gardent la même hauteur totale. */
    .hud-widget--color,
    .hud-widget--lang {
        max-width: calc(50vw - 20px);
    }
    .hud-widget--color .hud-widget-options,
    .hud-widget--lang .hud-widget-options {
        flex-wrap: wrap;
    }
    .hud-widget--color .color-swatch-dot {
        width: 30px;
        height: 30px;
    }
    .hud-widget--color .hud-widget-options {
        gap: 6px;
    }
    /* bottom relevé (16px -> 145px, demande explicite ci-dessus) : le footer
       flottant se place désormais au-dessus de la rangée couleur/langue au
       lieu qu'elles ne remontent vers lui. */
    .site-footer {
        left: 50%;
        bottom: 145px;
        width: calc(100% - 24px);
        max-width: calc(100% - 24px);
    }
    .site-footer .footer-inner {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        row-gap: 8px;
    }
    /* Colonne + centré en responsive (demande explicite : "mets IN et
       discord en dessous de '2026 Croisier Web'" puis "centre le logo et
       le texte + la ligne in et discord") — réservé au mobile/tablette,
       cf. .site-footer .footer-bottom en row+space-between pour le PC,
       juste au-dessus dans ce fichier ("c'était mieux, garde-les en
       ligne" ne concernait QUE le PC). */
    .site-footer .footer-bottom {
        flex-direction: column;
        align-items: center;
        border-left: none;
        padding-left: 0;
        justify-content: center;
        width: 100%;
    }
    .site-footer .footer-brand-row {
        justify-content: center;
    }
    .site-footer .footer-copy {
        text-align: center;
    }
    /* Réseaux sociaux sur 1 ligne en responsive (demande explicite : "met
       discord et linkdink sur une ligne au lieu de 2") : la version 2
       lignes (empilée, cf. règle desktop plus haut) reste réservée au
       PC — sur mobile/tablette, la place est plus limitée en largeur et
       les 2 icônes tiennent très bien côte à côte. */
    .site-footer .footer-socials {
        flex-direction: row;
        justify-content: center;
    }
}

@media (max-width: 640px) {
    /* Plus de remontée (demande explicite, "meilleure idée" : "mon compte
       couleur et langue toujours en bas de page... rajouter un padding sur
       le footer et pas sur les vignettes") : couleur/langue restent à la
       position basse générique (12px, cf. ".hud-widget" tout en haut de ce
       fichier) EN PERMANENCE, plus aucune surcharge de "bottom" ici. Seul
       le footer flottant (cf. ".site-footer" plus bas dans ce bloc) monte
       pour se placer au-dessus quand il apparaît. */
    .hud-widget--color,
    .hud-widget--lang {
        max-width: calc(50vw - 16px);
    }
    /* ─── Accordéon VERTICAL (demande explicite : "fait l'ouverture
       fermeture des sélecteurs à la verticale, uniquement sur mobile") :
       les pastilles couleur/langues s'empilent en colonne au lieu d'une
       rangée horizontale, et le repli anime max-height (au lieu de
       max-width/min-width, cf. règles desktop plus haut) pour rétrécir en
       hauteur plutôt qu'en largeur. Un max-height fini et identique en
       repos ET en overflow:hidden sont nécessaires pour que la transition
       anime réellement (même piège que "max-width:none" documenté plus haut
       pour .hud-lang-option — une transition ne peut pas interpoler depuis/
       vers "none"). ─── */
    .hud-widget--color .hud-widget-options,
    .hud-widget--lang .hud-widget-options {
        flex-direction: column;
        align-items: center;
    }
    .hud-widget--color .hud-color-option,
    .hud-widget--lang .hud-lang-option {
        max-height: 44px;
        transition: background-color .2s ease, border-color .2s ease, color .2s ease, transform .15s ease,
            opacity 1.6s ease, max-height 1.6s ease, min-width 1.6s ease,
            padding 1.6s ease, margin 1.6s ease, border-width 1.6s ease;
    }
    /* overflow:hidden posé UNIQUEMENT ici (état replié, options non actives)
       et pas sur .hud-color-option en base : rappel du bug déjà corrigé
       ailleurs dans ce fichier (cf. commentaire sur .hud-color-option
       "overflow:hidden RETIRÉ... rognait le tooltip") — un overflow:hidden
       permanent aurait de nouveau masqué le tooltip de la pastille active,
       toujours visible/interactive, elle. Ici il ne s'applique qu'aux
       pastilles en train de disparaître (pointer-events déjà coupé), sans
       affecter la pastille active qui garde son tooltip fonctionnel. */
    .hud-widget--color.is-widget-collapsed .hud-color-option:not(.is-active) {
        max-width: none;
        max-height: 0;
        overflow: hidden;
    }
    .hud-widget--lang.is-widget-collapsed .hud-lang-option:not(.is-active) {
        max-width: none;
        max-height: 0;
        overflow: hidden;
    }
    /* bottom relevé (10px -> 160px, demande explicite ci-dessus) : le
       footer flottant se place désormais au-dessus de la rangée couleur/
       mon compte/langue au lieu qu'elles ne remontent vers lui. */
    .site-footer {
        bottom: 160px;
        width: calc(100% - 16px);
        max-width: calc(100% - 16px);
        padding: 10px 14px 12px;
    }
    /* Les 4 boutons sur une seule ligne (demande explicite, spécifique au
       mobile — la grille 2x2 PC, cf. règle de base, reste inchangée à
       partir de 641px) : repasse en flex row plutôt que la grille 2
       colonnes, avec un gap/padding/police resserrés pour que les 4
       tiennent côte à côte sur un petit écran. */
    /* gap 4px -> 8px (demande explicite "créer un léger espace entre les
       boutons de navigation") : les 4 boutons restaient un peu trop
       collés les uns aux autres sur 1 seule ligne. */
    #footer-mini-nav > ul {
        display: flex;
        flex-wrap: nowrap;
        gap: 8px;
    }
    #footer-mini-nav > ul > li > a { width: 74px; padding: 5px 7px; font-size: .62rem; }
    /* Logo + copyright sur 2 lignes séparées ET centrés (demande explicite
       répétée : d'abord "le logo et '2026 Croisierweb' doivent être sur 2
       lignes différentes", puis "centre le logo et le texte... + la ligne
       in et discord") : le logo agrandi (64px de haut, cf. .footer-logo)
       ne laisse plus assez de place à côté du texte sur un écran étroit —
       .footer-brand-row repasse donc en colonne ici, logo au-dessus du
       texte, tous deux centrés horizontalement (align-items:center, plus
       flex-start) — cf. aussi .footer-copy text-align:center et
       .footer-socials justify-content:center posés au niveau du palier
       900px (hérités ici, cette media query est imbriquée dans la plage
       plus large 641-900px). */
    .site-footer .footer-brand-row {
        flex-direction: column;
        align-items: center;
        gap: 6px;
    }
    /* Barre grise masquée en colonne (demande explicite logo/texte sur 2
       lignes) : un séparateur vertical n'a plus de sens une fois le logo
       empilé au-dessus du copyright plutôt qu'à côté. */
    .site-footer .footer-brand-divider {
        display: none;
    }
}


/* ========================= landingpage.php ========================= */

.section-company {
    position: relative;
}

/* Même technique que sur le reste du site (.page-XXX::before) : un calque de
   fond en position fixed, cadré sur la fenêtre plutôt que sur la section.
   .section-company englobe aussi le bloc d'avis sous le hero, donc sa hauteur
   totale dépasse largement celle de l'écran ; l'ancien "background: ... cover"
   posé directement sur la section se calculait sur toute cette hauteur et
   zoomait l'image au point de ne plus laisser voir ni la nébuleuse ni le cadre
   décoratif (rendu presque uniformément noir, quelle que soit la longueur de
   la page). En le cadrant sur la fenêtre, l'image garde son cadrage d'origine
   partout, y compris sur mobile. */
.section-company::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    /* Teinte retirée d'ici (déplacée sur ::after, cf. ci-dessous) : demande
       explicite "je la veux avant l'apparition du bg (image) et qu'elle
       s'annule dès l'apparition de celle-ci" — l'image reste donc affichée
       sans filtre permanent, la teinte n'existe plus que comme un calque
       temporaire par-dessus qui disparaît juste après le chargement. */
    background: var(--space-bg) center / cover no-repeat;
    /* Dérive lente façon Ken Burns (demande explicite, phase intro jugée
       "un peu fade") : léger zoom + léger glissement, aller-retour continu,
       pour que le fond ne soit jamais complètement figé pendant la frappe.
       Très lent (26s) et de faible amplitude pour rester discret. */
    animation: heroBgDrift 26s ease-in-out infinite alternate;
    will-change: transform;
}

@keyframes heroBgDrift {
    from { transform: scale(1) translate(0, 0); }
    to   { transform: scale(1.06) translate(-1.2%, -1.2%); }
}

/* Calque de teinte bleu nuit étoilé temporaire : visible en premier (quasi
   opaque, l'image dessous n'est donc pas visible tant qu'il est là), et
   reste affichée jusqu'à l'arrivée du trou noir (demande explicite : "je
   la veux jusqu'à l'arrivée du trou noir, fin de la saisie"), pas juste
   un court instant après le chargement. var(--reveal-delay) est calculée
   en PHP à partir de la durée de frappe du tagline (cf. index.php) — la
   même variable qui déclenche le dézoom du trou noir — et posée en
   inline ICI SUR .section-company (pas seulement .section-company-hero,
   plus bas dans l'arbre) car les custom properties ne remontent jamais
   d'un descendant vers un ancêtre : ce pseudo-élément, sur .section-company
   lui-même, ne pouvait pas lire une variable posée plus bas. Même z-index
   que ::before (0) : généré après lui dans l'ordre de la boîte, il se
   peint donc par-dessus (au même niveau d'empilement), tout en restant
   derrière le contenu réel (.section-company > *, z-index:1). */
.section-company::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    /* Assombri (demande explicite) : le but est un contraste plus net
       entre le tout début du chargement (très sombre) et la fin (une fois
       la teinte effacée, l'image apparaît nettement plus claire). */
    background: linear-gradient(rgba(2,5,15,.97), rgba(1,2,8,.99));
    animation: sectionCompanyTintFade .8s ease-in var(--reveal-delay, 1.5s) forwards;
}

@keyframes sectionCompanyTintFade {
    from { opacity: 1; }
    to   { opacity: 0; }
}

.section-company > * {
    position: relative;
    z-index: 1;
}

.section-company-hero {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 100dvh;
    padding-top: 150px;
    padding-bottom: 60px;
}

/* ─── Champ d'étoiles scintillantes (demande explicite, phase intro jugée
   "un peu fade") ─── 2 calques (::before/::after) avec des positions et
   des rythmes de scintillement différents, pour un effet moins mécanique
   qu'un seul calque qui clignote d'un bloc. Purement décoratif, posé
   derrière le trou noir/le contenu (z-index:0, généré avant
   .index-hero-black-hole dans le flux). Positions en % : couvrent
   exactement la hauteur de .section-company-hero (100dvh mini), pas
   besoin de répétition/tuilage. */
.section-company-hero::before,
.section-company-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

.section-company-hero::before {
    background-image:
        radial-gradient(1.5px 1.5px at 8% 22%,  rgba(255,255,255,.9), transparent 100%),
        radial-gradient(1px   1px   at 22% 68%, rgba(255,255,255,.7), transparent 100%),
        radial-gradient(2px   2px   at 38% 12%, rgba(255,255,255,.85),transparent 100%),
        radial-gradient(1px   1px   at 52% 82%, rgba(255,255,255,.6), transparent 100%),
        radial-gradient(1.5px 1.5px at 68% 34%, rgba(255,255,255,.9), transparent 100%),
        radial-gradient(1px   1px   at 84% 58%, rgba(255,255,255,.65),transparent 100%),
        radial-gradient(2px   2px   at 93% 18%, rgba(255,255,255,.85),transparent 100%),
        radial-gradient(1px   1px   at 14% 90%, rgba(255,255,255,.6), transparent 100%),
        radial-gradient(1.5px 1.5px at 46% 46%, rgba(255,255,255,.75),transparent 100%),
        radial-gradient(1px   1px   at 76% 88%, rgba(255,255,255,.6), transparent 100%);
    animation: heroStarsTwinkleA 5s ease-in-out infinite;
}

.section-company-hero::after {
    background-image:
        radial-gradient(1px 1px at 30% 30%, rgba(200,225,255,.8), transparent 100%),
        radial-gradient(1px 1px at 60% 60%, rgba(200,225,255,.7), transparent 100%),
        radial-gradient(1px 1px at 88% 40%, rgba(200,225,255,.75),transparent 100%),
        radial-gradient(1px 1px at 12% 55%, rgba(200,225,255,.65),transparent 100%),
        radial-gradient(1px 1px at 44% 78%, rgba(200,225,255,.7), transparent 100%),
        radial-gradient(1px 1px at 70% 15%, rgba(200,225,255,.75),transparent 100%);
    animation: heroStarsTwinkleB 7.5s ease-in-out infinite;
    animation-delay: -2.3s;
}

@keyframes heroStarsTwinkleA {
    0%, 100% { opacity: .55; }
    50%      { opacity: 1; }
}

@keyframes heroStarsTwinkleB {
    0%, 100% { opacity: .9; }
    50%      { opacity: .4; }
}

/* ─── Trou noir décoratif au centre de la 1ère section (index.php) ───
   Même habillage/mêmes keyframes que .hero-black-hole (services.php) :
   dézoom d'entrée (heroBlackHoleLife, top-level donc réutilisable ici sans
   dupliquer le keyframe) puis disque d'accrétion (::before, blackHoleSpin)
   + horizon des événements (::after, blackHolePulse) qui tournent/pulsent
   en continu. z-index:0 explicite : simple garde-fou, le placement avant
   .container.company-inner dans le markup suffit déjà à le garder derrière
   (aucun des deux n'a de z-index qui inverserait l'ordre du DOM). */
/* ─── Indice du trou noir avant son arrivée (demande explicite, phase
   intro jugée "un peu fade") ─── Petit point lumineux, MÊME position
   exacte que .index-hero-black-hole (top:50dvh + translate(-50%,-50%)),
   scintille doucement pendant la frappe puis s'éteint pile quand le vrai
   trou noir apparaît : 2 animations sur "opacity", la 2e (fade, listée en
   dernier) l'emporte sur la 1re (twinkle) pendant qu'elle est active — le
   scintillement cède donc proprement la place à l'extinction sans
   qu'elles ne se mélangent. Palette bleutée, cohérente avec le trou noir
   recoloré d'index.php. */
.index-hero-hole-hint {
    position: absolute;
    top: 50dvh;
    left: 50%;
    width: 5px;
    height: 5px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: rgba(var(--hole-light, 210,230,255), .95);
    box-shadow:
        0 0 8px 3px rgba(var(--hole-mid, 140,190,255), .55),
        0 0 22px 9px rgba(var(--hole-glow, 80,150,255), .25);
    z-index: 0;
    pointer-events: none;
    animation:
        indexHoleHintTwinkle 2.2s ease-in-out infinite,
        indexHoleHintFade .5s ease-in forwards;
    animation-delay: 0s, calc(var(--reveal-delay, 1.5s) - .5s);
}

@keyframes indexHoleHintTwinkle {
    0%, 100% { opacity: .55; }
    50%      { opacity: 1; }
}

@keyframes indexHoleHintFade {
    from { opacity: 1; }
    to   { opacity: 0; }
}

.index-hero-black-hole {
    position: absolute;
    /* top:50dvh (et non 50%) : .section-company-hero a min-height:100dvh
       MAIS AUSSI padding-top:150px + padding-bottom:60px ajoutés par-dessus
       (box-sizing content-box), donc sa boîte réelle dépasse largement
       100dvh — un top:50% se centrait alors sur CETTE boîte gonflée, pas
       sur l'écran (décalage vers le bas d'environ (150-60)/2 ≈ 45px selon
       le contenu, d'où le "pas bien centré" signalé). dvh est une unité de
       longueur toujours relative au VIEWPORT, quelle que soit la taille du
       parent positionné : 50dvh tombe donc pile au centre réel de l'écran
       au chargement (quand la page n'a pas encore défilé), tout en restant
       position:absolute (contrairement à fixed, l'élément défile bien avec
       la section une fois la page parcourue). */
    top: 50dvh;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 0;
    height: 0;
    z-index: 0;
    opacity: 0;
    pointer-events: none;
    /* Délai avant que le dézoom ne débute : le trou noir apparaît
       immédiatement immense (scale 16, écran couvert) et y reste jusqu'à
       var(--reveal-delay) — posée en inline sur .section-company-hero
       (cf. index.php), calculée en PHP à partir de la longueur du texte
       tapé par la machine à écrire (cf. .site_description_devise
       .typewriter plus bas) : le dézoom n'a plus lieu à un 1.5s fixe mais
       une fois la saisie terminée, quelle que soit la langue (repli sur
       1.5s si la variable n'est pas définie). Puis le dézoom (scale 16 ->
       1) se joue sur 1.3s. "both" (et non simplement "forwards") : tient
       la frame 0% (opacity:1, scale:16) PENDANT le délai, sinon l'élément
       retomberait sur son opacity:0 statique le temps du délai puis
       réapparaîtrait d'un coup au démarrage de l'animation — même piège
       d'enchaînement déjà rencontré ailleurs sur ce projet. */
    animation: heroBlackHoleLife 1.3s cubic-bezier(.16,1,.3,1) var(--reveal-delay, 1.5s) both;
}

.index-hero-black-hole::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(390px, 55vw, 690px);
    height: clamp(390px, 55vw, 690px);
    margin-top: -1px;
    border-radius: 50%;
    /* Teinte bleutée demandée explicitement, UNIQUEMENT sur index.php :
       même structure de dégradé (angles, alpha, position des stops,
       flou, rotation) que la version jaune/or partagée par les 4 autres
       instances (services.php, accueil.php, why-target, services-cta),
       simplement recolorée ambre -> bleu. Comme .index-hero-black-hole
       est une classe distincte propre à index.php (pas de sélecteur
       partagé), ce changement ne touche aucune autre page. */
    /* Couleurs pilotées par --hole-light/-mid/-soft/-base (cf. bloc
       .img-accent-* tout en haut du fichier) : repli bleu ci-dessous si
       aucune préférence n'est active (visiteur anonyme ou préférence non
       connectée), recoloré dès qu'un client a choisi une couleur en Mon
       profil, quelle qu'elle soit. */
    background:
        conic-gradient(
            from -20deg,
            rgba(255,255,255,0)                    0deg,
            rgba(var(--hole-mid, 140,190,255),.6)   38deg,
            rgba(var(--hole-base, 60,150,255),.68)  68deg,
            rgba(var(--hole-light, 200,225,255),.7) 92deg,
            rgba(var(--hole-soft, 110,180,255),.36) 118deg,
            rgba(255,255,255,0)                     152deg,
            rgba(255,255,255,0)                     222deg,
            rgba(var(--hole-soft, 90,170,255),.22)  250deg,
            rgba(var(--hole-soft, 90,170,255),.4)   282deg,
            rgba(var(--hole-light, 200,225,255),.55) 302deg,
            rgba(var(--hole-base, 50,150,255),.4)   320deg,
            rgba(255,255,255,0)                     360deg
        );
    box-shadow: 0 0 clamp(41px, 5.8vw, 72px) clamp(12px, 1.8vw, 22px) rgba(var(--hole-glow, 80,150,255),.30);
    --hole-blur: 22px;
    animation:
        blackHoleSpin 22s linear infinite,
        blackHoleFlicker 6.5s ease-in-out infinite;
    pointer-events: none;
}

.index-hero-black-hole::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(200px, 28vw, 350px);
    height: clamp(200px, 28vw, 350px);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    /* Version "réaliste" restaurée (demande explicite : "on avait obtenu un
       résultat très réaliste", plus de barre horizontale) : la bande
       linéaire equatoriale est retirée — un seul radial-gradient forme un
       cœur noir opaque avec un fin anneau photonique clair à 58-66%
       (l'horizon des événements), plus proche d'une vraie photo de trou
       noir. Complété par un léger backdrop-filter (flou + saturation) sur
       le bord pour un rendu moins "à plat". */
    background:
        radial-gradient(circle, #000000 0%, #000000 58%, rgba(var(--hole-light, 200,225,255),.85) 62%, #000000 66%, rgba(0,0,0,0) 76%);
    backdrop-filter: blur(2px) saturate(1.15);
    -webkit-backdrop-filter: blur(2px) saturate(1.15);
    box-shadow: 0 0 clamp(45px, 6.2vw, 78px) clamp(15px, 2.1vw, 26px) rgba(0,0,0,.85);
    animation: blackHolePulse 4.5s ease-in-out infinite;
    pointer-events: none;
}

/* Ancienne intro (logo + accroche dupliqués, centrés en absolute sur la
   section, qui s'effaçaient en fondu à 1.5s pendant qu'une DEUXIÈME copie
   du logo à l'intérieur de .company-inner apparaissait à une position
   différente) retirée : demande explicite "le logo de l'état 1 doit être
   le même qu'à l'état 2, pas de repop" — deux <img> distincts qui se
   croisaient en fondu à des positions légèrement différentes créaient un
   effet de saut/duplication. Le VRAI logo (.company-logomain, cf. plus
   bas — celui qui a le lien vers index.php + l'effet de parallaxe souris,
   cf. main.js) et le VRAI accroche (.site_description_devise, réordonnée
   juste après lui ci-dessous) sont maintenant visibles dès le chargement,
   sans aucune animation d'entrée : un seul élément par rôle, jamais
   dupliqué, jamais recaché/re-fondu — donc littéralement "le même, sans
   repop". Le reste du contenu (liens .highlight, bouton, petit logo du
   bas) continue lui d'apparaître en cascade à partir de 1.5s (cf. plus
   bas), pendant que le trou noir se dézoome : ce sont ces éléments-là qui
   marquent la transition vers l'état 2, pas le logo/l'accroche qui restent
   un point fixe stable pendant toute la séquence. */

.company-inner {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    max-width: 900px;
    padding: 40px 20px;
    /* Remonte tout le bloc d'environ 10px (demande explicite), sans toucher
       au centrage vertical de .section-company-hero lui-même. */
    transform: translateY(-10px);
}

/* ─── 3 blocs centrés sur le trou noir (demande explicite) ───
   Bloc 1 (logo + accroche) / écart / bloc 2 (highlights, en plein centre
   du disque) / écart identique / bloc 3 (rockette + "Visiter le site").
   Les 2 spacers .index-hero-gap partagent la même classe (donc la même
   hauteur) : les 2 écarts sont égaux par construction, sans avoir à les
   calculer à la main. Le gap:14px de .company-inner (flex column)
   s'ajoute uniformément avant/après CHAQUE bloc et CHAQUE spacer, donc de
   façon symétrique des deux côtés — il ne casse pas l'égalité des 2
   écarts. Hauteur du spacer calée sur le disque d'accrétion du trou noir
   (::before, clamp(390px,55vw,690px)) en un peu plus petit, pour laisser
   voir le cœur + une partie du halo sans écarter les blocs à l'excès sur
   petit écran. */
.index-hero-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}

/* Logo + sous-titre : 2 demandes successives à concilier — (1) "je ne veux
   plus que ça reste fixe/suive le scroll" (position:fixed retiré) puis
   (2) "ils devraient être en haut de la page au centre" (pas au milieu de
   l'écran, où le remflouement dans le flux de .company-inner les avait
   fait atterrir, centrés verticalement avec les highlights/le bouton).
   Solution : position:absolute (PAS fixed) ancré près du haut de
   .section-company-hero (position:relative, cf. plus haut) — sibling de
   .index-hero-black-hole dans le markup, donc en dehors du flux de
   .company-inner. Contrairement à fixed, un élément en absolute défile
   NORMALEMENT avec le reste du document (il sort de l'écran avec sa
   section quand on scrolle) : "en haut de la page", mais plus "fixe". */
.index-hero-block--top {
    position: absolute;
    top: clamp(24px, 5vh, 56px);
    left: 50%;
    transform: translateX(-50%);
    width: auto;
    max-width: 480px;
    z-index: 2;
}

@media (max-width: 900px) {
    .index-hero-block--top {
        max-width: calc(100vw - 170px);
    }
}

/* Décalage vers le bas (demande explicite : "le logo et texte... doivent
   être décalés vers le bas sinon ils sont cachés par la vignette
   navigation") : sur mobile, la vignette "Navigation" (.hud-widget--nav,
   cf. plus haut) est centrée en haut de l'écran et peut désormais dépasser
   ~56px de haut (clamp d'origine ci-dessus) une fois son contenu répliqué
   sur 2 lignes — elle recouvrait donc le logo/l'accroche. */
@media (max-width: 640px) {
    /* 170px -> 130px (demande explicite : "remonter un peu le logo et le
       texte... pour qu'il ne déborde pas sur le trou noir") : la valeur de
       170px (cf. commentaire ci-dessus) restait nécessaire pour ne pas
       passer sous le widget "Navigation" (.hud-widget--nav, top:12px à
       cette largeur), mais laissait le bloc logo+accroche déborder sur le
       trou noir (centré à 50dvh) sur les écrans mobiles les plus courts.
       130px garde une marge de sécurité sous le widget (qui culmine autour
       de ~70-90px selon qu'il passe sur 1 ou 2 lignes) tout en remontant le
       bloc pour l'éloigner du trou noir. À revérifier si "Navigation"
       venait à s'agrandir encore. */
    .index-hero-block--top {
        top: 130px;
    }
}

.index-hero-block--bottom {
    transform: translateY(-50px);
}

.company-logo {
    transform: translateY(-50px);
}

.index-hero-gap {
    width: 100%;
    height: clamp(150px, 20vw, 240px);
}

/* Remonte légèrement le bloc 3 (rockette + "Visiter le site") — demande
   explicite — en réduisant SPÉCIFIQUEMENT le 2e écart (entre le bloc 2 et
   le bloc 3), sans toucher au 1er (entre le bloc 1 et le bloc 2) : les 2
   écarts ne sont donc plus rigoureusement identiques, ce resserrement
   ciblé étant une demande plus récente et plus précise. */
.index-hero-gap--tight {
    /* Resserré une nouvelle fois (demande explicite "remonte encore le
       bouton + rockette") : 110-190px -> 80-150px. */
    height: clamp(80px, 11vw, 150px);
}

.site_description {
    font-size: 1.5rem;
    line-height: 1.85;
    font-weight: 600;
    max-width: 820px;
    margin: 0 auto;
    color: rgba(255,255,255,0.95);
    letter-spacing: 0.2px;
    opacity: 0;
    /* Easing amélioré (demande explicite "améliore la fluidité de leur
       animation d'apparition") : cubic-bezier(.16,1,.3,1), la même courbe
       de décélération douce déjà utilisée pour le trou noir/les autres
       entrées de cette cascade, au lieu du "ease-out" générique — rendu
       plus fluide/premium. Durée légèrement allongée (0.9s -> 1.1s) pour
       laisser la décélération se lire pleinement. */
    animation: fadeUp 1.1s cubic-bezier(.16,1,.3,1) forwards;
    /* .company-inner ne fait plus de fondu global (cf. commentaire plus
       haut — logo/accroche sont désormais visibles en permanence, sans
       fondu de conteneur) : ce délai part donc directement de
       var(--reveal-delay) (le moment où le trou noir commence son
       dézoom, lui-même calé sur la fin de la machine à écrire, cf.
       .index-hero-black-hole plus haut), plutôt que d'un 1.5s fixe. */
    animation-delay: var(--reveal-delay, 1.5s);
}

/* Copie visible/interactive des highlights, positionnée pile au centre du
   trou noir (demande explicite "place les highlight pile au centre du
   trou noir, ne touche pas à l'emplacement des autres éléments"). Le
   bloc .index-hero-block--center d'origine, dans le flux, devient
   visibility:hidden (cf. .index-hero-highlights-placeholder plus bas) :
   il continue à réserver exactement le même espace entre les 2 écarts
   (donc le logo/accroche au-dessus et la rockette/bouton en dessous ne
   bougent pas d'un pixel), pendant que CETTE copie, sortie du flux et
   positionnée en absolute, se cale sur .section-company-hero avec
   EXACTEMENT la même formule que .index-hero-black-hole (top:50dvh +
   translate(-50%,-50%)) : garanti pixel-parfait au centre réel du trou
   noir, sans dépendre du centrage flex de .company-inner (lequel est
   décalé par le padding-top/bottom asymétrique de la section — même bug
   déjà contourné pour le trou noir lui-même). Le "transform" ci-dessous
   ne rentre plus en conflit avec l'animation fadeUp (qui anime désormais
   "translate" en longhand, cf. animation.css) : les 2 propriétés
   coexistent sans s'écraser. */
/* Conteneur devenu un point d'ancrage 0x0 (demande explicite : "diaporama"
   horizontal en boucle autour du trou noir) — même principe EXACT que
   .index-hero-black-hole (0x0 + top:50dvh/left:50%) : chaque highlight
   (cf. .site_description .highlight plus bas) est désormais position:
   absolute par rapport à CE point, avec sa propre trajectoire horizontale
   (@keyframes highlightOrbitLoop) plutôt qu'un simple alignement en ligne
   dans le flux du texte. */
.index-hero-highlights-centered {
    position: absolute;
    top: 50dvh;
    left: 50%;
    width: 0;
    height: 0;
    z-index: 1;
    pointer-events: none;
}

/* ─── Bouton "Explorer" + rockette, sous la sphère du trou noir, dans le
   halo (demande explicite : "je les veux plus [bas]. Ils doivent être en
   dessous de la sphère du trou noir. Dans le halo.") ───
   Même ancrage EXACT que le trou noir/les highlights ci-dessus
   (top:50dvh + left:50% + translate(-50%,-50%) : les 3 partagent donc le
   même point central, quel que soit le contenu qui précède dans le flux
   de .company-inner). Le translateY additionnel (après le -50%,-50%, donc
   appliqué APRÈS le centrage — les transforms s'enchaînent dans l'ordre
   d'écriture) enfonce le bouton sous l'horizon des événements (::after,
   rayon clamp(100px,14vw,175px)) sans dépasser le disque d'accrétion/halo
   (::before, rayon clamp(195px,27.5vw,345px)) : la valeur clamp() ci-
   dessous (150-260px, mise à l'échelle en vw) reste toujours strictement
   entre les deux rayons, à toutes les tailles d'écran. */
.index-hero-actions-centered {
    position: absolute;
    top: 50dvh;
    left: 50%;
    transform: translate(-50%, -50%) translateY(clamp(150px, 20vw, 260px));
    z-index: 1;
    pointer-events: auto;
}

/* Fondu du contenu du hero au lancement (demande explicite : "le contenu
   de la page/section se rend invisible via un fondu, de la durée du
   pré-lancement de la rockette") : posée/retirée par main.js sur
   .section-company-hero en même temps que .launching sur le bouton, donc
   strictement synchronisée. :not(.index-hero-actions-centered):not(
   .index-hero-black-hole) exclut la rockette/le bouton ET le trou noir de
   ce fondu (demande explicite : "le trou noir lui doit rester visible") —
   seuls le logo+accroche et les highlights disparaissent, pendant que la
   rockette tourne autour du trou noir toujours visible en arrière-plan.
   !important nécessaire : plusieurs de ces enfants portent une animation
   d'entrée "forwards" qui garde sinon la main sur "opacity", quelle que
   soit la spécificité d'une règle statique concurrente (piège de cascade
   déjà rencontré ailleurs sur ce projet). Durée 1.05s = EXACTEMENT celle
   du pré-lancement (cf. .hero-actions .btn.launching ci-dessous). */
.section-company-hero.is-launch-fadeout > *:not(.index-hero-actions-centered):not(.index-hero-black-hole) {
    opacity: 0 !important;
    transition: opacity 1.05s ease !important;
    pointer-events: none;
}

/* Bloc d'origine (resté dans le flux pour réserver l'espace) : invisible
   et retiré de l'arbre d'accessibilité, la copie ci-dessus étant la seule
   version réellement affichée/cliquable. */
.index-hero-highlights-placeholder {
    visibility: hidden;
}

.site_description_devise {
    /* Réagrandi (.62rem -> .88rem, demande explicite "augmente titre +
       descriptif") : reste compact pour la bannière fine épinglée en haut
       de page (cf. .index-hero-block--top), mais nettement plus lisible
       que la taille très réduite du tour précédent. */
    font-size: .88rem;
    line-height: 1.5;
    font-weight: 700;
    max-width: 100%;
    margin: 0 auto 6px;
    /* Marge du haut réduite encore (10px -> 2px, demande explicite) pour
       coller davantage au logo. Réordonnée juste après .company-logomain
       dans le markup (au lieu
       d'après .site_description) : c'est maintenant elle qui joue le rôle
       "accroche juste sous le logo" pendant l'état 1, avec le même
       habillage "kicker" que précédemment (demande explicite "garde le
       même style pour les 2 états") — sauf qu'il n'y a plus qu'UN SEUL
       élément (plus de doublon .index-hero-intro-text à faire disparaître
       en fondu), donc plus de fondu d'entrée ici non plus : visible dès le
       chargement, comme le logo, en même temps que lui. */
    text-transform: uppercase;
    /* Réajusté avec la police (.88rem ci-dessus) : 1.2px était calibré pour
       .62rem, un peu court une fois la police réagrandie. */
    letter-spacing: 1.6px;
    /* rgba(var(--header-accent)) plutôt que le bleu (11,110,253) en dur
       d'origine (demande explicite : "actuellement reflet bleu") — suit
       désormais la couleur d'accent sélectionnée, comme le reste du site. */
    filter: drop-shadow(0 2px 14px rgba(var(--header-accent), .35));
    /* max-content (et non le comportement par défaut d'un <p>, qui prendrait
       toute la largeur disponible) : le texte est maintenant entièrement
       porté par .typewriter ci-dessous (largeur animée 0 -> 100%, cf. plus
       bas) — sans ce width figé sur la valeur FINALE du texte, margin:auto
       recentrerait ce <p> à CHAQUE frame de l'animation (sa largeur de
       contenu changeant), donnant l'impression que le texte "pousse depuis
       le centre" plutôt que de se taper normalement de gauche à droite à
       une position fixe. */
    width: max-content;
    max-width: 100%;
}

/* Machine à écrire (demande explicite) : le texte se tape en direct plutôt
   que d'apparaître d'un coup. --type-chars/--type-duration sont posées en
   inline sur .section-company-hero (cf. index.php), calculées côté PHP à
   partir de la longueur RÉELLE du texte traduit (fr/en/de n'ont pas la
   même longueur, donc pas le même temps de frappe). steps(N) découpe la
   révélation en N paliers (1 par caractère) plutôt qu'un fondu continu,
   pour un vrai effet de frappe caractère par caractère. background/
   background-clip/-webkit-text-fill-color redéclarés ICI (et non hérités
   de .site_description_devise) : ces propriétés ne sont pas héritées, et
   c'est ce span qui porte réellement le texte désormais. */
.site_description_devise .typewriter {
    display: inline-block;
    overflow: hidden;
    white-space: nowrap;
    vertical-align: bottom;
    width: 0;
    max-width: 100%;
    padding-right: 3px;
    border-right: 2px solid rgba(var(--header-accent), .85);
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent), .95) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    /* 3e animation (typewriterCaretHide) : demande explicite, le curseur
       clignotant doit disparaître une fois la frappe terminée plutôt que
       de continuer à clignoter indéfiniment. Listée en DERNIER : les 2
       animations touchent "border-color", donc à partir de son délai
       (var(--type-duration), le même instant où la frappe se termine),
       elle prend le dessus sur le clignotement infini et fixe la
       bordure à transparent pour de bon (forwards). */
    animation:
        typewriterReveal var(--type-duration, 1.8s) steps(var(--type-chars, 30), end) forwards,
        typewriterCaret .8s step-end infinite,
        typewriterCaretHide .01s linear var(--type-duration, 1.8s) forwards;
}

@keyframes typewriterReveal {
    from { width: 0; }
    to   { width: 100%; }
}

@keyframes typewriterCaretHide {
    to { border-color: transparent; }
}

@keyframes typewriterCaret {
    0%, 100% { border-color: transparent; }
    50%      { border-color: rgba(var(--header-accent), .85); }
}

/* Accroche sur 2 lignes en mobile (demande explicite répétée : "n'a
   toujours pas de 2ème ligne, on ne voit pas la phrase en entière") : ce
   bloc avait déjà été ajouté une fois, mais placé PLUS HAUT dans le
   fichier (près de .index-hero-block--top) — à spécificité strictement
   égale (.site_description_devise .typewriter, 2 classes des 2 côtés),
   c'est la déclaration la PLUS TARDIVE dans le fichier qui gagne, or la
   règle de base ci-dessus (avec l'animation typewriterReveal qui contraint
   à 1 seule ligne) était déclarée APRÈS ce premier essai et l'écrasait
   entièrement en silence — bug réel de position dans la cascade, pas un
   problème de sélecteur. Replacé ici, APRÈS la règle de base, pour gagner
   réellement. */
@media (max-width: 640px) {
    .site_description_devise {
        width: 100%;
        max-width: 230px;
        margin-left: auto;
        margin-right: auto;
    }
    .site_description_devise .typewriter {
        display: inline;
        white-space: normal;
        overflow: visible;
        width: auto;
        max-width: 100%;
        border-right: none;
        padding-right: 0;
        animation: none;
    }
}

/* Revenu à la version d'origine (demande explicite "remets les highlights
   comme avant") : simple lien texte, sans pastille/fond permanent. Une
   apparition individuelle EST cependant redemandée depuis (émergence
   depuis le trou noir + flash lumineux, cf. highlightPlanetEmerge plus bas) —
   ce n'est pas la même chose que l'ancienne "cascade" de pastilles
   retirée ici : aucun changement de couleur/fond permanent, juste du
   mouvement/lumière à l'arrivée. */
/* ─── Inversion demandée explicitement : "d'abord les planètes, puis au
   hover les vignettes" — au repos, seul le disque planète (::before,
   cf. plus bas) est visible ; la vignette (fond vitré + quadrillage) ET
   le texte du lien restent invisibles tant qu'on ne survole/focus pas.
   L'ancienne émergence/flash (highlightPlanetEmerge/highlightPlanetFlashPulse) qui
   animaient CE texte sont déplacées sur le disque planète ci-dessous
   (cf. highlightPlanetEmerge/highlightPlanetFlashPulse) : c'est
   maintenant LUI l'élément visible en permanence, donc lui qui doit
   "émerger" à l'arrivée et pulser périodiquement pour attirer l'œil —
   le texte, invisible par défaut, n'a plus besoin de sa propre animation
   d'entrée. */
.site_description .highlight {
    color: rgb(var(--accent-harmony-1));
    text-decoration: none;
    font-weight: 600;
    /* Légèrement agrandi (demande explicite), relatif à la taille du
       paragraphe parent pour rester cohérent si celle-ci change. */
    font-size: 1.1em;
    padding: 4px 14px;
    border-radius: 14px;
    /* Vignette (fond vitré + quadrillage) : plus jamais montrée (demande
       explicite passée "supprimer l'ancien hover, vignette et texte") —
       laissé en "none"/transparent pour ne pas avoir à toucher au markup. */
    background: none;
    border: 1px solid transparent;
    /* Conteneur (.index-hero-highlights-centered) devenu un point
       d'ancrage 0x0 (demande explicite "diaporama" en boucle) : chaque
       lien est désormais position:absolute par rapport à CE point, plutôt
       qu'aligné dans le flux du texte du paragraphe — cf. @keyframes
       highlightOrbitLoop plus bas pour la trajectoire horizontale.
       top/left:0 + le "translate(-50%,-50%)" inclus dans CHAQUE palier du
       keyframe centrent le lien pile sur le point d'ancrage, quel que soit
       le décalage horizontal du moment. z-index:0 : force ce lien à ouvrir
       SON PROPRE contexte d'empilement — sans ça, le z-index négatif du
       disque planète (::before, cf. plus bas) "s'échappe" vers le contexte
       d'empilement le plus proche EN AMONT (bug réel déjà rencontré). */
    position: absolute;
    top: 0;
    left: 0;
    z-index: 0;
    pointer-events: auto;
    /* Trajectoire horizontale en boucle (demande explicite : "rotation
       horizontale de gauche à droite [...] disparaisse à droite fin du
       halo et réapparaisse à gauche début du halo, type diaporama") —
       linear (vitesse constante, pas d'accélération/décélération, effet
       "tapis roulant") + infinite. --orbit-range calé sur le RAYON du halo
       de .index-hero-black-hole::before (clamp(195px,27.5vw,345px)) : la
       planète disparaît/réapparaît pile au bord du halo, jamais avant ni
       après. Délai négatif par lien (cf. :nth-of-type plus bas) : répartit
       les 5 planètes tout le long de la trajectoire dès la 1re frame,
       plutôt que de toutes les faire démarrer groupées à gauche. */
    --orbit-range: clamp(195px, 27.5vw, 345px);
    animation: highlightOrbitLoop 26s linear infinite;
    /* VRAI BUG TROUVÉ (capture d'écran + confirmation cache à l'appui) :
       ce texte était caché via "opacity: 0" posé ICI, sur .highlight
       lui-même. Or l'opacity d'un élément s'applique à la totalité de son
       rendu, PSEUDO-ÉLÉMENTS INCLUS — le disque planète (::before,
       cf. plus bas), même avec sa propre opacity:1 explicite, était donc
       systématiquement rendu à 0% d'opacité lui aussi : impossible pour un
       enfant/pseudo-élément de "dépasser" l'opacité de son parent, quelle
       que soit sa propre valeur. C'est ce qui rendait le disque
       invisible EN PERMANENCE, même la couleur de secours pourtant
       inconditionnelle (cf. ::before plus bas). Remplacé par
       "color: transparent" : le texte devient illisible SANS toucher à
       l'opacity de l'élément parent, donc sans plus jamais affecter le
       disque planète. */
    color: transparent;
    text-shadow: none;
    transition: color 0.25s ease, background 0.25s ease, box-shadow 0.25s ease, text-shadow 0.25s ease, border-color .3s ease, backdrop-filter .3s ease;
}

/* Trajectoire du "diaporama" : translateX de -orbit-range à +orbit-range
   (donc sur toute la largeur du halo), "translate(-50%,-50%)" répété à
   CHAQUE palier pour garder le lien centré sur son point d'ancrage tout du
   long (translateX s'applique ensuite, décalage additionnel). Fondu aux 2
   bouts (0%/100% à opacity:0, 8%/92% à opacity:1) : la planète apparaît/
   disparaît en douceur pile au bord du halo plutôt qu'un "pop" brutal —
   opacity posée ICI, sur .highlight (le lien), cache par la même occasion
   son disque ::before ET son tooltip ::after (l'opacity d'un parent
   s'applique à tout son contenu, pseudo-éléments inclus, cf. commentaire
   plus haut) : le trio lien/planète/tooltip apparaît et disparaît comme un
   seul bloc. */
@keyframes highlightOrbitLoop {
    0% {
        transform: translate(-50%, -50%) translateX(calc(-1 * var(--orbit-range, 260px)));
        opacity: 0;
    }
    8% { opacity: 1; }
    92% { opacity: 1; }
    100% {
        transform: translate(-50%, -50%) translateX(var(--orbit-range, 260px));
        opacity: 0;
    }
}

/* Délais négatifs répartissant les 5 planètes tout le long de la
   trajectoire (26s / 5 ≈ 5.2s d'écart) dès la toute première frame — un
   délai NÉGATIF démarre l'animation comme si elle tournait déjà depuis ce
   temps-là, évitant que les 5 ne partent groupées à gauche avant de
   s'étaler progressivement au 1er tour. */
.site_description .highlight:nth-of-type(1) { animation-delay: -0s; }
.site_description .highlight:nth-of-type(2) { animation-delay: -5.2s; }
.site_description .highlight:nth-of-type(3) { animation-delay: -10.4s; }
.site_description .highlight:nth-of-type(4) { animation-delay: -15.6s; }
.site_description .highlight:nth-of-type(5) { animation-delay: -20.8s; }

/* Figer le diaporama au survol (demande explicite : "en cas de survol
   d'une planète, le diaporama se fige") — :has() sur le conteneur détecte
   le survol/focus de N'IMPORTE LEQUEL des 5 liens et met en pause TOUS les
   highlightOrbitLoop (pas seulement celui survolé), pour un vrai arrêt sur
   image d'ensemble plutôt qu'un seul élément figé pendant que les autres
   continuent de défiler autour de lui. Le tooltip (cf. plus bas) s'active
   en parallèle via son propre :hover/:focus-visible, indépendant de ceci.
   (Tentative précédente : ramener les 5 planètes au point d'ancrage 0x0
   au survol — cassait le hover, puisque translateX(0) superpose les 5
   planètes pile les unes sur les autres, rendant le survol de chacune
   individuellement impossible. Retour au simple gel sur place.) */
.index-hero-highlights-centered:has(.highlight:hover, .highlight:focus-visible) .highlight {
    animation-play-state: paused;
}

/* Disque planète : visible EN PERMANENCE, repos ET survol (une image de
   planète par lien, même illustrations que le widget couleur/les capsules
   de services.php, cf. data-planet posé en PHP sur pages/index.php) — le
   texte, lui, reste en permanence transparent (plus de vignette du tout,
   demande explicite "supprimer l'ancien hover, vignette et texte"). Seul
   son scale change au survol (cf. règle :hover plus bas). ::before (et non
   ::after) : ::after est déjà réservé au tooltip (cf. [data-tooltip]::after
   plus bas). Taille FIXE en px (58x58, comme .capsule-planet-disc sur
   services.php) plutôt qu'un inset en % : un inset en % suivrait le ratio
   très large/peu haut du lien texte dessous et produirait une ellipse
   aplatie plutôt qu'un cercle — une taille fixe garantit un disque
   parfaitement rond, centré via top/left 50% + translate(-50%,-50%).
   Émergence + flash (cf. @keyframes highlightPlanetEmerge/
   highlightPlanetFlashPulse plus bas) : ce disque "émerge" du trou noir à
   l'arrivée puis pulse toutes les 3s pour attirer l'œil. */
.site_description .highlight::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 58px;
    height: 58px;
    /* Fond de secours (demande explicite "je pense que le problème c'est
       cette opacité 0") : couleur pleine posée EN DESSOUS de l'image.
       BUG TROUVÉ (capture d'écran à l'appui : ni image ni couleur ne
       s'affichaient, juste le trou noir à travers) : ces 2 propriétés
       étaient fusionnées dans UN SEUL raccourci "background: couleur
       image position/taille repeat;". Or si var(--highlight-planet-img)
       échoue à se résoudre à l'exécution (quelle qu'en soit la raison),
       la spec CSS invalide TOUTE la déclaration raccourcie, pas juste la
       partie image — la couleur de secours disparaissait donc avec elle.
       Déclarations séparées ci-dessous : background-color ne dépend
       d'AUCUNE variable, donc s'affiche de façon garantie et
       inconditionnelle, même si background-image échoue seule. */
    background-color: rgb(var(--accent-harmony-1));
    background-image: var(--highlight-planet-img);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgba(255,255,255,.12), 0 4px 16px rgba(0,0,0,.5);
    /* opacity retirée du système d'animation ci-dessous (demande explicite
       "le problème c'est cette opacité 0") : auparavant highlightPlanetEmerge
       animait opacity 0 -> 1 avec un fill-mode "forwards" (pas "backwards"),
       ce qui laisse un flou sur l'état réellement rendu pendant le délai
       selon les navigateurs. Statique et non négociable désormais : le
       disque est TOUJOURS à opacity:1, seul le survol (règle plus bas) le
       passe à 0. L'effet d'arrivée (ex-"émergence") repose uniquement sur
       scale/filter, jamais sur opacity. */
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
    transition: opacity .4s cubic-bezier(.16,1,.3,1), transform .4s cubic-bezier(.16,1,.3,1);
    /* Émergence à l'arrivée (une fois, "forwards") + flash récurrent
       (glow coloré toutes les 3s, "infinite") — mêmes durées/délais que
       l'ancien système posé sur le texte, simplement reciblés ici. Les 2
       keyframes ne touchent plus qu'à transform/filter (cf. plus bas),
       jamais à opacity : le disque reste garanti visible même si
       l'animation ne se déclenche jamais pour une raison quelconque. */
    animation:
        highlightPlanetEmerge 1.4s cubic-bezier(.16,1,.3,1) forwards,
        highlightPlanetFlashPulse 3s ease-in-out infinite;
    animation-delay:
        var(--reveal-delay, 1.5s),
        calc(var(--reveal-delay, 1.5s) + 1.4s);
    /* z-index:0 (et non plus -1) : le lien parent (.site_description
       .highlight) ouvre désormais son propre contexte d'empilement
       (z-index:0 posé dessus, cf. plus haut) — un z-index négatif ici
       s'échapperait de CE contexte local et irait se placer derrière le
       fond de la section/page (bug réel : planète invisible au repos,
       coincée derrière la vignette au survol). 0 suffit : au repos la
       vignette est transparente (rien à couvrir la planète), et au survol
       c'est l'opacity:0 ci-dessous qui fait disparaître la planète, pas
       l'empilement. */
    z-index: 0;
    pointer-events: none;
}

/* Demande explicite (index.php) : la planète "eau" (icône du highlight
   qui gravite autour du trou noir) passe de planet-bleu.webp à
   planet-terre.webp. */
.site_description .highlight[data-planet="eau"]      { --highlight-planet-img: url('../image/planet-terre.webp'); }
.site_description .highlight[data-planet="orange"]   { --highlight-planet-img: url('../image/planet-orange.webp'); }
.site_description .highlight[data-planet="blanc"]     { --highlight-planet-img: url('../image/planet-blanc.webp'); }
.site_description .highlight[data-planet="vert"]      { --highlight-planet-img: url('../image/planet-vert.webp'); }
.site_description .highlight[data-planet="violette"]  { --highlight-planet-img: url('../image/planet-violet.webp'); }

/* Ancien hover (vignette fond vitré + texte réapparaissant) SUPPRIMÉ
   (demande explicite "supprimer l'ancien hover, vignette et texte") : le
   texte reste en permanence transparent (cf. .site_description .highlight
   plus haut, color:transparent) et la vignette n'est plus jamais montrée.
   Le retour visuel au survol se fait désormais uniquement sur le disque
   planète (scale, cf. ::before juste en dessous) et sur le tooltip (glow,
   cf. [data-tooltip]::after plus bas) — plus légers, cohérents avec le
   fait que le tooltip est maintenant visible en permanence. */

/* Survol/focus : la planète grossit légèrement (demande explicite "ajouter
   un transform scale au planet au hover"), sans jamais disparaître —
   !important nécessaire : highlightPlanetEmerge (forwards) continue à
   imposer sa valeur finale de "transform" en continu une fois terminée
   (règle de cascade déjà rencontrée sur ce fichier : une animation active
   l'emporte sur une déclaration statique normale, même plus spécifique).
   highlightPlanetFlashPulse (glow infini sur "filter") continue de tourner
   en parallèle sans conflit, puisqu'il ne touche pas "transform". */
.site_description .highlight:hover::before,
.site_description .highlight:focus-visible::before {
    transform: translate(-50%, -50%) scale(1.15) !important;
}

/* Émergence depuis le trou noir, désormais posée sur le disque planète
   (cf. .site_description .highlight::before plus haut) plutôt que sur le
   texte : petit/flou/invisible -> léger dépassement de taille avec un pic
   de luminosité (brightness) façon flash -> taille et luminosité
   normales. */
@keyframes highlightPlanetEmerge {
    /* opacity retirée de ces 3 paliers (demande explicite : "le problème
       c'est cette opacité 0") — seuls scale/filter animent désormais. Le
       disque part très réduit + flouté (quasi indiscernable, mais JAMAIS
       transparent) puis grossit/se stabilise ; l'effet "émergence" reste
       identique à l'œil, sans dépendre du comportement d'opacity pendant
       le délai (animation-fill-mode "forwards" uniquement, jamais
       "backwards" ici, cf. règle de base plus haut). */
    0% {
        transform: translate(-50%, -50%) scale(.4);
        filter: blur(6px) brightness(1);
    }
    60% {
        transform: translate(-50%, -50%) scale(1.08);
        filter: blur(0) brightness(1.8);
    }
    100% {
        transform: translate(-50%, -50%) scale(1);
        filter: blur(0) brightness(1);
    }
}

/* Flash lumineux récurrent (demande explicite d'origine : "toutes les 3
   sec"), désormais sur le disque planète — c'est lui qui reste visible en
   permanence, donc lui qui doit attirer l'œil périodiquement. Glow coloré
   (drop-shadow suivant la paire harmonisante --accent-harmony-1/-2 active,
   pas juste --header-accent) + léger brightness en appoint. */
@keyframes highlightPlanetFlashPulse {
    0%, 100% {
        filter: brightness(1) drop-shadow(0 0 0 rgba(var(--accent-harmony-2), 0));
    }
    50% {
        filter: brightness(1.15) drop-shadow(0 0 14px rgba(var(--accent-harmony-2), .85));
    }
}

/* Balayage gauche -> droite du flash (demande explicite, remplace le
   flash synchronisé d'origine) : chaque mot de la phrase (5 <a class=
   "highlight"> enfants directs du même <p>, cf. pages/index.php) reçoit un
   décalage croissant sur SA SEULE 2e animation (highlightPlanetFlashPulse) — la
   1re (highlightPlanetEmerge, arrivée groupée) reste inchangée pour les 5. */
/* Décalage par mot déplacé sur ::before (demande explicite "planètes
   d'abord") : c'est désormais le disque planète qui porte les 2 animations
   (émergence + flash, cf. .site_description .highlight::before plus haut),
   donc c'est lui qu'il faut cibler ici pour le balayage gauche -> droite du
   flash. */
.site_description .highlight:nth-of-type(1)::before {
    animation-delay: var(--reveal-delay, 1.5s), calc(var(--reveal-delay, 1.5s) + 1.4s + 0s);
}
.site_description .highlight:nth-of-type(2)::before {
    animation-delay: var(--reveal-delay, 1.5s), calc(var(--reveal-delay, 1.5s) + 1.4s + .18s);
}
.site_description .highlight:nth-of-type(3)::before {
    animation-delay: var(--reveal-delay, 1.5s), calc(var(--reveal-delay, 1.5s) + 1.4s + .36s);
}
.site_description .highlight:nth-of-type(4)::before {
    animation-delay: var(--reveal-delay, 1.5s), calc(var(--reveal-delay, 1.5s) + 1.4s + .54s);
}
.site_description .highlight:nth-of-type(5)::before {
    animation-delay: var(--reveal-delay, 1.5s), calc(var(--reveal-delay, 1.5s) + 1.4s + .72s);
}

/* ─── Tooltips des highlights (demande explicite, index.php) ─── Même
   technique attr(data-tooltip)::after déjà utilisée ailleurs sur le site
   (cf. .method-step-badge[data-tooltip]) : contenu piloté par un attribut
   HTML (donc traduit via __('tooltip_site_description_X') côté PHP,
   multilingue par construction), pas de duplication de texte en CSS.
   Positionné au-dessus du lien précis (pas du paragraphe), grâce au
   position:relative posé sur .site_description .highlight ci-dessus. */
.site_description .highlight[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 12px);
    left: 50%;
    width: max-content;
    /* Agrandis (demande explicite) : 200px/.78rem/6-11px -> 260px/.92rem/10-16px. */
    max-width: 260px;
    background: rgba(10, 14, 30, .97);
    border: 1px solid rgba(255, 255, 255, .12);
    color: #fff;
    border-radius: 10px;
    font-size: .92rem;
    font-weight: 500;
    line-height: 1.4;
    text-align: center;
    text-shadow: none;
    white-space: normal;
    padding: 10px 16px;
    /* Revenu à caché par défaut (demande explicite "on enlève les tooltips
       visibles en permanence") : le test précédent ("visible avant hover")
       est annulé, le tooltip ne s'affiche plus qu'au survol/focus du
       highlight (cf. règle plus bas) — cohérent avec le nouveau diaporama
       qui se fige au survol ("le tooltip est activé" à ce moment-là). */
    opacity: 0;
    visibility: hidden;
    /* Glow de base à 0 (demande explicite "les faire briller au hover") :
       transitionne vers un vrai glow coloré au survol/focus du highlight
       parent (cf. règle plus bas), qui l'emporte sur l'animation de
       flottaison ci-dessous (celle-ci ne touche que "transform", jamais
       "filter"/"box-shadow" : aucun conflit). */
    filter: brightness(1) drop-shadow(0 0 0 rgba(var(--accent-harmony-2), 0));
    box-shadow: 0 4px 16px rgba(0, 0, 0, .4);
    pointer-events: none;
    transition: filter .3s ease, box-shadow .3s ease, border-color .3s ease;
    z-index: 5;
    /* Flottaison douce et continue (demande explicite "leur donner
       l'animation flotaison") : même principe que .company-logomain img
       (@keyframes floatSub), mais un keyframe dédié ici puisque la
       position de repos inclut translateX(-50%) (centrage horizontal) en
       plus du bobbing vertical — floatSub seul écraserait ce centrage. */
    animation: highlightTooltipFloat 3s ease-in-out infinite;
}

/* Flottaison du tooltip : bobbing vertical léger autour de sa position de
   repos (translateX(-50%) conservé aux 2 paliers pour rester centré). */
@keyframes highlightTooltipFloat {
    0%, 100% { transform: translateX(-50%) translateY(0); }
    50%      { transform: translateX(-50%) translateY(-6px); }
}

/* Garde-fou anti-"dédoublement" (bug réel déjà rencontré : le lot de
   highlights caché, .index-hero-highlights-placeholder, réservé
   uniquement pour garder l'espacement entre logo et bouton, a lui aussi
   des tooltips — un "visibility:visible" posé sur [data-tooltip]::after
   peut toujours réinverser le "visibility:hidden" hérité du conteneur
   caché). Redondant tant que la règle de base reste à opacity:0/
   visibility:hidden par défaut (cf. plus haut), mais laissé en place en
   sécurité si jamais elle repasse à "visible en permanence" un jour. */
.index-hero-highlights-placeholder .highlight[data-tooltip]::after {
    opacity: 0 !important;
    visibility: hidden !important;
}

/* Glow/"briller" au survol du highlight parent (demande explicite : "les
   faire briller au hover des planètes") — !important nécessaire sur
   "filter" pour la même raison que le scale de la planète : sans lui, un
   hover pourrait perdre la course face à l'animation infinie posée juste
   au-dessus si jamais le navigateur les traite en concurrence sur la même
   propriété. */
.site_description .highlight[data-tooltip]:hover::after,
.site_description .highlight[data-tooltip]:focus-visible::after {
    /* opacity/visibility réactivées ICI (demande explicite "le tooltip est
       activé" au survol) — remplace l'ancien "toujours visible" par un
       vrai hover-only, cohérent avec le diaporama qui se fige en même
       temps (cf. .index-hero-highlights-centered:has(...) plus haut). */
    opacity: 1;
    visibility: visible;
    filter: brightness(1.25) drop-shadow(0 0 10px rgba(var(--accent-harmony-2), .85)) !important;
    border-color: rgba(var(--accent-harmony-1), .6);
    box-shadow: 0 0 24px rgba(var(--accent-harmony-2), .4), 0 4px 16px rgba(0, 0, 0, .5);
}

/* "Orbiter" (3e lien, hm.php) : tooltip forcé sur une seule ligne (demande
   explicite), quelle que soit la langue — le texte le plus long
   (allemand/anglais) ne doit pas non plus repasser à la ligne. */
.site_description .highlight:nth-of-type(3)[data-tooltip]::after {
    white-space: nowrap;
    max-width: none;
}

.company-logo img {
    max-width: 120px;
    /* opacity était déclarée à .75 en statique ici : comme fadeUp (forwards,
       sans backwards) ne s'applique QU'une fois l'animation démarrée, cette
       valeur .75 servait de facto d'état "avant animation" — le logo était
       donc visible dès le chargement (retour explicite), pas cachée
       jusqu'à reveal-delay+.4s comme voulu. Remplacé par un keyframe dédié
       (fadeUpMuted) qui part bien d'opacity:0 et s'arrête à .75 (le rendu
       "grisé" voulu au repos), au lieu de réutiliser fadeUp qui finit à 1. */
    margin-top: 30px;
    margin-bottom: 50px;
    border-radius: 14px;
    opacity: 0;
    animation: fadeUpMuted 1.8s ease-out forwards;
    animation-delay: calc(var(--reveal-delay, 1.5s) + .4s);
}

.company-logomain img {
    /* Réagrandi (130px -> 190px -> 215px -> 240px, demande explicite
       répétée "augmente [encore] légèrement la taille du logo") : passage
       de max-width à width (demande non suivie d'effet visible la fois
       précédente) — max-width ne fait QUE plafonner, il ne force jamais
       une image DONT LA TAILLE NATURELLE est déjà inférieure au plafond à
       s'agrandir. width force la taille réelle affichée quelle que soit
       la résolution native du fichier logo_*.png. */
    width: 240px;
    max-width: 100%;
    margin-bottom: 4px;
    border-radius: 16px;
    opacity: 0.9;
    filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.4));
    will-change: transform, filter;
    transition: transform 0.2s ease-out, filter 0.3s ease;
    transform: translateY(0) scale(1);
    animation: floatSub 3s ease-in-out infinite;
}

.company-logo img:hover {
    animation: none;
    transform: scale(1.2);
    opacity: 0.9;
}

.company-logooffre img {
    max-width: 250px;
    margin-bottom: 10px;
    border-radius: 20px;
    opacity: 0.9;
    filter: drop-shadow(0 25px 60px rgba(0, 0, 0, 0.4));
    will-change: transform, filter;
    transition: transform 0.2s ease-out, filter 0.3s ease;
    transform: translateY(0) scale(1);
    animation: logoBreath 6s cubic-bezier(0.16, 1, 0.3, 1) infinite;
}

.hero-actions {
    /* Réduit (50px -> 16px, demande explicite "diminue l'écart") : ce
       margin-top s'ajoutait au gap:14px de .company-inner, creusant un
       espace plus grand que les autres écarts verticaux du bloc.
       .site_description_devise (l'accroche) a depuis été réordonnée juste
       après le logo (elle n'est plus juste au-dessus de .hero-actions,
       c'est maintenant .site_description qui l'est), mais la valeur reste
       cohérente avec le reste du rythme vertical. */
    /* Remonté une nouvelle fois (demande explicite) : 16px -> 2px, en plus
       du resserrement du gap ci-dessus. */
    margin-top: 2px;
    margin-bottom: 10px;
    /* Le fondu du bloc entier (calé sur var(--reveal-delay)) est retiré
       (demande explicite : la rockette et "Visiter le site" doivent
       arriver PENDANT la teinture bleu étoilé/la frappe, donc bien AVANT
       reveal-delay) — cf. .btn-content et .hero-actions .tooltip-text-index
       plus bas, qui animent maintenant chacun leur propre entrée,
       décalée l'une de l'autre, à un délai fixe court. .hero-actions
       lui-même reste un simple conteneur de mise en page, toujours
       présent, sans plus jouer d'animation propre. */
}

.rocket-icon {
    width: 64px;
    height: 64px;
    transition: transform 0.3s ease;

}

/* ─── index.php : la rockette puis "Visiter le site" arrivent depuis le
   bas PENDANT la teinture bleu étoilé/la frappe du tagline (demande
   explicite), pas après le trou noir. Délai fixe court plutôt que
   var(--reveal-delay) : le minimum possible de reveal-delay est 1.5s
   (durée de frappe mini 1.2s + .3s de marge, cf. index.php) — les délais
   ci-dessous tombent systématiquement pendant la frappe, quelle que soit
   la langue. .btn-content (rockette) en premier, .tooltip-text-index
   (légende) juste après avec un léger décalage. Trajet allongé (demande
   explicite "arrivent de tout en bas de la section, ça prolongera un peu
   l'animation") : keyframe dédié heroActionRiseFar (distance en vh, pas
   18px comme fadeUp) plutôt que fadeUp lui-même, réutilisé ailleurs avec
   une petite distance qu'on ne veut pas changer globalement. "translate"
   en longhand (même principe que fadeUp, cf. animation.css) : ne rentre
   pas en conflit avec le transform statique (centrage horizontal) de
   .tooltip-text-index ni avec le transform de hover sur .btn/.rocket-icon
   (propriétés distinctes). */
@keyframes heroActionRiseFar {
    from {
        opacity: 0;
        translate: 0 clamp(160px, 30vh, 320px);
    }
    to {
        opacity: 1;
        translate: 0 0;
    }
}

.btn-content {
    display: inline-block;
    opacity: 0;
    animation: heroActionRiseFar 1.3s cubic-bezier(.16,1,.3,1) forwards;
    animation-delay: .35s;
}

.hero-actions .tooltip-text-index {
    opacity: 0;
    animation: heroActionRiseFar 1.15s cubic-bezier(.16,1,.3,1) forwards;
    animation-delay: .6s;
}

.tooltip-text-index {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%) translateY(10px);
    /* Habillage aligné sur celui des tooltips des highlights (demande
       explicite) : cf. .site_description .highlight[data-tooltip]::after,
       même fond sombre/bordure/rayon/typo. Agrandi (demande explicite) :
       .78rem/6-11px -> .95rem/9-16px, comme les tooltips des highlights. */
    background: rgba(10, 14, 30, .97);
    border: 1px solid rgba(255, 255, 255, .12);
    color: #fff;
    padding: 9px 16px;
    border-radius: 10px;
    font-size: .95rem;
    font-weight: 500;
    white-space: nowrap;
    pointer-events: none;
    opacity: 1;
    /* Repop plus naturel (demande explicite) : la transition déclarée ICI,
       sur l'état de repos, pilote le retour à la normale (quand
       .tooltip-suppressed est retiré) — plus lente et avec la même
       décélération douce que le reste de la cascade, plutôt qu'un "ease"
       générique. La DISPARITION, elle, reste rapide (cf. transition
       dédiée sur .tooltip-suppressed ci-dessous) : CSS utilise la
       transition de la règle qui devient active, donc les 2 sens peuvent
       avoir des vitesses différentes. */
    transition: opacity 0.5s cubic-bezier(.16,1,.3,1), transform 0.2s ease;
}

/* Demande explicite : "enlève complètement le bleu autour de la rockette,
   c'est plus simple" — l'habillage cockpit (fond/bordure bleus, crochets)
   est retiré. Seul le repositionnement (top:100% + margin-top, plutôt que
   bottom:-6px + le translateY(10px) hérité de .tooltip-text-index de
   base) est conservé : c'est ce qui empêchait la légende de chevaucher la
   boîte du bouton, un problème indépendant de la couleur. transform
   réécrit sans translateY : le décalage vertical est géré par margin-top. */
.hero-actions .tooltip-text-index {
    top: 100%;
    bottom: auto;
    transform: translateX(-50%);
    /* Réduit encore (14px -> 4px -> 2px) + padding vertical resserré
       (6px -> 3px, hérité sinon de .tooltip-text-index de base) : le
       reste de l'écart signalé venait aussi du padding vertical de la
       légende elle-même, pas seulement de la marge. */
    margin-top: 2px;
    padding-top: 3px;
    padding-bottom: 3px;
}

/* display:block (au lieu d'inline, valeur par défaut d'un <svg>) : retire
   le petit espace de "ligne de base" typographique sous l'icône, qui
   participait lui aussi à l'écart perçu avec la légende en dessous. */
.hero-actions .rocket-icon {
    display: block;
    margin: 0 auto;
    /* Agrandie (demande explicite), spécifique à index.php — ne touche pas
       .rocket-icon générique (64x64) réutilisé ailleurs sur le site. */
    width: 84px;
    height: 84px;
}

.tooltip-hidden {
    opacity: 0;
    transform: translateX(-50%) translateY(20px);
}

.hero-actions .btn {
    display: inline-block;
    /* Agrandi (demande explicite), pour accompagner la rockette/légende
       elles-mêmes agrandies ci-dessus. */
    padding: 16px 28px;
    border-radius: 12px;
    color: #fff;
    font-weight: 600;
    font-size: 1.15rem;
    text-decoration: none;
    position: relative;
    overflow: visible;
    opacity: 0.95;
    transform: scale(0.98);
    transition: transform 0.3s ease, opacity 0.3s ease;
}

/* Le bouton-poussoir circulaire (dôme bleu, anneau lumineux, glow sur la
   rockette) est retiré — demande explicite "enlève complètement le bleu
   autour de la rockette, c'est plus simple, ne garde que la rockette et
   le bouton". Le bouton retombe sur la règle .hero-actions .btn de base
   ci-dessus (simple, sans fond/bordure) : juste la rockette + la légende
   "Visiter le site" en dessous. */

.hero-actions .btn:hover {
    transform: scale(1.05);
    animation: shakeSoft 0.6s infinite;
}

.hero-actions .btn:hover .rocket-icon {
    transform: scale(1.8);
}

/* ─── Survol des mots .highlight (index.php) : simple shake de la rockette,
   sans déclencher l'animation complète de décollage (.launching, flamme +
   fumée + translation) réservée au clic — cf. main.js. ─── */
.hero-actions .btn.highlight-shake {
    animation: shakeSoft 0.6s infinite;
}

.hero-actions .btn.highlight-shake .rocket-icon {
    animation: rocketShake 0.8s infinite;
}

/* Demande explicite : "Visiter le site" doit disparaître au survol de la
   rockette, comme c'était le cas auparavant — comportement rétabli ici,
   et étendu au survol d'un highlight (.highlight-shake, même classe que
   le shake ci-dessus) puisque ce survol secoue la même rockette. Simple
   opacité à 0 : la transition déjà déclarée sur .tooltip-text-index de
   base (opacity 0.2s ease) suffit à rendre la disparition douce.
   !important nécessaire : .tooltip-text-index porte une animation
   d'entrée (heroActionRiseFar, fill "forwards") qui, une fois terminée,
   garde la main sur "opacity" et bat toute règle statique de même
   propriété, quelle que soit sa spécificité (piège de cascade déjà
   rencontré ailleurs sur ce projet) — sauf "!important", qui l'emporte
   sur une animation dans l'ordre de cascade CSS. */
.hero-actions .btn:hover .tooltip-text-index,
.hero-actions .btn.tooltip-suppressed .tooltip-text-index,
.hero-actions .btn.launching .tooltip-text-index,
.hero-actions .btn.is-orbiting .tooltip-text-index {
    /* Disparition rapide et nette (contrairement au repop, plus lent —
       cf. transition de base sur .tooltip-text-index) : transition
       redéclarée ici pour que CE sens précis (vers l'invisible) reste
       vif, quelle que soit la cascade plus haut. */
    transition: opacity 0.2s ease !important;
    opacity: 0 !important;
}

/* Durée alignée sur EXACTEMENT la portion "pré-lancement" gardée dans
   @keyframes rocketLaunch (animation.css) : 1.4s -> 1.05s, soit pile les
   75% déjà occupés par la compression/vibration/décollage lent avant
   l'ancienne "sortie écran" (retirée, cf. animation.css) — le rendu du
   pré-lancement lui-même est donc rigoureusement identique à avant, il
   se contente de s'arrêter net là où il s'arrêtait déjà visuellement.
   main.js retire cette classe et ajoute .is-orbiting au bout de ce même
   1.05s, pour enchaîner sans à-coup sur la spirale ci-dessous. */
.hero-actions .btn.launching {
    animation: rocketLaunch 1.05s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

/* ─── Phase 2 du lancement (demande explicite : "au lieu d'aller tout
   droit, [...] la rockette tourne autour du trou noir puis fini sa course
   au centre, dans le sens horaire") ───
   Prend le relais de .launching une fois le pré-lancement terminé
   (cf. main.js, qui retire "launching" et ajoute "is-orbiting" au même
   instant) : la rockette part donc de la pose figée par rocketLaunch
   (translateY(-30px) scale(1.08), sa dernière valeur tenue) pour
   enchaîner sur la spirale ci-dessous sans saut visuel.
   --rocket-orbit-r reprend EXACTEMENT la valeur du translateY appliqué à
   .index-hero-actions-centered (clamp(150px,20vw,260px), cf. plus haut) :
   comme les transforms d'un élément sont relatifs à SA PROPRE position
   (celle déjà décalée par le parent), un translate(0, -R) à 100% annule
   précisément ce décalage parent et fait donc atterrir la rockette pile
   au centre visuel/réel du trou noir, quelle que soit la taille d'écran.
   Les étapes intermédiaires suivent un arc horaire (bas -> gauche -> haut
   -> droite, cf. rotate() qui grandit dans le même sens) à rayon
   décroissant (spirale qui se resserre en "tombant" vers le trou noir) ;
   coordonnées calculées via x=-R*sin(θ), y=R*cos(θ) avec θ croissant de
   0° à ~330° (repère où θ=0 est le point de départ, en bas). */
.hero-actions .btn.is-orbiting {
    --rocket-orbit-r: clamp(150px, 20vw, 260px);
    animation: rocketOrbitToCenter 1.3s cubic-bezier(.45, 0, .55, 1) forwards;
}

@keyframes rocketOrbitToCenter {
    0% {
        transform: translateY(-30px) scale(1.08) rotate(0deg);
        opacity: 1;
    }
    20% {
        /* θ≈72°, rayon 85% */
        transform: translate(calc(var(--rocket-orbit-r) * -0.808), calc(var(--rocket-orbit-r) * -0.737)) scale(0.88) rotate(144deg);
    }
    40% {
        /* θ≈144°, rayon 65% */
        transform: translate(calc(var(--rocket-orbit-r) * -0.382), calc(var(--rocket-orbit-r) * -1.526)) scale(0.68) rotate(288deg);
    }
    60% {
        /* θ≈216°, rayon 42% */
        transform: translate(calc(var(--rocket-orbit-r) * 0.247), calc(var(--rocket-orbit-r) * -1.340)) scale(0.48) rotate(432deg);
    }
    80% {
        /* θ≈288°, rayon 18% */
        transform: translate(calc(var(--rocket-orbit-r) * 0.171), calc(var(--rocket-orbit-r) * -0.944)) scale(0.28) rotate(576deg);
        opacity: 1;
    }
    100% {
        /* Centre exact du trou noir : rayon 0 */
        transform: translate(0, calc(var(--rocket-orbit-r) * -1)) scale(0.08) rotate(720deg);
        opacity: 0;
    }
}

.hero-actions .btn::after {
    content: "";
    position: absolute;
    bottom: -18px;
    left: 50%;
    transform: translateX(-50%) scaleY(0);
    width: 12px;
    height: 30px;
    background: radial-gradient(circle, rgba(255,255,255,0.15), rgba(255,255,255,0.15), transparent);
    filter: blur(2px);
    border-radius: 50%;
}

.hero-actions .btn.launching::after,
.hero-actions .btn.is-orbiting::after {
    animation: flame 0.18s infinite alternate;
    opacity: 1;
}

.hero-actions .btn::before {
    content: "";
    position: absolute;
    bottom: -50px;
    left: 50%;
    transform: translateX(-50%);
    width: 4px;
    height: 80px;
    background: linear-gradient(to top, rgba(255,255,255,0.15), transparent);
    opacity: 0;
}

.hero-actions .btn.launching::before,
.hero-actions .btn.is-orbiting::before {
    opacity: 1;
    animation: smokeTrail 0.5s infinite linear;
}

.btn.launching .rocket-icon,
.btn.is-orbiting .rocket-icon {
    animation: rocketShake 0.8s infinite;
}

.rocket-wrapper {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
	padding: 30px 50px;
    cursor: pointer;
}

.rocket-wrapper:hover .tooltip-text,
.btn:hover .tooltip-text {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}



/* ========================= Accueil.php ========================= */

main .hero {
    position: relative;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    /* Espace quasi supprimé (demande explicite : l'ancien header flottant
       centré, qui imposait une réserve en haut, a été retiré du site —
       remplacé par 2 vignettes HUD en coins haut-gauche/haut-droite qui ne
       gênent plus le centre. Le titre peut donc démarrer tout en haut,
       avec juste un léger décalage). */
    padding-top: 6px;
    /* flex-start (plus space-between) : les 3 blocs (fenêtre, cockpit,
       divider) restent groupés avec un petit écart fixe entre eux au lieu
       d'être étirés sur toute la hauteur — l'espace restant, s'il y en a,
       devient simplement plus de fond visible en bas (invisible, l'image
       de fond couvre toute la section). */
    justify-content: flex-start;
    /* Espace ajouté entre les 3 blocs (fenêtre titre/CTA, cockpit/points,
       divider fusée) : pousse chaque bloc un peu plus bas, sans casser le
       flex-start ci-dessus (la section grandit simplement en hauteur). */
    gap: clamp(28px, 5vh, 56px);
    text-align: center;
    /* var(--space-bg) au lieu de l'ancienne var(--cockpit-bg) (demande
       explicite : tous les fichiers cockpit_*.png/grandcockpit.png ont été
       supprimés du dossier image) — même fond spatial générique que le
       reste du site. */
    background:
        radial-gradient(circle at center, rgba(0,0,0,0.05), rgba(0,0,0,0.5)),
        var(--space-bg) center / cover no-repeat;
    /* Demande explicite (1ère passe) : "la capsule doit faire toute la
       largeur et être hors section. Ajoute un margin bottom à la section
       d'avant pour lui laisser la place." — réserve l'espace dans lequel
       .metal-plate-dome-cap (posé entre le hero et #method-heading, cf.
       accueil.php et .capsule-dome-wrap plus bas) vient se loger, ancré sur
       son bord bas.
       Demande explicite (2e passe) : "créer un écart important avec la
       première section bienvenue à bord". Le dôme reste ancré bottom:0 sur
       .capsule-dome-wrap (donc toujours pile contre #method-heading, aucun
       chevauchement) et garde sa propre hauteur inchangée (1er clamp
       ci-dessous) — seul un espace vide SUPPLÉMENTAIRE (2e clamp) est ajouté
       au total réservé ici. Comme le dôme n'occupe que la fin de cet espace
       (côté bas), ce supplément se traduit visuellement par du vide entre le
       bas du hero et le haut du dôme, donnant l'impression que la fusée
       flotte dans l'espace avant l'intérieur du vaisseau. */
    margin-bottom: calc(clamp(240px, 28vh, 360px) + clamp(160px, 20vh, 260px));
}

/* Vignette cockpit — assombrit le cadre, laisse la fenêtre centrale transparente */
main .hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(
        ellipse 54% 46% at 50% 38%,
        transparent 0%,
        transparent 46%,
        rgba(0, 3, 20, 0.52) 72%,
        rgba(0, 3, 20, 0.8) 100%
    );
    pointer-events: none;
    z-index: 0;
}

/* Liseré HUD bas de section */
main .hero::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),0.4), transparent);
    pointer-events: none;
    z-index: 1;
}

/* ═══════════════════════════════════════════════════════════════════
   HERO ACCUEIL.PHP — 5 PLANÈTES DÉCORATIVES + TROU NOIR AU CLIC
   (cf. markup dans pages/accueil.php, bloc .hero-space en tout premier
   enfant de .hero). Séquence complète déclenchée par main.js au clic sur
   "Explorer" (#hero-explore-btn) : voir .hero.is-launching plus bas pour
   le détail (contenu qui disparaît, trou noir qui apparaît, planètes
   avalées), et main.js bloc "SÉQUENCE TROU NOIR HERO ACCUEIL" pour le
   timing exact et la redirection vers services.php. ═══════════════════ */

/* Calque purement décoratif : couvre toute la section, ne capte AUCUN
   clic lui-même (pointer-events:none) — seules les boules de planète
   individuelles (cf. .home-hero-planet plus bas) redeviennent
   cliquables/survolables. Même z-index que .hero-window-area : les
   planètes se posent DERRIÈRE la fenêtre cockpit là où elles se
   chevauchent, mais restent visibles dans tout le reste de l'espace
   (haut, côtés) où il n'y a rien d'autre. */
.hero-space {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
}

/* ─── Trou noir CENTRÉ EN ARRIÈRE-PLAN (demande explicite : "centre un trou
   noir au milieu en arrière-plan, couleur sélectionnée dans le sélecteur
   de couleur") — visible en permanence désormais (plus seulement révélé au
   clic sur Explorer, cf. .hero.is-launching plus bas qui l'agrandit encore
   pour l'effet "avalé"). Même habillage EXACT que .why-target-cta-halo/
   .services-cta-halo (disque d'accrétion ::before + horizon des
   événements ::after) : juste un peu plus petit, pensé pour le centre de
   CETTE section plutôt qu'une section CTA dédiée. Couleur pilotée par
   --hole-light/-mid/-soft/-base/-glow (cf. .img-accent-* tout en haut de ce
   fichier, posées sur <body> selon la couleur choisie dans le sélecteur) :
   déjà la couleur sélectionnée, aucun calcul supplémentaire nécessaire.
   z-index:0 + DOM en tout premier enfant de .hero-space : reste bien
   DERRIÈRE les 4 planètes latérales (z-index:1) et derrière le titre/la
   planète bleue/la box CTA (.hero-window-area, même z-index que .hero-space
   mais placée après lui dans le DOM = passe devant), donc un pur décor de
   fond, jamais au-dessus du contenu. */
.home-hero-halo {
    position: absolute;
    /* Centre redescendu (demande explicite "mets le trou noir plus bas") :
       42% -> 55%. --swallow-dy de chaque planète (cf. plus bas, formule
       dy = 55% - top-de-la-planète) recalculé en conséquence pour que la
       séquence "avalée" continue de converger exactement vers ce nouveau
       centre. */
    top: 55%;
    left: 50%;
    width: 0;
    height: 0;
    opacity: 1;
    pointer-events: none;
    transition: opacity .5s ease;
    z-index: 0;
}

/* Voile plein écran (position:fixed, indépendant de la section) qui passe
   au noir total juste avant la redirection : garantit un fondu 100% noir
   quel que soit le ratio d'écran, en complément du trou noir qui grossit
   (cf. .hero.is-launching .home-hero-halo plus bas) — "ceinture et
   bretelles" pour être sûr qu'aucun coin de l'écran ne reste visible. */
.home-hero-blackout {
    position: fixed;
    inset: 0;
    background: #000;
    opacity: 0;
    pointer-events: none;
    z-index: 999;
    transition: opacity .7s ease;
}

.home-hero-halo::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(320px, 46vw, 600px);
    height: clamp(320px, 46vw, 600px);
    transform: translate(-50%, -50%);
    margin-top: -1px;
    border-radius: 50%;
    /* Teinte bleue par défaut (demande explicite : "pour la couleur par
       défaut, le trou noir ici doit être bleu") — mêmes valeurs de repli
       EXACTEMENT que .index-hero-black-hole (index.php), qui est déjà bleu
       par défaut, pour rester cohérent site-wide. Anneau incandescent
       toujours recoloré dès qu'un client choisit une autre couleur en Mon
       profil (cf. --hole-light/-mid/-soft/-base, .img-accent-* tout en
       haut du fichier), seul le REPLI change. */
    /* Bande horizontale déplacée sur ::after (demande explicite : elle ne
       doit pas tourner avec l'anneau — contrairement à ce calque animé par
       blackHoleSpin). */
    background:
        conic-gradient(
            from -20deg,
            rgba(255,255,255,0)                    0deg,
            rgba(var(--hole-mid, 140,190,255),.6)   38deg,
            rgba(var(--hole-base, 60,150,255),.68)  68deg,
            rgba(var(--hole-light, 200,225,255),.7) 92deg,
            rgba(var(--hole-soft, 110,180,255),.36) 118deg,
            rgba(255,255,255,0)                     152deg,
            rgba(255,255,255,0)                     222deg,
            rgba(var(--hole-soft, 90,170,255),.22)  250deg,
            rgba(var(--hole-soft, 90,170,255),.4)   282deg,
            rgba(var(--hole-light, 200,225,255),.55) 302deg,
            rgba(var(--hole-base, 50,150,255),.4)   320deg,
            rgba(255,255,255,0)                     360deg
        );
    box-shadow: 0 0 clamp(34px, 4.8vw, 63px) clamp(10px, 1.5vw, 19px) rgba(var(--hole-glow, 80,150,255),.28);
    --hole-blur: 20px;
    animation:
        blackHoleSpin 22s linear infinite,
        blackHoleFlicker 6.5s ease-in-out infinite;
    pointer-events: none;
}

.home-hero-halo::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(170px, 24vw, 320px);
    height: clamp(170px, 24vw, 320px);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    /* Version "réaliste" restaurée (demande explicite : "on avait obtenu un
       résultat très réaliste", plus de barre horizontale) : la bande
       linéaire equatoriale est retirée — un seul radial-gradient forme un
       cœur noir opaque avec un fin anneau photonique clair à 58-66%
       (l'horizon des événements), plus proche d'une vraie photo de trou
       noir. Complété par un léger backdrop-filter (flou + saturation) sur
       le bord pour un rendu moins "à plat". */
    background:
        radial-gradient(circle, #000000 0%, #000000 58%, rgba(var(--hole-light, 200,225,255),.85) 62%, #000000 66%, rgba(0,0,0,0) 76%);
    backdrop-filter: blur(2px) saturate(1.15);
    -webkit-backdrop-filter: blur(2px) saturate(1.15);
    box-shadow: 0 0 clamp(37px, 5.3vw, 70px) clamp(13px, 1.8vw, 24px) rgba(0,0,0,.85);
    animation: blackHolePulse 4.5s ease-in-out infinite;
    pointer-events: none;
}

/* ─── Les 5 planètes ───
   Positions en % de .hero-space (donc de .hero, 100dvh) : 1 "Terre" en
   haut/centre (.--top, centrée via margin-left plutôt que
   translateX(-50%) — la propriété transform est déjà prise par
   floatUpDown/le trou noir, cf. plus bas), 2 de chaque côté à des
   hauteurs différentes pour un rendu plus organique qu'un simple
   alignement. Flottement (floatUpDown, cf. animation.css) directement
   sur cet élément externe ; le survol (zoom + halo) est porté par
   l'enfant .home-hero-planet-ball pour ne pas entrer en conflit avec
   cette même propriété transform. */
.home-hero-planet {
    position: absolute;
    display: block;
    pointer-events: auto;
    z-index: 1;
    text-decoration: none;
    /* heroPlanetFloat (et non le floatUpDown partagé, animation.css) :
       demande explicite "augmente l'effet de flottaison, pour cette
       section seulement" — keyframe dédiée avec une amplitude bien plus
       marquée (cf. plus bas), floatUpDown restant inchangé pour ses autres
       usages ailleurs sur le site. */
    animation: heroPlanetFloat 5s ease-in-out infinite;
}

@keyframes heroPlanetFloat {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-18px); }
}

/* Planète centrale (bleue) : n'est plus dans le calque décoratif
   .hero-space (retirée de la séquence trou noir, qui n'avale plus que les
   4 planètes latérales — cf. .hero.is-launching .home-hero-planet plus
   bas) — désormais dans le flux, entre le <h1> et .hero-window-content
   (demande explicite "hors de la box"), cf. markup dans accueil.php.
   Réutilise .home-hero-planet-ball/-orbit/-rocket et la couleur
   .home-hero-planet--bleu, mais avec sa propre classe de positionnement
   (position:relative, pas absolute). Taille agrandie une 2e fois, cette
   fois SEULEMENT pour cette planète (demande explicite "agrandis la
   planète bleue uniquement", 120px -> 150px, les 4 latérales ne bougent
   pas), marge basse pour l'espacer de la box maintenant qu'elle n'est plus
   dans le flex-gap de .hero-window-content. */
.hero-central-planet {
    position: relative;
    display: block;
    width: 150px;
    height: 150px;
    /* Marge haute ajoutée (demande explicite "descends un peu la planète
       bleue et les 2 boutons") : pousse la planète (et donc la box CTA en
       dessous, dans le même flux) plus bas, sans toucher au h1 au-dessus,
       déjà "bien placé". */
    margin: 20px auto 28px;
    pointer-events: auto;
    text-decoration: none;
    /* heroPlanetFloat : même amplitude accentuée que les 4 planètes
       latérales (demande explicite, cf. commentaire sur .home-hero-planet
       plus haut). */
    animation: heroPlanetFloat 5.4s ease-in-out infinite;
    /* --swallow-dx/-dy (demande explicite : "rajouter l'avalement de la
       planète bleue" à la séquence trou noir) : bien qu'elle soit dans le
       flux normal (contrairement aux 4 planètes latérales, position:absolute
       dans .hero-space), le trajet ne dépend que d'un déplacement RELATIF
       (translate), donc les mêmes unités vw/dvh fonctionnent pareil. Déjà
       centrée horizontalement (margin:auto) : dx=0. Verticalement, estimation
       de sa position (sous le h1, en haut de section) jusqu'au centre du trou
       noir à 55% -> ~28dvh. */
    --swallow-dx: 0vw;
    --swallow-dy: 28dvh;
}

/* Magma et glace : même taille que la centrale (120px, demande explicite —
   les 5 planètes légèrement agrandies). --swallow-dy recalculé (12dvh ->
   25dvh = 55% - 30%) suite au trou noir redescendu à 55% (demande
   explicite "mets le trou noir plus bas") : la cible de "l'avalage" reste
   exactement le nouveau centre. */
.home-hero-planet--left-1 {
    top: 30%;
    left: 8%;
    width: 120px;
    height: 120px;
    animation-duration: 4.6s;
    animation-delay: -1.2s;
    --swallow-dx: 42vw;
    --swallow-dy: 25dvh;
}
.home-hero-planet--right-1 {
    top: 30%;
    right: 8%;
    width: 120px;
    height: 120px;
    animation-duration: 5.8s;
    animation-delay: -.4s;
    --swallow-dx: -42vw;
    --swallow-dy: 25dvh;
}
/* Violette et hébergement (verte) : légèrement plus petites que les 3
   autres (demande explicite), agrandies dans la même proportion.
   Ramenées plus au centre (demande explicite : 13% -> 24%) : ça libère
   justement l'espace côté extérieur pour leur nouveau titre (cf.
   .home-hero-planet-label plus bas). --swallow-dx recalculé pareil
   (50% - décalage), pour que le trajet vers le trou noir central reste
   cohérent avec la nouvelle position de départ. --swallow-dy recalculé
   (-18dvh -> -5dvh = 55% - 60%) suite au trou noir redescendu à 55%. */
.home-hero-planet--left-2 {
    top: 60%;
    left: 24%;
    width: 106px;
    height: 106px;
    animation-duration: 5.1s;
    animation-delay: -2.1s;
    --swallow-dx: 26vw;
    --swallow-dy: -5dvh;
}
.home-hero-planet--right-2 {
    top: 60%;
    right: 24%;
    width: 106px;
    height: 106px;
    animation-duration: 4.9s;
    animation-delay: -3s;
    --swallow-dx: -26vw;
    --swallow-dy: -5dvh;
}

/* ─── Titres à côté des 4 planètes latérales (demande explicite) ───
   aria-hidden : l'accessible name reste porté par l'aria-label de l'<a>
   parent, ce span est une légende purement visuelle. position:absolute
   par rapport à l'ancre (.home-hero-planet, déjà position:absolute) : suit
   donc le flottement/la position de la planète sans calcul supplémentaire.
   pointer-events:none : la légende ne doit pas gêner le survol de la
   planète elle-même (le lien couvre tout, légende comprise, via l'ancre
   parente). */
/* Étiquette "Voir les tarifs" (mobile uniquement, cf. accueil.php et
   responsive.css @media max-width:768px) : masquée par défaut sur PC/tablette
   pour ne pas se superposer à "Création site web" (--dsk-text, visible sans
   override, cf. règle .home-hero-planet-label ci-dessous). */
.home-hero-planet-label--tarifs-text {
    display: none;
}

.home-hero-planet-label {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: max-content;
    max-width: 140px;
    font-family: var(--font-title);
    /* Agrandi légèrement (demande explicite, .85rem -> .95rem). */
    font-size: .95rem;
    font-weight: 600;
    line-height: 1.25;
    color: rgba(255, 255, 255, .85);
    text-shadow: 0 2px 10px rgba(0, 0, 0, .55);
    pointer-events: none;
    z-index: 2;
    /* Couleur/ombre animées : au survol de la planète (cf. règle plus bas),
       le titre reprend la couleur de la planète. */
    transition: color .3s ease;
}
/* Espacées un peu plus de leur planète (demande explicite, 14px -> 24px). */
.home-hero-planet-label--right {
    left: calc(100% + 24px);
    text-align: left;
}
.home-hero-planet-label--left {
    right: calc(100% + 24px);
    text-align: right;
}
/* Sous la planète centrale bleue (demande explicite : "création site web"
   en dessous), plutôt qu'à côté comme les 4 planètes latérales. */
.home-hero-planet-label--below {
    /* Espace très légèrement augmenté avec la planète bleue (demande
       explicite, 14px -> 18px). */
    top: calc(100% + 18px);
    left: 50%;
    transform: translateX(-50%);
    text-align: center;
    max-width: 160px;
}

/* Au survol/focus d'une planète, son titre adopte la couleur propre de
   cette planète (demande explicite) — réutilise --planet-color, déjà posée
   par planète (cf. .home-hero-planet--magma/--glace/--violette/
   --hebergement/--bleu plus haut) et disponible en cascade sur ce span
   enfant. */
.home-hero-planet:hover .home-hero-planet-label,
.home-hero-planet:focus .home-hero-planet-label,
.hero-central-planet:hover .home-hero-planet-label,
.hero-central-planet:focus .home-hero-planet-label {
    color: var(--planet-color);
}

/* Mêmes 5 textures/couleurs EXACTEMENT que les vignettes de services.php
   (cf. .service-capsule--refonte/--cloud/--programmation/--conseil/
   --featured dans ce même fichier). */
/* Demande explicite (nouvelle inversion) : la planète centrale ("Bienvenue
   à bord" / Création de sites, cf. .hero-central-planet dans accueil.php)
   repasse de planet-bleu.webp à planet-terre.webp. --planet-color reste figé
   en bleu (59,130,246, cf. .accent-blue) : ne pilote que le TITRE au survol
   (.home-hero-planet:hover .home-hero-planet-label), une identité
   catégorielle distincte de la texture affichée, inchangée par cette
   demande. */
.home-hero-planet--bleu       { --planet-color: rgb(59, 130, 246); --planet-img: url('../image/planet-terre.webp'); }
/* Image corrigée (planet-rouge.webp -> planet-orange.webp, demande explicite
   "planète orange") : planet-rouge.webp est un rendu lave/magma noir-rouge,
   pas orange — les 2 images étant opaques (pas de transparence), c'est
   l'image, pas --planet-color, qui détermine la teinte visible. */
.home-hero-planet--magma      { --planet-color: #f59e0b; --planet-img: url('../image/planet-orange.webp'); }
.home-hero-planet--glace      { --planet-color: #f1f5f9; --planet-img: url('../image/planet-blanc.webp'); }
.home-hero-planet--violette   { --planet-color: #8b5cf6; --planet-img: url('../image/planet-violet.webp'); }
/* Image corrigée (planet-blanc.webp -> planet-vert.webp, demande explicite
   "planète verte") : même souci que magma ci-dessus, planet-blanc.webp
   donnait une planète blanche/grise, en doublon avec .home-hero-planet--glace. */
.home-hero-planet--hebergement{ --planet-color: #10b981; --planet-img: url('../image/planet-vert.webp'); }

.home-hero-planet-ball {
    display: block;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background-color: var(--planet-color);
    background-image: var(--planet-img);
    background-size: cover;
    background-position: center;
    box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22);
    transition: transform .4s ease, box-shadow .4s ease;
}

/* Survol/focus (désormais de vrais liens) : léger zoom + halo blanc qui se
   superpose à l'ombrage "planète" existant. */
.home-hero-planet:hover .home-hero-planet-ball,
.home-hero-planet:focus .home-hero-planet-ball,
.hero-central-planet:hover .home-hero-planet-ball,
.hero-central-planet:focus .home-hero-planet-ball {
    transform: scale(1.12);
    box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 28px rgba(255,255,255,.4);
}

/* ─── Roquette en orbite au survol ───
   Élément séparé de .home-hero-planet-ball (qui gère déjà le zoom au
   survol) et de .home-hero-planet (qui gère le flottement continu) : sa
   propre rotation ne rentre donc en conflit avec aucune des deux (même
   logique que le reste de ce fichier — un effet transform par élément).
   inset négatif : le cercle d'orbite dépasse la boule, la roquette tournant
   donc juste à l'extérieur de la planète plutôt que par-dessus. Resserré
   (demande explicite "un poil trop à l'extérieur, rapproche-la de la
   planète" : -26px -> -14px). Invisible au repos, révélée + mise en
   rotation uniquement au survol. */
.home-hero-planet-orbit {
    position: absolute;
    inset: -14px;
    border-radius: 50%;
    pointer-events: none;
    opacity: 0;
    transition: opacity .3s ease;
}

/* Rotation/accélération/traînée désormais pilotées par main.js (bloc "HERO
   ACCUEIL — ROQUETTE PLANÈTES", demande explicite "accélère à l'infini,
   traînée qui s'allonge jusqu'au tour complet" — impossible à exprimer avec
   une seule @keyframes à durée fixe). CSS ne gère plus que la révélation
   (opacité) au survol/focus. */
.home-hero-planet:hover .home-hero-planet-orbit,
.home-hero-planet:focus .home-hero-planet-orbit,
.hero-central-planet:hover .home-hero-planet-orbit,
.hero-central-planet:focus .home-hero-planet-orbit {
    opacity: 1;
}

.home-hero-planet-rocket {
    position: absolute;
    top: 0;
    left: 50%;
    /* Roquette agrandie (demande explicite, une 2e fois : 14px -> 22px ->
       26px) : les attributs width/height="14" posés en dur sur les 5 <svg>
       dans accueil.php sont ici surchargés en CSS (une seule règle pour les
       5 planètes plutôt que 5 éditions HTML identiques). */
    width: 26px;
    height: 26px;
    /* rotate(90deg) (demande explicite, "tournées de 90° vers la droite") :
       sans ce rotate, le nez de la roquette pointe en permanence
       radialement vers l'extérieur (loin du centre) tout au long de la
       rotation du wrapper .home-hero-planet-orbit — un vecteur qui part
       "vers l'extérieur" et suit une rotation rigide reste "vers
       l'extérieur" à n'importe quel angle. Avec ce quart de tour en plus,
       le nez pointe tangentiellement, dans le sens du déplacement : la
       roquette a donc l'air de VOLER en orbite autour de la planète,
       plutôt que de simplement pivoter sur elle-même en pointant dehors. */
    transform: translate(-50%, -50%) rotate(90deg);
    /* Couleur SECONDAIRE de la paire (demande explicite : "la roquette doit
       également avoir la couleur secondaire") — même variable que la
       traînée (--planet-trail-color) ; --planet-rocket-color reste défini
       par planète mais n'est plus utilisé ici (repli conservé au cas où). */
    color: var(--planet-trail-color, var(--planet-rocket-color, #ffffff));
    filter: drop-shadow(0 0 4px currentColor);
}

/* Traînée : remplacée par un anneau SVG (cercle en pointillés, cf. markup
   dans accueil.php) plutôt qu'un simple trait — seule façon de la faire
   "s'allonger jusqu'au tour complet de la planète" (demande explicite),
   un trait fixe ne pouvant pas devenir un anneau. Le cercle SVG occupe
   tout le repère de .home-hero-planet-orbit (même wrapper tournant que la
   roquette, donc toujours parfaitement synchronisé avec elle) ; main.js
   pilote stroke-dasharray/stroke-dashoffset pour révéler une portion
   d'arc croissante juste derrière la roquette (cf. bloc "HERO ACCUEIL —
   ROQUETTE PLANÈTES"). Rayon du cercle (attribut r, dans le markup
   accueil.php) resserré 48 -> 49 (demande explicite : la traînée doit
   coller à la roquette, qui orbite au bord de .home-hero-planet-orbit,
   soit un rayon de 50 dans ce repère 0-100) — RADIUS dans main.js doit
   rester identique à cet attribut r pour un stroke-dasharray juste.
   rotate(-90deg) : place le point de départ du tracé
   SVG (par défaut à 3h) à midi, exactement où se trouve la roquette. */
.home-hero-planet-rocket-trail-svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
    transform: rotate(-90deg);
}
.home-hero-planet-rocket-trail-circle {
    fill: none;
    stroke: currentColor;
    stroke-width: 3;
    stroke-linecap: round;
    /* Traînée = couleur SECONDAIRE de la paire (demande explicite) — même
       variable que la roquette désormais (.home-hero-planet-rocket
       ci-dessus, elle aussi passée à --planet-trail-color sur demande
       explicite) — cf. --planet-trail-color définie par planète juste en
       dessous. */
    color: var(--planet-trail-color, #ffffff);
    opacity: .8;
    /* Valeurs de repos (aucune traînée visible) — recalculées en continu
       par main.js dès le survol/focus. */
    stroke-dasharray: 0 302;
    stroke-dashoffset: 0;
    filter: drop-shadow(0 0 3px currentColor);
}

/* Couleur de la roquette (primaire) et de la traînée (secondaire) propres à
   chaque planète (demande explicite : "respecter notre jeu de 2 couleurs")
   — mêmes paires exactement que les thèmes d'accent du site (cf.
   .accent-amber/-emerald/-cyan/-gold/-blue/-violet et leur commentaire
   plus haut dans ce fichier, --accent-harmony-1/-2) :
   bleu (centrale)         -> bleu / blanc      (accent-blue)
   glace ("Blanc")         -> blanc / gris      (accent-cyan)
   hébergement ("Vert")    -> vert / citron     (accent-emerald)
   violette ("Violet")     -> violet / rose     (accent-violet)
   magma ("Orange")        -> orange / jaune    (accent-amber) — corrigé
   (demande explicite "la traînée de la planète orange doit être jaune") :
   la boule reste orange (planet-orange.webp), la traînée (couleur
   secondaire, cf. --planet-trail-color) passe du noir au jaune. */
.home-hero-planet--magma       .home-hero-planet-orbit { --planet-rocket-color: rgb(249, 115, 22);  --planet-trail-color: rgb(250, 204, 21); }
.home-hero-planet--glace       .home-hero-planet-orbit { --planet-rocket-color: #ffffff;             --planet-trail-color: rgb(100, 116, 139); }
.home-hero-planet--hebergement .home-hero-planet-orbit { --planet-rocket-color: #10b981;             --planet-trail-color: rgb(163, 230, 53); }
.home-hero-planet--violette    .home-hero-planet-orbit { --planet-rocket-color: #8b5cf6;             --planet-trail-color: rgb(236, 72, 153); }
.home-hero-planet--bleu        .home-hero-planet-orbit { --planet-rocket-color: rgb(var(--header-accent)); --planet-trail-color: rgb(226, 232, 240); }

/* ─── SÉQUENCE "TROU NOIR" au clic sur Explorer OU sur l'une des 5
   planètes (classe posée par main.js sur .hero — demande explicite : "que
   le clic soit sur le bouton Explorer ou sur l'une des planètes, l'animation
   doit se déclencher") ───
   1) Le titre et la box CTA (cockpit) disparaissent en fondu simple
      (#hero-heading, .hero-window-content), de même que la liste de points
      et le divider.
   2) La planète centrale bleue N'EST PLUS dans ce fondu global (demande
      explicite : "rajouter l'avalement de la planète bleue") : elle a
      désormais sa PROPRE animation d'avalement (cf. règle
      .hero-central-planet plus bas), identique dans l'esprit à celle des 4
      planètes latérales plutôt qu'un simple fondu d'opacité hérité du
      parent.
   3) Le trou noir (.home-hero-halo), déjà visible en permanence en
      arrière-plan (demande explicite, cf. règle plus haut), grossit alors
      démesurément autour de ce même centre.
   4) AVALEMENT SÉLECTIF (demande explicite : "si le clic est sur Explorer,
      toutes les planètes sont avalées ; si le clic est sur une planète,
      seule elle est avalée, les autres disparaissent en fondu") : main.js
      pose .is-swallow-target sur l'élément cliqué (les 5 planètes, cas
      Explorer, ou seulement la planète visée sinon). Seules les planètes
      .is-swallow-target jouent @keyframes homeHeroPlanetSwallow (filent
      vers le centre en rétrécissant, comme aspirées par le trou noir qui
      grossit) ; les autres se contentent d'un simple fondu d'opacité (cf.
      règles .home-hero-planet:not(.is-swallow-target)/.hero-central-planet
      :not(.is-swallow-target) plus bas). Dans tous les cas, les titres (cf.
      .home-hero-planet-label plus bas) disparaissent immédiatement, sans
      être traînés/déformés par une éventuelle transformation (demande
      explicite "enlève les titres associés aux planètes pendant
      l'animation").
   main.js attend la fin de cette séquence avant de rediriger vers la page
   liée à l'élément réellement cliqué (Explorer ou la planète — demande
   explicite "le visiteur est ensuite redirigé en fonction d'où il a
   cliqué", cf. bloc "SÉQUENCE TROU NOIR HERO ACCUEIL" dans main.js). */
main .hero.is-launching #hero-heading,
main .hero.is-launching .hero-window-content,
main .hero.is-launching .hero-cockpit-area,
main .hero.is-launching .section-divider {
    opacity: 0;
    transition: opacity .6s ease;
    pointer-events: none;
}

/* Roquette en orbite (cf. .home-hero-planet-orbit plus haut) : masquée
   immédiatement dès le début de la séquence (demande explicite "enlève la
   roquette qui tourne autour des planètes en hover pendant l'animation"),
   quel que soit l'état :hover/:focus hérité du survol au moment du clic —
   sans ça, la roquette pouvait continuer de tourner par-dessus l'avalement
   ou le fondu. "main" ajouté pour l'emporter sur la règle de révélation au
   survol (même nombre de classes, la spécificité seule ne suffirait pas à
   garantir l'ordre). Complète le garde-fou côté JS (cf. main.js, bloc
   "ROQUETTE PLANÈTES", qui arrête aussi la boucle requestAnimationFrame). */
main .hero.is-launching .home-hero-planet-orbit {
    opacity: 0 !important;
    transition: opacity .2s ease;
}

/* Titres des 5 planètes (4 latérales + centrale bleue, cf.
   .home-hero-planet-label plus bas) : masqués immédiatement pendant la
   séquence d'avalement, plutôt que de suivre visuellement le
   translate/scale/rotate de leur planète (ce qui les faisait traîner/
   se déformer de façon peu lisible). */
.hero.is-launching .home-hero-planet-label {
    opacity: 0;
    transition: opacity .3s ease;
}

/* Avalement de la planète centrale bleue (demande explicite) : même
   traitement que les 4 planètes latérales (cf. @keyframes
   homeHeroPlanetSwallow plus bas), avec son propre --swallow-dx/-dy posé
   sur .hero-central-planet (cf. règle plus haut). Démarre en même temps que
   le début du fondu du titre/box CTA (pas de délai supplémentaire), donc
   AVANT les 4 planètes latérales (.45s -> .9s) : elle est la plus proche du
   centre visuellement et peut "partir" la première sans casser l'effet de
   stagger des 4 autres. */
.hero.is-launching .hero-central-planet.is-swallow-target {
    animation: homeHeroPlanetSwallow 1.8s cubic-bezier(.55,0,.85,.35) forwards;
    animation-delay: .3s;
}

main .hero.is-launching::before,
main .hero.is-launching::after {
    opacity: 0;
    transition: opacity .6s ease;
}

.hero.is-launching .home-hero-halo {
    opacity: 1;
    /* Une fois la dernière planète avalée (délai .9s + durée 1.8s = 2.7s),
       le trou noir grossit démesurément autour de ce même centre (42%/50%,
       transform-origin par défaut) jusqu'à couvrir tout l'écran — sensation
       de "rentrer dedans". Démarre pile quand la dernière planète disparaît. */
    animation: homeHeroHaloGrow 1s ease-in forwards;
    animation-delay: 2.7s;
}

/* Le disque d'accrétion (anneau clair) s'efface pendant que l'horizon des
   événements (::after, disque noir) grossit : sans ça, l'anneau clair
   s'agrandirait lui aussi et laisserait une bordure lumineuse disgracieuse
   au lieu d'un noir net. */
.hero.is-launching .home-hero-halo::before {
    transition: opacity .8s ease;
    transition-delay: 2.7s;
    opacity: 0;
}

@keyframes homeHeroHaloGrow {
    0%   { transform: scale(1); }
    100% { transform: scale(18); }
}

/* Voile plein écran : commence à s'assombrir un peu après le début du
   grossissement du trou noir (2.7s + .4s = 3.1s) et termine à 3.8s, juste
   avant la redirection (cf. main.js, bloc "SÉQUENCE TROU NOIR HERO
   ACCUEIL") — assure un noir total même sur les écrans très larges où le
   disque du trou noir pourrait ne pas couvrir les coins. */
.hero.is-launching .home-hero-blackout {
    opacity: 1;
    transition-delay: 3.1s;
}

/* ─── Avalement sélectif (demande explicite : "si le clic est sur Explorer,
   toutes les planètes sont avalées ; si le clic est sur une planète, seule
   elle est avalée, les autres disparaissent en fondu") ───
   main.js pose .is-swallow-target sur l'élément (ou les 5 éléments, cas
   Explorer) réellement visé par le clic. Seuls les éléments qui portent
   cette classe jouent l'animation homeHeroPlanetSwallow ci-dessous ; les
   4 (ou 5) autres planètes, elles, se contentent d'un simple fondu
   d'opacité (cf. règle .home-hero-planet:not(.is-swallow-target) plus
   bas), plutôt que de foncer vers le trou noir alors qu'elles n'ont pas été
   cliquées. */
.hero.is-launching .home-hero-planet.is-swallow-target {
    /* Durée doublée (.9s -> 1.8s, demande explicite) : les planètes mettent
       plus longtemps à filer vers le centre et rétrécir. */
    animation: homeHeroPlanetSwallow 1.8s cubic-bezier(.55,0,.85,.35) forwards;
    animation-delay: .3s;
}
.hero.is-launching .home-hero-planet--left-1.is-swallow-target { animation-delay: .45s; }
.hero.is-launching .home-hero-planet--right-1.is-swallow-target { animation-delay: .6s; }
.hero.is-launching .home-hero-planet--left-2.is-swallow-target { animation-delay: .75s; }
.hero.is-launching .home-hero-planet--right-2.is-swallow-target { animation-delay: .9s; }

/* Planètes (latérales + centrale) NON ciblées par le clic (cas "clic sur
   une planète précise") : simple fondu, comme le titre/la box CTA, plutôt
   que l'avalement réservé à celle réellement cliquée. Ne matche AUCUN
   élément dans le cas "Explorer" (les 5 portent alors .is-swallow-target). */
.hero.is-launching .home-hero-planet:not(.is-swallow-target),
.hero.is-launching .hero-central-planet:not(.is-swallow-target) {
    opacity: 0;
    transition: opacity .6s ease;
    pointer-events: none;
}

/* Trajet vers le centre (--swallow-dx/--swallow-dy propres à chaque
   planète, cf. plus haut) + rotation + rétrécissement jusqu'à
   disparition — même esprit que @keyframes blackHoleSwallowSpiral
   (why-target-cta-halo/services-cta-halo) mais en ligne droite plutôt
   qu'en spirale, chaque planète n'étant pas déjà en orbite circulaire. */
@keyframes homeHeroPlanetSwallow {
    0%   { transform: translate(0, 0) scale(1) rotate(0deg); opacity: 1; }
    70%  { transform: translate(calc(var(--swallow-dx) * .82), calc(var(--swallow-dy) * .82)) scale(.4) rotate(300deg); opacity: 1; }
    100% { transform: translate(var(--swallow-dx), var(--swallow-dy)) scale(0) rotate(480deg); opacity: 0; }
}

/* ── Zone fenêtre (logo + titre + CTA) ── */
/* flex:1 étirait cette zone pour occuper tout l'espace disponible dans le
   flex column .hero (justify-content:space-between) : sur les écrans hauts
   / contenu court, ça créait un grand vide entre le CTA "Voir les offres et
   tarifs" et le premier point de .hero-cockpit-area ("Des prix clairs et
   sans surprise"). La zone garde maintenant sa hauteur naturelle, et .hero
   est passé à justify-content:flex-start : les 3 blocs (fenêtre, cockpit,
   divider) restent groupés avec un petit écart entre eux au lieu d'être
   étirés sur toute la hauteur de la section.
   padding-top quasi supprimé (demande explicite, confirmée : l'ancien
   header flottant centré qui justifiait cette réserve n'existe plus — il a
   été remplacé par 2 vignettes HUD en coins (Navigation en haut-gauche,
   Mon compte en haut-droite, cf. partials/footer.php .hud-widget--nav/
   --account, top:22px, ancrées sur les côtés), qui laissent le centre du
   haut de page entièrement libre. clamp 96-130px -> clamp 8-24px, puis
   redescendu un peu (demande explicite "descends un petit peu le titre") :
   clamp 8-24px -> clamp 32px-56px. */
.hero-window-area {
    position: relative;
    z-index: 1;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: clamp(32px, 5vh, 56px);
    /* Cette boîte est pleine largeur (flex, justify-content:center ne fait
       que centrer son contenu À L'INTÉRIEUR) alors que même z-index que
       .hero-space (1) + DOM après lui = elle passe devant en cas d'égalité
       de z-index. Résultat : ses zones vides (hors du panneau titre/CTA)
       interceptaient le survol des planètes décoratives d'accueil.php
       situées dessous (cf. .home-hero-planet). pointer-events:none ici +
       auto sur .hero-window-content (le panneau visible) : le clic/survol
       traverse le vide et atteint les planètes, sans rien changer au
       rendu visuel ni à l'interactivité du panneau/CTA. */
    pointer-events: none;
}

main .hero .container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
    width: 100%;
}




/* Panneau de verre centré dans la fenêtre : traité comme un hublot de
   cockpit plutôt qu'une simple vitre plate — chevrons HUD dans les 4
   coins, très fines lignes de balayage horizontales, liseré interne
   lumineux et petit voyant de statut qui clignote en haut du panneau. */
.hero-window-content {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 22px;
    /* Descendue encore un peu (demande explicite), séparément de la
       planète bleue au-dessus (déjà descendue via .hero-central-planet) :
       24px -> 40px. */
    margin-top: 40px;
    padding: 36px 32px 32px;
    max-width: 540px;
    width: 100%;
    pointer-events: auto;

    /* Opacité remontée 0.22 -> 0.62 + flou 3px -> 7px (demande explicite :
       "l'élément central de la page... alors que cela doit être les 2
       boutons", pas le trou noir derrière) : le panneau reste un hublot
       (translucide, scanlines + halo visibles) mais masque bien davantage le
       trou noir/disque d'accrétion en mouvement derrière lui, pour que les 2
       CTA ("Explorer"/"Créer un site") restent l'élément visuellement
       dominant plutôt que d'être noyés dans l'animation en arrière-plan. */
    background:
        repeating-linear-gradient(180deg, rgba(255,255,255,0.014) 0px, rgba(255,255,255,0.014) 1px, transparent 1px, transparent 3px),
        rgba(0, 5, 22, 0.62);
    backdrop-filter: blur(7px);
    -webkit-backdrop-filter: blur(7px);
    border-radius: 18px;
    border: 1px solid rgba(120,170,255,0.16);
    box-shadow:
        0 0 80px rgba(var(--header-accent),0.1),
        inset 0 0 40px rgba(0,0,0,0.2),
        inset 0 0 0 1px rgba(120,170,255,0.05),
        inset 0 54px 80px -60px rgba(var(--header-accent),0.22),
        inset 0 -54px 80px -60px rgba(0,0,0,0.4);
}

.cockpit-corner {
    position: absolute;
    width: 22px;
    height: 22px;
    border: 2px solid rgba(140,195,255,0.55);
    filter: drop-shadow(0 0 4px rgba(var(--header-accent),0.35));
    pointer-events: none;
    z-index: 1;
}

.cockpit-corner--tl { top: 12px; left: 12px; border-right: none; border-bottom: none; border-top-left-radius: 6px; }
.cockpit-corner--tr { top: 12px; right: 12px; border-left: none; border-bottom: none; border-top-right-radius: 6px; }
.cockpit-corner--bl { bottom: 12px; left: 12px; border-right: none; border-top: none; border-bottom-left-radius: 6px; }
.cockpit-corner--br { bottom: 12px; right: 12px; border-left: none; border-top: none; border-bottom-right-radius: 6px; }

.cockpit-status-light {
    position: absolute;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgb(var(--header-accent));
    box-shadow: 0 0 8px rgba(var(--header-accent),.9), 0 0 18px rgba(var(--header-accent),0.6);
    animation: capsuleStatusPulse 2.8s ease-in-out infinite;
    z-index: 1;
}

.highlight-accueil {
    background: rgba(var(--header-accent), 0.10);
    box-shadow: 0 0 14px rgba(var(--header-accent), 0.15);
    color: #ffffff;
    padding: 2px 6px;
    border-radius: 6px;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
}

/* Style repris du h1 "À propos." de presentation.php (demande explicite :
   "le style de titre doit être le même que celui utilisé pour le titre 'à
   propos' de la page présentation") — cf. .partners-hero-layout h1 plus
   bas dans ce fichier : même dégradé diagonal blanc -> couleur d'accent,
   même graisse/line-height/taille. */
main .hero h1 {
    font-family: var(--font-title);
    /* Réduit légèrement (demande explicite, clamp 2.2-3.2rem -> 2-2.9rem). */
    font-size: clamp(2rem, 3.6vw, 2.9rem);
    font-weight: 800;
    /* Marge basse (demande explicite : titre "hors de la box", tout en
       haut) — remplace l'espacement qu'apportait auparavant le gap flex de
       .hero-window-content quand le h1 vivait à l'intérieur. */
    margin: 0 0 22px;
    line-height: 1.15;
    /* FIX : le "> " (::before) se retrouvait seul sur sa propre ligne,
       au-dessus du titre. Cause : .highlight-accueil (span enfant) anime sa
       propre largeur jusqu'à 100%, un pourcentage qui se résout ici contre
       la largeur PLEINE du h1 (bloc en display:flex, sans contrainte de
       taille) — beaucoup plus large que le texte réel, ce qui poussait le
       contenu à passer à la ligne entre "> " et le span. width:max-content
       (comme .site_description_devise sur index.php, même mécanisme)
       force le h1 à épouser la largeur réelle de son contenu : le span à
       100% correspond alors à la largeur du texte, plus de retour à la
       ligne. align-items:center du flex parent (.container.hero-content)
       centre ce bloc désormais plus étroit. */
    width: max-content;
    max-width: 100%;
}

/* Tout le texte du h1 est porté par ce span (cf. markup accueil.php : un
   seul .highlight-accueil enveloppe tout le titre) — c'est donc lui, pas le
   h1, qui doit recevoir le dégradé pour que ça se voie. Override complet
   (et non un simple ajustement de couleur) : la pastille/chip habituelle de
   .highlight-accueil (fond teinté, halo, padding, coins arrondis, cf. règle
   générale plus haut dans ce fichier) est neutralisée ici pour retrouver le
   même rendu que .partners-hero-layout h1 — texte nu en dégradé diagonal
   blanc -> couleur d'accent, sans boîte.
   Machine à écrire IDENTIQUE à .site_description_devise .typewriter sur
   index.php (demande explicite "même animation... durée et répétition") :
   mêmes 3 animations (typewriterReveal/typewriterCaret/typewriterCaretHide,
   cf. keyframes plus haut dans ce fichier), même durée calculée en PHP
   (--type-chars/--type-duration posées en inline sur le <h1>, cf. markup
   accueil.php) — frappe UNE fois au chargement (steps() + forwards), pas de
   boucle, comme sur index.php. */
main .hero h1 .highlight-accueil {
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent), .90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    box-shadow: none;
    padding: 0;
    border-radius: 0;
    display: inline-block;
    overflow: hidden;
    white-space: nowrap;
    vertical-align: bottom;
    width: 0;
    max-width: 100%;
    padding-right: 3px;
    border-right: 2px solid rgba(var(--header-accent), .85);
    /* heroTitleTypewriterReveal (dédiée), PAS le typewriterReveal partagé
       (index.php) : celui-ci anime jusqu'à "100%", un pourcentage qui se
       résout contre le h1 — ici flex item d'un conteneur .container.hero-
       content, dont le sizing (même avec width:max-content posé sur le h1)
       ne suffit pas à donner une largeur "au texte" fiable, d'où le "> "
       qui se retrouvait seul sur sa ligne (le span s'étirait bien plus
       large que le texte réel). Solution robuste : cible une largeur ABSOLUE
       en "ch" (police monospace, --type-chars posé en inline sur le <h1>,
       cf. markup accueil.php) plutôt qu'un pourcentage — plus aucune
       dépendance à la largeur d'un ancêtre. */
    animation:
        heroTitleTypewriterReveal var(--type-duration, 1.8s) steps(var(--type-chars, 30), end) forwards,
        typewriterCaret .8s step-end infinite,
        typewriterCaretHide .01s linear var(--type-duration, 1.8s) forwards;
}

@keyframes heroTitleTypewriterReveal {
    from { width: 0; }
    to   { width: calc(var(--type-chars, 20) * 1ch + .5ch); }
}

/* Le curseur bloc générique (h1::after) est masqué spécifiquement ici : la
   frappe machine à écrire ci-dessus a déjà son propre curseur clignotant
   (border-right), qui disparaît en fin de frappe exactement comme sur
   index.php — un 2e curseur bloc serait redondant. Le préfixe "> "
   (::before), lui, reste affiché comme sur tous les autres h1 du site. */
#hero-heading::after {
    content: none;
}

main .hero .subtitle {
    font-size: 1.4rem;
    font-weight: 600;
    margin: 0;
    max-width: 560px;
    line-height: 1.65;
    background: linear-gradient(180deg, rgba(100,160,255,0.95), rgba(var(--header-accent),0.82));
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* ── Zone cockpit / dashboard (hero-points) ── */
.hero-cockpit-area {
    position: relative;
    z-index: 1;
    padding: 18px 20px 14px;
    display: flex;
    justify-content: center;
    /* Même souci/même fix que .hero-window-area plus haut : boîte pleine
       largeur qui bloquait le survol des planètes décoratives d'accueil.php
       situées derrière (côtés gauche/droite bas, cf. .home-hero-planet--
       left-2/--right-2). */
    pointer-events: none;
}

main .hero-points {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    pointer-events: auto;
}

main .hero-points li {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
    padding: 10px 18px;
    border-radius: 10px;
    width: 100%;
    max-width: 460px;

    background: rgba(0, 0, 0, 0.52);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(var(--header-accent),0.22);
    box-shadow: 0 0 14px rgba(var(--header-accent),0.08);

    text-align: left;

    transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}


main .hero-points li:hover {
    transform: translateY(-2px);
    border-color: rgba(var(--header-accent),0.45);
    box-shadow: 0 0 22px rgba(var(--header-accent),0.2);
}

/* Écart réduit entre le dernier point ("Un site qui reste votre
   propriété") et la roquette-divider "en savoir plus" qui suit (demande
   explicite) — scopé à .hero (et non .section-divider directement, classe
   partagée par 8+ autres dividers du site) : ne touche pas le gap flex
   général de .hero (qui espace aussi .hero-window-area <-> .hero-cockpit-
   area, inchangé), seul ce dernier écart est resserré via une marge
   négative. */
main .hero .section-divider {
    margin-top: -22px;
}

/* ═══════════════════════════════════════════════════════════════════
   HERO ACCUEIL.PHP — SÉQUENCE D'INTRODUCTION AU CHARGEMENT (demande
   explicite) : "qu'il n'y ait que le titre et le trou noir qui soient
   visibles [au départ], puis la roquette du bouton 'En savoir plus' (la
   petite roquette du divider tout en bas du hero, qui mène à #solution)
   sort du trou noir et rejoint sa place, son texte s'affiche, et dans le
   même temps le reste de la section (uniquement) arrive en fondu."
   Réutilise le système EXISTANT .section-divider/.is-visible (posé par
   l'IntersectionObserver "SCROLL REVEAL" dans main.js, qui ajoute déjà
   .is-visible dès qu'un divider entre dans le viewport — quasi immédiat
   pour celui du hero, visible dès le chargement) plutôt que d'en créer un
   nouveau : seul le POINT DE DÉPART du vol de la roquette est changé (cf.
   règle plus bas) — une distance bien plus grande, approximative mais
   suffisante pour un effet purement décoratif ("elle vient du trou noir")
   plutôt que le petit pop générique (-47px) des 7 autres dividers du
   site. Le texte "EN SAVOIR PLUS" (.divider-action::after, toujours
   présent dans le DOM) n'a besoin d'aucune règle supplémentaire : étant un
   pseudo-élément d'un descendant de .rocket-wrapper, il hérite déjà
   visuellement de l'opacité animée de son parent (0 -> 1 avec .is-visible),
   donc apparaît automatiquement en même temps que la roquette. Le reste du
   hero (planète bleue, CTA, points, 4 planètes latérales) est cette fois
   masqué par défaut et réapparaît en fondu via la classe
   .hero-intro-revealed, ajoutée par main.js dans le MÊME callback que
   .is-visible (bloc "SCROLL REVEAL"), donc synchronisée avec l'arrivée de
   la roquette. Filet de sécurité : @media (prefers-reduced-motion) et un
   <noscript> (cf. accueil.php) affichent tout immédiatement si
   l'animation/JS est indisponible — le système is-launching (clic
   Explorer/planètes, plus haut dans ce fichier) reste totalement
   indépendant de cette séquence d'intro. ═══════════════════════════ */
main .hero .hero-central-planet,
main .hero .hero-window-content,
main .hero .hero-cockpit-area,
main .hero .hero-space .home-hero-planet {
    opacity: 0;
    pointer-events: none;
    /* Fondu prolongé (demande explicite "prolonge un peu le fondu",
       1s -> 1.8s). */
    transition: opacity 1.8s ease;
}

/* BUG TROUVÉ (capture d'écran utilisateur à l'appui, clic sur la planète
   bleue / sur Explorer) : une fois l'intro terminée, .hero garde la classe
   .hero-intro-revealed en PERMANENCE. Au clic (planète ou Explorer),
   .is-launching s'ajoute EN PLUS — .hero porte alors les deux classes à la
   fois. Ces 4 sélecteurs et ceux de .hero.is-launching (masquage pendant le
   lancement, cf. règles plus haut : #hero-heading/.hero-window-content/
   .hero-cockpit-area, + le fondu .home-hero-planet:not(.is-swallow-target))
   ont EXACTEMENT la même spécificité (main + 3 classes) : à égalité, c'est
   l'ordre dans le fichier qui tranche, et cette règle-ci — plus bas — gagnait
   à tort, gardant CTA/points/planètes latérales visibles pendant toute
   l'animation d'avalement au lieu de les faire disparaître. :not(.is-launching)
   neutralise cette règle dès que .is-launching est posée, laissant les
   règles de lancement reprendre la main (même principe que
   :not(.is-visible) plus haut sur .rocket-wrapper). */
main .hero.hero-intro-revealed:not(.is-launching) .hero-central-planet,
main .hero.hero-intro-revealed:not(.is-launching) .hero-window-content,
main .hero.hero-intro-revealed:not(.is-launching) .hero-cockpit-area,
main .hero.hero-intro-revealed:not(.is-launching) .hero-space .home-hero-planet {
    opacity: 1;
}

/* 2e BUG TROUVÉ (signalé : "planète violette et verte, ni le hover ni le
   clic ne fonctionnent") : .hero-cockpit-area est la boîte pleine largeur
   qui enveloppe .hero-points — elle a délibérément pointer-events:none
   (cf. règle plus haut, ligne ~6638) pour laisser le survol/clic traverser
   son espace vide jusqu'aux planètes latérales--left-2/--right-2
   (violette/hébergement, cf. .home-hero-planet--left-2/--right-2), qui sont
   positionnées derrière elle à la même hauteur (top:60%) mais EN DEHORS de
   la zone visible de .hero-points (max-width:460px, centrée). La règle
   ci-dessus posait "pointer-events: auto" sur .hero-cockpit-area EN PLUS de
   l'opacité — avec 4 classes de spécificité, elle écrasait complètement le
   pointer-events:none d'origine (1 seule classe) dès l'intro terminée,
   rendant TOUTE la largeur de la bande à nouveau capteuse de clics/survol
   et bloquant les 2 planètes du dessous en permanence après le chargement.
   pointer-events:auto reste nécessaire pour .hero-central-planet et
   .hero-window-content (les 2 seuls éléments de cette liste qui SONT censés
   être cliquables), donc séparé dans sa propre règle plutôt que retiré
   partout. */
main .hero.hero-intro-revealed:not(.is-launching) .hero-central-planet,
main .hero.hero-intro-revealed:not(.is-launching) .hero-window-content,
main .hero.hero-intro-revealed:not(.is-launching) .hero-space .home-hero-planet {
    pointer-events: auto;
}

/* Roquette du divider du hero : part de beaucoup plus loin (façon "sort du
   trou noir", vers son centre à 55% de la hauteur de la section, cf.
   .home-hero-halo plus haut) que le petit pop générique (-47px) des autres
   dividers du site, et vole plus lentement (1.5s au lieu de .65s) pour
   laisser le temps de "voir" le trajet. Transition redéclarée ici (et non
   sur .is-visible) : c'est la valeur active AVANT le basculement de classe
   qui pilote l'animation, même convention que la règle générique
   d'origine (cf. .section-divider .rocket-wrapper plus bas dans ce
   fichier). :not(.is-visible) est nécessaire ici : sans ça, cette règle
   (3 classes + le type "main" en plus) resterait plus spécifique que
   .section-divider.is-visible .rocket-wrapper (3 classes seulement, plus
   bas) même une fois .is-visible ajoutée, empêchant le retour à la pose de
   repos (translateY(8px) scale(1)) — avec :not(), la règle ne matche plus
   du tout dès que .is-visible apparaît, et la règle générique d'arrivée
   reprend proprement la main. */
main .hero .section-divider:not(.is-visible) .rocket-wrapper {
    transform: translateY(-38dvh) scale(.2);
    /* Apparition adoucie (demande explicite "fait apparaître un poil plus
       doucement la roquette") : fondu d'opacité allongé (1.1s -> 1.9s) pour
       une matérialisation plus graduelle, et vol légèrement rallongé (1.5s
       -> 1.7s) avec une courbe plus progressive au départ. Le minuteur JS
       (FLIGHT_DURATION, cf. main.js) a été resynchronisé sur cette nouvelle
       durée. */
    transition:
        opacity 1.9s ease .1s,
        transform 1.7s cubic-bezier(.25,.1,.25,1) .1s;
}

@media (prefers-reduced-motion: reduce) {
    main .hero .hero-central-planet,
    main .hero .hero-window-content,
    main .hero .hero-cockpit-area,
    main .hero .hero-space .home-hero-planet {
        opacity: 1;
        pointer-events: auto;
        transition: none;
    }
    main .hero .section-divider .rocket-wrapper {
        transform: none;
        transition: none;
    }
}

/* Punchline (ligne 1) — porte le point bleu, ex ::before de li */
.hero-point-title {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 0.9rem;
    font-weight: 600;
    color: rgba(255,255,255,0.85);
}

.hero-point-title::before {
    content: "";
    display: block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--brand-color);
    box-shadow: 0 0 8px rgba(var(--header-accent),0.9);
}

/* Explication (ligne 2) — alignée sous le texte de la punchline (point
   bleu 6px + gap 9px = 15px de retrait), pas sous le point lui-même. */
.hero-point-desc {
    padding-left: 15px;
    font-size: 0.76rem;
    font-weight: 400;
    line-height: 1.4;
    color: rgba(255,255,255,0.52);
}

/* ── Rocket wrapper ── */
main .hero .rocket-wrapper {
    position: relative;
    z-index: 1;
    display: flex;
    justify-content: center;
    padding-bottom: 45px;
}




/* ===================== SECTION FUSIONNÉE SOLUTION + OFFRES ===================== */


.sol-off {
    /* min-height -> height (demande explicite : "essaie de faire en sorte
       que cette section fasse bien que 100dvh") : min-height laissait la
       section grandir au-delà d'un écran si le contenu (fusée verticale +
       pricing) l'exigeait. height fixe la borde à 100dvh ; overflow:hidden
       ci-dessous absorbe le débordement éventuel plutôt que de repousser
       la section suivante. */
    height: 100dvh;
    overflow: hidden;
    /* demande explicite : réduction de largeur -10%/côté, cf. commentaire
       détaillé sur .method plus haut. */
    width: 90%;
    margin-left: auto;
    margin-right: auto;
    display: flex;
    flex-direction: column;
    /* padding-top ajouté (demande explicite : "le contenu est trop collé en
       haut") : .sol-off n'avait AUCUN padding-top jusqu'ici (seul de toutes
       les sections "dans le vaisseau" — .method/.why-target/.modules en ont
       tous un), ce qui collait .sol-off-inner directement contre le nouveau
       bandeau .section-sas. Même échelle que .method (clamp 90-116/120px)
       pour rester cohérent. */
    padding-top: clamp(90px, 10vh, 120px);
    /* Léger padding-bas : même principe que les autres sections (method,
       problem, why-target, modules, home-service-section) — le divider
       reste un peu au-dessus de la barre qui referme la section plutôt que
       collé dessus. */
    padding-bottom: clamp(28px, 4vh, 44px);
    position: relative;
    /* demande explicite : "uniformise le bg [des 7 sections de la fusée] à
       la façon des sites évolutifs construits autour de modules" — reprend
       exactement le fond de main .modules, cf. commentaire détaillé sur
       .method plus haut. */
    background:
        radial-gradient(ellipse at 0% 100%,   rgba(var(--header-accent),.18) 0%, transparent 45%),
        radial-gradient(ellipse at 100% 0%,   rgba(var(--header-accent),.10) 0%, transparent 45%),
        radial-gradient(ellipse at 50% 50%,   rgba(var(--header-accent),.05) 0%, transparent 65%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.025) 0,
            rgba(255,255,255,.025) 1px,
            transparent 1px,
            transparent 44px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.018) 0,
            rgba(255,255,255,.018) 1px,
            transparent 1px,
            transparent 44px
        ),
        rgba(7,10,18,.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-top: 1px solid rgba(var(--header-accent),.14);
    border-bottom: 1px solid rgba(var(--header-accent),.14);
}

.sol-off::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at 50% 50%, rgba(var(--header-accent),.07) 0%, transparent 65%);
    pointer-events: none;
    z-index: 0;
}

/* ─── BANDE "PLAQUE DE MÉTAL" (transition entre 2 sections, demande
   explicite) ───
   Générique et réutilisable (à l'origine .sol-off-interior, posée en haut
   de #solution juste après le hero — demande explicite "donner
   l'impression que l'on est maintenant à l'intérieur du vaisseau" — puis
   demandée à nouveau "à la fin de la section Pourquoi choisir
   CroisierWeb", cf. .metal-plate-band--bottom sur #why-target plus bas) :
   même texture métallique (reflet diagonal façon métal brossé, fines
   stries horizontales, jointures verticales de plaques boulonnées, rangée
   de rivets, liseré biseauté) partagée par les 2 variantes, seuls le sens
   du dégradé/biseau et le positionnement changent :
   - .metal-plate-band--top : premier enfant flex d'une section
     (display:flex; flex-direction:column), se pose donc naturellement tout
     en haut sans positionnement absolu — dégradé sombre au bord HAUT qui
     s'estompe vers le bas (plafond).
   - .metal-plate-band--bottom : positionnement absolute (bottom:0) pour
     rester collée au bord bas de la section quel que soit son padding
     interne — dégradé miroir, sombre au bord BAS qui s'estompe vers le
     haut (cloison/plancher). */
.metal-plate-band {
    position: relative;
    z-index: 2;
    flex-shrink: 0;
    height: clamp(56px, 8vh, 84px);
    pointer-events: none;
}

.metal-plate-band::after {
    content: "";
    position: absolute;
    left: 4%;
    right: 4%;
    height: 3px;
    background-image: radial-gradient(circle, rgba(0,0,0,.6) 0 1.4px, transparent 1.6px);
    background-size: 44px 3px;
    background-repeat: repeat-x;
    background-position: left center;
    opacity: .85;
    pointer-events: none;
}

/* Liseré lumineux horizontal (même esprit que .rocketv-nose-seam) : la
   "jointure" visible entre la plaque et la paroi de la cabine. */
.metal-plate-band-seam {
    position: absolute;
    left: 8%;
    right: 8%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.5), transparent);
}

.metal-plate-band--top {
    background:
        /* reflet diagonal, effet de brillance sur métal brossé */
        linear-gradient(115deg,
            transparent 30%,
            rgba(255,255,255,.07) 45%,
            rgba(255,255,255,.15) 50%,
            rgba(255,255,255,.07) 55%,
            transparent 70%
        ),
        /* fines stries horizontales, texture métal brossé */
        repeating-linear-gradient(180deg,
            rgba(255,255,255,.045) 0,
            rgba(255,255,255,.045) 1px,
            transparent 1px,
            transparent 3px
        ),
        /* jointures verticales des plaques boulonnées */
        repeating-linear-gradient(90deg,
            rgba(0,0,0,.4) 0,
            rgba(0,0,0,.4) 1px,
            transparent 1px,
            transparent 180px
        ),
        /* teinte de couleur du sélecteur, imprimée sur le métal (demande
           explicite, 2e passe : "le gris" restait dominant — base recolorée
           en quasi-noir + couche de couleur remontée à .85 en haut, même
           traitement que .section-sas) */
        linear-gradient(180deg,
            rgba(var(--header-accent),.85) 0%,
            rgba(var(--header-accent),.55) 45%,
            rgba(var(--header-accent),.15) 80%,
            transparent 100%
        ),
        /* base quasi noire qui s'estompe vers le bas */
        linear-gradient(180deg,
            rgba(30,34,42,.95) 0%,
            rgba(24,27,34,.85) 55%,
            rgba(20,22,28,0) 100%
        );
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.22),
        inset 0 -1px 0 rgba(var(--header-accent),.75),
        inset 0 -16px 26px -18px rgba(0,0,0,.65);
}
.metal-plate-band--top::after { bottom: 8px; }
.metal-plate-band--top .metal-plate-band-seam { bottom: 0; }
.metal-plate-band--top .cockpit-status-light { top: 16px; }

/* Modificateur additionnel (à combiner avec --top, cf. .reviews-section
   --accueil dans accueil.php) : bascule en position absolue collée au bord
   HAUT plutôt que de compter sur l'ordre des enfants flex. Nécessaire pour
   les sections en justify-content:flex-end (le contenu est groupé vers le
   BAS, donc un premier enfant flex classique ne se retrouve pas forcément
   tout en haut de la section, contrairement à .sol-off/.why-target qui
   groupent depuis le haut). */
.metal-plate-band--top.metal-plate-band--pin-top {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
}

.metal-plate-band--bottom {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    /* Le fond/texture est désormais porté par .metal-plate-band-curve (voir
       plus bas) : ce conteneur ne fait plus que positionner ses enfants
       (courbe + seam + coins + voyant + ::before/::after). */
}

/* demande explicite (6e passe) : "je pensais à la courbure de la barre
   métallique elle-même" — pas seulement le petit anneau (::after) posé
   dessus, mais TOUTE la plaque de fin de FAQ. Élément réel dédié (plutôt
   qu'un clip-path direct sur .metal-plate-band--bottom) car ce dernier
   porte déjà ::before (lueur de combustion) + ::after (anneau segmenté) et
   plusieurs enfants absolute (seam, coins, voyant) qui doivent rester NON
   rognés par la courbe — seule cette couche de fond/texture est courbée.
   clip-path: ellipse(...) plutôt que border-radius : sur une forme aussi
   plate (large de ~90% de la page, haute de 56-84px), un border-radius%
   n'aurait dessiné une vraie courbe visible sur TOUTE la largeur qu'à 50%
   pile (les 2 coins se rejoignant exactement au centre) — un ellipse{}
   dont le centre est placé sous la plaque donne le même résultat "plein au
   centre, qui s'amenuise vers les bords" mais avec une flèche de courbure
   réglable indépendamment de la largeur réelle (ici ~24% de la hauteur,
   soit ~14-20px). */
.metal-plate-band-curve {
    content: "";
    position: absolute;
    inset: 0;
    clip-path: ellipse(90% 140% at 50% 140%);
    background:
        /* reflet diagonal, effet de brillance sur métal brossé */
        linear-gradient(115deg,
            transparent 30%,
            rgba(255,255,255,.07) 45%,
            rgba(255,255,255,.15) 50%,
            rgba(255,255,255,.07) 55%,
            transparent 70%
        ),
        /* fines stries horizontales, texture métal brossé */
        repeating-linear-gradient(180deg,
            rgba(255,255,255,.045) 0,
            rgba(255,255,255,.045) 1px,
            transparent 1px,
            transparent 3px
        ),
        /* jointures verticales des plaques boulonnées */
        repeating-linear-gradient(90deg,
            rgba(0,0,0,.4) 0,
            rgba(0,0,0,.4) 1px,
            transparent 1px,
            transparent 180px
        ),
        /* teinte de couleur du sélecteur, imprimée sur le métal (miroir de
           --top, 2e passe : base recolorée en quasi-noir + couleur remontée
           à .85 — même demande explicite) */
        linear-gradient(0deg,
            rgba(var(--header-accent),.85) 0%,
            rgba(var(--header-accent),.55) 45%,
            rgba(var(--header-accent),.15) 80%,
            transparent 100%
        ),
        /* base quasi noire qui s'estompe vers le haut (miroir de --top) */
        linear-gradient(0deg,
            rgba(30,34,42,.95) 0%,
            rgba(24,27,34,.85) 55%,
            rgba(20,22,28,0) 100%
        );
    box-shadow:
        inset 0 -1px 0 rgba(255,255,255,.22),
        inset 0 1px 0 rgba(var(--header-accent),.75),
        inset 0 16px 26px -18px rgba(0,0,0,.65),
        /* demande explicite : "rendre la barre métallique du bas plus type
           réacteur" — lueur chaude interne près du bord bas, en écho aux
           flammes juste en dessous (.rocket-engine-flames-wrap) */
        inset 0 -10px 22px -6px rgba(255,110,20,.4);
}
/* Cette occurrence de --bottom est unique sur le site (bandeau de fin de
   #faq-preview, juste au-dessus de .rocket-engine-flames-wrap) : ::before/
   ::after peuvent donc être entièrement redessinés ici sans impacter
   d'autres bandes (.metal-plate-band--top ailleurs sur la page, qui garde
   le simple pointillé générique). */

/* Lueur de "chambre de combustion" : dégradé radial chaud centré, calé sur
   la largeur des flammes (.rocket-engine-flames = min(78%,980px)), qui
   remonte depuis le bord bas de la bande — sert de transition visuelle
   entre le métal et les flammes. */
.metal-plate-band--bottom::before {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 0;
    width: min(60%, 620px);
    height: 85%;
    transform: translateX(-50%);
    background: radial-gradient(ellipse at 50% 100%,
        rgba(255,150,40,.55) 0%,
        rgba(255,80,10,.26) 38%,
        transparent 72%
    );
    filter: blur(3px);
    pointer-events: none;
}

/* Anneau segmenté façon "collerette de tuyère" (même esprit que
   .rocketv-nozzle, référence donnée) : alternance de plaques claires/
   sombres (vannes de turbine) au lieu du simple pointillé générique,
   posée près du bord bas — juste au-dessus des flammes — plutôt qu'en
   haut comme le pointillé d'origine. */
.metal-plate-band--bottom::after {
    top: auto;
    left: 50%;
    right: auto;
    /* décalé au-dessus du voyant central (.cockpit-status-light, bottom:16px
       + 6px de diamètre) pour ne pas s'y superposer. */
    bottom: 30px;
    width: min(72%, 760px);
    /* demande explicite (2e passe) : "toujours pas assez courbé, de la
       place encore avant le bouton FAQ" — un border-radius% sur une forme
       de seulement 7px de haut ne pouvait de toute façon jamais dépasser
       ~3.5px de flèche (rayon vertical max = moitié de la hauteur), donc
       quasi invisible à cette échelle. Hauteur presque triplée (20px, la
       bande dispose bien de cette marge sous le contenu de la FAQ) pour
       que le même principe de lentille (border-radius:50%, coins qui se
       rejoignent au centre) produise une flèche de courbure réellement
       visible (~10px), sans toucher au voyant ni remonter jusqu'au
       contenu au-dessus. */
    height: 20px;
    transform: translateX(-50%);
    background-image:
        repeating-linear-gradient(90deg,
            rgba(8,9,13,.9) 0,
            rgba(8,9,13,.9) 9px,
            rgba(215,219,226,.55) 9px,
            rgba(215,219,226,.55) 12px,
            rgba(8,9,13,.9) 12px,
            rgba(8,9,13,.9) 21px
        ),
        radial-gradient(circle, rgba(0,0,0,.7) 0 1.4px, transparent 1.6px);
    background-size: 21px 20px, 42px 3px;
    background-repeat: repeat-x, repeat-x;
    background-position: left center, left top;
    background-color: transparent;
    /* demande explicite : "ajoute une légère courbe pour augmenter l'effet
       réacteur" — border-radius en % (pas une valeur fixe en px) : les
       coins gauche/droite réclament chacun jusqu'à 50% de la largeur
       totale et se rejoignent donc AU MILIEU de la bande plutôt que de
       rester des coins isolés, ce qui courbe l'anneau sur toute sa
       longueur façon lentille/anneau de tuyère vu de face (plein au
       centre, qui s'amenuise vers les bords) plutôt qu'un simple
       rectangle à coins arrondis. */
    border-radius: 50%;
    opacity: 1;
    box-shadow:
        inset 0 1px 1px rgba(0,0,0,.65),
        inset 0 -1px 0 rgba(255,255,255,.14),
        0 0 12px rgba(255,120,30,.4);
}
.metal-plate-band--bottom .metal-plate-band-seam { top: 0; }
/* Voyant repositionné près du bord bas (miroir de --top) : la partie
   "pleine/opaque" de la plaque est ici en BAS (le dégradé s'estompe vers le
   haut, cf. --bottom plus haut), donc le voyant doit rester proche de ce
   bord plein pour se détacher nettement, plutôt que sur le bord qui
   s'efface vers la transparence. */
.metal-plate-band--bottom .cockpit-status-light { top: auto; bottom: 16px; }

/* ─── COQUE LATÉRALE "À L'INTÉRIEUR DE LA FUSÉE" (bords métalliques
   verticaux, demande explicite) ───
   Portée demandée : de "3 trajectoires de lancement" (#solution) jusqu'à
   la fin de "Pourquoi choisir CroisierWeb" (#why-target) inclus — les
   sections "dans le vaisseau" entre l'espace du hero et la sortie vers
   Livre d'or (#module, #method-heading, #probleme au milieu). Bordure
   verticale visible et crédible (pas un simple accent discret, demande
   explicite) : même langage visuel que .metal-plate-band (stries
   brossées, jointures de plaques boulonnées, rivets, liseré lumineux)
   mais tourné à 90°, sur toute la hauteur de la section plutôt que juste
   en haut/bas — pour renforcer l'impression d'être dans un couloir/une
   coursive cylindrique. Chaque section visée est déjà position:relative
   (règle générique .site-main > * tout en haut de ce fichier), donc ces
   bords s'y positionnent sans réglage supplémentaire par section. */
.rocket-hull-edge {
    position: absolute;
    top: 0;
    bottom: 0;
    width: clamp(14px, 2.2vw, 30px);
    z-index: 1;
    pointer-events: none;
    background:
        /* reflet vertical, brillance métal brossé (miroir du reflet
           diagonal horizontal des bandes haut/bas) */
        linear-gradient(200deg,
            transparent 30%,
            rgba(255,255,255,.06) 45%,
            rgba(255,255,255,.13) 50%,
            rgba(255,255,255,.06) 55%,
            transparent 70%
        ),
        /* fines stries VERTICALES, texture métal brossé */
        repeating-linear-gradient(90deg,
            rgba(255,255,255,.045) 0,
            rgba(255,255,255,.045) 1px,
            transparent 1px,
            transparent 3px
        ),
        /* jointures HORIZONTALES des plaques boulonnées, empilées le long
           de la coque plutôt que côte à côte comme sur les bandes
           horizontales */
        repeating-linear-gradient(0deg,
            rgba(0,0,0,.4) 0,
            rgba(0,0,0,.4) 1px,
            transparent 1px,
            transparent 160px
        ),
        /* teinte de couleur du sélecteur, imprimée sur le métal (demande
           explicite, 2e passe : "les barres verticales qui délimitent la
           largeur de chaque section" restaient grises — même traitement
           que .section-sas/.metal-plate-band : base recolorée en quasi-noir
           + couche de couleur remontée à une opacité bien plus haute,
           répartie sur toute la hauteur puisque la coque reste opaque du
           haut en bas, contrairement aux bandes qui s'estompent). */
        linear-gradient(180deg, rgba(var(--header-accent),.6) 0%, rgba(var(--header-accent),.38) 50%, rgba(var(--header-accent),.6) 100%),
        /* base quasi noire pleine : paroi solide, pas de fondu vers la
           transparence comme les bandes haut/bas (la coque reste opaque
           sur toute la hauteur pour rester crédible). */
        linear-gradient(180deg, rgba(26,29,36,.95), rgba(20,22,28,.95));
}

/* Rangée de rivets verticale (miroir de .metal-plate-band::after). */
.rocket-hull-edge::after {
    content: "";
    position: absolute;
    top: 4%;
    bottom: 4%;
    width: 3px;
    background-image: radial-gradient(circle, rgba(0,0,0,.6) 0 1.4px, transparent 1.6px);
    background-size: 3px 44px;
    background-repeat: repeat-y;
    opacity: .85;
}

/* ─── Tremblements (demande explicite : "fait des tremblements uniquement
   sur les parties métalliques") ───
   Micro-vibration façon "réacteur qui tourne", réservée aux éléments
   purement décoratifs (coques latérales, bandeaux de sas, bandes
   métalliques, capsule) — jamais sur le contenu (titres/textes/boutons)
   pour ne pas nuire à la lecture ni à l'accessibilité. steps(1,end) plutôt
   qu'un easing lisse : à-coups discrets façon vibration mécanique, pas un
   mouvement fluide. Déphasage léger par élément (animation-delay négatif)
   pour éviter que tout tremble exactement en même temps, plus organique. */
@keyframes metalRumble {
    0%   { transform: translate(0, 0); }
    20%  { transform: translate(.5px, -.4px); }
    40%  { transform: translate(-.4px, .5px); }
    60%  { transform: translate(.4px, .4px); }
    80%  { transform: translate(-.5px, -.3px); }
    100% { transform: translate(0, 0); }
}

.rocket-hull-edge,
.section-sas,
.metal-plate-band--top,
.metal-plate-band--bottom,
.metal-plate-dome-cap,
.section-curtain {
    animation: metalRumble .22s steps(1, end) infinite;
}
.section-sas          { animation-delay: -.06s; }
.metal-plate-band--top    { animation-delay: -.11s; }
.metal-plate-band--bottom { animation-delay: -.16s; }
.metal-plate-dome-cap  { animation-delay: -.04s; }
.section-curtain       { animation-delay: -.09s; }

/* Flash d'engagement du sas : bref éclat de luminosité sur la coque/le
   bandeau au moment précis de l'ouverture (.section-curtain-open), en plus
   du tremblement continu — renforce la sensation mécanique d'un
   verrou/hublot qui vient de s'actionner. */
@keyframes sasEngageFlash {
    0%   { filter: brightness(1); }
    30%  { filter: brightness(1.4); }
    100% { filter: brightness(1); }
}
.section-curtain-open .section-sas,
.section-curtain-open .rocket-hull-edge {
    animation: metalRumble .22s steps(1, end) infinite, sasEngageFlash .4s ease-out;
}
.section-curtain-open .section-sas { animation-delay: -.06s, 0s; }

/* Contenu réel des 7 sections "dans le vaisseau" masqué tant que la porte
   du sas est fermée (demande explicite) — jusqu'ici seul l'aspect visuel
   du sas (portes/vapeur/hublot) réagissait à .section-curtain-open, le
   contenu réel de la section (titres, textes, cartes...) restait toujours
   visible en dessous, quel que soit l'état de la porte. Ciblé via le
   sibling général après .rocket-hull-edge--right — toujours le dernier
   élément purement décoratif avant le vrai contenu dans ces 7 sections
   (cf. pages/accueil.php) — plutôt qu'une liste d'exclusions, pour rester
   robuste si d'autres éléments décoratifs s'ajoutent avant lui (cf.
   .faq-fuel-immersion sur #faq-preview, placé encore plus tôt). :has()
   scope la règle aux seules sections ayant un .section-curtain, sans
   toucher les autres <section> de la page (hero, why-cta,
   new-hebergement...).
   pointer-events:none tant que fermé évite de pouvoir interagir avec un
   lien/bouton invisible (ex : la carte cliquable de l'étape 1 "De l'idée à
   la mise en orbite"). Délai à l'ouverture (.25s) pour laisser le temps à
   la porte de coulisser avant que le contenu n'apparaisse ; fermeture
   immédiate (pas de délai) pour rester synchrone avec la porte qui se
   referme.
   :not(.metal-plate-band) ajouté (bug réel constaté : "la barre horizontale
   de la dernière section [FAQ]... cachée derrière la porte sas") —
   .metal-plate-band--bottom (bande métallique de fin, cf. #faq-preview dans
   pages/accueil.php) est un sibling après .rocket-hull-edge--right comme
   .container, donc balayé par cette même règle et masqué (opacity:0) tant
   que .section-curtain-open n'est pas posée. Sur une section aussi haute
   que la FAQ, l'utilisateur peut atteindre cette bande (tout en bas) après
   que l'observateur de scroll-reveal ait déjà retiré .section-curtain-open
   (section largement défilée) — elle reste alors invisible, comme le
   #faq-preview ci-dessus le laissait déjà craindre pour .faq-fuel-immersion.
   Purement décorative comme .section-divider (déjà exclu) : ne doit jamais
   dépendre de l'état de la porte. */
section:has(> .section-curtain) > .rocket-hull-edge--right ~ *:not(.section-divider):not(.metal-plate-band) {
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
}
section:has(> .section-curtain).section-curtain-open > .rocket-hull-edge--right ~ *:not(.section-divider):not(.metal-plate-band) {
    opacity: 1;
    pointer-events: auto;
    transition: opacity .5s ease .25s;
}

@media (prefers-reduced-motion: reduce) {
    .rocket-hull-edge,
    .section-sas,
    .metal-plate-band--top,
    .metal-plate-band--bottom,
    .metal-plate-dome-cap,
    .section-curtain,
    .section-curtain-open .section-sas,
    .section-curtain-open .rocket-hull-edge {
        animation: none;
    }
    .section-curtain-panel,
    .section-sas-hatch-spokes {
        transition-duration: .01ms;
    }
    section:has(> .section-curtain) > .rocket-hull-edge--right ~ *:not(.section-divider):not(.metal-plate-band),
    section:has(> .section-curtain).section-curtain-open > .rocket-hull-edge--right ~ *:not(.section-divider):not(.metal-plate-band) {
        transition-duration: .01ms;
    }
}

.rocket-hull-edge--left {
    left: 0;
    box-shadow:
        inset 1px 0 0 rgba(255,255,255,.18),
        inset -1px 0 0 rgba(0,0,0,.35),
        inset 16px 0 22px -18px rgba(0,0,0,.55);
}
.rocket-hull-edge--left::after { right: 6px; }
.rocket-hull-edge--left .rocket-hull-edge-seam { right: 0; }

.rocket-hull-edge--right {
    right: 0;
    box-shadow:
        inset -1px 0 0 rgba(255,255,255,.18),
        inset 1px 0 0 rgba(0,0,0,.35),
        inset -16px 0 22px -18px rgba(0,0,0,.55);
}
.rocket-hull-edge--right::after { left: 6px; }
.rocket-hull-edge--right .rocket-hull-edge-seam { left: 0; }

/* Liseré lumineux vertical (même esprit que .metal-plate-band-seam, tourné
   à 90°) : la "jointure" visible entre la coque et l'intérieur de la
   cabine. */
.rocket-hull-edge-seam {
    position: absolute;
    top: 6%;
    bottom: 6%;
    width: 1px;
    background: linear-gradient(180deg, transparent, rgba(var(--header-accent),.5), transparent);
}

/* ─── Porte de sas : panneaux coulissants + bouffée de vapeur (demande
   explicite : "ouverture de porte en sas + effet vapeur") ───
   .section-curtain est le conteneur (calé sous le bandeau .section-sas,
   pleine hauteur de la section, overflow hidden pour masquer les panneaux
   une fois coulissés hors champ). Les 2 panneaux (--left/--right) recouvrent
   toute la section par défaut (portes fermées) ; l'ajout de la classe d'état
   .section-curtain-open (posée en JS au déclenchement du scroll-reveal de
   la section) les fait coulisser à ±100% (portes ouvertes) et déclenche les
   3 bouffées de vapeur (haut/centre/bas) en même temps que la rotation du
   volant de hublot (.section-sas-hatch-spokes, cf. plus bas). */
.section-curtain {
    position: absolute;
    top: clamp(64px, 8vh, 96px);
    right: 0;
    bottom: 0;
    left: 0;
    /* Sous .rocket-hull-edge (z-index:1) : les bords de coque restent
       toujours visibles, la porte coulisse "entre" eux plutôt que de les
       recouvrir (physiquement plus cohérent) — z-index adapté par rapport
       à la valeur de référence (4/5) pour rester cohérent avec la valeur
       actuelle de .rocket-hull-edge/.section-sas sur ce fichier (1/2). */
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
}
.section-curtain-panel {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 50%;
    pointer-events: none;
    transition: transform .22s ease;
    background:
        linear-gradient(115deg,
            transparent 30%,
            rgba(255,255,255,.08) 45%,
            rgba(255,255,255,.16) 50%,
            rgba(255,255,255,.08) 55%,
            transparent 70%
        ),
        repeating-linear-gradient(90deg,
            rgba(255,255,255,.055) 0px,
            rgba(255,255,255,.055) 1px,
            rgba(0,0,0,.32) 1px,
            rgba(0,0,0,.32) 2px,
            transparent 2px,
            transparent 11px
        ),
        radial-gradient(circle, rgba(0,0,0,.55) 0 1.3px, transparent 1.5px),
        linear-gradient(180deg, rgba(var(--header-accent),.5) 0%, rgba(var(--header-accent),.26) 50%, rgba(var(--header-accent),.5) 100%),
        linear-gradient(180deg, rgba(22,25,31,.97), rgba(16,18,23,.97));
    background-size: auto, auto, 26px 26px, auto, auto;
    background-repeat: no-repeat, repeat, repeat, no-repeat, no-repeat;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.14),
        inset 0 -1px 0 rgba(0,0,0,.4),
        inset 0 0 46px rgba(0,0,0,.35),
        0 10px 26px -12px rgba(0,0,0,.65);
}
.section-curtain-panel--left  { left: 0; }
.section-curtain-panel--right { right: 0; }

/* Liseré lumineux vertical au bord intérieur de chaque panneau. */
.section-curtain-panel--left::after,
.section-curtain-panel--right::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background: linear-gradient(180deg, transparent, rgba(var(--header-accent),.55), transparent);
    opacity: .85;
}
.section-curtain-panel--left::after  { right: 0; box-shadow: inset -6px 0 10px -6px rgba(0,0,0,.6); }
.section-curtain-panel--right::after { left: 0;  box-shadow: inset 6px 0 10px -6px rgba(0,0,0,.6); }

/* Chevrons diagonaux de marquage, estompés vers le centre du panneau (même
   esprit que .section-sas::before/::after). */
.section-curtain-panel--left::before,
.section-curtain-panel--right::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: clamp(22px, 3vw, 36px);
    background: repeating-linear-gradient(135deg,
        rgba(var(--header-accent),.3) 0px,
        rgba(var(--header-accent),.3) 6px,
        rgba(10,12,16,.5) 6px,
        rgba(10,12,16,.5) 14px
    );
    opacity: .5;
}
.section-curtain-panel--left::before {
    right: 2px;
    -webkit-mask-image: linear-gradient(270deg, rgba(0,0,0,.9), transparent);
            mask-image: linear-gradient(270deg, rgba(0,0,0,.9), transparent);
}
.section-curtain-panel--right::before {
    left: 2px;
    -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,.9), transparent);
            mask-image: linear-gradient(90deg, rgba(0,0,0,.9), transparent);
}

/* État ouvert : les 2 panneaux coulissent hors champ, chacun de son côté. */
.section-curtain-open .section-curtain-panel--left  { transform: translateX(-100%); }
.section-curtain-open .section-curtain-panel--right { transform: translateX(100%); }

/* Bouffées de vapeur (haut/centre/bas), invisibles au repos, déclenchées
   uniquement à l'ouverture via .section-curtain-open (animation one-shot,
   pas de boucle infinie). */
.section-curtain-vapor {
    position: absolute;
    left: 50%;
    width: 140px;
    height: 140px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255,255,255,.72) 0%, rgba(255,255,255,.32) 45%, transparent 74%);
    filter: blur(5px);
    opacity: 0;
    pointer-events: none;
}
.section-curtain-vapor--center {
    top: 50%;
    transform: translate(-50%, -50%) scale(.35);
}
.section-curtain-vapor--top,
.section-curtain-vapor--bottom {
    width: 95px;
    height: 95px;
    background: radial-gradient(circle, rgba(255,255,255,.5) 0%, rgba(255,255,255,.2) 45%, transparent 74%);
}
.section-curtain-vapor--top {
    top: clamp(40px, 12vh, 100px);
    transform: translate(-50%, -50%) scale(.35);
}
.section-curtain-vapor--bottom {
    bottom: clamp(24px, 6vh, 60px);
    transform: translate(-50%, 50%) scale(.35);
}
@keyframes vaporPuff {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(.3); }
    22%  { opacity: .95; }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.9); }
}
@keyframes vaporPuffSubtleTop {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(.3); }
    22%  { opacity: .5; }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.7); }
}
@keyframes vaporPuffSubtleBottom {
    0%   { opacity: 0; transform: translate(-50%, 50%) scale(.3); }
    22%  { opacity: .5; }
    100% { opacity: 0; transform: translate(-50%, 50%) scale(1.7); }
}
.section-curtain-open .section-curtain-vapor--center { animation: vaporPuff .75s ease-out; }
.section-curtain-open .section-curtain-vapor--top    { animation: vaporPuffSubtleTop .75s ease-out; }
.section-curtain-open .section-curtain-vapor--bottom { animation: vaporPuffSubtleBottom .75s ease-out; }

/* ─── SAS entre les sections intérieures de la fusée (demande explicite :
   "enlève les barres métalliques... enfin non, enlève le visuel tunnel sur
   les dividers, cela ne correspond pas à ma demande. Je veux un visuel en
   haut de chaque section intérieure pour donner l'impression de sas
   différents, là il n'y a que des bg différents") ───
   Remplace l'effet "tunnel" (anneaux concentriques posés sur les dividers
   ENTRE les sections, .tunnel-divider — supprimé) par un vrai marqueur de
   seuil posé EN HAUT de chaque section "dans le vaisseau" elle-même (7 au
   total : #method-heading -> #faq-preview) : bandeau métallique (même
   texture brossée/rivetée que .metal-plate-band) surmonté d'un volant de
   hublot de sas (cercle façon valve/porte étanche) à cheval sur son bord
   bas, comme un vrai sas de vaisseau qu'on vient de refermer derrière soi.
   position:absolute + top:0 (pas de dépendance à l'ordre flex ni au
   justify-content de la section, contrairement à .metal-plate-band--top) :
   fonctionne uniformément sur les 7 sections quelle que soit leur mise en
   page interne. Se loge dans le padding-top déjà réservé par chaque
   section (hérité de l'ancienne bande métallique). Purement décoratif
   (aria-hidden), pointer-events:none. */
.section-sas {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2;
    height: clamp(64px, 8vh, 96px);
    pointer-events: none;
    background:
        linear-gradient(115deg,
            transparent 30%,
            rgba(255,255,255,.07) 45%,
            rgba(255,255,255,.15) 50%,
            rgba(255,255,255,.07) 55%,
            transparent 70%
        ),
        repeating-linear-gradient(180deg,
            rgba(255,255,255,.045) 0,
            rgba(255,255,255,.045) 1px,
            transparent 1px,
            transparent 3px
        ),
        repeating-linear-gradient(90deg,
            rgba(0,0,0,.4) 0,
            rgba(0,0,0,.4) 1px,
            transparent 1px,
            transparent 180px
        ),
        /* teinte de couleur du sélecteur, imprimée sur le métal (demande
           explicite, 2e passe : "le gris" restait dominant malgré le 1er
           réglage — la base "métal" ci-dessous n'est plus un gris neutre
           mais un fond quasi noir, et la couche de couleur passe à une
           opacité bien plus haute en haut du bandeau (.85) pour que la
           teinte du thème soit la couleur qui domine vraiment, pas un
           simple reflet sur du gris) — placée AU-DESSUS de la base (1er
           listé = 1er peint dessus en CSS multi-background). */
        linear-gradient(180deg,
            rgba(var(--header-accent),.85) 0%,
            rgba(var(--header-accent),.55) 45%,
            rgba(var(--header-accent),.15) 80%,
            transparent 100%
        ),
        linear-gradient(180deg,
            rgba(30,34,42,.95) 0%,
            rgba(24,27,34,.85) 55%,
            rgba(20,22,28,0) 100%
        );
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.22),
        inset 0 -1px 0 rgba(var(--header-accent),.75),
        inset 0 -16px 26px -18px rgba(0,0,0,.65);
}

/* Bandes de marquage "danger/sas" aux 2 extrémités du bandeau (chevrons
   diagonaux, très estompés vers le centre) : renforce la lecture "porte de
   sas" sans verser dans le cartoon/industriel criard. */
.section-sas::before,
.section-sas::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: clamp(28px, 4vw, 46px);
    background: repeating-linear-gradient(135deg,
        rgba(var(--header-accent),.35) 0px,
        rgba(var(--header-accent),.35) 6px,
        rgba(10,12,16,.5) 6px,
        rgba(10,12,16,.5) 14px
    );
    opacity: .55;
    -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,.9), transparent);
            mask-image: linear-gradient(90deg, rgba(0,0,0,.9), transparent);
}
.section-sas::before { left: 0; }
.section-sas::after  {
    right: 0;
    -webkit-mask-image: linear-gradient(270deg, rgba(0,0,0,.9), transparent);
            mask-image: linear-gradient(270deg, rgba(0,0,0,.9), transparent);
}

/* Liseré lumineux horizontal, même esprit que .metal-plate-band-seam. */
.section-sas-seam {
    position: absolute;
    left: 8%;
    right: 8%;
    bottom: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.5), transparent);
}

/* Volant de hublot du sas : à cheval sur le bord bas du bandeau (moitié
   dans le bandeau, moitié dans la section) — lecture "porte qu'on vient de
   franchir/refermer". */
.section-sas-hatch {
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translate(-50%, 50%);
    width: clamp(34px, 4.4vw, 52px);
    height: clamp(34px, 4.4vw, 52px);
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, rgba(255,255,255,.28), rgba(60,66,78,.98) 45%, rgba(30,34,42,.98) 100%);
    box-shadow:
        0 0 0 3px rgba(20,23,29,.9),
        0 0 0 4px rgba(var(--header-accent),.45),
        inset 0 2px 3px rgba(255,255,255,.25),
        inset 0 -3px 5px rgba(0,0,0,.5),
        0 4px 10px rgba(0,0,0,.5);
}

/* Croix de rayons (façon volant de porte étanche) + noyau lumineux central. */
.section-sas-hatch-spokes {
    position: absolute;
    inset: 22%;
    border-radius: 50%;
    background:
        linear-gradient(rgba(15,17,22,.9), rgba(15,17,22,.9)) center / 100% 16% no-repeat,
        linear-gradient(rgba(15,17,22,.9), rgba(15,17,22,.9)) center / 16% 100% no-repeat;
    transition: transform .22s ease;
}
/* Rotation du volant type "écrou de porte étanche" à l'ouverture (demande
   explicite : "animation de ecrou qui tourne"). */
.section-curtain-open .section-sas-hatch-spokes {
    transform: rotate(45deg);
}
/* Voyant central : rouge = verrouillé (repos), vire au vert = déverrouillé
   dès l'ouverture (.section-curtain-open) — même logique de code couleur
   qu'un vrai sas. */
.section-sas-hatch-spokes::before {
    content: "";
    position: absolute;
    inset: 30%;
    border-radius: 50%;
    background: rgba(255,64,48,.85);
    box-shadow: 0 0 6px rgba(255,64,48,.75);
    transition: background-color .3s ease, box-shadow .3s ease;
}
.section-curtain-open .section-sas-hatch-spokes::before {
    background: rgba(52,220,120,.9);
    box-shadow: 0 0 7px rgba(52,220,120,.8);
}

/* ─── Capsule/cockpit du sommet de la fusée, HORS section (demande
   explicite, 2e correction) ───
   1ère version : border-radius direct sur .metal-plate-band--top (ne
   faisait que creuser un arc À L'INTÉRIEUR de sa propre boîte). 2e
   version : élément à part mais encore enfant de #method-heading, insets
   left/right 12% (pas pleine largeur) et positionné par un top négatif
   relatif à la section (fonctionnait, mais restait structurellement
   "dans" #method-heading). Demande explicite suivante : "la capsule doit
   faire toute la largeur et être hors section. Ajoute un margin bottom à
   la section d'avant pour lui laisser la place." — cette 3e version pose
   le dôme dans un wrapper à PART (.capsule-dome-wrap, hauteur nulle, cf.
   accueil.php), placé entre .hero et #method-heading dans le markup
   (même principe que .rocket-engine-flames-wrap plus bas) : le dôme n'est
   plus enfant d'AUCUNE section. .hero a maintenant un margin-bottom (cf.
   règle .hero plus haut) de la même hauteur que ce dôme, qui lui réserve
   la place — le dôme, ancré par bottom:0 sur le point zéro du wrapper,
   remonte exactement dans cet espace réservé, sans jamais chevaucher ni
   le hero ni #method-heading. left:0/right:0 (au lieu de 12%) : pleine
   largeur, demande explicite.
   4e version (demande explicite : "réduire la largeur des sections 10%
   environ de chaque côté... il faut adapter la capsule en conséquence") :
   les 7 sections "dans le vaisseau" (#method-heading -> #faq-preview) sont
   désormais réduites à 80% de largeur (10% de marge de chaque côté, cf.
   règles de ces sections plus bas) pour donner l'impression que la fusée
   flotte réellement dans l'espace. Le dôme n'étant PAS enfant d'une
   section (cf. plus haut), il doit suivre cette largeur explicitement :
   left:10%/right:10% au lieu de 0/0, pour rester aligné avec le haut de
   la coque désormais plus étroite juste en dessous. */
.capsule-dome-wrap {
    position: relative;
    height: 0;
    z-index: 3;
    pointer-events: none;
}

.metal-plate-dome-cap {
    position: absolute;
    /* 5% de chaque côté (au lieu de 10%) : demande explicite "passe la
       largeur de la fusée à 90%" — reste synchronisé avec les 7 sections
       "dans le vaisseau" (width:90% désormais, cf. .method et suivantes). */
    left: 5%;
    right: 5%;
    bottom: 0;
    /* Hauteur encore augmentée (2e demande explicite "augmente encore la
       hauteur de la capsule") : une vraie capsule/cockpit de fusée est
       nettement plus haute que large à l'arc. Doit rester synchronisée
       avec le margin-bottom de .hero plus haut (même clamp), qui réserve
       exactement cet espace. */
    height: clamp(240px, 28vh, 360px);
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    pointer-events: none;
    background:
        /* teinte de couleur du sélecteur, imprimée sur le métal (2e passe :
           le gris restait dominant — base recolorée en quasi-noir + couche
           de couleur remontée à .8 en haut, même traitement que
           .section-sas/.metal-plate-band) */
        linear-gradient(180deg,
            rgba(var(--header-accent),.8) 0%,
            rgba(var(--header-accent),.5) 45%,
            rgba(var(--header-accent),.15) 80%,
            transparent 100%
        ),
        linear-gradient(180deg,
        rgba(32,36,44,.97) 0%,
        rgba(26,29,36,.97) 60%,
        rgba(20,22,28,.97) 100%
    );
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.22),
        inset 0 -1px 0 rgba(var(--header-accent),.75),
        0 -12px 28px -10px rgba(0,0,0,.55);
}

/* Logo CroisierWeb intégré au centre de la capsule (demande explicite :
   "y intégrer le logo CroisierWeb en plein centre de la couleur
   sélectionnée dans le sélecteur de couleur") — même fichier
   $_logoFileNoir que le footer/index.php/services.php (cf. accueil.php),
   qui suit déjà automatiquement la couleur choisie en Mon profil. Ancré
   dans le tiers bas du dôme plutôt qu'au centre géométrique de la boîte :
   la forme (border-radius 50% 50% 0 0 / 100% 100%) est un arc qui se
   resserre vers le haut, seul le bas reste pleine largeur/pleine
   "épaisseur" visuelle — y centrer le logo évite qu'il ne soit à cheval
   sur la partie la plus fine de la courbe. */
.metal-plate-dome-cap-logo {
    position: absolute;
    left: 50%;
    bottom: 14%;
    transform: translateX(-50%);
    height: clamp(32px, 5vw, 58px);
    width: auto;
    object-fit: contain;
    filter: drop-shadow(0 0 12px rgba(var(--header-accent),.6));
    pointer-events: none;
}

/* ─── Flammes des réacteurs, HORS de #why-target (demande explicite : "la
   fusée va vers le haut donc les flammes sont en bas", puis "mets les
   flammes en dessous de la section (hors section)") ───
   .why-target a overflow:hidden (comme la plupart des sections de cette
   page, pour contenir ses dégradés de fond) : tout élément qui dépasserait
   sous son bord bas y serait rogné, invisible. Les flammes sont donc
   posées dans un wrapper à PART, entre les 2 sections dans le markup (cf.
   accueil.php), pas comme enfant de #why-target ni de #why-cta — aucun des
   deux ne peut les rogner. Le wrapper est de hauteur nulle (ne pousse
   aucun contenu, ne change rien à l'espacement existant entre les 2
   sections) : les flammes sont positionnées en absolute à partir de ce
   point zéro, uniquement VERS LE BAS (donc bien "hors" et "en dessous" de
   #why-target). 3 grandes flammes côte à côte, remplissant au moins 60% de
   la largeur (demande explicite), centrées, hauteur au moins 20-30dvh
   (demande explicite, clamp pour rester raisonnable sur les très petits/
   grands écrans). Base large/opaque en HAUT (juste sous la coque, la
   "source") qui s'estompe vers la transparence en descendant (la pointe de
   la flamme, la plus loin du réacteur). */
.rocket-engine-flames-wrap {
    position: relative;
    height: 0;
    z-index: 3;
    pointer-events: none;
}

.rocket-engine-flames {
    position: absolute;
    left: 50%;
    top: 0;
    transform: translateX(-50%);
    width: min(78%, 980px);
    height: clamp(220px, 28dvh, 380px);
    display: flex;
    justify-content: center;
    align-items: flex-start;
    gap: clamp(14px, 3vw, 42px);
    pointer-events: none;
}

/* Demande explicite (3e passe) : "regarde celles présentes dans 3
   trajectoires [.rocketv-flame, la petite fusée de la vignette offres],
   elles sont top, il faut juste les agrandir" — abandon du rendu "gazeux"
   (dégradé radial diffus + noyau qui dérive) de la 2e passe, remplacé par
   EXACTEMENT la même recette que .rocketv-flame (cf. plus bas dans ce
   fichier : dégradé linéaire jaune->orange->rouge->transparent, bord
   arrondi seulement à une extrémité, flicker rapide par scaleX/scaleY),
   simplement mise à l'échelle pour occuper toute la hauteur/largeur de
   .rocket-engine-flames. Sens conservé de la 2e passe ("pointe en haut
   près de la coque, base large en bas") : le dégradé va donc du clair en
   BAS vers transparent en HAUT (inverse de .rocketv-flame, qui pointe vers
   le bas), et seuls les 2 coins du HAUT sont arrondis. 3 largeurs
   étagées (30/36/30%) comme les 3 .rocketv-flame (a/b/c), la centrale
   étant la plus grande/la plus haute. */
/* demande explicite (4e passe) : "un effet plus réaliste des flammes et
   [...] en fonction de la couleur sélectionnée" — 2 changements par
   rapport à la version précédente (dégradé jaune->orange->rouge fixe,
   identique pour tout le monde) :
   1. Réalisme : noyau blanc quasi-opaque tout en bas (le point le plus
      chaud d'une vraie flamme, juste à la sortie de la tuyère) au lieu de
      démarrer directement sur du jaune ; dégradé à 5 arrêts (blanc -> jaune
      -> orange -> rouge braise -> panache) au lieu de 3 pour une
      transition plus progressive/organique ; flicker à plusieurs paliers
      (scaleX/scaleY ET léger translateX, cf. keyframes plus bas) au lieu
      d'un simple aller-retour from/to, pour un tremblement moins
      mécanique/plus vivant.
   2. Couleur sélectionnée : le panache (pointe la plus froide/éloignée de
      la coque) n'est plus rouge fixe mais rgba(var(--header-accent)) — la
      base reste blanc/jaune/orange (couleurs de combustion réelles,
      indépendantes du thème) pour rester lisible comme "flamme", seule la
      partie la plus diffuse se teinte de la couleur du sélecteur, comme le
      reste des éléments lumineux du site (halos, coque, bande réacteur
      juste au-dessus). Lueur (box-shadow) elle aussi accent-aware. */
/* demande explicite (5e passe) : "l'intégralité de la flamme, pas un
   ajout" — la version précédente ne teintait que les tout derniers % (la
   pointe) en rgba(var(--header-accent)), le jaune/orange/rouge fixe restait
   dominant sur l'essentiel de la flamme. Désormais le corps ENTIER de la
   flamme est construit à partir de rgba(var(--header-accent)) à
   différentes opacités (dense à la base, se dilue vers la pointe) ; seul
   un tout petit noyau quasi-blanc subsiste tout en bas (le point de
   combustion le plus chaud, juste à la sortie de la tuyère — réalisme
   thermique, pas une couleur "fixe" distincte de l'accent). Le flou (cf.
   filter) reste identique à la passe précédente, jugé réussi. 2 couches :
   le noyau blanc (1ère, au-dessus) + le corps accent (2e, dessous). */
.rocket-engine-flame {
    flex: 0 0 27%;
    max-width: 320px;
    height: 76%;
    align-self: flex-start;
    display: block;
    border-radius: 50% 50% 0 0;
    background-image:
        linear-gradient(to top, rgba(255,255,255,.9) 0%, transparent 16%),
        linear-gradient(to top,
            rgba(var(--header-accent),.95) 0%,
            rgba(var(--header-accent),.8) 34%,
            rgba(var(--header-accent),.55) 62%,
            rgba(var(--header-accent),.25) 84%,
            transparent 100%
        );
    filter: blur(14px) saturate(1.15);
    transform-origin: center top;
    animation: rocketEngineFlameFlicker .3s ease-in-out infinite alternate;
    box-shadow: 0 0 46px 6px rgba(var(--header-accent),.3);
}

.rocket-engine-flame:nth-child(2) {
    flex-basis: 32%;
    max-width: 380px;
    height: 100%;
    filter: blur(18px) saturate(1.15);
    background-image:
        linear-gradient(to top, rgba(255,255,255,.9) 0%, transparent 14%),
        linear-gradient(to top,
            rgba(var(--header-accent),.98) 0%,
            rgba(var(--header-accent),.84) 32%,
            rgba(var(--header-accent),.58) 60%,
            rgba(var(--header-accent),.28) 82%,
            transparent 100%
        );
    animation-duration: .42s;
    animation-direction: alternate-reverse;
    box-shadow: 0 0 64px 10px rgba(var(--header-accent),.34);
}
.rocket-engine-flame:nth-child(3) {
    animation-duration: .36s;
}

@keyframes rocketEngineFlameFlicker {
    0%   { transform: scaleX(1)    scaleY(1)   translateX(0); }
    28%  { transform: scaleX(.88)  scaleY(.92) translateX(-2.5%); }
    52%  { transform: scaleX(1.05) scaleY(.86) translateX(2%); }
    76%  { transform: scaleX(.82)  scaleY(.9)  translateX(-1.5%); }
    100% { transform: scaleX(.72)  scaleY(.78) translateX(1%); }
}

@media (prefers-reduced-motion: reduce) {
    .rocket-engine-flame { animation: none; }
}

/* ─── INNER ROW ─── */

.sol-off-inner {
    flex: 1;
    min-height: 0;
    max-width: 1200px;
    width: 100%;
    margin: 0 auto;
    padding: clamp(1rem, 2vh, 2rem) clamp(1rem, 3vw, 2rem);
    display: flex;
    /* flex-end -> center (retour arrière, demande explicite : "le titre et
       le bouton ne sont pas au centre de la section") : flex-end collait
       tout le rang (titre+bouton ET fusée) en bas de .sol-off-inner — avec
       une colonne fusée bien plus haute que la colonne titre/bouton, le
       titre se retrouvait pincé tout en bas au lieu d'être centré, ET la
       fusée, elle aussi ancrée par le bas, débordait par le HAUT dans la
       bande .section-sas plutôt que d'avoir de la marge des deux côtés.
       Retour à center : répartit l'espace de façon symétrique, corrige les
       deux problèmes à la fois. */
    align-items: center;
    gap: 120px;
    position: relative;
    z-index: 1;
}

/* ─── DIVIDER BAS ───
   L'espacement (min-height, margin, padding) est désormais géré une seule
   fois pour les 8 dividers de la page par .site-main .section-divider,
   plus bas dans ce fichier — on ne garde ici que ce qui est propre à cette
   section (flex-shrink dans le layout flex du hero, z-index). */
.sol-off .section-divider {
    flex-shrink: 0;
    position: relative;
    z-index: 1;
}

/* ─── CONTENU GAUCHE ─── */

.sol-off-content {
    flex: 1;
    min-width: 0;
    text-align: center;
    /* Centrage vertical propre à cette colonne (demande explicite : "remets
       le titre et son bouton au centre de sa colonne") : .sol-off-inner
       (le parent, flex row) a désormais align-items:flex-end (demande
       précédente, "réduit l'écart avec le divider") — sans ce centrage
       local, le titre+bouton, bien plus courts que la colonne fusée
       voisine, se retrouvaient collés en bas au lieu d'être centrés dans
       LEUR propre colonne. display:flex column + justify-content:center
       rend ce centrage indépendant de l'alignement choisi sur le parent. */
    display: flex;
    flex-direction: column;
    justify-content: center;
}


.sol-off-content h2 {
    font-size: clamp(1.4rem, 2vw, 2rem);
    /* Réduit de 120px fixe (démesuré, gonflait inutilement la hauteur totale
       du contenu et empêchait le centrage vertical de .sol-off-inner de
       vraiment se voir) à un clamp raisonnable — demande explicite :
       "réduire la taille sans supprimer de contenu". */
    margin-bottom: clamp(28px, 4vh, 48px);
}

.sol-off-offers-title {
    margin-top: clamp(20px, 3vh, 48px);
    margin-bottom: clamp(14px, 2vh, 28px);
}

.sol-off-content p {
    color: var(--brand-color);
    font-weight: 500;
    text-shadow: 0 0 10px rgba(var(--header-accent),.25);
    margin-bottom: 10px;
    line-height: 1.6;
    font-size: clamp(.85rem, 1vw, 1rem);
    
}

.btn-sol-off {
    display: inline-block;
    margin-top: 8px;
    padding: 12px 40px;
    background: rgba(var(--header-accent),.12);
    border: 1px solid rgba(var(--header-accent),.30);
    border-radius: 14px;
    color: #ffffff;
    font-weight: 600;
    font-size: 1rem;
    text-decoration: none;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 0 20px rgba(var(--header-accent),.06), inset 0 1px 0 rgba(255,255,255,.06);
    transition: background .25s ease, box-shadow .25s ease, transform .25s ease;
}

.btn-sol-off:hover {
    background: rgba(var(--header-accent),.2);
    box-shadow: 0 10px 30px rgba(var(--header-accent),.25);
    transform: translateY(-2px);
}

/* ─── GRILLE FUSÉE + PRICING ─── */

.sol-off-rocket-area {
    display: grid;
    grid-template-columns: 310px 170px;
    /* Plafonds vh réduits (demande explicite : "la fusée déborde dans la
       barre métallique", #solution est maintenant en height:100dvh fixe +
       overflow:hidden, cf. .sol-off) : les anciennes valeurs (12/15/15/15vh)
       laissaient trop peu de marge une fois padding-top + bande .section-sas
       + divider soustraits d'un écran plein — la fusée poussait alors sa
       propre section vers le haut, hors de la zone réservée. Valeurs plus
       basses, mêmes planchers px (inchangés pour rester lisible sur petit
       écran). */
    grid-template-rows:
        clamp(80px,  9vh, 110px)   /* nose */
        clamp(130px, 13vh, 210px)  /* sas 1 */
        clamp(130px, 13vh, 210px)  /* sas 2 */
        clamp(130px, 13vh, 210px)  /* sas 3 */
        auto;                        /* queue + flammes */
    flex-shrink: 0;
}

/* ========================= FUSÉE VERTICALE ========================= */

.rocketv-wrapper {
    grid-column: 1;
    grid-row: 1 / 6;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    position: relative;
    filter: drop-shadow(0 0 40px rgba(var(--header-accent),.12));
}

/* --- NOSE --- */

.rocketv-nose {
    position: relative;
    /* Doit rester synchronisé avec la 1ère valeur de grid-template-rows sur
       .sol-off-rocket-area (même clamp) : la colonne pricing (grid-row:1
       pour .pricing-spacer) suit la grille, mais .rocketv-wrapper (spans
       "1 / 6") est un flex column dont les enfants (nez, 3 sas, queue) se
       dimensionnent EUX-MÊMES via leur propre flex-basis — sans cette
       synchro, nez/sas ne s'alignent plus avec les cartes de prix en face,
       et la fusée peut déborder de la zone grid réduite. */
    height: clamp(80px, 9vh, 110px);
    flex-shrink: 0;
    overflow: hidden;
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    border-left: 2px solid rgba(0,0,0,.55);
    border-right: 2px solid rgba(0,0,0,.55);
    background:
        /* teinte de couleur du sélecteur au centre du nez (demande explicite
           "adapte la fusée à la couleur"), remplace l'ancien bleu marine fixe */
        linear-gradient(90deg,
            transparent 0%,
            transparent 18%,
            rgba(var(--header-accent),.55) 40%,
            rgba(var(--header-accent),.55) 60%,
            transparent 82%,
            transparent 100%
        ),
        linear-gradient(90deg,
            rgba(0,0,0,.72) 0%,
            rgba(0,0,0,.12) 18%,
            rgba(10,12,18,.9) 40%,
            rgba(10,12,18,.9) 60%,
            rgba(0,0,0,.12) 82%,
            rgba(0,0,0,.72) 100%
        ),
        linear-gradient(180deg, rgba(var(--header-accent),.5) 0%, rgba(8,10,16,.95) 100%);
}

.rocketv-nose-highlight {
    position: absolute;
    top: 14%;
    left: 50%;
    transform: translateX(-50%);
    width: 22%;
    height: 42%;
    background: radial-gradient(ellipse, rgba(255,255,255,.09) 0%, transparent 70%);
    border-radius: 50%;
    pointer-events: none;
}

.rocketv-nose-window {
    position: absolute;
    bottom: 20%;
    left: 50%;
    transform: translateX(-50%);
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(var(--header-accent),.18) 0%, rgba(0,0,0,.6) 100%);
    border: 2px solid rgba(var(--header-accent),.35);
    box-shadow: 0 0 18px rgba(var(--header-accent),.28), inset 0 0 10px rgba(0,0,0,.7);
    animation: noseWindowGlow 4s ease-in-out infinite;
}

.rocketv-nose-window::before {
    content: "";
    position: absolute;
    top: 18%;
    left: 18%;
    width: 30%;
    height: 30%;
    border-radius: 50%;
    background: rgba(255,255,255,.12);
}

@keyframes noseWindowGlow {
    0%, 100% { box-shadow: 0 0 14px rgba(var(--header-accent),.25), inset 0 0 10px rgba(0,0,0,.7); }
    50%       { box-shadow: 0 0 28px rgba(var(--header-accent),.55), inset 0 0 10px rgba(0,0,0,.5); }
}

.rocketv-nose-seam {
    position: absolute;
    bottom: 0;
    left: 4%;
    right: 4%;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(255,255,255,.18), transparent);
}

/* --- SAS COULEURS + HAUTEURS --- */

/* ─── Couleurs des 3 "sas" (Essentiel/Business/Premium) : demande explicite
   (2e passe) "essaie avec les mêmes teintes pour Essentiel et Premium, et
   une teinte néon (de la couleur PRINCIPALE) pour Business". Essentiel ET
   Premium partagent désormais la même teinte "mid" (= --accent-harmony-2,
   la couleur secondaire telle quelle) ; Business utilise "neon" (désormais
   une version éclaircie/boostée de --header-accent, la couleur PRINCIPALE,
   cf. .accent-* tout en haut du fichier pour le détail du calcul). Défaut
   bleu pour accueil.php via $_header_accent_map (partials/header.php). ─── */
.rocketv-sas--1 {
    --sv-color: rgb(var(--offer-tint-mid));
    --sv-soft:  rgba(var(--offer-tint-mid),.14);
    --sv-glow:  rgba(var(--offer-tint-mid),.32);

    height: 180px;
}

.rocketv-sas--2 {
    --sv-color: rgb(var(--offer-tint-neon));
    --sv-soft:  rgba(var(--offer-tint-neon),.14);
    --sv-glow:  rgba(var(--offer-tint-neon),.32);

    height: 180px;
}

.rocketv-sas--3 {
    --sv-color: rgb(var(--offer-tint-mid));
    --sv-soft:  rgba(var(--offer-tint-mid),.14);
    --sv-glow:  rgba(var(--offer-tint-mid),.32);

    height: 180px;
}

/* --- SAS BASE --- */

.rocketv-sas {
    display: flex;
    flex-direction: row;
    align-items: center;
    /* Synchronisé avec les 3 lignes "sas" de grid-template-rows sur
       .sol-off-rocket-area, cf. .rocketv-nose plus haut pour le détail.
       Remonté de 190px à 210px max / 100px à 130px min (bug réel constaté :
       "on ne peut plus voir le texte en entier" — au survol, la description
       .rocketv-sas-body p se révèle (opacity/max-height) mais la ligne
       min-height:0 ci-dessous empêche désormais la ligne de grandir toute
       seule pour l'accueillir ; il faut donc que le gabarit fixe soit assez
       grand dès le départ pour la contenir en entier, sans quoi elle serait
       simplement rognée par overflow:hidden). */
    flex: 0 0 clamp(130px, 13vh, 210px);
    /* Empêche la taille automatique du contenu (titre + description révélée
       au survol) de faire grandir la ligne au-delà de son flex-basis fixe
       ci-dessus — bug réel constaté : sans ça, la description qui apparaît
       au survol repoussait la ligne suivante et chevauchait "Express",
       cachant même le titre "Business". Avec min-height:0, tout ce qui ne
       tient pas est proprement rogné par overflow:hidden plutôt que de
       déborder sur les voisins. */
    min-height: 0;
    gap: 16px;
    padding: clamp(14px, 2vh, 26px) 20px;
    text-decoration: none;
    color: inherit;
    position: relative;
    overflow: hidden;
    transition: filter .3s ease;
    background:
        /* teinte de couleur du sélecteur sur le fuselage (miroir de
           .rocketv-nose/.rocketv-tail), demande explicite "adapte la
           fusée à la couleur" */
        linear-gradient(90deg,
            transparent 0%,
            transparent 16%,
            rgba(var(--header-accent),.28) 34%,
            rgba(var(--header-accent),.28) 66%,
            transparent 84%,
            transparent 100%
        ),
        linear-gradient(90deg,
            rgba(0,0,0,.62) 0%,
            rgba(0,0,0,.08) 16%,
            rgba(8,10,16,.85) 34%,
            rgba(8,10,16,.85) 66%,
            rgba(0,0,0,.08) 84%,
            rgba(0,0,0,.62) 100%
        );
    border-left:   2px solid rgba(0,0,0,.55);
    border-right:  2px solid rgba(0,0,0,.55);
    border-top:    2px solid rgba(255,255,255,.13);
    border-bottom: 2px solid rgba(255,255,255,.04);
    box-shadow: inset 0 0 32px rgba(0,0,0,.28);
}

.rocketv-sas::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(255,255,255,.012) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.012) 1px, transparent 1px);
    background-size: 22px 22px;
    pointer-events: none;
}

.rocketv-sas::after {
    content: "";
    position: absolute;
    right: 0;
    top: 12%;
    bottom: 12%;
    width: 2px;
    background: linear-gradient(to bottom, transparent, var(--sv-color), transparent);
    opacity: 0;
    transition: opacity .3s ease;
}

.rocketv-sas:hover { filter: brightness(1.14); }
.rocketv-sas:hover::after { opacity: 1; }

/* Featured */

.rocketv-sas--featured {
    background:
        /* teinte "néon" de la ligne mise en avant, suit --offer-tint-neon
           (déjà dynamique par couleur sélectionnée) au lieu du bleu marine
           fixe précédent */
        linear-gradient(90deg,
            transparent 0%,
            transparent 16%,
            rgba(var(--offer-tint-neon),.22) 34%,
            rgba(var(--offer-tint-neon),.22) 66%,
            transparent 84%,
            transparent 100%
        ),
        linear-gradient(90deg,
            rgba(0,0,0,.62) 0%,
            rgba(0,0,0,.06) 16%,
            rgba(8,10,16,.88) 34%,
            rgba(8,10,16,.88) 66%,
            rgba(0,0,0,.06) 84%,
            rgba(0,0,0,.62) 100%
        );
    /* Teinte "néon" de la couleur secondaire (--offer-tint-neon, cf. règle
       .rocketv-sas--2 plus haut) — remplace l'orange fixe posé au tour
       précédent, désormais dynamique par couleur sélectionnée. */
    border-top-color:    rgba(var(--offer-tint-neon),.35);
    border-bottom-color: rgba(var(--offer-tint-neon),.18);
    box-shadow:
        inset 0 0 32px rgba(0,0,0,.28),
        -6px 0 28px rgba(var(--offer-tint-neon),.06),
         6px 0 28px rgba(var(--offer-tint-neon),.06);
}

/* --- PORTHOLE --- */

.rocketv-porthole {
    width: clamp(36px, 4.5vw, 52px);
    height: clamp(36px, 4.5vw, 52px);
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--sv-soft);
    border: 2px solid var(--sv-color);
    box-shadow: 0 0 20px var(--sv-glow), inset 0 0 14px rgba(0,0,0,.55);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    transition: box-shadow .3s ease;
}

.rocketv-porthole::before,
.rocketv-porthole::after {
    content: "";
    position: absolute;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: rgba(255,255,255,.22);
    top: 50%;
    transform: translateY(-50%);
}
.rocketv-porthole::before { left:  -10px; }
.rocketv-porthole::after  { right: -10px; }

.rocketv-porthole-core {
    display: block;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--sv-soft) 0%, transparent 100%);
    border: 1px solid var(--sv-color);
    animation: rocketvPorthole 3s ease-in-out infinite;
}

@keyframes rocketvPorthole {
    0%, 100% { box-shadow: 0 0 6px  var(--sv-glow); }
    50%       { box-shadow: 0 0 20px var(--sv-color); }
}

.rocketv-sas:hover .rocketv-porthole {
    box-shadow: 0 0 32px var(--sv-color), inset 0 0 14px rgba(0,0,0,.3);
}

.rocketv-porthole--gold {
    /* Teinte "néon" de la couleur secondaire (--offer-tint-neon) — cette
       classe n'a plus rien à voir avec l'accent "gold" (rouge) du sélecteur
       de couleur malgré son nom (conservé tel quel : le renommer risquerait
       de casser d'autres usages de .rocketv-porthole--gold ailleurs sur le
       site). Remplace l'orange fixe posé au tour précédent, lui-même un
       remplacement du rouge (185,28,28) d'origine. */
    border-color: rgba(var(--offer-tint-neon),.55);
    background: rgba(var(--offer-tint-neon),.09);
    box-shadow: 0 0 22px rgba(var(--offer-tint-neon),.32), inset 0 0 14px rgba(0,0,0,.55);
}
.rocketv-porthole--gold .rocketv-porthole-core {
    background: radial-gradient(circle, rgba(var(--offer-tint-neon),.55) 0%, transparent 100%);
    border-color: rgba(var(--offer-tint-neon),.55);
    animation: rocketvGold 3s ease-in-out infinite;
}
@keyframes rocketvGold {
    0%, 100% { box-shadow: 0 0 6px  rgba(var(--offer-tint-neon),.5); }
    50%       { box-shadow: 0 0 24px rgba(var(--offer-tint-neon),.95); }
}
.rocketv-sas--featured:hover .rocketv-porthole {
    box-shadow: 0 0 36px rgba(var(--offer-tint-neon),.65), inset 0 0 14px rgba(0,0,0,.3);
}

/* --- CONTENU SAS --- */

.rocketv-sas-body { flex: 1; min-width: 0; }

.rocketv-sas-body h3 {
    font-family: "Space Grotesk", sans-serif;
    font-size: clamp(.82rem, 1vw, 1rem);
    font-weight: 700;
    color: #fff;
    margin: 0;
    line-height: 1.3;
    background: none;
    box-shadow: none;
    padding: 0;
    transition: margin .3s ease;
}



.rocketv-sas-body p {
    font-size: clamp(.72rem, .85vw, .84rem);
    color: rgba(255,255,255,.55);
    line-height: 1.6;
    margin: 0;
    opacity: 0;
    max-height: 0;
    overflow: hidden;
    transition: opacity .35s ease, max-height .35s ease;
}

.rocketv-sas:hover .rocketv-sas-body p {
    opacity: 1;
    max-height: 200px;
}

.rocketv-sas-cta {
    font-size: .85rem;
    font-weight: 700;
    color: var(--sv-color);
    opacity: 0;
    flex-shrink: 0;
    transition: opacity .25s ease, transform .25s ease;
}
.rocketv-sas:hover .rocketv-sas-cta { opacity: 1; transform: translateX(4px); }

.rocketv-ribbon {
    position: absolute;
    top: 8px;
    right: 32px;
    background: rgba(251,191,36,.12);
    color: #fbbf24;
    border: 1px solid rgba(251,191,36,.38);
    padding: 2px 8px;
    border-radius: 14px;
    font-size: .6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    z-index: 2;
    animation: ribbonPulse 4s ease-in-out infinite;
    /* Libellé plus long ("Réservé aux professionnels") : autoriser le retour
       à la ligne dans une largeur bornée plutôt que de déborder de la carte. */
    max-width: 110px;
    white-space: normal;
    text-align: center;
    line-height: 1.15;
}

/* --- QUEUE --- */

.rocketv-tail {
    position: relative;
    /* Réduit (même passe que .rocketv-nose/.rocketv-sas) pour laisser plus
       de marge à la fusée dans une section désormais bornée à 100dvh. */
    height: clamp(40px, 5vh, 64px);
    flex-shrink: 0;
    clip-path: polygon(6% 0, 94% 0, 100% 100%, 0 100%);
    background:
        /* teinte de couleur du sélecteur au centre de la queue (miroir du
           traitement de .rocketv-nose) */
        linear-gradient(90deg,
            transparent 0%,
            transparent 20%,
            rgba(var(--header-accent),.4) 50%,
            transparent 80%,
            transparent 100%
        ),
        linear-gradient(90deg,
            rgba(0,0,0,.72) 0%,
            rgba(0,0,0,.1) 20%,
            rgba(6,8,14,.9) 50%,
            rgba(0,0,0,.1) 80%,
            rgba(0,0,0,.72) 100%
        );
    border-top: 2px solid rgba(255,255,255,.1);
}

.rocketv-tail::before {
    content: "";
    position: absolute;
    left: 12%;
    right: 12%;
    top: 38%;
    height: 2px;
    background: repeating-linear-gradient(
        to right,
        rgba(255,255,255,.2) 0,
        rgba(255,255,255,.2) 3px,
        transparent 3px,
        transparent 14px
    );
}

.rocketv-tail::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(var(--header-accent),.45), transparent);
}

.rocketv-fin {
    position: absolute;
    bottom: 0;
    width: 42px;
    height: 58px;
    background:
        linear-gradient(180deg, rgba(var(--header-accent),.3), rgba(var(--header-accent),.12) 60%, transparent),
        linear-gradient(180deg, rgba(8,10,18,.97), rgba(14,16,26,.95));
}
.rocketv-fin--left  { left:  -38px; clip-path: polygon(100% 0, 100% 100%, 0 100%); }
.rocketv-fin--right { right: -38px; clip-path: polygon(0 0,   100% 100%, 0 100%); }

.rocketv-nozzle {
    position: absolute;
    bottom: -20px;
    left: 50%;
    transform: translateX(-50%);
    width: 90px;
    height: 22px;
    background: rgba(4,6,18,.99);
    border: 1px solid rgba(255,255,255,.07);
    clip-path: polygon(12% 0, 88% 0, 100% 100%, 0 100%);
    border-radius: 0 0 6px 6px;
}

.rocketv-nozzle::after {
    content: "";
    position: absolute;
    inset: 2px;
    background: radial-gradient(ellipse at 50% 0%, rgba(255,120,0,.3), transparent 70%);
}

/* --- FLAMMES --- */

.rocketv-exhaust {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    justify-content: center;
    gap: 10px;
    padding-top: clamp(10px, 1.2vh, 18px);
    /* Réduit, même passe que .rocketv-tail juste au-dessus. */
    height: clamp(48px, 6vh, 88px);
    flex-shrink: 0;
    pointer-events: none;
}

.rocketv-flame {
    display: block;
    border-radius: 0 0 50% 50%;
    transform-origin: center top;
    filter: blur(3.5px);
}

.rocketv-flame--a {
    width: 16px;
    height: clamp(38px, 6vh, 65px);
    background: linear-gradient(to bottom, rgba(255,255,180,.98), rgba(255,180,30,.9), rgba(255,60,0,.75), transparent);
    animation: rocketvFlicker .09s ease-in-out infinite alternate;
}
.rocketv-flame--b {
    width: 26px;
    height: clamp(52px, 8vh, 92px);
    background: linear-gradient(to bottom, rgba(255,240,100,.96), rgba(255,130,20,.86), rgba(255,40,0,.72), transparent);
    filter: blur(5px);
    animation: rocketvFlicker .13s ease-in-out infinite alternate-reverse;
}
.rocketv-flame--c {
    width: 14px;
    height: clamp(34px, 5.5vh, 58px);
    background: linear-gradient(to bottom, rgba(255,255,220,.96), rgba(255,180,50,.82), rgba(255,80,0,.66), transparent);
    animation: rocketvFlicker .11s ease-in-out infinite alternate;
}

@keyframes rocketvFlicker {
    from { transform: scaleX(1)   scaleY(1); }
    to   { transform: scaleX(.58) scaleY(.62); }
}

/* ========================= PRICING ========================= */

.pricing-spacer { grid-column: 2; grid-row: 1; }

/* --1 = Premium ET --3 = Essentiel partagent la même teinte "mid"
   (--offer-tint-mid = --accent-harmony-2 telle quelle, demande explicite
   "mêmes teintes pour Essentiel et Premium") ; --2 = Business (teinte
   "neon", désormais basée sur --header-accent, la couleur PRINCIPALE — cf.
   commentaire détaillé sur .accent-* tout en haut du fichier). Défaut bleu
   pour accueil.php via $_header_accent_map (header.php). */
.pricing-card--1 { --pc-color: rgb(var(--offer-tint-mid));  --pc-glow: rgba(var(--offer-tint-mid),.25);  grid-column: 2; grid-row: 2; }
.pricing-card--2 { --pc-color: rgb(var(--offer-tint-neon)); --pc-glow: rgba(var(--offer-tint-neon),.25); grid-column: 2; grid-row: 3; }
.pricing-card--3 { --pc-color: rgb(var(--offer-tint-mid));  --pc-glow: rgba(var(--offer-tint-mid),.25);  grid-column: 2; grid-row: 4; }

.pricing-card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0 0 0 22px;
    position: relative;
    border-left: 2px solid rgba(255,255,255,.06);
    transition: border-color .3s ease;
}

.pricing-card + .pricing-card {
    border-top: 1px solid rgba(255,255,255,.04);
}

.pricing-card::before {
    content: "";
    position: absolute;
    left: -1px;
    top: 50%;
    transform: translateY(-50%);
    width: 14px;
    height: 2px;
    background: var(--pc-color);
    opacity: .5;
    transition: opacity .3s ease, width .3s ease;
}

.pricing-card:hover { border-left-color: var(--pc-color); }
.pricing-card:hover::before { opacity: 1; width: 18px; }

.pricing-amount {
    font-family: "Space Grotesk", sans-serif;
    font-size: clamp(1rem, 1.4vw, 1.45rem);
    font-weight: 700;
    color: var(--pc-color);
    line-height: 1;
    text-shadow: 0 0 20px var(--pc-glow);
}

.pricing-currency {
    font-size: .85rem;
    font-weight: 600;
    opacity: .75;
}

.pricing-type {
    font-size: .75rem;
    /* Contraste relevé (.45 -> .68) : ce texte porte une information réelle
       (le type de tarification), pas un simple ornement — demande explicite
       "améliore ce qui est visuellement fade". */
    color: rgba(255,255,255,.68);
    margin-top: 6px;
    line-height: 1.4;
    max-width: 140px;
}


/* ===================== MODULES ===================== */

main .modules {
    /* min-height:100dvh + flex column : la section occupe au moins un
       écran plein (cf. .modules .container ci-dessous, flex:1) et le
       divider (enfant flex suivant) reste tout en bas, juste au-dessus de
       la barre de couleur (border-bottom) qui referme la section — d'où le
       padding-bottom réduit par rapport au padding-top. */
    min-height: 100dvh;
    /* demande explicite : réduction de largeur -10%/côté, cf. commentaire
       détaillé sur .method plus haut (même principe pour les 7 sections
       "dans le vaisseau"). */
    width: 90%;
    margin-left: auto;
    margin-right: auto;
    display: flex;
    flex-direction: column;
    padding: clamp(50px, 8vh, 100px) 0 clamp(28px, 4vh, 44px);
    position: relative;
    background:
        /* Coin bas-gauche : bleu brand */
        radial-gradient(ellipse at 0% 100%,   rgba(var(--header-accent),.18) 0%, transparent 45%),
        /* Coin haut-droit : bleu doux */
        radial-gradient(ellipse at 100% 0%,   rgba(var(--header-accent),.10) 0%, transparent 45%),
        /* Centre : lueur ambiante */
        radial-gradient(ellipse at 50% 50%,   rgba(var(--header-accent),.05) 0%, transparent 65%),
        /* Grille technique */
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.025) 0,
            rgba(255,255,255,.025) 1px,
            transparent 1px,
            transparent 44px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.018) 0,
            rgba(255,255,255,.018) 1px,
            transparent 1px,
            transparent 44px
        ),
        rgba(7,10,18,.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-top: 1px solid rgba(var(--header-accent),.14);
    border-bottom: 1px solid rgba(var(--header-accent),.14);
    overflow: hidden;
}

/* Scan-line d'ambiance */
main .modules::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        180deg,
        transparent 0%,
        rgba(var(--header-accent),.03) 50%,
        transparent 100%
    );
    pointer-events: none;
}

main .modules .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
    position: relative;
    z-index: 1;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* center -> flex-end (demande explicite : "réduit au maximum l'écart
       avec le divider rockette", section garde son min-height:100dvh mais
       le contenu colle désormais au divider en bas plutôt que d'être
       centré — le vide résiduel se retrouve en haut de section). */
    justify-content: flex-end;
    width: 100%;
}

main .modules .section-divider {
    flex-shrink: 0;
}

/* ─── EN-TÊTE ─── */

.modules-header {
    text-align: center;
    margin-bottom: clamp(32px, 5vh, 60px);
}

.modules-header h2 {
    font-size: clamp(1.6rem, 2.5vw, 2.2rem);
    margin-bottom: 16px;
    display: inline-block;
}

main .modules p {
    color: var(--brand-color);
    font-weight: 500;
    text-shadow: 0 0 10px rgba(var(--header-accent),.25);
    margin: 0 auto;
    max-width: 600px;
    line-height: 1.7;
    font-size: clamp(.9rem, 1.1vw, 1rem);
}

/* ─── LAYOUT DEUX COLONNES ─── */

.modules-layout {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(20px, 4vw, 60px);
    align-items: start;
}

/* ─── BLOC ─── */

.modules-block {
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.06);
    border-radius: 20px;
    padding: clamp(20px, 3vw, 36px);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
}

/* Coin lumineux par bloc */
.modules-block--included::before {
    content: "";
    position: absolute;
    top: -40px;
    right: -40px;
    width: 120px;
    height: 120px;
    background: radial-gradient(circle, rgba(var(--header-accent),.15) 0%, transparent 70%);
    pointer-events: none;
}

.modules-block--optional::before {
    content: "";
    position: absolute;
    top: -40px;
    right: -40px;
    width: 120px;
    height: 120px;
    /* demande explicite : "utiliser la couleur secondaire de la couleur
       principale sélectionnée" pour la grille "Exemple de modules
       activables" — remplace l'amber fixe par --accent-harmony-2. */
    background: radial-gradient(circle, rgba(var(--accent-harmony-2),.12) 0%, transparent 70%);
    pointer-events: none;
}

/* ─── LABEL DE BLOC ─── */

.modules-block-label {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 24px;
    padding-bottom: 16px;
    border-bottom: 1px solid rgba(255,255,255,.06);
}

.modules-block-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    font-size: .85rem;
    font-weight: 700;
    flex-shrink: 0;
}

.modules-block-badge--blue {
    background: rgba(var(--header-accent),.15);
    color: rgb(var(--header-accent));
    border: 1px solid rgba(var(--header-accent),.35);
    box-shadow: 0 0 12px rgba(var(--header-accent),.2);
}

.modules-block-badge--amber {
    /* demande explicite : couleur secondaire de la couleur principale
       sélectionnée (--accent-harmony-2) au lieu de l'amber fixe */
    background: rgba(var(--accent-harmony-2),.12);
    color: rgb(var(--accent-harmony-2));
    border: 1px solid rgba(var(--accent-harmony-2),.35);
    box-shadow: 0 0 12px rgba(var(--accent-harmony-2),.18);
}

.modules-block-label h3 {
    font-family: "Space Grotesk", sans-serif;
    font-size: clamp(.85rem, 1.1vw, 1rem);
    font-weight: 600;
    color: rgba(255,255,255,.85);
    margin: 0;
    padding: 0;
    background: none;
    box-shadow: none;
    border: none;
    white-space: nowrap;
    text-shadow: none;
    backdrop-filter: none;
}

/* ─── LISTE ─── */

main .modules-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 0;
    list-style: none;
    margin: 0;
}

main .modules-list li {
    border-radius: 10px;
    padding: 12px 14px 12px 18px;
    font-size: clamp(.84rem, 1vw, .95rem);
    line-height: 1.5;
    color: rgba(255,255,255,.82);
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.05);
    transition: transform .2s ease, box-shadow .2s ease, background .2s ease, border-color .2s ease;
    position: relative;
    overflow: visible;
}

/* Accent gauche : inclus = bleu */
.modules-block--included .modules-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 3px;
    border-radius: 10px 0 0 10px;
    background: linear-gradient(to bottom, rgba(var(--header-accent),.8), rgba(var(--header-accent),.2));
}

/* Accent gauche : optionnel = couleur secondaire de la couleur principale
   sélectionnée (--accent-harmony-2), demande explicite */
.modules-block--optional .modules-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 3px;
    border-radius: 10px 0 0 10px;
    background: linear-gradient(to bottom, rgba(var(--accent-harmony-2),.7), rgba(var(--accent-harmony-2),.15));
}

.modules-block--included .modules-list li:hover {
    transform: translateX(4px);
    background: rgba(var(--header-accent),.06);
    border-color: rgba(var(--header-accent),.2);
    box-shadow: 0 4px 16px rgba(var(--header-accent),.1);
    color: #fff;
}

.modules-block--optional .modules-list li:hover {
    transform: translateX(4px);
    background: rgba(var(--accent-harmony-2),.05);
    border-color: rgba(var(--accent-harmony-2),.18);
    box-shadow: 0 4px 16px rgba(var(--accent-harmony-2),.08);
    color: #fff;
}

/* Tooltip */
.modules-list li::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    background: rgba(10,14,30,.95);
    color: #fff;
    padding: 6px 12px;
    border-radius: 8px;
    font-size: .75rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease, transform .2s ease;
    z-index: 20;
    border: 1px solid rgba(255,255,255,.08);
    backdrop-filter: blur(8px);
    transform: translateX(-50%) translateY(6px);
}

.modules-list li:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ─── CTA ─── */

.modules-cta {
    display: flex;
    justify-content: center;
    margin-top: clamp(28px, 4vw, 40px);
}

.modules-cta-link {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 14px 28px;
    background: rgba(var(--header-accent),.10);
    border: 1px dashed rgba(var(--header-accent),.35);
    border-radius: 14px;
    color: rgba(255,255,255,.85);
    text-decoration: none;
    font-size: .95rem;
    font-weight: 500;
    transition: background .25s ease, border-color .25s ease, transform .25s ease, box-shadow .25s ease;
    position: relative;
    overflow: hidden;
}

.modules-cta-link::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at 50% 50%, rgba(var(--header-accent),.12), transparent 70%);
    opacity: 0;
    transition: opacity .3s ease;
}

.modules-cta-link:hover {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.6);
    transform: translateY(-2px);
    box-shadow: 0 10px 30px rgba(var(--header-accent),.2);
    color: #fff;
}

.modules-cta-link:hover::before { opacity: 1; }

.modules-cta-link .rocket-icon {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    transition: transform .25s ease;
}

/* ─── Traînée derrière la rockette (même technique que .cta-rocket-wrap /
   .cta-rocket-trail, cf. plus haut dans ce fichier) : un vrai <span> frère
   du svg qui porte SEUL le translate/rotate du décollage, + une traînée
   révélée en fondu au survol/focus. Classes réutilisées telles quelles pour
   les autres contextes .rocket-icon (.page-sur/.page-vitrine/.page-pro
   .btn-primary) plus bas dans ce fichier. ─── */
.rocket-icon-wrap {
    position: relative;
    display: inline-flex;
    transition: transform .3s ease;
}

.rocket-icon-trail {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 2px;
    height: 8px;
    transform: translateX(-50%);
    transform-origin: 50% 0%;
    background: linear-gradient(to bottom, rgba(255,255,255,.6), transparent);
    border-radius: 2px;
    opacity: 0;
    transition: opacity .3s ease, height .3s ease;
    pointer-events: none;
}

.modules-cta-link:hover .rocket-icon-wrap,
.modules-cta-link:focus-visible .rocket-icon-wrap {
    transform: translateY(-3px) rotate(10deg);
}

.modules-cta-link:hover .rocket-icon-trail,
.modules-cta-link:focus-visible .rocket-icon-trail {
    opacity: .85;
    height: 11px;
}





/* ===================== METHOD ===================== */

/* min-height (pas height + overflow:hidden) : la section vise un écran
   plein comme .sol-off, mais sans jamais couper de contenu si le total
   (en-tête + 6 étapes + CTA + divider) dépasse malgré tout 100dvh sur un
   écran donné — elle s'agrandit simplement un peu au lieu de masquer le
   titre, une étape ou le divider (ce qui s'est produit avec height fixe +
   overflow:hidden). Le contenu reste volontairement compact via clamp()
   pour rester proche d'un écran sur la plupart des tailles. */
.method {
    min-height: 100dvh;
    /* demande explicite : "réduire la largeur des sections 10% environ de
       chaque côté... pour donner l'impression que la fusée est réellement
       dans l'espace" — la section (fond, coque, bandeau sas compris,
       puisqu'ils sont tous positionnés relativement à cette boîte) est
       désormais centrée et réduite à 80% de la largeur du viewport, le
       fond spatial global (.site-main::before) restant visible de chaque
       côté. */
    width: 90%;
    margin-left: auto;
    margin-right: auto;
    padding: clamp(90px, 10vh, 116px) 0 clamp(28px, 4vh, 44px);
    display: flex;
    flex-direction: column;
    position: relative;
    /* demande explicite : "uniformise le bg [des 7 sections de la fusée] à
       la façon des sites évolutifs construits autour de modules" — reprend
       exactement le fond de main .modules (mêmes dégradés d'angle, même
       grille technique, mêmes bordures/backdrop-filter) au lieu d'un
       habillage propre à chaque section. */
    background:
        radial-gradient(ellipse at 0% 100%,   rgba(var(--header-accent),.18) 0%, transparent 45%),
        radial-gradient(ellipse at 100% 0%,   rgba(var(--header-accent),.10) 0%, transparent 45%),
        radial-gradient(ellipse at 50% 50%,   rgba(var(--header-accent),.05) 0%, transparent 65%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.025) 0,
            rgba(255,255,255,.025) 1px,
            transparent 1px,
            transparent 44px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.018) 0,
            rgba(255,255,255,.018) 1px,
            transparent 1px,
            transparent 44px
        ),
        rgba(7,10,18,.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-top: 1px solid rgba(var(--header-accent),.14);
    border-bottom: 1px solid rgba(var(--header-accent),.14);
}

.method::before {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        0deg,
        transparent 0,
        transparent 3px,
        rgba(0,0,0,.03) 3px,
        rgba(0,0,0,.03) 4px
    );
    pointer-events: none;
    z-index: 0;
}

/* .method n'a plus de hauteur fixe (min-height:100dvh, pas d'overflow:hidden) :
   le container et le divider se comportent comme deux enfants flex normaux,
   dimensionnés à leur contenu. Rien ici ne doit clipper quoi que ce soit -
   plus prudent après plusieurs régressions de visibilité. */
.method .container {
    position: relative;
    z-index: 1;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
    width: 100%;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* center -> flex-end, cf. main .modules .container plus haut : réduit
       au maximum l'écart avec le divider, demande explicite. */
    justify-content: flex-end;
}

.method .section-divider {
    flex-shrink: 0;
}

/* ─── EN-TÊTE ─── */

.method-header {
    text-align: center;
    margin-top: 0;
    margin-bottom: clamp(10px, 2.2vh, 24px);
}

.method-header h2 {

    font-size: clamp(1.3rem, 2.4vw, 1.9rem);
    margin: 0;
}

/* ─── GRILLE ─── */

.method-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(10px, 1.4vh, 16px);
    margin-bottom: clamp(12px, 2.2vh, 22px);
}

/* ─── CTA "Créer un compte" sous les 6 étapes (bouton seul) ─── */
.method-cta {
    padding-top: clamp(12px, 2vh, 20px);
    border-top: 1px solid rgba(255,255,255,.08);
    text-align: center;
}

/* .btn-accueil porte un margin-bottom:130px pensé pour d'autres contextes
   (ex. hero) ; ici le bouton est juste avant le divider de fin de section,
   donc on le neutralise (même principe que .presentation-cta-buttons
   .btn-accueil et .home-service-box .btn-accueil ailleurs dans ce fichier). */
.method-cta .btn-accueil {
    margin-bottom: 0;
}

/* ─── Effet de brillance déclenché au survol de l'Étape 1 (cf. main.js,
   bloc "ÉTAPE 1 → CTA CRÉER UN COMPTE") : au hover de .method-step--1,
   le bouton "Créer un compte" reçoit .method-cta-btn--pulse. Overflow
   hidden + pseudo-élément en dégradé, même principe que
   .presentation-card-shine .capsule-shine (about.php). ─── */
.method-cta .btn-accueil.method-cta-btn--pulse {
    position: relative;
    overflow: hidden;
    background: rgba(var(--header-accent),.24);
    box-shadow: 0 0 0 2px rgba(var(--header-accent),.35), 0 12px 36px rgba(var(--header-accent),.3);
}

.method-cta .btn-accueil.method-cta-btn--pulse::before {
    content: "";
    position: absolute;
    inset: -40% -10%;
    background: linear-gradient(115deg,
        transparent 38%,
        rgba(255,255,255,.55) 48%,
        rgba(255,255,255,.22) 53%,
        transparent 62%);
    transform: translateX(-60%);
    mix-blend-mode: screen;
    /* infinite : se répète tant que .method-cta-btn--pulse reste présente,
       c'est-à-dire tant que l'Étape 1 est survolée (cf. main.js, qui retire
       la classe au mouseleave au lieu de la retirer après un seul passage). */
    animation: methodCtaSheen 1.15s ease-in-out infinite;
}

@keyframes methodCtaSheen {
    0%   { transform: translateX(-60%); }
    100% { transform: translateX(60%); }
}

@media (prefers-reduced-motion: reduce) {
    .method-cta .btn-accueil.method-cta-btn--pulse::before { animation: none; }
}

/* ─── ÉTAPE ─── */

.method-step {
    position: relative;
    display: flex;
    gap: 18px;
    align-items: flex-start;
    padding: clamp(26px, 4vh, 40px) 20px 16px 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    border-radius: 16px;
    overflow: hidden;
    transition: background .25s ease, transform .25s ease, border-color .25s ease;
}

.method-step::before {
    content: "";
    position: absolute;
    left: 0;
    top: 18%;
    bottom: 18%;
    width: 3px;
    border-radius: 0 2px 2px 0;
    background: var(--ms-color);
    opacity: .65;
    transition: opacity .25s ease, top .25s ease, bottom .25s ease;
}

.method-step:hover {
    background: rgba(255,255,255,.052);
    transform: translateX(5px);
    border-color: rgba(255,255,255,.10);
}

/* ─── Étape 1 mise en avant en permanence (même sans hover) : sert de
   point d'entrée visuel vers le CTA "Créer un compte". Reprend le look
   habituellement réservé au hover (barre d'accent pleine opacité) mais en
   teinte --ms-color (bleu, propre à l'étape 1) au lieu du blanc générique
   du hover, pour rester distinguable une fois survolée. ─── */
.method-step--1 {
    background: rgba(var(--header-accent),.055);
    border-color: rgba(var(--header-accent),.30);
    box-shadow: 0 0 0 1px rgba(var(--header-accent),.10), 0 16px 40px -10px rgba(var(--header-accent),.22);
    /* .method-step--1 est un <a href="login.php"> (les 5 autres étapes
       restent des <div>) : on neutralise les styles de lien par défaut
       pour un rendu identique aux autres cartes. */
    text-decoration: none;
    color: inherit;
    cursor: pointer;
}

.method-step--1::before {
    opacity: 1;
    top: 8%;
    bottom: 8%;
}

.method-step:hover::before {
    opacity: 1;
    top: 8%;
    bottom: 8%;
}

/* ─── COULEURS PAR ÉTAPE ─── */

.method-step--1 { --ms-color: #3b82f6; }
.method-step--2 { --ms-color: #3b82f6; }
.method-step--3 { --ms-color: #8b5cf6; }
.method-step--4 { --ms-color: #3b82f6; }
.method-step--5 { --ms-color: #3b82f6; }
.method-step--6 { --ms-color: #8b5cf6; }

.method-step-badge {
    position: absolute;
    top: 12px;
    right: 12px;
    cursor: help;
}

/* .method-step a overflow:hidden (accent gauche + coins arrondis) : sans
   ça, la bulle de tooltip du badge — qui doit dépasser vers le haut —
   serait rognée. On ne relâche le clip qu'au survol/focus de la carte. */
.method-step:hover,
.method-step:focus-within {
    overflow: visible;
}

.method-step-badge[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 10px);
    right: 0;
    width: max-content;
    max-width: 220px;
    background: rgba(10,14,30,.97);
    border: 1px solid rgba(255,255,255,.10);
    color: #fff;
    border-radius: 8px;
    font-size: .72rem;
    font-weight: 500;
    line-height: 1.4;
    text-align: left;
    white-space: normal;
    padding: 8px 12px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .2s ease, visibility .2s ease, transform .2s ease;
    transform: translateY(4px);
    z-index: 30;
}

.method-step-badge[data-tooltip]:hover::after,
.method-step-badge[data-tooltip]:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* ─── NUMÉRO DÉCORATIF ─── */

.method-step-num {
    font-family: "Space Grotesk", sans-serif;
    font-size: clamp(1.8rem, 3vh, 2.6rem);
    font-weight: 800;
    color: var(--ms-color);
    opacity: .16;
    line-height: 1;
    flex-shrink: 0;
    user-select: none;
    transition: opacity .25s ease;
}

.method-step:hover .method-step-num {
    opacity: .30;
}

/* ─── CORPS ─── */

.method-step-body {
    flex: 1;
    min-width: 0;
}

.method-step-body h3 {
    font-family: "Space Grotesk", sans-serif;
    font-size: .96rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 6px;
    line-height: 1.25;
    background: none;
    box-shadow: none;
    padding: 0;
    text-shadow: 0 0 10px rgba(var(--header-accent),.20);
}

.method-step-body p {
    font-size: .84rem;
    color: rgba(255,255,255,.50);
    line-height: 1.5;
    margin: 0;
}

.method-step-link {
    display: inline-block;
    margin-top: 8px;
    font-size: .78rem;
    font-weight: 600;
    /* Contraste relevé (.45 -> .70) : c'est un vrai lien cliquable, pas un
       simple texte d'ambiance — demande explicite "améliore ce qui est
       visuellement fade". */
    color: rgba(255,255,255,.70);
    text-decoration: underline;
    text-decoration-color: rgba(255,255,255,.22);
    text-underline-offset: 3px;
    transition: color .2s ease, text-decoration-color .2s ease;
}

.method-step-link:hover,
.method-step-link:focus-visible {
    color: var(--ms-color);
    text-decoration-color: var(--ms-color);
}

/* ─── DIVIDER ───
   L'espacement de ce divider (comme des 6 autres de la page) est géré par
   la règle unique .site-main .section-divider plus bas dans ce fichier. */


/* ===================== PROBLEM ===================== */

.problem {
    /* min-height:100dvh + flex column, même principe que .why-target /
       .modules / .home-service-section : .problem-layout (flex:1, cf. plus
       bas) remplit l'espace disponible et le divider reste juste au-dessus
       de la barre de couleur (border-top) qui ouvre la section suivante.
       Demande explicite (1ère passe) : "Sans présence digitale a besoin
       d'être légèrement réduite en hauteur" — 100dvh -> 92dvh en min-height
       (seule cette section, les autres gardent 100dvh).
       Demande explicite (2e passe, bug réel constaté) : "j'aimerais que
       l'on puisse voir le divider suivant" — un min-height ne PLAFONNE pas
       la hauteur, il ne fait que fixer un minimum ; comme le contenu (titre
       + 2 groupes de 3 points) dépassait déjà 92dvh, le divider en bas se
       retrouvait hors écran malgré ce changement. height (au lieu de
       min-height) + overflow:hidden plafonne réellement la section, même
       principe que .sol-off/.why-target plus haut — combiné au resserrement
       des espacements internes de .problem-content ci-dessous pour que le
       contenu tienne sans être rogné. */
    height: 94dvh;
    overflow: hidden;
    /* demande explicite : réduction de largeur -10%/côté, cf. commentaire
       détaillé sur .method plus haut. */
    width: 90%;
    margin-left: auto;
    margin-right: auto;
    display: flex;
    flex-direction: column;
    /* padding-top passé de 20px à la même échelle que les sections voisines
       (demande explicite : "contenu trop collé en haut") : 20px suffisait
       avant l'ajout du bandeau .section-sas en haut de section, désormais
       trop court. */
    padding: clamp(90px, 10vh, 120px) 0 clamp(28px, 4vh, 44px);
    position: relative;
    /* demande explicite : "uniformise le bg [des 7 sections de la fusée] à
       la façon des sites évolutifs construits autour de modules" — reprend
       exactement le fond de main .modules, cf. commentaire détaillé sur
       .method plus haut. */
    background:
        radial-gradient(ellipse at 0% 100%,   rgba(var(--header-accent),.18) 0%, transparent 45%),
        radial-gradient(ellipse at 100% 0%,   rgba(var(--header-accent),.10) 0%, transparent 45%),
        radial-gradient(ellipse at 50% 50%,   rgba(var(--header-accent),.05) 0%, transparent 65%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.025) 0,
            rgba(255,255,255,.025) 1px,
            transparent 1px,
            transparent 44px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.018) 0,
            rgba(255,255,255,.018) 1px,
            transparent 1px,
            transparent 44px
        ),
        rgba(7,10,18,.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-top: 1px solid rgba(var(--header-accent),.14);
    border-bottom: 1px solid rgba(var(--header-accent),.14);
}

.problem::before {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        0deg,
        transparent 0,
        transparent 3px,
        rgba(0,0,0,.03) 3px,
        rgba(0,0,0,.03) 4px
    );
    pointer-events: none;
    z-index: 0;
}

/* ─── LAYOUT ─── */

.problem-layout {
    position: relative;
    z-index: 1;
    display: flex;
    /* Demande explicite ("Sans présence digitale" : "image à gauche, grid
       à droite") : le HTML garde l'ordre .problem-content puis
       .problem-visual (inchangé, important pour l'ordre de lecture au
       clavier/lecteur d'écran — le texte doit rester lu avant l'image
       décorative), row-reverse inverse seulement l'ordre VISUEL en
       desktop. Le mobile garde sa propre règle column-reverse (cf.
       responsive.css, non affectée par ce changement). */
    flex-direction: row-reverse;
    /* center -> flex-end (demande explicite : "réduit au maximum l'écart
       avec le divider rockette"), même logique que .sol-off-inner : colle
       le contenu en bas de .problem-layout, contre le divider. */
    align-items: flex-end;
    gap: 100px;
    max-width: 1300px;
    margin: 0 auto;
    /* réduit (demande explicite : "voir le divider suivant") : la section
       est désormais plafonnée à height:94dvh (cf. .problem plus haut), ce
       petit espace en moins aide le contenu à tenir sans être rogné. */
    margin-top: 20px;
    padding: 0 clamp(1rem, 3vw, 2rem);
    flex: 1;
    min-height: 0;
    width: 100%;
    box-sizing: border-box;
}

.problem .section-divider {
    flex-shrink: 0;
}

/* ─── CONTENU ─── */

.problem-content {
    flex: 1;
    min-width: 0;
    /* padding vertical resserré (demande explicite : "voir le divider
       suivant"), cf. .problem plus haut. */
    padding: 24px 32px;
    border-radius: 18px;
    background: rgba(255,255,255,.032);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
}

.problem-content::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(var(--header-accent),.45), rgba(var(--accent-harmony-2),.35), transparent);
}

.problem-content h2 {
    font-size: clamp(1.5rem, 2.5vw, 2rem);
    font-weight: 700;
    line-height: 1.25;
    /* réduit (demande explicite : "voir le divider suivant"), cf. .problem
       plus haut. */
    margin: 0 0 .7rem;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.problem-content p {
    color: rgba(255,255,255,.60);
    font-size: .96rem;
    line-height: 1.75;
    /* réduit (demande explicite : "voir le divider suivant"), cf. .problem
       plus haut. */
    margin: 0 0 .5rem;
}

/* ─── RÉSULTAT ─── */

.problem-result {
    /* réduits (demande explicite : "voir le divider suivant"), cf.
       .problem plus haut. */
    margin-top: .9rem !important;
    font-weight: 700 !important;
    font-size: 1.05rem !important;
    color: rgb(var(--header-accent)) !important;
    padding: 8px 14px 8px 16px !important;
    border-left: 3px solid rgb(var(--header-accent)) !important;
    border-radius: 0 8px 8px 0 !important;
    background: rgba(var(--header-accent),.07) !important;
    line-height: 1.5 !important;
    margin-bottom: 0 !important;
}

/* ─── POINTS ─── */

.problem-points {
    list-style: none;
    padding: 0;
    /* réduit (demande explicite : "voir le divider suivant"), cf. .problem
       plus haut. */
    margin: .8rem 0 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.problem-points li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    /* padding vertical réduit (demande explicite : "voir le divider
       suivant"), cf. .problem plus haut. */
    padding: 8px 16px;
    border-radius: 10px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    color: rgba(255,255,255,.58);
    font-size: .92rem;
    line-height: 1.55;
    transition: background .22s ease, border-color .22s ease, transform .22s ease;
}

.problem-points li::before {
    content: "→";
    color: rgb(var(--header-accent));
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}

.problem-points li:hover {
    background: rgba(var(--header-accent),.07);
    border-color: rgba(var(--header-accent),.18);
    color: rgba(255,255,255,.78);
    transform: translateX(4px);
}

/* ─── VISUEL ─── */

.problem-visual {
    flex: 0 0 420px;
    text-align: center;
    position: relative;
    z-index: 1;
    /* demande explicite : "descendre un peu l'image" — align-items:flex-end
       sur .problem-layout ancre déjà le BAS de l'image sur la même ligne
       que le texte ; un margin-top n'aurait ici aucun effet visuel (il
       n'ajoute que du vide au-dessus, l'ancrage flex-end recolle quand même
       le bas de la boîte à la même ligne). translateY, purement visuel, la
       décale réellement vers le bas. */
    transform: translateY(52px);
}

.problem-visual img {
    width: 100%;
    transform: scale(1.04);
    filter: drop-shadow(0 24px 48px rgba(0,0,0,.40))
            drop-shadow(0 0 40px rgba(var(--header-accent),.12));
    transition: transform .4s ease, filter .4s ease;
}

.problem-visual:hover img {
    transform: scale(1.07);
    filter: drop-shadow(0 28px 56px rgba(0,0,0,.45))
            drop-shadow(0 0 56px rgba(var(--header-accent),.20));
}

.problem-visual-caption {
    margin-top: 24px;
    font-size: .82rem;
    color: rgba(255,255,255,.38);
    line-height: 1.5;
    letter-spacing: .02em;
}

/* ─── DIVIDER ───
   L'espacement est géré par .site-main .section-divider (règle unique pour
   les 8 dividers de la page) ; on ne garde ici que le z-index. */
.problem .section-divider {
    position: relative;
    z-index: 1;
}

/* Écart avec le contenu (.problem-layout) légèrement réduit par rapport à
   l'écart uniforme des 8 dividers (spécificité renforcée pour primer sur
   .site-main .section-divider ci-dessous). */
.site-main .problem .section-divider {
    margin-top: clamp(14px, 2.5vh, 26px);
}


/* ===================== WHY-TARGET ===================== */

.why-target {
    /* min-height:100dvh + flex column, même principe que .modules plus
       haut : .why-target .container (flex:1, cf. plus bas) remplit
       l'espace disponible et le divider reste juste au-dessus de la barre
       de couleur (border-top) qui ouvre la section suivante — d'où le
       padding-bottom réduit par rapport au padding-top. */
    min-height: 100dvh;
    /* demande explicite : réduction de largeur -10%/côté, cf. commentaire
       détaillé sur .method plus haut. */
    width: 90%;
    margin-left: auto;
    margin-right: auto;
    display: flex;
    flex-direction: column;
    padding: 80px 0 clamp(44px, 6vh, 64px);
    position: relative;
    overflow: hidden;
    /* demande explicite : "uniformise le bg [des 7 sections de la fusée] à
       la façon des sites évolutifs construits autour de modules" — reprend
       exactement le fond de main .modules, cf. commentaire détaillé sur
       .method plus haut. */
    background:
        radial-gradient(ellipse at 0% 100%,   rgba(var(--header-accent),.18) 0%, transparent 45%),
        radial-gradient(ellipse at 100% 0%,   rgba(var(--header-accent),.10) 0%, transparent 45%),
        radial-gradient(ellipse at 50% 50%,   rgba(var(--header-accent),.05) 0%, transparent 65%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.025) 0,
            rgba(255,255,255,.025) 1px,
            transparent 1px,
            transparent 44px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.018) 0,
            rgba(255,255,255,.018) 1px,
            transparent 1px,
            transparent 44px
        ),
        rgba(7,10,18,.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-top: 1px solid rgba(var(--header-accent),.14);
    border-bottom: 1px solid rgba(var(--header-accent),.14);
}

.why-target::before {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        0deg,
        transparent 0,
        transparent 3px,
        rgba(0,0,0,.03) 3px,
        rgba(0,0,0,.03) 4px
    );
    pointer-events: none;
    z-index: 0;
}

.why-target .container {
    position: relative;
    z-index: 1;
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* center -> flex-end, cf. .method .container plus haut : réduit au
       maximum l'écart avec le divider, demande explicite. */
    justify-content: flex-end;
    width: 100%;
}

/* ===================== CTA "Lancer mon site" — section dédiée =====================
   Extrait de #why-target (où le CTA "trou noir" était intégré en bas de la
   carte 2 colonnes) : sa propre section désormais, séparée de #why-target
   par un écart important (gros padding-top), avec pour seul fond
   bgsiteindex.png (+ overlay sombre pour la lisibilité) — sans les halos
   radiaux ni la grille de #why-target. overflow:hidden conservé car
   nécessaire pour rogner le disque du "trou noir" (.why-target-cta-halo)
   s'il déborde. */
.why-cta-section {
    /* Padding haut/bas ASYMÉTRIQUE (demande explicite : "garde le même
       espace entre la FAQ et le trou noir mais rapproche les 2 dernières
       sections du trou noir") — le haut garde l'écart doublé d'origine
       (FAQ -> trou noir inchangé), seul le bas est nettement réduit pour
       que #new-hebergement et la newsletter se rapprochent du trou noir. */
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    padding: clamp(1280px, 144vw, 1920px) 0 clamp(100px, 12vw, 180px);
    position: relative;
    overflow: hidden;
    /* Fond propre retiré (demande explicite : "je ne veux que le bg de la
       page ici") : cette section repeignait sa propre image + voile sombre
       par-dessus le fond fixe déjà posé une fois pour toutes sur
       .site-main::before — désormais transparente, seul ce fond fixe
       (bgsiteindex.png + voile) reste visible, à l'identique du reste de la
       page.
       border-top retiré (demande explicite, bug réel constaté : "il y a une
       ligne bleue horizontale qui traverse tout l'écran" en haut de cette
       section) : cette section n'est PAS une des 7 sections "dans le
       vaisseau" (donc pas réduite à 90% comme elles), le trait restait
       ainsi visible sur toute la largeur de l'écran — incohérent avec le
       reste du fond déjà retiré ("juste le bg de la page ici"). */
}

.why-cta-section .container {
    position: relative;
    z-index: 1;
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
}

.why-target .section-divider {
    flex-shrink: 0;
}

/* ─── GRILLE 2 COLONNES ─── */

.why-target-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    align-items: start;
}

/* Fusion "Pourquoi choisir" + "Pour qui" en une seule carte à 2 colonnes,
   uniquement dans la section "why-target" — scopé par #why-target pour ne
   pas affecter .home-service-dual-grid (Hébergement/Accompagnement) ni les
   cartes solo (refonte/programmation) qui réutilisent aussi .why-box /
   .target-box plus bas dans accueil.php. Les 2 boîtes perdent leur fond/
   bordure propres et deviennent de simples colonnes de la carte commune,
   séparées par un léger trait vertical (border-right sur .why-box). */
#why-target .why-target-grid {
    gap: 0;
    padding: 36px 0;
    border-radius: 18px;
    background: rgba(255,255,255,.032);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

#why-target .why-box,
#why-target .target-box {
    background: none;
    border: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-radius: 0;
    padding: 0 36px;
}

#why-target .why-box {
    border-right: 1px solid rgba(255,255,255,.09);
}

/* ─── BOÎTES ─── */

.why-box,
.target-box {
    padding: 32px 28px;
    border-radius: 18px;
    background: rgba(255,255,255,.032);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    gap: 20px;
    position: relative;
    overflow: hidden;
}

.why-box::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(var(--header-accent),.55), transparent);
}

.target-box::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(var(--accent-harmony-1),.55), transparent);
}

/* ─── LABEL / BADGE ─── */

.wt-box-label {
    display: flex;
    align-items: center;
    gap: 10px;
}

.wt-badge {
    font-size: 1rem;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 999px;
    letter-spacing: .05em;
    line-height: 1;
}

.wt-badge--blue {
    color: rgb(var(--header-accent));
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.28);
    box-shadow: 0 0 12px rgba(var(--header-accent),.15);
}

.wt-badge--cyan {
    color: #3b82f6;
    background: rgba(59,130,246,.10);
    border: 1px solid rgba(59,130,246,.28);
    box-shadow: 0 0 12px rgba(59,130,246,.15);
}

.wt-badge--violet {
    color: #8b5cf6;
    background: rgba(139,92,246,.10);
    border: 1px solid rgba(139,92,246,.28);
    box-shadow: 0 0 12px rgba(139,92,246,.15);
}

/* ─── TITRES ─── */

.why-box h2,
.target-box h2 {
    font-size: clamp(1.3rem, 2.2vw, 1.75rem);
    font-weight: 700;
    line-height: 1.25;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.target-box h2 {
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
}

/* ─── LISTES ─── */

.feature-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 0;
    margin: 0;
    list-style: none;
}

.feature-list li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    border-radius: 12px;
    background: rgba(255,255,255,.026);
    border: 1px solid rgba(255,255,255,.06);
    color: rgba(255,255,255,.62);
    font-size: .92rem;
    line-height: 1.55;
    transition: background .22s ease, border-color .22s ease, transform .22s ease, color .22s ease;
}

.feature-list--why li::before {
    content: "✓";
    color: rgb(var(--header-accent));
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}

.feature-list--target li::before {
    content: "→";
    color: rgb(var(--accent-harmony-1));
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}

.feature-list--why li:hover {
    background: rgba(var(--header-accent),.07);
    border-color: rgba(var(--header-accent),.18);
    color: rgba(255,255,255,.82);
    transform: translateX(4px);
}

.feature-list--target li:hover {
    background: rgba(var(--accent-harmony-1),.07);
    border-color: rgba(var(--accent-harmony-1),.18);
    color: rgba(255,255,255,.82);
    transform: translateX(4px);
}

/* ─── CTA INTÉGRÉ ─── */

.why-target-cta {
    text-align: center;
    margin-top: 5px;
}

.wt-cta-sep {
    width: 1px;
    height: 24px;
    background: linear-gradient(to bottom, rgba(var(--header-accent),.40), transparent);
    margin: 0 auto 24px;
}

.why-target-cta h2 {
    font-size: clamp(1.5rem, 2.8vw, 2.1rem);
    font-weight: 700;
    /* Décalage vers le bas (demande explicite, plusieurs ajustements
       successifs : texte+CTA trop hauts par rapport au centre du disque). */
    margin: 80px 0 16px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    /* Annule le halo générique "contour" posé sur tous les h2 du site
       (règle h2{} globale) : ce titre flotte sur le trou noir ci-dessous,
       sans contour rectangulaire autour du texte (cf. .services-cta h2,
       même traitement). */
    box-shadow: none;
}

/* ─── CTA "Lancer mon site" : effet "trou noir" ───
   Même technique que .services-cta-halo (services.php), à échelle réduite
   puisque ce CTA est un bloc compact intégré à la section #why-target et
   non une section pleine page dédiée. Réutilise les keyframes globales
   blackHoleSpin/blackHolePulse définies plus bas dans ce fichier. Aucun
   overflow:hidden ici : la section #why-target (qui a déjà overflow:hidden)
   se charge de rogner le disque s'il déborde, comme pour .services-cta. */
/* Dimensions alignées sur .services-cta-halo (services.php) — même
   taille de trou noir sur les deux pages (demande explicite).
   Padding SYMÉTRIQUE (et non plus 4px en bas contre 240-420px en haut,
   demande explicite "remonter le texte au centre du trou noir") : le
   cercle (::before/::after) se centre sur top:50% de CETTE boîte
   (padding + contenu) — avec un padding asymétrique, ce centre tombait
   loin au-dessus du texte (poussé vers le bas de la boîte). Padding
   réduit et égal des deux côtés : le texte/bouton se retrouvent
   exactement au centre du disque. .why-cta-section (la section
   englobante) a de toute façon un très grand padding propre
   (clamp(640px,72vw,960px)) qui donne largement assez de marge au
   disque/anneau sans que le halo ait besoin de son propre padding
   massif. */
.why-target-cta-halo {
    position: relative;
    padding: 24px 20px;
}

.why-target-cta-halo::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(440px, 62vw, 780px);
    height: clamp(440px, 62vw, 780px);
    margin-top: -1px;
    border-radius: 50%;
    /* Demande explicite ("pour la section trou noir, mets-le à la couleur
       sélectionnée") : la palette jaune/or fixe (calée sur une image de
       référence lors d'une demande précédente) est remplacée par des
       teintes dérivées de --header-accent. Mêmes paliers d'opacité/angles
       conservés pour garder la forme du disque — seule sa couleur change
       désormais avec le thème. (.hero-black-hole et .services-cta-halo
       sur services.php suivent désormais la même recette — demande
       explicite "tous les trous noirs de la page doivent hériter de la
       couleur active"). */
    /* Bande horizontale déplacée sur ::after (demande explicite : elle ne
       doit pas tourner avec l'anneau — contrairement à ce calque animé par
       blackHoleSpin — cf. trou noir1.jpg où la lueur équatoriale reste
       fixe sur la face du disque pendant que l'anneau tourne autour). */
    background:
        conic-gradient(
            from -20deg,
            rgba(var(--header-accent),0)      0deg,
            rgba(var(--header-accent),.6)     38deg,
            rgba(var(--header-accent),.68)    68deg,
            rgba(var(--header-accent),.7)     92deg,
            rgba(var(--header-accent),.36)    118deg,
            rgba(var(--header-accent),0)      152deg,
            rgba(var(--header-accent),0)      222deg,
            rgba(var(--header-accent),.22)    250deg,
            rgba(var(--header-accent),.4)     282deg,
            rgba(var(--header-accent),.55)    302deg,
            rgba(var(--header-accent),.4)     320deg,
            rgba(var(--header-accent),0)      360deg
        );
    box-shadow: 0 0 clamp(46px, 6.5vw, 82px) clamp(14px, 2vw, 25px) rgba(var(--header-accent),.30);
    --hole-blur: 22px;
    animation:
        blackHoleSpin 22s linear infinite,
        blackHoleFlicker 6.5s ease-in-out infinite;
    pointer-events: none;
    z-index: 0;
}

.why-target-cta-halo::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(230px, 32vw, 400px);
    height: clamp(230px, 32vw, 400px);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    /* Version "réaliste" restaurée (demande explicite : "on avait obtenu un
       résultat très réaliste", plus de barre horizontale) : la bande
       linéaire equatoriale est retirée — un seul radial-gradient forme un
       cœur noir opaque avec un fin anneau photonique clair à 58-66%
       (l'horizon des événements, coloré --header-accent), plus proche
       d'une vraie photo de trou noir. Complété par un léger backdrop-filter
       (flou + saturation) sur le bord pour un rendu moins "à plat". */
    background:
        radial-gradient(circle, #000000 0%, #000000 58%, rgba(var(--header-accent),.85) 62%, #000000 66%, rgba(0,0,0,0) 76%);
    backdrop-filter: blur(2px) saturate(1.15);
    -webkit-backdrop-filter: blur(2px) saturate(1.15);
    box-shadow: 0 0 clamp(52px, 7.2vw, 90px) clamp(17px, 2.4vw, 30px) rgba(0,0,0,.85);
    animation: blackHolePulse 4.5s ease-in-out infinite;
    pointer-events: none;
    z-index: 1;
}

.why-target-cta-halo h2,
.why-target-cta-halo .cta-text,
.why-target-cta-halo .btn-accueil {
    position: relative;
    z-index: 2;
}

/* ─── Rockette en orbite autour du trou noir ───
   Wrapper carré centré sur le même point que le disque (::after) et
   l'anneau (::before). Le rocket-icon est fixé au bord haut du wrapper
   (top:0, left:50%) et tourne AVEC le wrapper : la rotation du parent
   suffit à le faire orbiter, pas besoin d'animer sa position directement.
   z-index:2 pour passer au-dessus de l'anneau et du disque (::before/
   ::after sont respectivement z-index 0 et 1). */
.why-target-cta-orbit {
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(350px, 51vw, 610px);
    height: clamp(350px, 51vw, 610px);
    transform: translate(-50%, -50%) rotate(0deg);
    z-index: 2;
    pointer-events: none;
    animation: blackHoleOrbitSpin 8s linear infinite;
}

.why-target-cta-orbit-rocket {
    position: absolute;
    top: 0;
    left: 50%;
    width: 36px;
    height: 36px;
    transform: translate(-50%, -50%) rotate(90deg);
    color: rgba(255,255,255,.85);
    /* lueur suit désormais --header-accent (demande explicite couleur
       sélectionnée) au lieu d'un bleu clair fixe. */
    filter: drop-shadow(0 0 6px rgba(var(--header-accent),.55));
    transition: opacity .3s ease;
    /* pointer-events réactivé sur la rockette uniquement (le wrapper
       .why-target-cta-orbit reste pointer-events:none) : nécessaire pour
       que :hover se déclenche — demande explicite "rajoute un tooltip à
       la rockette en rotation autour". */
    pointer-events: auto;
}

/* ─── Traînée derrière la rockette en orbite (demande explicite) ───
   Même ancrage/rotation de base que .why-target-cta-orbit-rocket
   (top:0, left:50%, rotate(90deg)), mais SANS le translate(-50%,-50%) de
   centrage : la barre part du point d'ancrage (là où se trouve la
   rockette) et s'étend uniquement vers le "bas" en repère local — ce qui,
   une fois la même rotation appliquée, retombe exactement du côté
   "arrière" (moteur) de la rockette plutôt que réparti moitié devant/
   moitié derrière. Comme elle est un enfant du même wrapper que la
   rockette (.why-target-cta-orbit, qui tourne via blackHoleOrbitSpin),
   elle reste correctement alignée derrière elle tout au long de l'orbite. */
.why-target-cta-orbit-trail {
    position: absolute;
    top: 0;
    left: 50%;
    width: 4px;
    height: 56px;
    transform-origin: 50% 0%;
    transform: translateX(-50%) rotate(90deg);
    /* suit désormais --header-accent (demande explicite couleur
       sélectionnée) au lieu d'un bleu clair fixe. */
    background: linear-gradient(to bottom, rgba(var(--header-accent),.55) 0%, rgba(var(--header-accent),.18) 55%, rgba(var(--header-accent),0) 100%);
    border-radius: 2px;
    filter: blur(1.5px);
    pointer-events: none;
    transition: opacity .3s ease;
}

/* ─── Tooltip "Salut !" au survol de la rockette en orbite (demande
   explicite, 2e passe : "le tooltip doit suivre la rockette") ───
   1ère version : élément statique positionné une fois pour toutes en haut
   du cercle — lisible, mais ne suivait pas la rockette dans sa course.
   2e version (celle-ci) : .why-target-cta-tooltip-anchor est un enfant du
   MÊME wrapper rotatif que la rockette (.why-target-cta-orbit, animé par
   blackHoleOrbitSpin) et partage le MÊME point d'ancrage (top:0, left:50%)
   — il est donc entraîné exactement comme elle, en cercle, à chaque
   instant. Sa propre animation blackHoleOrbitCounterSpin tourne à la même
   vitesse mais en sens inverse : la rotation du parent s'annule pour ce
   sous-arbre, si bien que la pastille (positionnée juste au-dessus du
   point d'ancrage dans ce repère "stabilisé") reste toujours droite et
   lisible, tout en étant repositionnée en continu à côté de la rockette
   pendant qu'elle orbite. */
.why-target-cta-tooltip-anchor {
    position: absolute;
    top: 0;
    left: 50%;
    width: 0;
    height: 0;
    transform: translate(-50%, -50%) rotate(0deg);
    animation: blackHoleOrbitCounterSpin 8s linear infinite;
    z-index: 3;
}

.why-target-cta-tooltip {
    position: absolute;
    left: 0;
    top: -20px;
    transform: translate(-50%, -100%);
    background: rgba(var(--header-accent),.16);
    color: #fff;
    padding: 6px 16px;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 700;
    white-space: nowrap;
    letter-spacing: .03em;
    border: 1px solid rgba(var(--header-accent),.35);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    opacity: 0;
    pointer-events: none;
    /* demande explicite : "laisse le tooltip actif au moins 1.5s" — délai
       avant que le fondu de disparition ne démarre (le tooltip reste donc
       pleinement visible 1.5s après la fin du survol), puis fondu rapide.
       La règle :hover ci-dessous définit sa PROPRE transition (sans délai)
       qui prend le dessus à l'apparition : apparition instantanée, disparition
       différée. */
    transition: opacity .25s ease 1.5s;
}

.why-target-cta-orbit:has(.why-target-cta-orbit-rocket:hover) .why-target-cta-tooltip {
    opacity: 1;
    transition: opacity .2s ease;
}

@keyframes blackHoleOrbitCounterSpin {
    from { transform: translate(-50%, -50%) rotate(0deg); }
    to   { transform: translate(-50%, -50%) rotate(-360deg); }
}

@keyframes blackHoleOrbitSpin {
    from { transform: translate(-50%, -50%) rotate(0deg); }
    to   { transform: translate(-50%, -50%) rotate(360deg); }
}

/* ─── État "avalée" : au clic sur "Créer mon site" (cf. main.js) ───
   Le wrapper accélère puis rétrécit (scale → 0) autour de son propre
   centre : combiné à la rotation, la rockette part en spirale vers le
   centre du disque et disparaît, comme aspirée par le trou noir. */
.why-target-cta-halo.is-swallowing .why-target-cta-orbit {
    /* linear (et non plus un cubic-bezier ease-in) : l'accélération est
       désormais encodée directement dans l'espacement des paliers du
       keyframe (cf. @keyframes blackHoleSwallowSpiral) — une easing
       supplémentaire ici la ferait "doubler" et rendrait la fin
       illisible. Durée raccourcie (3.4s -> 2.4s, demande explicite). */
    animation: blackHoleSwallowSpiral 2.4s linear forwards;
}

.why-target-cta-halo.is-swallowing .why-target-cta-orbit-rocket,
.why-target-cta-halo.is-swallowing .why-target-cta-orbit-trail,
.why-target-cta-halo.is-swallowing .why-target-cta-tooltip {
    opacity: 0;
    /* Délai/durée mis à l'échelle de la nouvelle durée totale (2.4s), même
       proportion qu'avant (~67%->81% de l'animation) : la rockette
       disparaît à 1.95s — c'est CE moment précis que main.js utilise pour
       déclencher la navigation, plutôt que d'attendre la fin complète de
       la spirale (demande explicite). */
    transition: opacity .35s ease 1.6s;
}

/* ─── Spirale d'aspiration (demande explicite, 2 ajustements) ───
   1. Pas de "repop" : rotate() part de calc(var(--swallow-start) + Xdeg)
      plutôt que d'un fixe 0deg. --swallow-start est posée en JS juste
      avant l'ajout de .is-swallowing (cf. main.js) avec l'angle EXACT où
      la rockette se trouvait dans sa rotation continue (blackHoleOrbitSpin)
      au moment du clic — la spirale part donc de sa position réelle,
      jamais d'un saut visuel vers le haut du cercle.
   2. Plusieurs tours de plus en plus rapides avant l'aspiration : les
      paliers de rotation ci-dessous couvrent des deltas croissants par
      tranche de temps égale (220°, 360°, 480°, 640°, 850° ≈ 7 tours au
      total) — accélération progressive plutôt qu'une vitesse constante.
      translateY (décalage vers le "bas" du trou noir) reste quasi nul
      pendant les premiers tours et ne s'accentue que sur les 2 derniers
      paliers : la rockette n'est vraiment "tirée" vers le bas qu'en toute
      fin de spirale. Valeurs en clamp() car ce keyframe est partagé entre
      .why-target-cta-orbit (accueil.php) et .services-cta-orbit
      (services.php, disque plus grand). */
@keyframes blackHoleSwallowSpiral {
    0%   { transform: translate(-50%, -50%) translateY(0)                             rotate(calc(var(--swallow-start, 0deg) + 0deg))    scale(1);   }
    18%  { transform: translate(-50%, -50%) translateY(0)                             rotate(calc(var(--swallow-start, 0deg) + 220deg))  scale(.94); }
    38%  { transform: translate(-50%, -50%) translateY(2px)                           rotate(calc(var(--swallow-start, 0deg) + 580deg))  scale(.82); }
    58%  { transform: translate(-50%, -50%) translateY(6px)                           rotate(calc(var(--swallow-start, 0deg) + 1060deg)) scale(.62); }
    78%  { transform: translate(-50%, -50%) translateY(clamp(16px, 3.4vw, 40px))      rotate(calc(var(--swallow-start, 0deg) + 1700deg)) scale(.34); }
    100% { transform: translate(-50%, -50%) translateY(clamp(28px, 5.8vw, 68px))      rotate(calc(var(--swallow-start, 0deg) + 2550deg)) scale(0);   }
}

/* Le remplissage translucide standard de .btn-accueil (rgba(var(--accent-harmony-2),.14))
   se lit trop clair/lavé une fois posé sur le disque d'accrétion du trou
   noir : version plus sombre et plus opaque pour que le bouton se détache
   nettement. */
.why-target-cta-halo .btn-accueil {
    background: rgba(6, 10, 28, .62);
    border-color: rgba(var(--accent-harmony-2), .45);
}

.why-target-cta-halo .btn-accueil:hover {
    background: rgba(6, 10, 28, .78);
    border-color: rgba(var(--accent-harmony-2), .65);
}

.cta-text {
    color: rgba(255,255,255,.58);
    font-size: .98rem;
    max-width: 620px;
    margin: 0 auto 32px;
    line-height: 1.7;
}

/* Recoloré sur --accent-harmony-3 (demande explicite, précisée depuis :
   "il faut que cela soit du ton de la couleur principale sélectionnée...
   une variante du bleu utilisé", etc. pour chaque couleur) — remplace
   --accent-harmony-2 utilisé jusqu'ici par une VARIANTE (plus sombre) de
   la couleur principale de chaque thème (cf. --accent-harmony-3, posée
   sur chaque .accent-* tout en haut de ce fichier), pour que ce bouton
   générique (CTA "Livre d'or" sur index.php, "Se connecter", "Visiter le
   site"/services.php, etc. — cf. tous les usages de .btn-accueil dans ce
   fichier) reste dans le même ton que le reste de la page tout en s'en
   distinguant légèrement. */
.btn-accueil {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 15px 44px;
    font-size: 1.05rem;
    font-weight: 600;
    border-radius: 999px;
    background: rgba(var(--accent-harmony-3), .14);
    border: 1px solid rgba(var(--accent-harmony-3), .32);
    color: #ffffff;
    text-decoration: none;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 0 24px rgba(var(--accent-harmony-3), .08), inset 0 1px 0 rgba(255,255,255,.07);
    transition: background .25s ease, box-shadow .25s ease, transform .25s ease;
    margin-bottom: 130px;
}

.btn-accueil:hover {
    background: rgba(var(--accent-harmony-3), .22);
    box-shadow: 0 12px 36px rgba(var(--accent-harmony-3), .28);
    transform: translateY(-2px);
}

/* ========================= services.php ========================= */

/* ─── BACKGROUND ESPACE FIXE ─── */
.page-service::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-service > * {
    position: relative;
    z-index: 1;
}

/* ─── HERO ─── */
/* La hero est suivie d'un .section-divider (160px) : on retire cette
   hauteur pour que hero + divider tiennent ensemble dans 100dvh, sans
   avoir besoin de scroller davantage pour voir le divider. On retire
   aussi les 25px de SCROLL_OFFSET (main.js) laissés en haut à l'arrivée
   par ancre, pour que le bas du divider ne soit pas coupé. */
/* ─── TITRE VISIBLE DE LA HERO ───
   padding-top ramené de 200px à 60px : les 140px en trop réservaient la
   place du header flottant (84px) + son sous-menu "Services" (~195px au
   survol) qui restait visible en permanence en haut de la page. Depuis que
   le header de cette page reste masqué à l'arrivée et ne réapparaît qu'au
   scroll (cf. body:has(main.page-service, main.account-page)
   .site-header:not(.visible) plus haut), cette réserve n'a plus lieu
   d'être — 60px ne sert plus qu'à garder un peu d'air en haut du titre.
   Section calée sur 100dvh (plein écran) comme demandé. */
.page-service .services-hero {
    /* Hauteur/centrage 100dvh réservés au desktop (cf. media query
       min-width:1200px) : sur mobile/tablette, la grille empilée des 5
       vignettes est bien plus haute que 100dvh — un align-items:center
       dans une boîte de hauteur fixe aurait débordé le contenu par le
       haut ET par le bas (masqué derrière le header fixe / chevauchant
       la section suivante). Ici : hauteur naturelle (auto). */
    padding: 60px 0 40px;
    position: relative;
}

.page-service .hero-content {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* Le <h1> ne contient plus que le logo CroisierWeb flottant
   (.services-hero-logo), visible à TOUTES les tailles d'écran — le texte
   d'origine "Où va-t-on ?" a été retiré définitivement (demande
   explicite), donc l'effet terminal générique du h1 (prompt "> " +
   curseur) est également neutralisé ci-dessous, à tous les breakpoints. */
.services-hero-title {
    margin: 0;
    text-align: center;
}

.services-hero-title::before,
.services-hero-title::after {
    content: none;
}

/* Logo cliquable (renvoie vers accueil.php, demande explicite) : simple
   wrapper autour de l'image existante, mêmes conventions que
   .site-footer .footer-logo-link plus haut dans ce fichier. */
.services-hero-logo-link {
    display: block;
    line-height: 0;
    transition: opacity .2s ease;
}
.services-hero-logo-link:hover,
.services-hero-logo-link:focus-visible {
    opacity: .85;
}

.services-hero-logo {
    display: block;
    width: clamp(160px, 20vw, 260px);
    height: auto;
    margin: 0 auto;
    /* Même effet de flottaison que le logo d'index.php (.company-logomain
       img), cf. @keyframes floatSub dans animation.css. */
    animation: floatSub 3s ease-in-out infinite;
}

/* Titre "Explorer" au-dessus du logo, mobile/tablette uniquement (demande
   explicite) : reprend exactement le visuel du bouton "Explorer"
   (.hero-cta-row .btn-secondary) du hero d'accueil.php. Cette fois un
   vrai lien (ancre vers #services-cta, la dernière section avant le
   footer) : au clic, défile en douceur jusqu'au bas de la page (géré par
   le gestionnaire de clic générique des ancres, cf. main.js). Léger
   effet de pression au clic pour le retour visuel. Masqué par défaut,
   réaffiché en mobile dans responsive.css (@media max-width:960px). */
.services-hero-explore-title {
    display: none;
    margin: 0 auto 14px;
    padding: 12px 26px;
    width: fit-content;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.32);
    border-radius: 14px;
    color: rgba(255,255,255,.92);
    font-weight: 600;
    font-size: 1.02rem;
    text-decoration: none;
    cursor: pointer;
    transition: transform .18s ease, background .2s ease, border-color .2s ease;
}

.services-hero-explore-title:active {
    transform: scale(.93);
    background: rgba(255,255,255,.10);
    border-color: rgba(255,255,255,.5);
}

/* ─── Bouton "Actualiser la page" (sous le titre) ───
   Icône seule (pas de texte), volontairement discrète au repos ; forte
   animation d'apparition (pop + rotation) déclenchée par défaut après un
   court délai. En desktop (>=1200px), le délai est repoussé à 4s pour
   apparaître juste après la fin de l'atterrissage de la vignette centrale
   (4s, cf. animation-delay plus bas dans ce fichier). */
.services-hero-refresh {
    /* Masqué par défaut (mobile/tablette) : réservé aux utilisateurs PC,
       réaffiché uniquement dans le @media (min-width:1200px) plus bas. */
    display: none;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    margin-top: 10px;
    padding: 0;
    border-radius: 50%;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.14);
    color: rgba(255,255,255,.5);
    cursor: pointer;
    opacity: 0;
    animation: heroRefreshPopIn .65s cubic-bezier(.34,1.56,.64,1) forwards;
    animation-delay: .3s;
    transition: background .2s ease, border-color .2s ease, color .2s ease;
    /* .hero-grid (desktop) chevauche cette zone via son margin-top:-70px
       (cf. plus bas) : sans position/z-index explicites, les capsules de
       la grille passaient devant le bouton et bloquaient le clic en
       desktop (le bouton restait donc fonctionnel seulement là où rien ne
       le recouvre, ex. mobile). z-index élevé pour rester cliquable en
       toutes circonstances, y compris pendant le vol de la roquette
       "actualiser" (cf. z-index:5 sur .hero-orbit-lines plus bas). */
    position: relative;
    z-index: 6;
}

.services-hero-refresh svg {
    width: 17px;
    height: 17px;
    transition: transform .5s ease;
}

.services-hero-refresh:hover,
.services-hero-refresh:focus-visible {
    background: rgba(var(--header-accent),.12);
    border-color: rgba(var(--header-accent),.4);
    color: #fff;
}

.services-hero-refresh:hover svg,
.services-hero-refresh:focus-visible svg {
    transform: rotate(180deg);
}

.services-hero-refresh:active {
    background: rgba(var(--header-accent),.22);
}

.services-hero-refresh:focus-visible {
    outline: 2px solid rgba(var(--header-accent),.6);
    outline-offset: 2px;
}

@keyframes heroRefreshPopIn {
    0%   { opacity: 0; transform: scale(.3) rotate(-120deg); }
    55%  { opacity: 1; transform: scale(1.18) rotate(14deg); }
    75%  { transform: scale(.94) rotate(-6deg); }
    100% { opacity: 1; transform: scale(1) rotate(0deg); }
}

/* ─── HERO GRID CAPSULES ─── */
.hero-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 20px;
    width: 100%;
}

/* Le SVG des traits de connexion (decoratif, desktop uniquement) n'est
   positionné en absolute que dans la media query orbite (>=1200px) : en
   dessous de ce seuil, sans cette règle, il reste un enfant flex normal
   du .hero-grid (taille intrinsèque ~300×150px) et s'intercale entre les
   vignettes — d'où l'écart vertical qui isolait "Création site web" des
   4 autres. On le masque totalement hors desktop. */
.hero-orbit-lines {
    display: none;
}

/* Trou noir d'entrée (cf. .hero-black-hole plus bas, media query orbite
   >=1200px) : purement décoratif et lié à la choreographie desktop des
   vignettes en orbite, masqué hors de ce contexte comme .hero-orbit-lines
   ci-dessus. */
.hero-black-hole {
    display: none;
}

.hero-grid .service-capsule {
    flex: 1 1 300px;
    max-width: 360px;
}

/* ─── CAPSULES DE SERVICE ─── */
.service-capsule {
    --capsule-color: rgb(var(--header-accent));
    --capsule-soft:  rgba(var(--header-accent),.12);
    --capsule-glow:  rgba(var(--header-accent),.22);

    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    padding: 28px 24px 22px;
    border-radius: 24px;
    text-decoration: none;
    color: inherit;
    overflow: hidden;
    background: rgba(7,10,18,.78);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    /* border-radius/background-color ajoutés (en plus de transform/box-
       shadow/border-color déjà présents) pour le survol "redevient planète"
       en desktop (cf. .page-service .hero-content.is-all-landed
       .service-capsule:hover plus bas) : transition douce de la carte vers
       la forme ronde/texturée et inversement. */
    transition: transform .35s ease, box-shadow .35s ease, border-color .35s ease, border-radius .35s ease, background-color .35s ease;
}

.service-capsule::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(255,255,255,.022) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.022) 1px, transparent 1px);
    background-size: 28px 28px;
    border-radius: inherit;
    pointer-events: none;
    transition: opacity .3s ease;
}

.service-capsule::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 15%;
    right: 15%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--capsule-color), transparent);
    opacity: .5;
    transition: opacity .35s ease, left .35s ease, right .35s ease;
}

.service-capsule--conseil {
    --capsule-color: #8b5cf6;
    --capsule-soft:  rgba(139,92,246,.12);
    --capsule-glow:  rgba(139,92,246,.22);
    /* Phase "boule" du voyage/déploiement sur services.php (cf.
       heroPlanetTravel / heroCapsuleDeploy) */
    --capsule-planet-img: url('../image/planet-violet.webp');
}

/* « Création site web » (--featured) est la vignette phare du hero de
   services.php : elle doit ressortir nettement par rapport aux 4 autres
   (taille supérieure, halo permanent, léger zoom au repos).
   Demande explicite : cette vignette reste TOUJOURS bleue, comme
   refonte/programmation/conseil sont fixés respectivement en
   amber/vert/violet — elle ne doit plus suivre la couleur active. */
.service-capsule--featured {
    --capsule-color: #3b82f6;
    --capsule-soft:  rgba(59,130,246,.16);
    --capsule-glow:  rgba(59,130,246,.32);
    /* Phase "boule" du voyage/déploiement sur services.php (cf.
       heroPlanetTravelCenter / heroCapsuleDeployCenter) */
    --capsule-planet-img: url('../image/planet-terre.webp');
    border-color: rgba(59,130,246,.55);
    border-width: 1.5px;
    background: rgba(59,130,246,.12);
    box-shadow: 0 22px 55px rgba(59,130,246,.24), 0 10px 26px rgba(0,0,0,.30);
    transform: scale(1.09);
    z-index: 2;
    animation: featuredCapsuleGlow 3.4s ease-in-out infinite;
}

@keyframes featuredCapsuleGlow {
    0%, 100% { box-shadow: 0 22px 55px rgba(59,130,246,.24), 0 10px 26px rgba(0,0,0,.30); }
    50%      { box-shadow: 0 26px 68px rgba(59,130,246,.40), 0 12px 30px rgba(0,0,0,.34); }
}

.hero-grid .service-capsule--featured {
    flex: 1 1 360px;
    max-width: 420px;
}

/* Sélecteur combiné (2 classes) pour battre en spécificité la règle
   générique .service-capsule:hover (plus bas dans ce fichier) et conserver
   le zoom permanent de la vignette au survol. */
.service-capsule.service-capsule--featured:hover {
    transform: scale(1.09) translateY(-8px);
    border-color: rgba(59,130,246,.8);
    box-shadow: 0 30px 72px rgba(59,130,246,.42), 0 0 42px rgba(59,130,246,.32);
}

/* Demande explicite : « Hébergement et maintenance » reste TOUJOURS
   blanche/pâle (même logique que --featured en bleu fixe), comme
   refonte/programmation/conseil sont fixés sur leur propre teinte —
   elle ne doit plus jamais afficher du bleu. */
.service-capsule--cloud {
    --capsule-color: #f1f5f9;
    --capsule-soft:  rgba(241,245,249,.14);
    --capsule-glow:  rgba(241,245,249,.24);
    /* Phase "boule" du voyage/déploiement sur services.php (cf.
       heroPlanetTravel / heroCapsuleDeploy) */
    --capsule-planet-img: url('../image/planet-blanc.webp');
}

.service-capsule--refonte {
    --capsule-color: #f59e0b;
    --capsule-soft:  rgba(245,158,11,.12);
    --capsule-glow:  rgba(245,158,11,.22);
    /* Image corrigée (planet-rouge.webp -> planet-orange.webp, demande
       explicite "planète orange") : planet-rouge.webp est un rendu
       lave/magma noir-rouge, pas orange — même correction déjà appliquée à
       .home-hero-planet--magma plus haut dans ce fichier.
       Phase "boule" du voyage/déploiement sur services.php (cf.
       heroPlanetTravel / heroCapsuleDeploy) */
    --capsule-planet-img: url('../image/planet-orange.webp');
}

.service-capsule--programmation {
    --capsule-color: #10b981;
    --capsule-soft:  rgba(16,185,129,.12);
    --capsule-glow:  rgba(16,185,129,.22);
    /* Image corrigée (planet-blanc.webp -> planet-vert.webp, demande
       explicite "planète verte") : planet-blanc.webp donnait une planète
       blanche/grise, en doublon avec .service-capsule--cloud — même
       correction déjà appliquée à .home-hero-planet--hebergement plus haut
       dans ce fichier.
       Phase "boule" du voyage/déploiement sur services.php (cf.
       heroPlanetTravel / heroCapsuleDeploy) */
    --capsule-planet-img: url('../image/planet-vert.webp');
}

.capsule-status {
    position: absolute;
    top: 18px;
    right: 18px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--capsule-color);
    box-shadow: 0 0 8px var(--capsule-color), 0 0 18px var(--capsule-soft);
    animation: capsuleStatusPulse 2.8s ease-in-out infinite;
    transition: opacity .25s ease;
}

@keyframes capsuleStatusPulse {
    0%, 100% { opacity: 1;   transform: scale(1); }
    50%       { opacity: .4; transform: scale(.75); }
}

.capsule-porthole {
    position: relative;
    width: 58px;
    height: 58px;
    flex-shrink: 0;
    transition: opacity .25s ease;
}

/* ─── Disque "planète" affiché par défaut une fois déployée, masqué au
   survol (desktop) — inversion demandée par rapport au comportement
   précédent (planète révélée au survol) ; cf.
   .page-service .hero-content.is-all-landed .service-capsule.is-deployed
   et son :hover plus bas ───
   Élément DÉDIÉ plutôt qu'un border-radius:50% appliqué à toute la carte :
   les cartes ayant une largeur ≠ hauteur (320×300, 400×300...), un
   border-radius:50% sur la boîte entière donnerait une ellipse étirée et
   peu lisible, surtout une fois les vignettes agrandies. Ici, taille FIXE
   et centrée, identique à la boule pendant la phase "voyage" (même
   ombrage) — la zone de survol/clic reste néanmoins celle de LA VIGNETTE
   ENTIÈRE (ce disque n'est qu'un habillage visuel par-dessus, la carte
   elle-même ne change ni de taille ni de position). */
.capsule-planet-disc {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 150px;
    height: 150px;
    border-radius: 50%;
    transform: translate(-50%, -50%) scale(.82);
    background-color: var(--capsule-color);
    background-image: var(--capsule-planet-img);
    background-size: cover;
    background-position: center;
    box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22);
    opacity: 0;
    pointer-events: none;
    transition: opacity .3s ease, transform .3s ease;
}

/* Centre ("Terre") : disque un peu plus grand, cohérent avec sa vignette
   (400x300, redevenue plus petite que les satellites 345x320 en largeur
   mais un peu plus grande en aire — léger disque plus grand tout de même
   pour rester visuellement la vignette phare). */
.service-capsule--featured .capsule-planet-disc {
    width: 165px;
    height: 165px;
}

.capsule-porthole::before {
    content: "";
    position: absolute;
    inset: -5px;
    border-radius: 50%;
    border: 1px solid var(--capsule-soft);
    pointer-events: none;
}

.porthole-inner {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background: var(--capsule-soft);
    border: 1.5px solid var(--capsule-color);
    box-shadow: 0 0 18px var(--capsule-glow), inset 0 0 14px rgba(0,0,0,.35);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--capsule-color);
    transition: box-shadow .35s ease, background .35s ease, background-image .35s ease;
}

.porthole-inner svg { width: 22px; height: 22px; transition: opacity .25s ease; }

.capsule-seam {
    width: 100%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.07), transparent);
    flex-shrink: 0;
    transition: opacity .25s ease;
}

.capsule-content h4 {
    font-size: 1rem;
    font-weight: 600;
    color: #ffffff;
    margin: 0 0 8px;
    line-height: 1.3;
}

.capsule-content p {
    font-size: .875rem;
    color: rgba(255,255,255,.55);
    line-height: 1.65;
    margin: 0;
}

.capsule-cta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .78rem;
    font-weight: 600;
    color: var(--capsule-color);
    letter-spacing: .06em;
    text-transform: uppercase;
    margin-top: 4px;
    opacity: .8;
    transition: gap .2s ease, opacity .2s ease;
}

/* ─── Rockette remplaçant les flèches "→" des liens/CTA (capsule-cta,
   planet-cta, livre-dor-cta-btn) : décolle (translate + rotation) au
   survol du lien parent plutôt que de rester statique comme l'ancienne
   flèche. ── */
.cta-rocket {
    flex-shrink: 0;
    transition: transform .3s ease;
}

/* ─── Wrapper générique + traînée, réutilisable partout où .cta-rocket
   apparaît (demande explicite : "applique-le à tous les boutons qui ont
   la rockette"). Même technique que .planet-cta-rocket (services.php,
   planètes) : un vrai <span> frère du svg plutôt qu'un ::before dessus
   (peu fiable en pseudo-élément sur <svg>). Le translate+rotate du
   décollage est porté par CE wrapper (et non plus directement par
   .cta-rocket) pour que svg + traînée bougent ensemble ; ainsi les
   sélecteurs :hover ci-dessous remplacent les anciens qui ciblaient
   .cta-rocket directement (.service-capsule:hover .cta-rocket,
   .livre-dor-cta-btn:hover .cta-rocket). ─── */
.cta-rocket-wrap {
    position: relative;
    display: inline-flex;
    transition: transform .3s ease;
}

.cta-rocket-trail {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 2px;
    height: 8px;
    transform: translateX(-50%);
    transform-origin: 50% 0%;
    background: linear-gradient(to bottom, rgba(255,255,255,.6), transparent);
    border-radius: 2px;
    opacity: 0;
    transition: opacity .3s ease, height .3s ease;
    pointer-events: none;
}

.service-capsule:hover .cta-rocket-wrap,
.service-capsule:focus-visible .cta-rocket-wrap,
.livre-dor-cta-btn:hover .cta-rocket-wrap,
.livre-dor-cta-btn:focus-visible .cta-rocket-wrap {
    transform: translate(3px, -3px) rotate(45deg);
}

.service-capsule:hover .cta-rocket-trail,
.service-capsule:focus-visible .cta-rocket-trail,
.livre-dor-cta-btn:hover .cta-rocket-trail,
.livre-dor-cta-btn:focus-visible .cta-rocket-trail {
    opacity: .85;
    height: 11px;
}

.service-capsule:hover {
    transform: translateY(-5px);
    border-color: var(--capsule-color);
    box-shadow: 0 24px 60px rgba(0,0,0,.30), 0 0 35px var(--capsule-glow);
}

.service-capsule:hover::after { left: 5%; right: 5%; opacity: .9; }
.service-capsule:hover .porthole-inner {
    box-shadow: 0 0 28px var(--capsule-color), 0 0 55px var(--capsule-glow), inset 0 0 12px rgba(0,0,0,.20);
}
.service-capsule:hover .capsule-cta { gap: 10px; opacity: 1; }

/* ─── MOBILE/TABLETTE (< 1200px, grille empilée d'origine) : "Création
   site web" doit apparaître EN PREMIER (order) et avoir la même taille
   que les 4 autres vignettes (on neutralise son scale(1.09) et son
   flex-basis/max-width agrandis, propres à la mise en avant desktop). ── */
@media (max-width: 1199.98px) {
    .hero-grid .service-capsule--featured {
        order: -1;
        transform: none;
        flex: 1 1 300px;
        max-width: 360px;
    }
    .hero-grid .service-capsule.service-capsule--featured:hover {
        transform: translateY(-5px);
    }

    /* Léger espace entre le titre et la 1ère vignette (Création site
       web) : sans marge dédiée, .services-hero-title (margin:0) et
       .hero-grid étaient collés. Resserré (20px -> 10px) pour rapprocher
       davantage le titre de la grille. */
    .page-service .services-hero-title {
        margin-bottom: 10px;
    }
}

/* ================================================================
   SERVICES.PHP — HERO EN « ORBITE » (desktop uniquement)
   Demande : "Création site web" fixe au centre, les 4 autres vignettes
   flottent autour (une à gauche, une à droite, deux en dessous),
   reliées par des traits, avec une rotation rapide à l'arrivée qui
   ralentit progressivement jusqu'à l'arrêt complet (animation ≤3s).
   Seuil relevé à 1200px (au lieu de 993px) : au-delà, .hero-content
   (max-width 1100px) est élargi à 1300px spécifiquement pour cette
   section, ce qui donne assez de place pour garder aux vignettes
   quasiment leur taille d'origine (320/360px sat.) et un centre
   agrandi (400/420px) sans qu'elles se chevauchent. En dessous de
   1200px on garde la grille empilée d'origine : les règles
   .hero-grid / .service-capsule plus haut dans ce fichier s'appliquent
   telles quelles, rien n'est modifié pour le mobile/tablette. ── */
@media (min-width: 1200px) {

    /* Logo : visible immédiatement sur mobile/tablette (comportement
       d'origine, cf. .services-hero-logo plus haut, hors media query).
       En desktop uniquement, masqué au chargement et révélé seulement une
       fois les 5 planètes posées ET entièrement déployées en vignette
       (demande explicite) — cf. .hero-content.is-all-landed
       .services-hero-logo plus bas et @keyframes heroLogoArrive. Le
       bouton "Actualiser" reste réservé au desktop (display:none par
       défaut, cf. .services-hero-refresh). */
    .services-hero-logo {
        opacity: 0;
    }
    .services-hero-refresh {
        display: inline-flex;
    }

    /* Hauteur fixe + centrage vertical : n'a de sens qu'ici, où le
       contenu (titre + orbite clampée à 680-780px) tient bien dans
       95dvh une fois les 200px de padding-top déduits. */
    .page-service .services-hero {
        height: 95dvh;
        display: flex;
        align-items: center;
    }

    .page-service .hero-content {
        max-width: 1300px;
    }

    /* Le titre "Tableau de bord" reste affiché en permanence (ancien
       comportement : il disparaissait une fois "Création site web" posée
       au centre — plus nécessaire depuis que ce titre est devenu un
       intitulé de page fixe plutôt qu'un message d'accroche ponctuel). */

    /* Bouton "Actualiser la page" : n'apparaît qu'une fois les 5 planètes
       posées ET la vignette centrale déployée (cf. .is-all-landed plus
       bas et heroCapsuleDeployCenter) — pas d'animation par défaut ici,
       elle n'est ajoutée que par la règle .is-all-landed. */
    .services-hero-refresh {
        opacity: 0;
        animation: none;
    }
    .page-service .hero-content.is-all-landed .services-hero-refresh {
        animation: heroRefreshPopIn .325s cubic-bezier(.34,1.56,.64,1) forwards;
        animation-delay: .6s;
    }

    /* Logo : arrive une fois TOUTE la choreographie de déploiement
       terminée — la dernière vignette à se transformer (Conseil) finit à
       .2s de délai + .6s de durée = .8s après .is-all-landed ; petite
       marge (.875s) pour laisser cette dernière transformation bien se
       lire avant l'arrivée du titre (délai divisé par 2 comme le reste de
       la chorégraphie, demande explicite). floatSub (flottaison continue,
       hors media query) tourne dès le chargement sans incidence tant que
       le logo est invisible (opacity:0, cf. règle desktop plus haut) ;
       heroLogoArrive ne pilote QUE l'opacité, jamais transform — sinon il
       entrerait en conflit avec floatSub (déjà expérimenté avec les
       vignettes, cf. heroCapsuleDeploy) et figerait la flottaison une
       fois l'entrée terminée. */
    .page-service .hero-content.is-all-landed .services-hero-logo {
        animation: floatSub 3s ease-in-out infinite, heroLogoArrive .3s ease forwards;
        animation-delay: 0s, .875s;
    }

    .page-service .hero-grid {
        display: block;
        position: relative;
        width: 100%;
        height: clamp(680px, 44vw, 780px);
        /* Rapproche la 1ère vignette visible (ancrée à top:30%, donc avec
           un vide non négligeable au-dessus d'elle dans cette boîte) du
           titre juste au-dessus. Ne perturbe pas la géométrie de l'orbite
           (traits SVG / positions top:%) : simple décalage du bloc entier. */
        margin-top: -70px;
    }

    /* SVG des traits de connexion (voir services.php pour le markup
       inline). Chaque trait a son propre fondu, calé juste après le
       déploiement RÉEL de SA vignette — donc seulement une fois les 5
       planètes posées (cf. délais ci-dessous, relatifs à .is-all-landed)
       — plutôt qu'un fondu générique unique. */
    .hero-orbit-lines {
        display: block;
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        z-index: 0;
        overflow: visible;
        pointer-events: none;
    }

    /* Pas d'animation par défaut : chaque trait n'apparaît qu'une fois les
       5 planètes posées (cf. .is-all-landed plus bas), juste après que SA
       vignette se soit déployée — pas avant, même si elle est arrivée
       depuis longtemps sous forme de boule. */
    .orbit-line {
        fill: none;
        stroke: rgba(255,255,255,.18);
        stroke-width: .35;
        opacity: 0;
        transition: stroke .3s ease, stroke-width .3s ease, filter .3s ease;
    }
    /* Délais resynchronisés sur les nouveaux temps de déploiement (relatifs
       à l'ajout de .is-all-landed, cf. .service-capsule--refonte/--cloud/
       --programmation/--conseil plus bas : délai de déploiement + 1.2s de
       durée (shake compris) + .05s de marge). Valeurs divisées par 2 en
       plus (chorégraphie raccourcie globalement, demande explicite). */
    .page-service .hero-content.is-all-landed .orbit-line--refonte       { animation: heroOrbitLineFade .2s ease forwards; animation-delay: .675s; }
    .page-service .hero-content.is-all-landed .orbit-line--cloud         { animation: heroOrbitLineFade .2s ease forwards; animation-delay: .725s; }
    .page-service .hero-content.is-all-landed .orbit-line--programmation { animation: heroOrbitLineFade .2s ease forwards; animation-delay: .775s; }
    .page-service .hero-content.is-all-landed .orbit-line--conseil       { animation: heroOrbitLineFade .2s ease forwards; animation-delay: .825s; }
    /* Fil vers le divider "Création site web" : calé sur le déploiement du
       centre (délai 0s + .6s de durée) + .025s. */
    .page-service .hero-content.is-all-landed .orbit-line--divider       { animation: heroOrbitLineFade .2s ease forwards; animation-delay: .625s; }
    /* Fil bouton "Actualiser" -> "Création site web" : même repère que
       l'apparition du bouton lui-même (cf. .services-hero-refresh plus
       haut), pour qu'ils se révèlent ensemble. Le passage au bleu (classe
       .is-active) est ensuite déclenché par JS, pas par ce délai.
       Demande explicite : ce fil (comme la vignette "Création site web"
       elle-même, cf. .service-capsule--featured plus haut) reste TOUJOURS
       bleu — remplace rgb(var(--header-accent)) par le même bleu fixe
       (#3b82f6) que la vignette, il ne doit plus suivre la couleur active. */
    .page-service .hero-content.is-all-landed .orbit-line--refresh       { animation: heroOrbitLineFade .2s ease forwards; animation-delay: .6s; }
    .orbit-line--refresh.is-active {
        stroke: #3b82f6;
        stroke-width: .7;
        filter: drop-shadow(0 0 2px #3b82f6) drop-shadow(0 0 5px rgba(59,130,246,.6));
    }

    /* ─── TROU NOIR D'ENTRÉE (voir markup services.php, .hero-black-hole) ───
       Même habillage EXACT que le trou noir du CTA final (::before disque
       d'accrétion + ::after horizon des événements, cf. .services-cta-halo
       plus bas dans ce fichier — mêmes keyframes blackHoleSpin/blackHolePulse,
       réutilisées telles quelles) recentré sur l'ancre de la vignette
       centrale (50%,38%, cf. --hole-top/--hole-left ci-dessous). L'ENTRÉE
       (cf. heroBlackHoleLife) est un "dézoom" : le trou noir apparaît déjà
       immense (couvre tout l'écran) puis rétrécit jusqu'à sa taille normale
       — écho volontaire/inversé du trou noir grossissant à la toute fin de
       la séquence "Explorer" d'accueil.php (cf. homeHeroHaloGrow), pour
       donner la sensation d'enchaîner sur la même plongée dans le trou
       noir d'une page à l'autre.
       SORTIE (demande explicite, nouvelle) : une fois toute la
       choreographie terminée (5 planètes déployées, texte et logo
       arrivés), le trou noir se referme à son tour (cf.
       .is-all-landed .hero-black-hole / @keyframes heroBlackHoleClose plus
       bas) — mouvement inverse et symétrique du dézoom d'entrée. Nuance
       avec la note historique ci-dessus : un essai différent (remplacer le
       trou noir par une image de galaxie statique en fin de choreographie)
       avait été testé puis retiré (moins convaincant) ; ici il ne s'agit
       pas d'un remplacement mais d'une fermeture progressive du trou noir
       LUI-MÊME, qui disparaît plutôt que de rester en permanence. */
    .hero-black-hole {
        display: block;
        position: absolute;
        top: var(--hole-top, 38%);
        left: var(--hole-left, 50%);
        transform: translate(-50%, -50%);
        width: 0;
        height: 0;
        z-index: 0;
        opacity: 0;
        pointer-events: none;
        /* Chorégraphie d'entrée raccourcie globalement (facteur ~0.5, demande
           explicite : "plus courte" dans tous les cas, pas seulement à la
           1ère visite) : toutes les durées/délais de cette section (trou
           noir -> trajet -> déploiement -> texte -> traits d'orbite -> logo
           -> easter eggs) ont été divisés par 2, en conservant exactement
           les mêmes proportions/synchronisations relatives. */
        animation: heroBlackHoleLife .65s cubic-bezier(.16,1,.3,1) forwards;
    }

    /* Fermeture du trou noir une fois TOUTE la choreographie visible
       terminée : délai calé pour démarrer juste après l'arrivée du logo
       (dernier élément à apparaître, cf. .services-hero-logo plus bas —
       arrivée à .875s+.3s = 1.175s après .is-all-landed), avec une petite
       marge de lecture (1.2s). heroBlackHoleLife reste dans la liste
       (fill "forwards", déjà figée sur son état final depuis longtemps) :
       heroBlackHoleClose, listée après, prend le dessus sur les propriétés
       qu'elle pilote (opacity/transform) pour cette fermeture — même
       mécanique que .capsule-planet-disc/.capsule-status plus bas dans ce
       fichier (une animation listée en dernier gagne sur les précédentes
       pour les propriétés qu'elle gère). */
    .page-service .hero-content.is-all-landed .hero-black-hole {
        animation:
            heroBlackHoleLife .65s cubic-bezier(.16,1,.3,1) forwards,
            heroBlackHoleClose .7s cubic-bezier(.55,0,.85,.35) 1.2s forwards;
    }

    .hero-black-hole::before {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: clamp(390px, 55vw, 690px);
        height: clamp(390px, 55vw, 690px);
        margin-top: -1px;
        border-radius: 50%;
        /* Demande explicite ("le trou, et tous ceux de la page, doivent
           hériter de la couleur active") : la palette jaune/or fixe est
           remplacée par des teintes dérivées de --header-accent, même
           recette que .why-target-cta-halo. Mêmes paliers d'opacité/angles
           conservés pour garder la forme du disque — seule sa couleur
           change désormais avec le thème. */
        /* Bande horizontale déplacée sur ::after (demande explicite : elle
           ne doit pas tourner avec l'anneau — contrairement à ce calque
           animé par blackHoleSpin — cf. trou noir1.jpg où la lueur
           équatoriale reste fixe pendant que l'anneau tourne autour). */
        background:
            conic-gradient(
                from -20deg,
                rgba(var(--header-accent),0)      0deg,
                rgba(var(--header-accent),.6)     38deg,
                rgba(var(--header-accent),.68)    68deg,
                rgba(var(--header-accent),.7)     92deg,
                rgba(var(--header-accent),.36)    118deg,
                rgba(var(--header-accent),0)      152deg,
                rgba(var(--header-accent),0)      222deg,
                rgba(var(--header-accent),.22)    250deg,
                rgba(var(--header-accent),.4)     282deg,
                rgba(var(--header-accent),.55)    302deg,
                rgba(var(--header-accent),.4)     320deg,
                rgba(var(--header-accent),0)      360deg
            );
        box-shadow: 0 0 clamp(41px, 5.8vw, 72px) clamp(12px, 1.8vw, 22px) rgba(var(--header-accent),.30);
        --hole-blur: 22px;
        animation:
            blackHoleSpin 22s linear infinite,
            blackHoleFlicker 6.5s ease-in-out infinite;
        pointer-events: none;
    }

    .hero-black-hole::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: clamp(200px, 28vw, 350px);
        height: clamp(200px, 28vw, 350px);
        transform: translate(-50%, -50%);
        border-radius: 50%;
        /* Version "réaliste" restaurée (demande explicite : "on avait
           obtenu un résultat très réaliste", plus de barre horizontale) :
           la bande linéaire equatoriale est retirée — un seul
           radial-gradient forme un cœur noir opaque avec un fin anneau
           photonique clair à 58-66% (l'horizon des événements, coloré
           --header-accent), plus proche d'une vraie photo de trou noir.
           Complété par un léger backdrop-filter (flou + saturation) sur le
           bord pour un rendu moins "à plat". */
        background:
            radial-gradient(circle, #000000 0%, #000000 58%, rgba(var(--header-accent),.85) 62%, #000000 66%, rgba(0,0,0,0) 76%);
        backdrop-filter: blur(2px) saturate(1.15);
        -webkit-backdrop-filter: blur(2px) saturate(1.15);
        box-shadow: 0 0 clamp(45px, 6.2vw, 78px) clamp(15px, 2.1vw, 26px) rgba(0,0,0,.85);
        animation: blackHolePulse 4.5s ease-in-out infinite;
        pointer-events: none;
    }

    /* Roquette qui file le long du trait : SMIL <animateMotion
       begin="indefinite">, déclenchée à la demande par assets/js/main.js
       (bloc "ROQUETTES SATELLITES — RYTHME VARIABLE") plutôt qu'une boucle
       continue — demande explicite : rythme d'envoi variable pendant le
       survol (tantôt 1 roquette, tantôt 2) plutôt qu'un flux ponctuel
       identique. Invisible tant qu'elle ne vole pas réellement (classe
       .is-active posée par le JS le temps du vol, cf. plus bas), pas
       simplement tant qu'on ne survole pas la vignette. */
    .orbit-rocket {
        opacity: 0;
        transition: opacity .3s ease;
    }
    /* Révélée uniquement pendant le vol (posée/retirée par le JS pour
       chacune des 2 roquettes de chaque ligne satellite, cf. ci-dessus) —
       même mécanisme que .orbit-rocket--refresh.is-active plus bas, mais
       générique puisque partagé par les 8 roquettes (2 par ligne x 4
       lignes) plutôt qu'une seule instance par ligne. */
    .orbit-rocket.is-active {
        opacity: 1;
    }
    .orbit-rocket--refonte path,       .orbit-rocket--refonte circle       { fill: #f59e0b; }
    /* Corrigé (demande explicite) : "Hébergement et maintenance" est fixée
       blanche/pâle (cf. .service-capsule--cloud, --capsule-color: #f1f5f9,
       "ne doit plus jamais afficher du bleu") — sa roquette utilisait
       encore l'ancien bleu par défaut, jamais mise à jour. */
    .orbit-rocket--cloud path,         .orbit-rocket--cloud circle         { fill: #f1f5f9; }
    .orbit-rocket--programmation path, .orbit-rocket--programmation circle { fill: #10b981; }
    .orbit-rocket--conseil path,       .orbit-rocket--conseil circle       { fill: #8b5cf6; }
    /* Corrigé (demande explicite : "Création site web" reste TOUJOURS
       bleue) : ce fil part de cette vignette (cf. .orbit-line--divider),
       sa roquette doit donc rester bleue elle aussi, jamais teintée par la
       couleur active. */
    .orbit-rocket--divider path,       .orbit-rocket--divider circle       { fill: #3b82f6; }
    /* Corrigé (demande explicite) : la roquette "Actualiser" relie le
       bouton à la vignette "Création site web", fixée bleue en permanence
       (cf. .service-capsule--featured plus haut) — elle doit donc toujours
       être bleue elle aussi, jamais teintée par la couleur active. */
    .orbit-rocket--refresh path,       .orbit-rocket--refresh circle       { fill: #3b82f6; }

    /* Roquette "Actualiser" : contrairement aux autres, révélée par JS
       (classe .is-active posée sur l'aller ET gardée pour le retour, cf.
       main.js) et non par un survol. Pendant qu'elle vole (ou repose sur
       la vignette "Création site web" après l'aller), le SVG entier passe
       au-dessus des vignettes pour que la roquette soit visible par-dessus
       la carte — même mécanisme :has() que l'élévation au survol
       ci-dessous. */
    .orbit-rocket--refresh.is-active {
        opacity: 1;
    }
    .hero-grid:has(.orbit-rocket--refresh.is-active) .hero-orbit-lines {
        z-index: 5;
    }

    .hero-grid:has(.service-capsule--refonte:hover) .orbit-line--refonte {
        stroke: #f59e0b;
        stroke-width: .7;
        filter: drop-shadow(0 0 2px #f59e0b) drop-shadow(0 0 5px rgba(245,158,11,.6));
    }

    /* Même correction blanche/pâle que la roquette ci-dessus (cf.
       .orbit-rocket--cloud) : le trait s'illuminait encore en bleu au
       survol, incohérent avec la couleur fixe de cette vignette. */
    .hero-grid:has(.service-capsule--cloud:hover) .orbit-line--cloud {
        stroke: #f1f5f9;
        stroke-width: .7;
        filter: drop-shadow(0 0 2px #f1f5f9) drop-shadow(0 0 5px rgba(241,245,249,.6));
    }

    .hero-grid:has(.service-capsule--programmation:hover) .orbit-line--programmation {
        stroke: #10b981;
        stroke-width: .7;
        filter: drop-shadow(0 0 2px #10b981) drop-shadow(0 0 5px rgba(16,185,129,.6));
    }

    .hero-grid:has(.service-capsule--conseil:hover) .orbit-line--conseil {
        stroke: #8b5cf6;
        stroke-width: .7;
        filter: drop-shadow(0 0 2px #8b5cf6) drop-shadow(0 0 5px rgba(139,92,246,.6));
    }

    /* Survol d'une des 4 vignettes satellites : son fil + sa roquette
       passent au-dessus de "Création site web" (z-index 2), sans
       changer leur relation aux autres vignettes ni au survol du fil
       "divider" (non concerné ici). La vignette survolée elle-même
       reste toujours au-dessus (cf. règle :hover un peu plus bas, qui
       élève son propre z-index au-delà de celui du SVG). */
    .hero-grid:has(.service-capsule--refonte:hover) .hero-orbit-lines,
    .hero-grid:has(.service-capsule--cloud:hover) .hero-orbit-lines,
    .hero-grid:has(.service-capsule--programmation:hover) .hero-orbit-lines,
    .hero-grid:has(.service-capsule--conseil:hover) .hero-orbit-lines {
        z-index: 3;
    }

    /* Fil "Création site web" -> divider : même traitement au survol de
       la vignette centrale (--featured) que les traits satellites.
       Corrigé (demande explicite : "Création site web" reste TOUJOURS
       bleue, comme refonte/cloud/programmation/conseil sont fixées sur
       leur propre teinte ci-dessus) : bleu fixe au lieu de
       rgb(var(--header-accent)), qui suivait encore la couleur active. */
    .hero-grid:has(.service-capsule--featured:hover) .orbit-line--divider {
        stroke: #3b82f6;
        stroke-width: .7;
        filter: drop-shadow(0 0 2px #3b82f6) drop-shadow(0 0 5px rgba(59,130,246,.6));
    }
    .hero-grid:has(.service-capsule--featured:hover) .orbit-rocket--divider { opacity: 1; }

    /* Taille des vignettes satellites ramenée à leur format d'origine
       (celui de la grille empilée : flex-basis 300 / max-width 360).
       Hauteur FIXE (et non min-height) : en position absolue, les
       vignettes ne s'alignent pas naturellement sur la plus haute comme
       dans une grille flex/grid — un min-height seul laissait donc
       "Conseil et Accompagnement" (titre + texte plus longs) dépasser
       "Programmation" (contenu plus court). On fixe une hauteur unique
       + line-clamp sur le titre et la description (cf. plus bas) pour
       garantir des cartes rigoureusement identiques quel que soit le
       texte. */
    .page-service .hero-grid .service-capsule {
        /* Point d'origine commun ("trou noir", cf. .hero-black-hole) d'où
           les 4 vignettes satellites ci-dessous jaillissent avant de
           rejoindre leur --settle-top/--settle-left respectif — voir
           @keyframes heroPlanetTravel. */
        --hole-top: 38%;
        --hole-left: 50%;

        position: absolute;
        top: 0;
        left: 0;
        /* Agrandies (320x300 -> 345x320, demande explicite "très légèrement")
           — cf. .service-capsule--featured plus bas pour la Terre, plus
           nettement agrandie. */
        width: 345px;
        max-width: 380px;
        height: 320px;
        margin: 0;
        z-index: 1;
        opacity: 0;
        /* PHASE 1 : la vignette voyage depuis le trou noir jusqu'à sa
           position (--settle-top/--settle-left), ENCORE sous forme de
           boule (cf. @keyframes heroPlanetTravel), "both" : la fin de ce
           trajet (opacity/transform/fond) reste acquise en base tant que
           les animations suivantes ne prennent pas le relais.
           PHASE 1.5 (heroPlanetIdleSpin, 2e animation de la liste) : dès
           que le trajet de CETTE vignette est fini (délai = son propre
           délai de départ + sa propre durée, cf. animation-delay ci-
           dessous et par vignette plus bas), la boule continue de tourner
           doucement sur elle-même, en continu, tant qu'elle attend que
           les autres planètes arrivent à leur tour — voir main.js pour le
           signal de fin d'attente (PHASE 2, .is-all-landed plus bas, qui
           remplace entièrement ces 2 animations par heroCapsuleDeploy).
           Délai de départ 1s (demande explicite) : le souci n'était pas la
           vitesse du trajet mais le fait que les planètes se voyaient
           apparaître trop tôt — désormais, PERSONNE ne commence à
           apparaître avant 1s, laissant le trou noir seul à l'écran
           pendant au moins cette seconde (cf. délais individuels
           --refonte/--cloud/--programmation/--conseil plus bas, tous
           désormais ≥1s, et heroPlanetTravelCenter plus bas). Durée
           encore raccourcie (2.8s -> 2.3s -> 1.4s -> .7s, demande explicite :
           les planètes doivent rejoindre leur place plus vite, puis
           chorégraphie entière raccourcie d'un facteur ~0.5 en plus) une
           fois ce délai initial écoulé (0.5s, ex-1s : même raccourcissement
           global ~0.5). */
        animation:
            heroPlanetTravel .7s linear .5s both,
            heroPlanetIdleSpin 5s linear 1.2s infinite,
            heroLandingFlash .5s ease-out 1.2s forwards;
    }

    /* Lisibilité du texte descriptif (demande explicite) : depuis que le fond
       de la vignette est quasi entièrement effacé par défaut (planète en
       suspension, cf. .service-capsule.is-deployed plus bas), le titre/texte
       flotte directement sur le fond du hero (étoiles, planète voisine...)
       sans plus aucun repère de contraste derrière lui. Renforcé ICI
       uniquement (scopé à ce hero) via une ombre portée marquée + une
       opacité de texte plus élevée pour le paragraphe — sans toucher au
       style de base de .capsule-content (h4/p, cf. plus haut), réutilisé
       ailleurs (ex. .presentation-grid) où le fond de carte reste opaque et
       n'a pas besoin de ce renfort. */
    .page-service .hero-grid .service-capsule .capsule-content h4 {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        text-shadow: 0 1px 3px rgba(0,0,0,.9), 0 2px 14px rgba(0,0,0,.7);
    }

    .page-service .hero-grid .service-capsule .capsule-content p {
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
        color: rgba(255,255,255,.85);
        text-shadow: 0 1px 3px rgba(0,0,0,.9), 0 2px 14px rgba(0,0,0,.7);
    }

    /* Texte masqué durant tout le voyage ET l'attente qui suit (aucune
       animation ici) : il ne se révèle qu'à la transformation, cf. la
       règle .hero-content.is-all-landed plus bas qui lui ajoute
       heroOrbitTextReveal au bon moment. */
    .page-service .hero-grid .service-capsule .capsule-content,
    .page-service .hero-grid .service-capsule .capsule-cta {
        opacity: 0;
        transition: opacity .25s ease;
    }

    /* animation-duration/-delay ci-dessous : listes à 3 valeurs (trajet,
       rotation d'attente, flash d'impact) — la 2e valeur de chaque liste
       décale le départ de heroPlanetIdleSpin pour qu'il prenne le relais
       pile à la fin du trajet PROPRE à cette vignette (délai de départ +
       durée du trajet), cf. .service-capsule de base pour la mécanique
       complète ; la 3e valeur (heroLandingFlash) partage exactement ce
       même repère, pour que le flash se déclenche pile à l'atterrissage. */
    .page-service .hero-grid .service-capsule--refonte {
        --settle-top: 30%;
        --settle-left: 16%;
        top: 30%;
        left: 16%;
        animation-delay: .5s, 1.2s, 1.2s;
    }
    /* Hébergement et maintenance : trajet +.2s (1.6s au lieu de 1.4s, cf.
       .service-capsule de base) — durée explicite en plus du délai de
       départ (base 1s + .1s = 1.1s), même logique pour --programmation et
       --conseil ci-dessous : un simple décalage de départ pour garder un
       effet de cascade dans l'émergence, une fois la seconde initiale
       "trou noir seul" écoulée. Écarts resserrés (+.3/+.6/+.9 -> +.2/+.4/
       +.6) en même temps que le raccourcissement de la durée de base
       (demande explicite : planètes plus rapides à rejoindre leur place),
       pour garder les mêmes proportions de cascade. Valeurs divisées par 2
       en plus (chorégraphie raccourcie globalement, demande explicite). */
    .page-service .hero-grid .service-capsule--cloud {
        --settle-top: 30%;
        --settle-left: 84%;
        top: 30%;
        left: 84%;
        animation-duration: .8s, 5s, .5s;
        animation-delay: .55s, 1.35s, 1.35s;
    }
    /* Programmation : trajet +.4s (1.8s), délai 1.2s — divisés par 2. */
    .page-service .hero-grid .service-capsule--programmation {
        --settle-top: 80%;
        --settle-left: 32%;
        top: 80%;
        left: 32%;
        animation-duration: .9s, 5s, .5s;
        animation-delay: .6s, 1.5s, 1.5s;
    }
    /* Conseil et accompagnement : trajet +.6s (2s), délai 1.3s — divisés par 2. */
    .page-service .hero-grid .service-capsule--conseil {
        --settle-top: 80%;
        --settle-left: 68%;
        top: 80%;
        left: 68%;
        animation-duration: 1s, 5s, .5s;
        animation-delay: .65s, 1.65s, 1.65s;
    }

    /* Centre : pas de trajet (déjà sur l'ancre du trou noir) — juste une
       brève apparition sous forme de boule, qui enchaîne elle aussi sur
       une rotation d'attente continue (heroPlanetIdleSpinCenter) jusqu'à
       la transformation (PHASE 2 plus bas). Délai avant l'apparition porté
       à 1.4s (base 1s commune à toutes les planètes + .4s de retard propre
       au centre) : au tout premier instant du chargement, "Création site
       web" (la Terre) n'est donc pas encore visible — elle reste à
       opacity:0 (frame 0% de heroPlanetTravelCenter, tenue par le fill
       "both") le temps de ce délai, puis apparaît normalement. Durée
       encore raccourcie (2s -> 1.6s -> 1s -> .5s, même demande que pour les
       4 satellites ci-dessus : planètes plus rapides à rejoindre leur
       place, puis chorégraphie entière raccourcie d'un facteur ~0.5 en
       plus) ; le délai de heroPlanetIdleSpinCenter suit (.7s + .5s = 1.2s)
       pour continuer à prendre le relais pile à la fin RÉELLE du trajet. */
    .page-service .hero-grid .service-capsule--featured {
        top: 38%;
        left: 50%;
        /* Agrandie une première fois (400x300 -> 460x340) puis rétrécie
           (demande explicite, "trop grande") : retour à sa taille
           d'origine 400x300 (ratio 4:3), d'où le scale(.25,.333) repris tel
           quel (au lieu de .25,.338) dans heroPlanetTravelCenter/
           heroPlanetIdleSpinCenter/heroCapsuleDeployCenter plus bas. */
        width: 400px;
        max-width: 420px;
        height: 300px;
        z-index: 2;
        animation:
            heroPlanetTravelCenter .5s linear .7s both,
            heroPlanetIdleSpinCenter 5s linear 1.2s infinite,
            heroLandingFlash .5s ease-out 1.2s forwards;
    }

    /* ═══════════════════════════════════════════════════════════════════
       PHASE 2 — TRANSFORMATION EN VIGNETTE (déclenchée par JS)
       Ne démarre QUE lorsque les 5 planètes ont toutes fini leur trajet et
       sont posées en boule à leur place : main.js écoute la fin
       ("animationend") de heroPlanetTravel/heroPlanetTravelCenter sur les 5
       vignettes puis, une fois les 5 reçues, ajoute la classe
       .is-all-landed sur .hero-content. Avant ce moment, AUCUNE vignette ne
       se déploie — même celle arrivée en premier (le centre, "Création
       site web") attend les autres. Léger décalage entre les 5 une fois le
       feu vert donné (0/.1/.2/.3/.4s) pour garder un effet de cascade dans
       le déploiement lui-même. ═══════════════════════════════════════ */
    .page-service .hero-content.is-all-landed .service-capsule {
        /* fill "both" (et non juste "forwards") : sur les vignettes
           décalées (--refonte/--cloud/--programmation/--conseil ci-dessous,
           animation-delay > 0), ça garde l'état d'arrivée de la PHASE 1
           (identique au frame 0% de heroCapsuleDeploy, cf. plus bas)
           affiché pendant leur délai d'attente propre — sans "both", la
           vignette flasherait un instant à son état non-animé (transform
           "none", etc.) avant que le délai ne s'écoule.
           Durée 1.2s (au lieu de 1s) : les .3s du début sont désormais le
           petit "shake" avant transformation (cf. heroCapsuleDeploy), le
           reste (.9s) est inchangé pour la transformation elle-même.
           Toutes les durées/délais de ce bloc PHASE 2 (déploiement, texte,
           planète) divisés par 2 en plus (chorégraphie raccourcie
           globalement, demande explicite, mêmes proportions conservées). */
        animation: heroCapsuleDeploy .6s cubic-bezier(.16,1,.3,1) both;
    }
    .page-service .hero-content.is-all-landed .service-capsule--refonte {
        animation-delay: .05s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--cloud {
        animation-delay: .1s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--programmation {
        animation-delay: .15s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--conseil {
        animation-delay: .2s;
    }
    /* Centre : démarre le premier (0s). featuredCapsuleGlow tournait ici en
       permanence juste après heroCapsuleDeployCenter — retiré (demande
       explicite : plus de halo par défaut, seulement au survol désormais,
       cf. .service-capsule--featured.is-deployed / :hover plus bas) : dès
       que .is-deployed est posé, cette liste `animation` est de toute façon
       entièrement remplacée. */
    .page-service .hero-content.is-all-landed .service-capsule--featured {
        animation: heroCapsuleDeployCenter .6s cubic-bezier(.16,1,.3,1) both;
    }

    .page-service .hero-content.is-all-landed .service-capsule .capsule-content,
    .page-service .hero-content.is-all-landed .service-capsule .capsule-cta {
        animation: heroOrbitTextReveal .8s ease forwards;
    }
    .page-service .hero-content.is-all-landed .service-capsule--refonte .capsule-content,
    .page-service .hero-content.is-all-landed .service-capsule--refonte .capsule-cta {
        animation-delay: .05s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--cloud .capsule-content,
    .page-service .hero-content.is-all-landed .service-capsule--cloud .capsule-cta {
        animation-delay: .1s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--programmation .capsule-content,
    .page-service .hero-content.is-all-landed .service-capsule--programmation .capsule-cta {
        animation-delay: .15s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--conseil .capsule-content,
    .page-service .hero-content.is-all-landed .service-capsule--conseil .capsule-cta {
        animation-delay: .2s;
    }

    /* Fondu croisé de la planète définitive (cf. @keyframes
       heroPlanetDiscReveal dans le bloc PHASE 2 plus bas) : mêmes délais que
       heroCapsuleDeploy(Center) sur cette même vignette (ci-dessus), pour
       rester bien synchronisée avec l'extinction de la boule. */
    .page-service .hero-content.is-all-landed .service-capsule .capsule-planet-disc {
        animation: heroPlanetDiscReveal .6s cubic-bezier(.16,1,.3,1) both;
    }
    .page-service .hero-content.is-all-landed .service-capsule--refonte .capsule-planet-disc {
        animation-delay: .05s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--cloud .capsule-planet-disc {
        animation-delay: .1s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--programmation .capsule-planet-disc {
        animation-delay: .15s;
    }
    .page-service .hero-content.is-all-landed .service-capsule--conseil .capsule-planet-disc {
        animation-delay: .2s;
    }

    .page-service .hero-grid .service-capsule:hover {
        transform: translate(-50%,-50%) translateY(-6px);
        /* Passe au-dessus du fil/roquette (élevé à 3 pendant ce survol,
           cf. règle :has() plus haut) : la vignette survolée reste
           toujours au premier plan. */
        z-index: 4;
    }

    .page-service .hero-grid .service-capsule.service-capsule--featured:hover {
        transform: translate(-50%,-50%) scale(1.13) translateY(-6px);
    }

    /* ═══════════════════════════════════════════════════════════════════
       PHASE 3 — SURVOL "REDEVIENT PLANÈTE" (desktop uniquement)
       1re tentative (retirée) : essayer de forcer border-radius/background/
       box-shadow au survol par-dessus heroCapsuleDeploy(Center) via
       !important. Ça ne marchait pas : une fois qu'une animation a
       "terminé" en fill both/forwards, elle CONTINUE de gagner sur une
       déclaration normale — mais elle gagne aussi sur les déclarations
       !important dans certains navigateurs pour les propriétés qu'elle
       gère encore activement via la liste `animation` de l'élément (la
       vignette avait toujours heroCapsuleDeploy dans sa liste
       d'animations, jamais retirée) : résultat, rien ne changeait, ou la
       planète apparaissait masquée derrière le rendu figé de la carte.
       Solution robuste : dès que le déploiement de CHAQUE vignette est
       réellement fini (cf. main.js, "animationend" sur heroCapsuleDeploy/
       heroCapsuleDeployCenter -> classe .is-deployed posée sur CETTE
       vignette précise), on retire complètement heroCapsuleDeploy(Center) de
       sa liste `animation` (animation:none — y compris featuredCapsuleGlow,
       qui ne reprend désormais qu'au survol, cf. plus bas : la garder active
       en permanence forçait box-shadow à chaque frame et empêchait
       "box-shadow: none" de s'appliquer par défaut) et on fige ses valeurs
       finales en dur (mêmes valeurs que le 100% du keyframe). Plus aucune
       animation ne contrôle alors transform/border-radius/background/
       box-shadow/opacity : un simple
       :hover classique (transition, sans !important) peut enfin reprendre
       la main normalement. ═══════════════════════════════════════════ */
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed {
        animation: none;
        opacity: 1;
        transform: translate(-50%,-50%) rotate(0deg) scale(1);
        border-radius: 24px;
        background-color: transparent;
        background-image: none;
        border-color: transparent;
        box-shadow: none;
        /* Fond encore plus effacé (demande explicite : "je veux vraiment les
           planètes en suspension") : le flou de fond hérité de
           .service-capsule (backdrop-filter) créait encore un voile visible
           même une fois le fond rendu transparent — désactivé par défaut,
           restauré au survol (cf. règle :hover plus bas) en même temps que
           le reste du "look carte". */
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }
    .page-service .hero-content.is-all-landed .service-capsule--featured.is-deployed {
        /* Corrigé (le fond n'était pas effacé pour "Création site web" : le
           halo featuredCapsuleGlow tournait encore EN PERMANENCE ici, et ses
           keyframes forcent box-shadow à chaque frame — une animation
           active gagne toujours sur une déclaration normale pour les
           propriétés qu'elle pilote, donc notre "box-shadow: none"
           ci-dessous n'avait jamais d'effet réel tant que cette animation
           restait active par défaut). Elle est donc retirée par défaut, tout
           comme heroCapsuleDeployCenter (animation: none, comme le reste),
           et ne reprend qu'au survol (cf. .service-capsule--featured.
           is-deployed:hover plus bas) : fond/bordure/ombre/halo masqués
           comme les autres tant qu'on ne survole pas. */
        animation: none;
        transform: translate(-50%,-50%) rotate(0deg) scale(1.09);
        background-color: transparent;
        border-color: transparent;
        box-shadow: none;
    }

    /* Comportement par défaut (demande explicite) : sans survol, on ne voit
       QUE la planète (.capsule-planet-disc) en suspension + le texte
       descriptif (.capsule-content, toujours visible, cf. plus haut) — tout
       le reste du "look carte" (fond/bordure/ombre/grille/liseré, point de
       statut en haut à droite, icône du hublot en haut à gauche, CTA
       "Explorer") reste masqué tant qu'on ne survole pas. Le survol inverse
       ça : planète masquée, carte révélée (cf. règles :hover plus bas). */
    /* animation: none — sans ça, l'animation heroPlanetDiscReveal (posée plus
       haut, fill-mode "both") reste active indéfiniment sur cet élément et
       son opacité de fin (1) prime TOUJOURS sur une déclaration normale,
       même plus spécifique (:hover incluse) : la planète ne pouvait donc
       jamais réellement disparaître au survol tant que cette animation
       n'était pas explicitement coupée ici. */
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed .capsule-planet-disc {
        animation: none;
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
    }

    .page-service .hero-content.is-all-landed .service-capsule.is-deployed::before,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed::after,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed .capsule-porthole,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed .capsule-seam,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed .capsule-cta {
        opacity: 0;
    }

    /* Même souci que .capsule-planet-disc ci-dessus : .capsule-status porte
       nativement une animation infinie (capsuleStatusPulse, cf. règle de
       base) qui, elle aussi, prime en permanence sur "opacity: 0" — sans la
       couper ici, le point lumineux restait visible (en pulsant) même hors
       survol. Isolé de la liste ci-dessus pour pouvoir lui couper SON
       animation spécifiquement. */
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed .capsule-status {
        animation: none;
        opacity: 0;
    }

    /* Survol : la planète s'efface et la carte (fond/bordure/ombre/flou)
       reprend le dessus — léger lift -6px conservé comme retour visuel du
       survol (indépendant de l'inversion planète/carte ci-dessus) + le
       scale(1.09) propre au centre. Fond/bordure/ombre/flou restaurés aux
       mêmes valeurs que l'ancien état "carte" par défaut (cf.
       .service-capsule / .service-capsule--featured de base plus haut). */
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover {
        transform: translate(-50%,-50%) translateY(-6px) scale(1);
        background-color: rgba(7,10,18,.78);
        border-color: rgba(255,255,255,.07);
        box-shadow: none;
        backdrop-filter: blur(20px);
        -webkit-backdrop-filter: blur(20px);
        /* Passe au-dessus du fil/roquette (élevé à 3 pendant ce survol, cf.
           règle :has() plus haut) : la vignette survolée reste toujours au
           premier plan. */
        z-index: 4;
    }
    .page-service .hero-content.is-all-landed .service-capsule--featured.is-deployed:hover {
        /* Le halo pulsant (featuredCapsuleGlow) ne reprend qu'ici, pendant le
           survol — cf. commentaire sur .service-capsule--featured.is-deployed
           plus haut : il ne doit plus tourner en permanence, seulement quand
           la carte est révélée. Corrigé (demande explicite : cette vignette
           reste TOUJOURS bleue) : background-color/box-shadow utilisaient
           encore rgb(var(--header-accent)) au lieu du bleu fixe déjà posé sur
           border-color juste en dessous — remplacés par le même bleu
           (#3b82f6 / rgba(59,130,246,...)) que .service-capsule--featured de
           base, pour ne plus suivre la couleur active au survol. */
        animation: featuredCapsuleGlow 3.4s ease-in-out infinite;
        transform: translate(-50%,-50%) translateY(-6px) scale(1.09);
        background-color: rgba(59,130,246,.12);
        border-color: rgba(59,130,246,.55);
        box-shadow: 0 22px 55px rgba(59,130,246,.24), 0 10px 26px rgba(0,0,0,.30);
    }

    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover .capsule-planet-disc {
        opacity: 0;
        transform: translate(-50%, -50%) scale(.82);
    }

    /* Contenu carte (grille de fond, liseré bas, point de statut, hublot,
       séparateur, CTA) : révélé en fondu le temps du survol, planète
       masquée pendant ce temps. .capsule-content (titre + texte) n'est PAS
       concerné : il reste affiché en permanence (cf. commentaire plus
       haut), donc pas de bascule d'opacité ici pour lui. */
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover::before,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover::after,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover .capsule-porthole,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover .capsule-seam,
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover .capsule-cta {
        opacity: 1;
    }

    /* Point de statut : ne redevient visible qu'au survol, et ne se remet à
       pulser (capsuleStatusPulse) que là aussi — cf. animation:none posé par
       défaut juste au-dessus. */
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover .capsule-status {
        animation: capsuleStatusPulse 2.8s ease-in-out infinite;
        opacity: 1;
    }

    /* Icône du hublot (en haut à gauche de la vignette) remplacée par la
       texture de LA planète de cette vignette pendant le survol (demande
       explicite) — le hublot lui-même ne redevient visible qu'au survol
       (cf. règle d'opacité juste au-dessus), c'est donc uniquement SON
       CONTENU qui change ici : l'icône ligne (boussole/nuage/chevrons/
       cœur) s'efface au profit d'une miniature de --capsule-planet-img
       (même variable que .capsule-planet-disc plus haut, cf.
       .service-capsule--refonte/--cloud/--programmation/--conseil). */
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover .porthole-inner {
        background-image: var(--capsule-planet-img);
        background-size: cover;
        background-position: center;
    }
    .page-service .hero-content.is-all-landed .service-capsule.is-deployed:hover .porthole-inner svg {
        opacity: 0;
    }
    @media (prefers-reduced-motion: reduce) {
        .page-service .hero-content,
        .page-service .hero-content * {
            animation-duration: .01s !important;
            animation-delay: 0s !important;
            animation-iteration-count: 1 !important;
            transition-duration: .01s !important;
            transition-delay: 0s !important;
        }
        /* Roquettes SVG (<animateMotion>, SMIL — non couvertes par les
           propriétés CSS animation/transition ci-dessus) : purement
           décoratives et non indispensables au parcours. */
        .orbit-rocket {
            display: none !important;
        }
    }

}

/* PHASE 1 — TRAJET (heroPlanetTravel) : la vignette n'est encore qu'une
   "planète" (boule) qui sort du trou noir et rejoint sa position, elle ne
   se transforme PAS en vignette ici (cf. PHASE 2, heroCapsuleDeploy plus
   bas, déclenchée séparément par JS une fois les 5 planètes en place).
   top/left animés en plus de transform/opacity/etc. : la boule part
   littéralement du trou noir d'entrée (--hole-top/--hole-left, cf.
   .hero-black-hole et .page-service .hero-grid .service-capsule) entre 0%
   et 15% (elle y tourne sur place, encore minuscule, le temps de bien
   marquer sa "naissance" au trou noir), puis VOYAGE en ligne droite
   jusqu'à sa position finale (--settle-top/--settle-left, propre à chaque
   vignette --refonte/--cloud/--programmation/--conseil) entre 15% et
   100% — rotation qui ralentit jusqu'à une vitesse de croisière lente
   plutôt que de s'arrêter net (cf. .16,1,.3,1 sur ce dernier tronçon),
   pour qu'elle ait l'air "posée mais toujours vivante" en boule une fois
   arrivée, dans l'attente de la PHASE 2. Durée volontairement courte (cf.
   animation-duration sur .service-capsule/--cloud/--programmation/
   --conseil) : le trajet doit être vif, contrairement à l'attente qui
   peut durer le temps que les autres planètes arrivent. */
/* Traînée lumineuse pendant le trajet (demande explicite) : lueur externe
   colorée (var(--capsule-color), même teinte que la sphère) ajoutée EN PLUS
   des ombres internes existantes — pleine intensité de 15% à 70% (tout le
   "vol"), puis rejoint la valeur de repos (aucune lueur externe) à 100%,
   pile à l'instant où heroPlanetIdleSpin prend le relais avec exactement
   le même box-shadow "nu" : aucun saut visuel à l'atterrissage, la lueur
   s'éteint juste avant. 70% n'a besoin de redéclarer QUE box-shadow — les
   autres propriétés (top/left/transform...) continuent de s'interpoler
   normalement entre 15% et 100%. */
@keyframes heroPlanetTravel {
    0%   { top: var(--hole-top); left: var(--hole-left); transform: translate(-50%,-50%) rotate(-720deg) scale(.28); opacity: 0; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: linear; }
    15%  { top: var(--hole-top); left: var(--hole-left); transform: translate(-50%,-50%) rotate(-612deg) scale(.28); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 34px 10px var(--capsule-color); }
    70%  { box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 34px 10px var(--capsule-color); }
    100% { top: var(--settle-top); left: var(--settle-left); transform: translate(-50%,-50%) rotate(-90deg) scale(.28); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: cubic-bezier(.16,1,.3,1); }
}

/* PHASE 1.5 — ATTENTE (heroPlanetIdleSpin) : une fois posée (fin de
   heroPlanetTravel ci-dessus), la boule continue de tourner doucement sur
   elle-même en boucle, le temps que les autres planètes arrivent à leur
   tour (cf. animation-delay 2e valeur sur .service-capsule de base et par
   vignette, calé pour démarrer pile à la fin DU TRAJET PROPRE à chacune).
   0% reprend très exactement l'état d'arrivée de heroPlanetTravel
   (rotate(-90deg) scale(.28), même fond "planète") pour un enchaînement
   sans à-coup ; 100% = +360° (un tour complet), boucle "infinite" douce et
   linéaire. Toutes les propriétés du "look boule" (opacity, border-radius,
   fond, ombre) sont réaffirmées à chaque palier — même raison que pour
   heroCapsuleDeploy plus bas : sans ça, dès que cette animation prend le
   relais de heroPlanetTravel, les propriétés qu'elle ne mentionne pas
   retomberaient sur les valeurs statiques non animées de .service-capsule
   (opacity:0 notamment). Remplacée entièrement (comme heroPlanetTravel)
   par heroCapsuleDeploy dès que .is-all-landed apparaît. */
@keyframes heroPlanetIdleSpin {
    0%   { transform: translate(-50%,-50%) rotate(-90deg) scale(.28); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    100% { transform: translate(-50%,-50%) rotate(-450deg) scale(.28); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
}

/* PHASE 2 — DÉPLOIEMENT (heroCapsuleDeploy) : reprend très exactement
   l'état d'arrivée de heroPlanetTravel ci-dessus (même rotate/scale/fond
   "planète" à 0%) pour un enchaînement sans à-coup. Avant de se
   transformer, la boule tremble légèrement sur place (0%->30%, cf.
   translate(x,y) ajouté APRÈS le translate(-50%,-50%) de centrage — un
   simple décalage additionnel en pixels, qui ne perturbe donc pas
   l'ancrage de la vignette) : un petit "shake" pour marquer le moment où
   elle s'apprête à se déployer. Termine ensuite (30%->100%, demande
   explicite : plus de stade "vignette" carrée visible entre le shake et
   l'état final) en s'éteignant sur place (couleur/image/bordure/ombre vers
   transparent, ENCORE petite et ronde, cf. palier 75% plus bas) avant de
   grandir jusqu'aux dimensions réelles de la carte une fois invisible —
   .capsule-planet-disc prend le relais visuel entre-temps (fondu croisé,
   cf. .service-capsule.is-deployed plus haut). Jamais lancée
   automatiquement : uniquement via la classe .is-all-landed posée par JS
   sur .hero-content (cf. règles plus haut), une fois les 5 planètes
   arrivées.
   opacity:1 explicite à chaque palier (important !) : quand cette
   animation remplace heroPlanetTravel (qui, lui, pilotait l'opacité), la
   propriété doit rester sous contrôle du keyframe tout du long — sinon,
   pendant l'intervalle où AUCUNE des deux animations ne déclare opacity,
   le navigateur retombe sur la valeur non animée de .service-capsule
   (opacity:0 statique), ce qui faisait disparaître la vignette au lieu de
   la voir se transformer. */
@keyframes heroCapsuleDeploy {
    0%   { opacity: 1; transform: translate(-50%,-50%) translate(0,0)     rotate(-90deg) scale(.28); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: ease-in-out; }
    6%   { opacity: 1; transform: translate(-50%,-50%) translate(-5px,1px)  rotate(-90deg) scale(.28); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    12%  { opacity: 1; transform: translate(-50%,-50%) translate(4px,-2px)  rotate(-90deg) scale(.28); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    18%  { opacity: 1; transform: translate(-50%,-50%) translate(-4px,2px)  rotate(-90deg) scale(.28); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    24%  { opacity: 1; transform: translate(-50%,-50%) translate(2px,-1px)  rotate(-90deg) scale(.28); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    30%  { opacity: 1; transform: translate(-50%,-50%) translate(0,0)     rotate(-90deg) scale(.28); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: cubic-bezier(.16,1,.3,1); }
    /* Corrigé (demande explicite : "avant la phase finale elle passe par le
       stade vignette, je ne veux pas — shake puis état final") : la boule ne
       doit plus jamais se dérouler en carte rectangulaire opaque. Elle reste
       d'abord identique à 30% (60% : même transform, rien ne bouge — la
       boule "tient" son état posé) puis s'éteint (couleur/image/bordure/
       ombre vers transparent) PENDANT qu'elle est ENCORE petite et ronde
       (60%->90%), pendant que .capsule-planet-disc apparaît en fondu croisé
       à SA place (cf. @keyframes heroPlanetDiscReveal plus bas — même axe
       temporel, décalée pour se chevaucher avec cette extinction, pas de
       "trou" entre les deux). Seule ENSUITE (90%->100%), une fois
       invisible, la boîte grandit jusqu'à ses dimensions réelles de carte —
       un changement de taille/forme totalement imperceptible puisque rien
       n'y est plus dessiné. */
    60%  { opacity: 1; transform: translate(-50%,-50%) rotate(-90deg) scale(.28); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    90%  { opacity: 1; transform: translate(-50%,-50%) rotate(-90deg) scale(.28); border-radius: 50%; background-color: transparent; background-image: none; border-color: transparent; box-shadow: none; }
    100% { opacity: 1; transform: translate(-50%,-50%) rotate(0deg) scale(1); border-radius: 24px; background-color: transparent; background-image: none; border-color: transparent; box-shadow: none; }
}

/* Fondu croisé de .capsule-planet-disc (texture planète définitive, cf.
   .capsule-planet-disc de base plus haut) pendant la 2e moitié de
   heroCapsuleDeploy/heroCapsuleDeployCenter : reste masquée pendant le shake
   ET le début de l'extinction de la boule (0%->55%), puis apparaît en fondu
   (55%->100%) pour se superposer à l'extinction de la boule (60%->90% sur le
   conteneur parent, cf. ci-dessus) sans jamais laisser de "trou" où ni l'une
   ni l'autre ne serait visible. Mêmes délai/durée/cadence que
   heroCapsuleDeploy(Center) sur cette même vignette (cf. règles
   ".is-all-landed .service-capsule--X .capsule-planet-disc" plus haut) pour
   rester parfaitement synchronisée. Une fois terminée (opacity:1, scale(1)),
   ces valeurs sont ensuite reprises à l'identique par .service-capsule.
   is-deployed .capsule-planet-disc (état de repos permanent) : aucun saut au
   moment où JS pose .is-deployed. */
@keyframes heroPlanetDiscReveal {
    0%, 55% { opacity: 0; transform: translate(-50%, -50%) scale(.6); }
    100%    { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* Le centre (--featured) fait 400×300px (rectangle 4:3, pas carré) : un
   scale() uniforme donne donc une boule OVALE (ratio conservé). Pour
   une vraie boule ronde pendant la phase 1, on compense avec un scale
   non-uniforme scale(sx, sy) où sy = sx × 4/3 (400×.25 = 300×.333 =
   ~100px des deux côtés → cercle). Au repos (100%), on repasse à un
   scale() uniforme classique qui restaure le vrai rectangle 400×300 — fond/
   halo restent transparents par défaut comme les 4 autres (featuredCapsuleGlow
   ne reprend qu'au survol désormais, cf. .service-capsule--featured.
   is-deployed:hover).
   Même découpage en 2 phases que heroPlanetTravel/heroCapsuleDeploy
   ci-dessus : le centre ne voyage pas (déjà posé sur l'ancre du trou
   noir), mais attend lui aussi la classe .is-all-landed avant de se
   transformer — cf. heroCapsuleDeployCenter plus bas. */
/* Même traînée lumineuse que heroPlanetTravel (satellites) ci-dessus,
   appliquée au centre. */
@keyframes heroPlanetTravelCenter {
    0%   { transform: translate(-50%,-50%) rotate(612deg) scale(.25, .333); opacity: 0; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: linear; }
    15%  { transform: translate(-50%,-50%) rotate(520deg) scale(.25, .333); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 34px 10px var(--capsule-color); }
    70%  { box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 34px 10px var(--capsule-color); }
    100% { transform: translate(-50%,-50%) rotate(80deg) scale(.25, .333); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: cubic-bezier(.16,1,.3,1); }
}

/* Flash d'impact à l'atterrissage (demande explicite) : un bref anneau
   lumineux qui se propage et se dissipe, déclenché pile au moment où
   heroPlanetTravel(Center) se termine et heroPlanetIdleSpin(Center) prend
   le relais (même délai que la 2e animation de la liste, cf. .service-
   capsule/--refonte/--cloud/--programmation/--conseil/--featured plus
   haut). Un 3e "calque" de box-shadow, EN PLUS des ombres internes de la
   sphère (déjà pilotées par heroPlanetIdleSpin en parallèle) : 0% et 100%
   correspondent exactement au box-shadow "au repos" (aucun saut visuel
   avant/après), le pic (30%) ajoute un anneau externe large et diffus qui
   se referme et s'efface aussitôt. */
@keyframes heroLandingFlash {
    0%   { box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 0 0 var(--capsule-color); }
    30%  { box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 55px 22px var(--capsule-color); }
    100% { box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22), 0 0 0 0 rgba(0,0,0,0); }
}

/* Même principe que heroPlanetIdleSpin (satellites) : rotation d'attente
   continue une fois heroPlanetTravelCenter terminé, en repartant très
   exactement de son état d'arrivée (rotate(80deg) scale(.25,.333)). */
@keyframes heroPlanetIdleSpinCenter {
    0%   { transform: translate(-50%,-50%) rotate(80deg) scale(.25, .333); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    100% { transform: translate(-50%,-50%) rotate(-280deg) scale(.25, .333); opacity: 1; border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
}

/* Même petit "shake" que heroCapsuleDeploy ci-dessus (0%->30%), puis même
   correctif (30%->100% : extinction sur place avant croissance invisible,
   plus de stade "vignette" visible — cf. commentaire détaillé sur
   heroCapsuleDeploy plus haut). */
@keyframes heroCapsuleDeployCenter {
    0%   { opacity: 1; transform: translate(-50%,-50%) translate(0,0)     rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: ease-in-out; }
    6%   { opacity: 1; transform: translate(-50%,-50%) translate(-5px,1px)  rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    12%  { opacity: 1; transform: translate(-50%,-50%) translate(4px,-2px)  rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    18%  { opacity: 1; transform: translate(-50%,-50%) translate(-4px,2px)  rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    24%  { opacity: 1; transform: translate(-50%,-50%) translate(2px,-1px)  rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    30%  { opacity: 1; transform: translate(-50%,-50%) translate(0,0)     rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); animation-timing-function: cubic-bezier(.16,1,.3,1); }
    /* Même correctif que heroCapsuleDeploy ci-dessus (demande explicite :
       plus de stade "vignette" visible, shake puis état final directement) :
       tient d'abord son état posé (60%), puis la couleur/bordure/ombre
       s'éteint pendant que la boule est ENCORE petite et ronde (60%->90%),
       en même temps que .capsule-planet-disc apparaît en fondu croisé (cf.
       @keyframes heroPlanetDiscReveal plus bas) — la boîte ne grandit
       jusqu'au rectangle final QU'UNE FOIS invisible (90%->100%). Fond/halo
       permanents (featuredCapsuleGlow) ne reprennent qu'au survol désormais
       (cf. .service-capsule--featured.is-deployed:hover), donc plus de
       couleur ici non plus par défaut. */
    60%  { opacity: 1; transform: translate(-50%,-50%) rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: var(--capsule-color); background-image: var(--capsule-planet-img); background-size: cover; background-position: center; box-shadow: inset -22px -22px 46px rgba(0,0,0,.45), inset 16px 16px 32px rgba(255,255,255,.22); }
    90%  { opacity: 1; transform: translate(-50%,-50%) rotate(80deg) scale(.25, .333); border-radius: 50%; background-color: transparent; background-image: none; border-color: transparent; box-shadow: none; }
    100% { opacity: 1; transform: translate(-50%,-50%) rotate(0deg) scale(1.09); border-radius: 24px; background-color: transparent; background-image: none; border-color: transparent; box-shadow: none; }
}

/* Apparition (seulement) du trou noir d'entrée (cf. .hero-black-hole) :
   "dézoom" — opacity reste à 1 du début à la fin, c'est le scale qui fait
   tout le travail (16 -> 1, autour du même point translate(-50%,-50%) déjà
   fixé sur l'élément). Fill "forwards" : la dernière image (scale 1) est
   conservée indéfiniment, le trou noir ne redisparaît jamais, il reste en
   fond en permanence. Le disque (::before) et l'horizon (::after)
   continuent en parallèle de tourner/pulser via leurs propres animations
   infinite, indépendamment de ce scale qui ne porte que sur le conteneur
   parent. */
@keyframes heroBlackHoleLife {
    /* 0% à opacity:0 (et non 1) : avec "animation-fill-mode: both", cette
       frame reste affichée STATIQUEMENT pendant tout le animation-delay
       (cf. .index-hero-black-hole : var(--reveal-delay)). Avant, opacity:1
       ici rendait le trou noir immense visible dès le chargement, pendant
       toute la frappe du tagline — demande explicite : il ne doit
       apparaître qu'une fois "votre présence dans l'espace numérique"
       entièrement affiché. À 1%, l'opacité bascule à 1 (toujours à
       scale(16)) : le trou noir apparaît donc et commence à dézoomer dans
       le même instant, sans palier statique visible avant le rétrécissement. */
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(16); }
    1%   { opacity: 1; transform: translate(-50%, -50%) scale(16); }
    100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* Fermeture (demande explicite) : mouvement inverse et symétrique du
   dézoom d'entrée ci-dessus — le trou noir se réduit jusqu'à un point puis
   disparaît, plutôt que de rester indéfiniment (cf. .is-all-landed
   .hero-black-hole plus haut pour le déclenchement/délai). Tenue à
   scale(1) jusqu'à 15% (petite marge avant que la fermeture ne démarre
   réellement, cf. .hero-black-hole::before/::after qui continuent de
   tourner/pulser sans interruption pendant ce temps). */
@keyframes heroBlackHoleClose {
    0%, 15% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    85%     { opacity: 1; transform: translate(-50%, -50%) scale(.04); }
    100%    { opacity: 0; transform: translate(-50%, -50%) scale(0); }
}

/* NOTE (chorégraphie raccourcie globalement d'un facteur ~0.5, demande
   explicite) : les valeurs ABSOLUES citées ci-dessous (1.2s, 1.6s, 1.4s,
   0.2s...) sont celles d'AVANT ce raccourcissement — les pourcentages du
   keyframe (87.5%, 100%) sont eux inchangés et restent exacts avec les
   durées actuelles (heroCapsuleDeploy .6s / heroOrbitTextReveal .8s, cf.
   règles plus haut) : le raisonnement proportionnel ci-dessous reste
   valable tel quel, seules les secondes absolues ont été divisées par 2.
   Re-retardé (demande explicite : "il ne doit y avoir que la planète de
   visible jusqu'à son arrivée, +0.2s avant l'arrivée du texte") : la seule
   tenue à 70% d'une durée PARTAGÉE avec heroCapsuleDeploy (1.2s) laissait
   encore le texte commencer à apparaître pendant la fin de l'atterrissage
   de la boule. Ici, la durée de CETTE animation est allongée à 1.6s (au
   lieu de 1.2s, cf. règle ".is-all-landed .service-capsule .capsule-content,
   .capsule-cta" plus haut) tout en gardant le même animation-delay par
   vignette (0/.1/.2/.3/.4s) que heroCapsuleDeploy(Center) : le texte reste
   donc à opacity:0 pendant 87.5% de 1.6s = 1.4s, soit EXACTEMENT les 1.2s
   du déploiement complet de la boule/planète (heroCapsuleDeploy, jusqu'à ce
   que .capsule-planet-disc soit à 100% visible) + 0.2s de marge avant que le
   texte ne commence son propre fondu (les 0.2s/12.5% restants). */
@keyframes heroOrbitTextReveal {
    0%, 87.5% { opacity: 0; }
    100%      { opacity: 1; }
}

@keyframes heroOrbitLineFade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Arrivée du logo/titre (cf. .services-hero-logo, .hero-content.is-all-landed) :
   simple fondu, volontairement sans toucher transform (déjà occupé par
   floatSub, la flottaison continue du logo — cf. commentaire sur la règle
   gated). */
@keyframes heroLogoArrive {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ─── SECTIONS LAYOUT — section + divider = 100dvh ─── */
/* Chaque section (sauf la dernière) est suivie d'un .section-divider
   (160px) menant à la section suivante : on retranche cette hauteur (+ les
   25px de SCROLL_OFFSET laissés en haut à l'arrivée par ancre, cf. main.js)
   pour que section + divider tiennent ensemble dans un seul écran quand on
   arrive sur l'ancrage. La dernière section (--last) n'a pas de divider
   qui suit : elle reprend quasi 100dvh plein écran (voir plus bas). */
.page-service .section-block {
    padding: 100px clamp(1rem, 4vw, 3rem);
    position: relative;
    min-height: calc(100dvh - 185px);
    display: flex;
    align-items: center;
    justify-content: center;

    opacity: 0;
    transform: perspective(1100px) translateZ(-120px) translateY(60px);
    transition:
        opacity 1.1s cubic-bezier(0.16, 1, 0.3, 1),
        transform 1.1s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: transform, opacity;
}

.page-service .section-block.section-block--last {
    min-height: calc(100dvh - 25px);
}

.section-block.is-visible {
    opacity: 1;
    transform: perspective(1100px) translateZ(0) translateY(0);
}

/* ─── DIVIDER : ligne se dessine puis la fusée tombe ─── */
.section-divider {
    min-height: 160px;
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

/* margin-top calé pour passer sous l'étiquette-texte de .divider-action
   (toujours visible, pas juste au survol : top:calc(100% + 14px) + ~27px de
   hauteur propre ≈ 41px sous la bulle) plutôt que sous la seule bulle — sinon
   la ligne traverse le texte au lieu de s'afficher après lui. Ordre voulu,
   de haut en bas : fusée, texte, barre. */
.section-divider .divider-line {
    width: 140px;
    max-width: 40%;
    height: 2px;
    margin: 41px auto 0;
    border-radius: 2px;
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.55), transparent);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}

.section-divider.is-visible .divider-line {
    transform: scaleX(1);
}

.section-divider .rocket-wrapper {
    opacity: 0;
    transform: translateY(-47px) scale(0.6);
    transition:
        opacity 0.5s ease 0.55s,
        transform 0.65s cubic-bezier(0.34, 1.56, 0.64, 1) 0.55s;
}

/* +8px sur la position finale (fusée un peu trop haute par rapport à la
   ligne juste en dessous, sur accueil.php ET services.php — règle non
   scopée, donc partagée par toutes les pages avec ce système de divider). */
.section-divider.is-visible .rocket-wrapper {
    opacity: 1;
    transform: translateY(8px) scale(1);
}

/* ─── ACCUEIL.PHP : espacement uniforme des 8 dividers inter-sections ───
   Chacun avait son propre traitement au cas par cas (certains gardaient le
   min-height:160px hérité de la règle générique ci-dessus, d'autres avaient
   été rapiécés séparément, et celui de la hero n'était même pas un
   .section-divider) : le rythme vertical variait d'une transition à
   l'autre. On unifie ici en une seule règle, avec un écart cohérent avant
   la bulle — y compris pour le divider de la hero, désormais structuré à
   l'identique. .site-main est propre à accueil.php (vérifié : aucune autre
   page ne porte cette classe), donc ceci ne touche pas les dividers de
   offres-site.php. */
.site-main .section-divider {
    min-height: 0;
    padding: 0;
    margin-top: clamp(18px, 3vh, 32px);
    margin-bottom: 0;
}

.site-main .section-divider .rocket-wrapper {
    padding: 10px 50px;
}

.layout-split {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 80px;
    max-width: 1400px;
    width: 100%;
    margin: 0 auto;
}

.layout-right { flex-direction: row-reverse; }

/* ========================= GALAXY TITLE BUBBLE ========================= */

@keyframes galaxyRotate {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@keyframes galaxyPulse {
    0%, 100% { box-shadow: 0 0 28px rgba(70,30,130,.16), 0 0 56px rgba(70,30,130,.06); }
    50%       { box-shadow: 0 0 44px rgba(70,30,130,.26), 0 0 88px rgba(70,30,130,.10); }
}

@keyframes galaxyPulseBlue {
    0%, 100% { box-shadow: 0 0 28px rgba(8,70,180,.18), 0 0 56px rgba(8,70,180,.07); }
    50%       { box-shadow: 0 0 44px rgba(8,70,180,.30), 0 0 88px rgba(8,70,180,.12); }
}

@keyframes galaxyPulseCyan {
    0%, 100% { box-shadow: 0 0 28px rgba(4,120,155,.18), 0 0 56px rgba(4,120,155,.07); }
    50%       { box-shadow: 0 0 44px rgba(4,120,155,.30), 0 0 88px rgba(4,120,155,.12); }
}

.title-bubble {
    flex: 0 0 380px;
    width: 380px;
    height: 380px;
    border-radius: 50%;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: clamp(2.1rem, 1.8vw, 2.55rem);
    font-weight: 800;
    letter-spacing: -.02em;
    color: #ffffff;
    padding: 0;

    --galaxy-speed: 22s;

    opacity: 0;
    transform: scale(0.08) rotate(-300deg);
    transition:
        opacity 0.85s cubic-bezier(0.16, 1, 0.3, 1) 0.2s,
        transform 1.1s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s;
    will-change: transform, opacity;
}

.section-block.is-visible .title-bubble {
    opacity: 1;
    transform: scale(1) rotate(0deg);
}

.title-bubble::before {
    content: "";
    position: absolute;
    inset: -10%;
    border-radius: 50%;
    background: conic-gradient(
        from 0deg,
        rgba(8,60,180,0)    0deg,
        rgba(8,60,180,.18)  28deg,
        rgba(8,60,180,0)    58deg,
        rgba(70,30,150,0)   118deg,
        rgba(70,30,150,.12) 148deg,
        rgba(70,30,150,0)   178deg,
        rgba(4,100,140,0)   238deg,
        rgba(4,100,140,.10) 268deg,
        rgba(4,100,140,0)   298deg,
        rgba(8,60,180,0)    360deg
    );
    animation: galaxyRotate var(--galaxy-speed) linear infinite;
    pointer-events: none;
    z-index: 0;
}

.title-bubble::after {
    content: "";
    position: absolute;
    inset: 20%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255,255,255,.07) 0%, transparent 70%);
    pointer-events: none;
    z-index: 0;
}

/* Voyage : zoom + accélération de rotation */
.title-bubble:hover {
    transform: scale(1.08);
    transition:
        transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0s,
        opacity 0s;
}
.section-title--essentiel {
    /* Corrigé (demande explicite : "il faut mettre galaxy web dans la
       bulle titre Création site web") : le fichier réel s'appelle
       galaxie-web.png (cf. assets/image/ et les 2 autres usages plus bas
       dans ce fichier) — "Galaxy-web.png" n'existait pas, l'image ne
       s'affichait donc jamais, seuls le glow bleu (galaxyPulseBlue) et la
       bordure restaient visibles. */
    background-image: url('../image/galaxie-web.png');
    /* cover seul ne laissait aucune marge verticale dans ce cercle 380px
       (la hauteur de la source cale exactement sur la hauteur de la boîte),
       ce qui exposait tel quel le bord haut tronqué du fichier source.
       170% auto crée de la marge, "center bottom" recadre vers le bas pour
       masquer ce bord tronqué. */
    background-size: 170% auto;
    background-position: center bottom;
    border: 1px solid rgba(30,65,165,.16);
    animation: galaxyPulseBlue 9s ease-in-out infinite;
    transition: background-image 0.3s ease;
}

/* Demande explicite : le bouton-titre "Création site web" doit devenir
   bleu au survol (comme les 4 autres titres de services.php ci-dessous),
   plutôt que son ancien bleu-marine quasi noir. */
.section-title--essentiel:hover {
    background-image: none;
    background-color: rgba(59,130,246,.92);
}

/* Demande explicite : le titre "Hébergement et maintenance" (section 4)
   passe de la galerie-galaxie teintée cyan à la texture planet-blanc,
   et devient bleu au survol (comme les 4 autres titres). */
.section-title--pro {
    background-image: url('../image/planet-blanc.webp');
    background-size: cover;
    background-position: center;
    border: 1px solid rgba(4,100,140,.16);
    animation: galaxyPulseCyan 9s ease-in-out infinite;
    transition: background-image 0.3s ease;
}

.section-title--pro:hover {
    background-image: none;
    background-color: rgba(59,130,246,.92);
}

/* Demande explicite : le titre "Conseil et accompagnement" (section 6)
   passe de la galerie-galaxie teintée violette à la texture planet-violet,
   et devient bleu au survol (comme les 4 autres titres). */
.section-title--surmesure {
    background-image: url('../image/planet-violet.webp');
    background-size: cover;
    background-position: center;
    border: 1px solid rgba(65,22,140,.16);
    animation: galaxyPulse 9s ease-in-out infinite;
    transition: background-image 0.3s ease;
}

.section-title--surmesure:hover {
    background-image: none;
    background-color: rgba(59,130,246,.92);
}

.section-title-link {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    text-decoration: none;
    color: inherit;
    width: 100%;
    padding: 20px;
}

.section-title-main {
    display: block;
    line-height: 1.2;
    text-shadow:
        0 2px 8px rgba(0,0,0,.95),
        0 0 24px rgba(0,0,0,.85),
        0 0 2px rgba(0,0,0,1);
}

.section-title-sub {
    display: inline-block;
    margin-top: 12px;
    font-size: .44em;
    font-weight: 500;
    opacity: .90;
    padding: 6px 12px;
    position: relative;
    text-align: center;
    transition: opacity .25s ease;
    color: rgba(255,255,255,.92);
    text-shadow:
        0 1px 6px rgba(0,0,0,.95),
        0 0 16px rgba(0,0,0,.85);
}

.section-title-sub::before,
.section-title-sub::after {
    content: "";
    display: block;
    width: 60%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(160,210,255,.55), transparent);
    margin: 0 auto;
}

.section-title-sub::before { margin-bottom: 6px; }
.section-title-sub::after  { margin-top: 6px; }
.title-bubble:hover .section-title-sub { opacity: 1; }

/* ─── OFFERS GRID ─── */
.layout-split .offers-grid {
    flex: 1;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 220px));
    gap: 80px 120px;
    justify-content: center;
    align-items: start;
}

/* « Création web » a 3 offres au lieu de 1-2 : avec le gap standard de
   120px elles retombent sur 2 colonnes (2 cartes + 1 en dessous), ce qui
   rend cette section bien plus haute que les autres et l'empêche de
   tenir dans un seul écran avec son divider. Un gap resserré permet aux
   3 cartes de tenir sur une seule ligne, comme les autres sections. */
#section-offers .offers-grid {
    gap: 80px 90px;
}


.section-title--essentiel::after,
.section-title--pro::after,
.section-title--surmesure::after,
.section-title--programmation::after,
.section-title--refonte::after {
    transition: opacity 0.6s ease;
    opacity: 0;
}

/* Chaque titre de section a désormais sa PROPRE image de fond au hover
   (demande explicite) au lieu d'une image générique partagée (l'ancienne
   valeur unique "fusee1.png" n'existait même pas dans assets/image, donc
   l'image ne s'affichait jamais, sur aucun des 5 titres) : chaque bouton-
   *-bleu.png est une image dédiée, déjà recadrée en cercle plein cadre
   (600×600, le disque touche les 4 bords du canevas), donc "cover" suffit à
   la faire remplir entièrement la bulle sans aucune marge visible. */
.section-title--essentiel {
    --bubble-img: url('../image/bouton-creation-site-bleu.png');
}
.section-title--refonte {
    --bubble-img: url('../image/bouton-refonte-bleu.png');
}
.section-title--pro {
    --bubble-img: url('../image/bouton-maintenance-hebergement-bleu.png');
}
.section-title--programmation {
    --bubble-img: url('../image/bouton-programmation-bleu.png');
}
.section-title--surmesure {
    --bubble-img: url('../image/bouton-conseil-accompagnement-bleu.png');
}

.section-title--essentiel::after,
.section-title--pro::after,
.section-title--surmesure::after,
.section-title--programmation::after,
.section-title--refonte::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: var(--bubble-img) center / cover;
    mix-blend-mode: overlay;
    pointer-events: none;
    z-index: 1;
    opacity: 0;
    transition: opacity 0.6s ease;
}

.section-title--essentiel:hover::after,
.section-title--pro:hover::after,
.section-title--surmesure:hover::after,
.section-title--programmation:hover::after,
.section-title--refonte:hover::after {
    opacity: 1;
}

/* ========================= PLANET CARDS ========================= */

@keyframes ribbonPulse {
    0%, 100% { box-shadow: 0 0 0    rgba(251,191,36,0); }
    50%       { box-shadow: 0 0 14px rgba(251,191,36,.38); }
}

@keyframes planetSpin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@keyframes highlightFloat {
    0%, 100% { opacity: .22; transform: scale(1); }
    50%       { opacity: .34; transform: scale(1.06); }
}

/* ─── Carte — conteneur principal ─── */
.planet-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 14px;
    text-decoration: none;
    color: inherit;
    background: transparent;
    border: none;

    opacity: 0;
    transform: translateY(100px) scale(0.45);
    filter: blur(8px);
    transition:
        opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.9s cubic-bezier(0.34, 1.56, 0.64, 1),
        filter 0.65s ease;
    will-change: transform, opacity;
    animation: none;
}

.planet-card.is-visible {
    opacity: 0.9;
    transform: translateY(0) scale(1);
    filter: blur(0);
}

.planet-card:nth-child(1) { transition-delay: 0.12s; }
.planet-card:nth-child(2) { transition-delay: 0.28s; }
.planet-card:nth-child(3) { transition-delay: 0.44s; }

.planet-card:hover {
    transform: scale(1.14);
    z-index: 2;
    transition: transform .65s cubic-bezier(0.22, 1, 0.36, 1);
}

/* ─── Sphère ─── */
.planet-sphere {
    position: relative;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    transition: transform .45s ease, box-shadow .45s ease;
}

/* Surface bands — ::before (tourne, clippé par overflow:hidden) */
.planet-sphere::before {
    content: "";
    position: absolute;
    inset: -25%;
    border-radius: 50%;
    pointer-events: none;
    z-index: 1;
    opacity: 0.30;
    animation: planetSpin 40s linear infinite;
}

/* Atmospheric rim — ::after (inner glow sur le bord) */
.planet-sphere::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    pointer-events: none;
    z-index: 3;
}

/* ─── Infos dans la sphère ─── */
.planet-info {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 300px;
    height: 300px;
    border-radius: 50%;
    clip-path: circle(50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 5;
    padding: 28px 20px 16px;
    gap: 8px;
    background: radial-gradient(
        circle at center,
        rgba(0,0,0,.72) 0%,
        rgba(0,0,0,.55) 50%,
        rgba(0,0,0,.28) 72%,
        transparent 90%
    );
}

/* Isolé dans sa propre couche de composition pour un rendu net et
   prévisible (le flou vit désormais sur .planet-info p uniquement, cf.
   juste en dessous — plus sur .planet-info dans son ensemble, demande
   explicite : le titre, lui, doit rester NET par défaut). */
.planet-info {
    isolation: isolate;
    transform: translateX(-50%) translateZ(0);
}

/* Texte quasi illisible au repos, revélé au survol/focus de la carte (même
   logique que .home-service-planet-text sur accueil.php) : flou volontaire,
   désormais porté par la description SEULE (.planet-info p) plutôt que par
   tout .planet-info — demande explicite : "le titre disparaît au survol et
   le descriptif devient lisible", donc titre et description doivent pouvoir
   évoluer indépendamment (l'un net->invisible, l'autre flou->net) plutôt
   qu'ensemble comme avant. Registre "tech"/"spatial" (var(--font-title) =
   JetBrains Mono) conservé sur la description. */
.planet-info p {
    font-family: var(--font-title);
    font-size: .85rem;
    letter-spacing: .01em;
    color: rgba(255,255,255,.95);
    line-height: 1.55;
    margin: 0;
    text-shadow:
        0 1px 6px rgba(0,0,0,.95),
        0 0 16px rgba(0,0,0,.85),
        0 0 2px rgba(0,0,0,1);
    filter: blur(5px);
    transition: filter .4s ease;
}

.planet-card:hover .planet-info p,
.planet-card:focus-visible .planet-info p {
    filter: blur(0);
}

/* Titre superposé au centre de la sphère (demande explicite, "essai") :
   .offer-planet-title réintègre .planet-info (avant la description dans le
   markup, cf. services.php — sections "Création sites web" et "Refonte de
   site & Audit") au lieu de rester sous/à côté de la planète. Net par
   défaut (contrairement à la description juste au-dessus) et c'est l'INVERSE
   qui s'efface au survol : le titre disparaît pendant que la description
   devient nette, pour que les deux ne se chevauchent jamais lisiblement en
   même temps. Scopé à ".planet-info .offer-planet-title" uniquement : les
   sections restées en layout "à côté" (Hébergement, Programmation, Conseil —
   hors de ce changement, cf. .offer-planet-title--beside plus bas) gardent
   leur titre toujours visible, inchangé. */
/* Demande explicite : le titre doit être au MILIEU de la planète, PAR-DESSUS
   le texte descriptif — pas seulement au-dessus de lui dans le flux (ce qui
   ne faisait que l'empiler plus haut dans le même cercle, sans réel
   chevauchement). Sorti du flux de .planet-info (flex column) et centré au
   même repère que la sphère elle-même (.planet-info est déjà positionné
   absolute, top:0/left:50%/translate(-50%), 300×300 — donc top:50%/left:50%
   ici centre le titre EXACTEMENT au milieu du disque) : la description
   (.planet-info p, restée seule dans le flux flex) se retrouve alors
   centrée au même endroit, avec le titre superposé par-dessus (z-index +
   élément positionné, qui peint toujours au-dessus du contenu non
   positionné du même contexte d'empilement). Le crossfade net/flou
   ci-dessous (titre visible/description floutée par défaut, inversé au
   survol) garantit qu'ils ne sont jamais lisibles en même temps malgré ce
   chevauchement. */
.planet-info .offer-planet-title {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;
    width: 80%;
    max-width: 240px;
    opacity: 1;
    transition: opacity .4s ease;
}

.planet-card:hover .planet-info .offer-planet-title,
.planet-card:focus-visible .planet-info .offer-planet-title {
    opacity: 0;
}

/* ─── services.php : titres Express/Business/Premium sous leur planète ───
   Demande explicite : contrairement aux autres .planet-card (dont le titre
   reste dans .planet-info, superposé à la sphère, flouté hors survol), les
   3 offres de création de site affichent leur titre EN DESSOUS de la
   planète (flow normal, après .planet-sphere, jamais flouté) — et repris
   avec exactement le même style que les titres de la section "continuer la
   visite" de pages/accueil.php (.home-service-planet-col h2) : même
   gabarit, même fond bleu doux + glow hérité de la règle générale "h2{}"
   (var(--title-accent-soft) tout en haut de ce fichier), repris ici
   explicitement puisque c'est un <h3> et non un <h2>. */
.offer-planet-title {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 2.6em;
    font-size: clamp(1.1rem, 1.6vw, 1.4rem);
    font-weight: 700;
    line-height: 1.3;
    margin: 0;
    color: #ffffff;
    background: rgba(var(--title-accent-soft), 0.10);
    box-shadow: 0 0 14px rgba(var(--title-accent-soft), 0.15);
    transition: background-color .4s ease, box-shadow .4s ease;
    /* <h3> reçoit par défaut la police "classique" (cf. règle générale
       "h3 { font-family: var(--font-title-classic); }" tout en haut de ce
       fichier) — surchargée ici pour reprendre la police "terminal" des
       <h2>, comme .home-service-planet-col h2 (demande explicite : même
       police ET même style que "continuer la visite"). */
    font-family: var(--font-title);
}

/* Reprend le préfixe "// " des <h2> (cf. règle générale "h2::before" tout en
   haut de ce fichier), absent des <h3> par défaut — dernier détail pour que
   ces titres soient visuellement identiques à ceux de "continuer la visite". */
.offer-planet-title::before {
    content: "// ";
    color: rgb(var(--title-accent));
    -webkit-text-fill-color: rgb(var(--title-accent));
    opacity: 0.65;
    font-weight: 600;
    font-size: 0.85em;
    transition: color .4s ease;
}

/* Demande explicite : chacune des 5 sections de services.php (Création
   sites web / Refonte de site / Hébergement et maintenance / Programmation
   / Conseil et accompagnement) a sa propre couleur fixe, qui ne doit plus
   dépendre de la couleur active du site — .offer-planet-title reposait sur
   var(--title-accent-soft)/var(--title-accent), qui SUIT la couleur active
   (cf. .accent-amber/.accent-emerald/etc. tout en haut de ce fichier) : les
   titres d'offres de chaque section prenaient donc tous la même teinte
   globale au lieu de leur couleur propre. Repris ici avec les mêmes teintes
   fixes que les vignettes du hero (--capsule-color de .service-capsule--
   refonte/--cloud/--programmation/--conseil/--featured), scopé par section
   (#section-offers/#refonte/#hebergement/#programmation/#conseil, uniques à
   services.php — cf. .planet-ribbon/.offer-planet-title, aucune autre page
   ne les utilise) pour ne pas affecter d'éventuels autres usages. */
#section-offers .offer-planet-title { background: rgba(59,130,246,.10); box-shadow: 0 0 14px rgba(59,130,246,.15); }
#section-offers .offer-planet-title::before { color: #3b82f6; -webkit-text-fill-color: #3b82f6; }

#refonte .offer-planet-title { background: rgba(245,158,11,.10); box-shadow: 0 0 14px rgba(245,158,11,.15); }
#refonte .offer-planet-title::before { color: #f59e0b; -webkit-text-fill-color: #f59e0b; }

#hebergement .offer-planet-title { background: rgba(241,245,249,.10); box-shadow: 0 0 14px rgba(241,245,249,.15); }
#hebergement .offer-planet-title::before { color: #f1f5f9; -webkit-text-fill-color: #f1f5f9; }

#programmation .offer-planet-title { background: rgba(16,185,129,.10); box-shadow: 0 0 14px rgba(16,185,129,.15); }
#programmation .offer-planet-title::before { color: #10b981; -webkit-text-fill-color: #10b981; }

#conseil .offer-planet-title { background: rgba(139,92,246,.10); box-shadow: 0 0 14px rgba(139,92,246,.15); }
#conseil .offer-planet-title::before { color: #8b5cf6; -webkit-text-fill-color: #8b5cf6; }

/* .planet-info ne contient désormais plus que la description (le titre est
   sorti, cf. .offer-planet-title ci-dessus) : recentrée verticalement dans
   le cercle sans le <h3> qu'elle centrait auparavant avec lui. */
.planet-info--no-title {
    justify-content: center;
}

/* ─── services.php : sections à UNIQUEMENT 2 planètes (Refonte, Hébergement
   & Maintenance, Programmation, Conseil & Accompagnement) — demande
   explicite : titre à CÔTÉ de la planète plutôt qu'en dessous (contrairement
   à la section "Offres" à 3 planètes, qui garde le titre en dessous), et
   côté alterné d'une section à l'autre : Refonte (titre à gauche),
   Hébergement (titre à droite), Programmation (titre à gauche), Conseil
   (titre à droite) — cf. classes .offers-grid--title-left/--title-right
   posées sur .offers-grid dans le markup.
   .offers-grid repasse en 1 seule colonne (les cartes, plus larges avec le
   titre à côté, ne tiennent plus 2 par ligne dans la largeur de la section
   .layout-split) : les 2 planètes de la section s'empilent verticalement. */
.offers-grid--paired {
    grid-template-columns: 1fr;
    max-width: 620px;
    gap: 48px;
    margin: 0 auto;
}

/* .planet-visual regroupe la sphère + l'overlay description (.planet-info),
   qui se positionne par rapport à CE wrapper plutôt que par rapport à toute
   la carte — nécessaire dès que la sphère n'est plus seule sur sa ligne
   (cf. .planet-visual-row ci-dessous), sinon le centrage absolu de
   .planet-info (left:50%) se ferait par rapport à la largeur totale de la
   ligne (sphère + titre) au lieu de la seule sphère. */
.planet-visual {
    position: relative;
    flex-shrink: 0;
}

/* Sphère + titre, côte à côte. Sens par défaut : titre à gauche, sphère à
   droite (ordre naturel du DOM, titre écrit en premier dans le markup) —
   .offers-grid--title-right inverse ce sens pour les sections où le titre
   doit apparaître à droite. */
.planet-visual-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 28px;
}
.offers-grid--title-right .planet-visual-row {
    flex-direction: row-reverse;
}

/* Largeur contrainte pour un titre à côté d'une sphère de 300px (sinon un
   titre court comme "Refonte" s'étirerait sur toute la largeur restante) —
   reprend .offer-planet-title tel quel (même police/fond/glow), juste plus
   étroit et permettant le retour à la ligne. */
.offer-planet-title--beside {
    max-width: 190px;
    white-space: normal;
}

/* Écran étroit : sphère (jusqu'à 320px) + titre côte à côte déborderait —
   on repasse le titre SOUS la planète (comme la section "Offres" à 3
   planètes), quel que soit le côté choisi pour la section sur desktop. */
@media (max-width: 640px) {
    .planet-visual-row,
    .offers-grid--title-right .planet-visual-row {
        flex-direction: column;
    }
    .offer-planet-title--beside {
        max-width: none;
    }
}

/* ─── Reflet spéculaire ─── */
.planet-highlight {
    position: absolute;
    top: 11%;
    left: 15%;
    width: 26%;
    height: 26%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255,255,255,.28) 0%, transparent 68%);
    pointer-events: none;
    z-index: 2;
    animation: highlightFloat 5s ease-in-out infinite;
}

/* ─── Anneau Saturn ─── */
.planet-ring {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) scaleY(.20);
    width: 155%;
    height: 155%;
    border-radius: 50%;
    border: 5px solid rgba(255,200,80,.30);
    box-shadow: 0 0 16px rgba(251,191,36,.20);
    pointer-events: none;
    z-index: 4;
    transition: border-color .65s ease, box-shadow .65s ease;
}

.planet-card:hover .planet-ring {
    border-color: rgba(255,200,80,.62);
    box-shadow: 0 0 32px rgba(251,191,36,.50);
}

.planet-card:hover{
    opacity: 1;
    
}


/* ─── Badge featured ─── */
.planet-ribbon {
    position: absolute;
    top: -10px;
    right: 2px;
    padding: 5px 16px;
    border-radius: 16px;
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    z-index: 6;
    /* Libellé plus long ("Réservé aux professionnels") : retour à la ligne
       borné plutôt qu'un débordement du badge hors de la carte planète. */
    max-width: 160px;
    white-space: normal;
    text-align: center;
    line-height: 1.2;
}

.planet-ribbon.pro {
    background: rgba(251,191,36,.12);
    color: #fbbf24;
    border: 1px solid rgba(251,191,36,.35);
    animation: ribbonPulse 4s ease-in-out infinite;
}

.planet-ribbon.essentiel {
    background: rgba(59,130,246,.12);
    color: #93c5fd;
    border: 1px solid rgba(59,130,246,.35);
}

/* Corrigé (demande explicite : "Création sites web" reste TOUJOURS bleue) :
   ce badge n'apparaît que sur l'offre "Premium" de #section-offers (cf.
   services.php, seule page à utiliser .planet-ribbon), donc toujours dans
   la section bleue — rgb(var(--header-accent)) le faisait suivre la couleur
   active au lieu de rester bleu comme .planet-ribbon.essentiel juste
   au-dessus, dans la même section. */
.planet-ribbon.surmesure {
    background: rgba(59,130,246,.12);
    color: #93c5fd;
    border: 1px solid rgba(59,130,246,.35);
}

/* ─── CTA sous la planète ─── */
.planet-cta {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--font-title);
    font-size: .74rem;
    font-weight: 700;
    color: rgba(255,255,255,.40);
    letter-spacing: .08em;
    text-transform: uppercase;
    transition: color .3s ease, letter-spacing .3s ease;
}

.planet-card:hover .planet-cta {
    color: rgba(255,255,255,.95);
    letter-spacing: .14em;
}

/* ─── Légère traînée derrière la rockette du CTA "Explorer" (demande
   explicite, uniquement ici — .cta-rocket est réutilisé ailleurs sur le
   site sans cet effet, cf. .service-capsule/.livre-dor-cta-btn). Un
   ::before posé directement sur le <svg> ne s'affichait pas de façon
   fiable selon les navigateurs (pseudo-élément sur un SVG inline) : la
   traînée est donc un vrai élément <span> frère du svg, tous deux enfants
   d'un wrapper .planet-cta-rocket qui porte SEUL le translate+rotate du
   décollage — svg et traînée bougent ensemble, sans dépendre d'un
   pseudo-élément. La traînée est positionnée "vers le bas" en repère
   local du wrapper ; une fois la rotation appliquée, elle retombe bien du
   côté opposé au sens du décollage. Invisible au repos, révélée en fondu
   au survol/focus de la carte. ─── */
.planet-cta-rocket {
    position: relative;
    display: inline-flex;
    transition: transform .3s ease;
}

.planet-card:hover .planet-cta-rocket,
.planet-card:focus-visible .planet-cta-rocket {
    transform: translate(3px, -3px) rotate(45deg);
}

.planet-cta-rocket-trail {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 2px;
    height: 8px;
    transform: translateX(-50%);
    transform-origin: 50% 0%;
    background: linear-gradient(to bottom, rgba(255,255,255,.6), transparent);
    border-radius: 2px;
    opacity: 0;
    transition: opacity .3s ease, height .3s ease;
    pointer-events: none;
}

.planet-card:hover .planet-cta-rocket-trail,
.planet-card:focus-visible .planet-cta-rocket-trail {
    opacity: .85;
    height: 11px;
}

/* ─── services.php : les 5 sections à planètes (#section-offers/#refonte/
   #hebergement/#programmation/#conseil) — clic sur une .planet-card ───
   Demande explicite : "peu importe la planète sélectionnée, je veux
   qu'elle se mette au centre de l'écran et que tout le contenu de la page
   s'estompe, ne reste que la planète cliquée. Puis la redirection se fait
   une fois la planète au centre." La sphère cliquée (.planet-sphere) est
   déplacée par JS (cf. assets/js/main.js) dans #planet-launch-layer, un
   calque fixe plein écran ajouté à la fin de <body> — donc au-dessus de
   <main>, qui s'estompe séparément ci-dessous, sans conflit d'opacité ni de
   contexte d'empilement avec la carte d'origine. Position de départ posée
   en inline par le JS (getBoundingClientRect, pour partir EXACTEMENT d'où
   la sphère se trouvait dans la grille) avant l'ajout de .is-centering, qui
   déclenche seul la transition CSS ci-dessous vers le centre de l'écran. */
#planet-launch-layer {
    position: fixed;
    inset: 0;
    z-index: 9999;
    pointer-events: none;
}
#planet-launch-layer .planet-sphere {
    position: fixed;
    margin: 0;
    transition:
        top .9s cubic-bezier(.65,0,.35,1),
        left .9s cubic-bezier(.65,0,.35,1),
        width .9s cubic-bezier(.65,0,.35,1),
        height .9s cubic-bezier(.65,0,.35,1),
        transform .9s cubic-bezier(.65,0,.35,1);
}
#planet-launch-layer .planet-sphere.is-centering {
    top: 50%;
    left: 50%;
    width: min(64vmin, 620px);
    height: min(64vmin, 620px);
    transform: translate(-50%, -50%);
}

/* Le reste du contenu de la page (hero + les 5 sections) s'estompe pendant
   ce temps — seule la sphère déplacée dans #planet-launch-layer (sortie de
   <main>) reste visible, grossissant vers le centre par-dessus. Les widgets
   flottants (Navigation/Mon compte/Couleur/Langue, cf. partials/footer.php,
   rendus hors de <main>) ne sont volontairement pas concernés : identiques
   sur la page de destination, ils n'ont pas besoin de disparaître. */
main.page-service.is-planet-launching {
    transition: opacity .9s ease;
    opacity: 0;
    pointer-events: none;
}

/* Accessibilité : si le JS détecte prefers-reduced-motion, il navigue tout
   de suite sans jamais poser .is-centering/.is-planet-launching — ce filet
   CSS coupe simplement toute transition résiduelle si ces classes se
   retrouvaient malgré tout posées (ex. saut direct entre deux frames). */
@media (prefers-reduced-motion: reduce) {
    #planet-launch-layer .planet-sphere,
    main.page-service.is-planet-launching {
        transition: none !important;
    }
}


/* ========================= VARIANTES PLANÈTES =========================
   Tier 1 — Essentiel  : ocean, desert
   Tier 2 — Pro        : ice, storm
   Tier 3 — Sur mesure : gold, nebula, forest
======================================================================= */

/* ─────────── TIER 1 ─────────── */

/* ── ocean : Terre vue de l'espace — océan profond, nuages quasi-invisibles ── */
.planet--ocean .planet-sphere {
    background-image: url('../image/planet-bleu.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 20px rgba(6,38,120,.20),
        0 0 42px rgba(3,22,88,.07),
        inset -30px -30px 60px rgba(0,0,14,.90);
}
.planet--ocean:hover .planet-sphere {
    box-shadow:
        0 0 38px rgba(6,38,120,.44),
        0 0 76px rgba(3,22,88,.15),
        inset -30px -30px 60px rgba(0,0,14,.90);
}
.planet--ocean .planet-sphere::before {
    background: repeating-linear-gradient(
        -15deg,
        transparent              0px,  transparent              32px,
        rgba(200,220,248,.06)   32px,  rgba(200,220,248,.06)   34px,
        transparent              34px,  transparent              64px,
        rgba(160,195,235,.04)   64px,  rgba(160,195,235,.04)   66px
    );
    animation-duration: 90s;
}
.planet--ocean .planet-sphere::after {
    box-shadow:
        inset 0 0 16px rgba(5,32,105,.14),
        inset 0 0 32px rgba(2,18,78,.07);
}

/* ── desert : Mars — rouille terne, poussière de fer ── */
.planet--desert .planet-sphere {
    background-image: url('../image/planet-jupiter.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 20px rgba(100,30,6,.22),
        0 0 42px rgba(115,40,5,.07),
        inset -30px -30px 60px rgba(16,2,0,.90);
}
.planet--desert:hover .planet-sphere {
    box-shadow:
        0 0 38px rgba(100,30,6,.46),
        0 0 76px rgba(115,40,5,.15),
        inset -30px -30px 60px rgba(16,2,0,.90);
}
.planet--desert .planet-sphere::before {
    background: repeating-linear-gradient(
        -20deg,
        rgba(105,40,8,.11)  0px,  rgba(105,40,8,.11) 22px,
        rgba(62,16,2,.08)  22px,  rgba(62,16,2,.08)  46px,
        rgba(82,28,4,.07)  46px,  rgba(82,28,4,.07)  72px
    );
    animation-duration: 60s;
}
.planet--desert .planet-sphere::after {
    box-shadow:
        inset 0 0 18px rgba(118,42,5,.16),
        inset 0 0 36px rgba(85,26,2,.08);
}

/* ─────────── TIER 2 ─────────── */

/* ── ice : Neptune — bleu-indigo très sombre, quasi-noir ── */
.planet--ice .planet-sphere {
    background-image: url('../image/planet-blanc.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 22px rgba(2,55,110,.22),
        0 0 44px rgba(0,38,88,.07),
        inset -30px -30px 60px rgba(0,3,14,.90);
}
.planet--ice:hover .planet-sphere {
    box-shadow:
        0 0 42px rgba(2,55,110,.46),
        0 0 85px rgba(0,38,88,.15),
        inset -30px -30px 60px rgba(0,3,14,.90);
}
.planet--ice .planet-sphere::before {
    background: repeating-linear-gradient(
        -35deg,
        transparent             0px,  transparent             40px,
        rgba(80,130,172,.06)   40px,  rgba(80,130,172,.06)   42px,
        transparent             42px,  transparent             78px,
        rgba(55,100,140,.04)   78px,  rgba(55,100,140,.04)   80px
    );
    animation-duration: 110s;
}
.planet--ice .planet-sphere::after {
    box-shadow:
        inset 0 0 14px rgba(2,55,110,.14),
        inset 0 0 28px rgba(0,35,82,.07);
}

/* ── storm : Maintenance — texture "custom" (déplacée depuis Bot Discord),
   reflet recoloré du violet d'origine vers le bleu/cyan de la section
   Hébergement (même famille que .planet--ice, sa voisine dans cette
   section) — cf. demande "reflet couleur de la section". ── */
.planet--storm .planet-sphere {
    background-image: url('../image/planet-orange.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 20px rgba(2,55,110,.20),
        0 0 42px rgba(0,38,88,.07),
        inset -30px -30px 60px rgba(0,0,10,.92);
}
.planet--storm:hover .planet-sphere {
    box-shadow:
        0 0 38px rgba(2,55,110,.44),
        0 0 76px rgba(0,38,88,.14),
        inset -30px -30px 60px rgba(0,0,10,.92);
}
.planet--storm .planet-sphere::before {
    background: repeating-linear-gradient(
        -8deg,
        rgba(20,60,110,.13)  0px,  rgba(20,60,110,.13) 18px,
        rgba(6,30,55,.09)  18px,  rgba(6,30,55,.09)  36px,
        rgba(12,45,80,.07) 36px,  rgba(12,45,80,.07) 58px
    );
    animation-duration: 25s;
}
.planet--storm .planet-sphere::after {
    box-shadow:
        inset 0 0 14px rgba(2,55,110,.14),
        inset 0 0 28px rgba(0,38,88,.07);
}

/* ── saturn : Hébergement & maintenance — corrigé (demande explicite : "doit
   être planet-blanc et non pas saturne") : la vraie texture Saturne
   (anneaux inclus, planet-saturn.webp) est remplacée par planet-blanc.webp,
   cohérente avec la couleur blanche fixe de cette section (cf.
   .planet--ice, sa voisine dans #hebergement, qui utilise déjà cette même
   texture). Halo sable/or conservé tel quel (non redemandé). ── */
.planet--saturn .planet-sphere {
    background-image: url('../image/planet-blanc.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 24px rgba(196,164,90,.24),
        0 0 48px rgba(196,164,90,.09),
        inset -30px -30px 60px rgba(20,14,4,.85);
}
.planet--saturn:hover .planet-sphere {
    box-shadow:
        0 0 46px rgba(196,164,90,.50),
        0 0 92px rgba(196,164,90,.20),
        inset -30px -30px 60px rgba(20,14,4,.85);
}
.planet--saturn .planet-sphere::before {
    background: repeating-linear-gradient(
        -12deg,
        rgba(196,164,90,.10) 0px,  rgba(196,164,90,.10) 24px,
        rgba(120,92,44,.07) 24px,  rgba(120,92,44,.07) 48px,
        transparent           48px,  transparent           72px
    );
    animation-duration: 65s;
}
.planet--saturn .planet-sphere::after {
    box-shadow:
        inset 0 0 18px rgba(196,164,90,.16),
        inset 0 0 36px rgba(196,164,90,.08);
}

/* ─────────── TIER 3 ─────────── */

/* ── gold : Jupiter/Saturne — ocre chaud, ceintures ocre et brun ── */
.planet--gold .planet-sphere {
    background-image: url('../image/planet-orange.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 28px rgba(115,68,12,.26),
        0 0 55px rgba(135,85,16,.09),
        0 0 90px rgba(88,42,3,.04),
        inset -30px -30px 60px rgba(18,3,0,.88);
}
.planet--gold:hover .planet-sphere {
    box-shadow:
        0 0 52px rgba(115,68,12,.54),
        0 0 105px rgba(135,85,16,.20),
        0 0 165px rgba(88,42,3,.09),
        inset -30px -30px 60px rgba(18,3,0,.88);
}
.planet--gold .planet-sphere::before {
    background: repeating-linear-gradient(
        -10deg,
        rgba(145,82,18,.12)  0px,  rgba(145,82,18,.12) 10px,
        rgba(88,34,4,.09)   10px,  rgba(88,34,4,.09)   22px,
        rgba(158,98,26,.07) 22px,  rgba(158,98,26,.07) 34px,
        rgba(118,50,7,.11)  34px,  rgba(118,50,7,.11)  44px,
        rgba(75,28,2,.08)   44px,  rgba(75,28,2,.08)   56px,
        rgba(135,72,14,.07) 56px,  rgba(135,72,14,.07) 68px,
        rgba(100,38,5,.09)  68px,  rgba(100,38,5,.09)  80px
    );
    animation-duration: 42s;
}
.planet--gold .planet-sphere::after {
    box-shadow:
        inset 0 0 18px rgba(145,82,18,.16),
        inset 0 0 38px rgba(110,50,5,.08);
}

/* ── nebula : océan cyan profond — Sur mesure ── */
.planet--nebula .planet-sphere {
    background-image: url('../image/planet-terre.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 28px rgba(59,130,246,.22),
        0 0 55px rgba(4,120,155,.08),
        0 0 90px rgba(2,70,100,.03),
        inset -30px -30px 60px rgba(0,5,18,.92);
}
.planet--nebula:hover .planet-sphere {
    box-shadow:
        0 0 52px rgba(59,130,246,.48),
        0 0 105px rgba(4,120,155,.18),
        0 0 165px rgba(2,70,100,.08),
        inset -30px -30px 60px rgba(0,5,18,.92);
}
.planet--nebula .planet-sphere::before {
    background: repeating-linear-gradient(
        -14deg,
        rgba(59,130,246,.08)   0px,  rgba(59,130,246,.08)  14px,
        rgba(4,100,130,.06)  14px,  rgba(4,100,130,.06)  30px,
        rgba(8,160,200,.05)  30px,  rgba(8,160,200,.05)  48px,
        rgba(2,60,90,.06)    48px,  rgba(2,60,90,.06)    68px
    );
    animation-duration: 34s;
}
.planet--nebula .planet-sphere::after {
    box-shadow:
        inset 0 0 20px rgba(59,130,246,.16),
        inset 0 0 42px rgba(4,120,155,.07);
}

/* ── forest : Accompagnement — reflet recoloré du vert d'origine vers un
   gris neutre, sur demande ("reflet gris"). ── */
.planet--forest .planet-sphere {
    background-image: url('../image/lune.png');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 26px rgba(148,163,184,.22),
        0 0 52px rgba(100,116,139,.07),
        0 0 88px rgba(71,85,105,.03),
        inset -30px -30px 60px rgba(4,4,4,.90);
}
.planet--forest:hover .planet-sphere {
    box-shadow:
        0 0 50px rgba(148,163,184,.46),
        0 0 100px rgba(100,116,139,.16),
        0 0 160px rgba(71,85,105,.08),
        inset -30px -30px 60px rgba(4,4,4,.90);
}
.planet--forest .planet-sphere::before {
    background: repeating-linear-gradient(
        -18deg,
        transparent             0px,  transparent             30px,
        rgba(120,130,145,.08)  30px,  rgba(120,130,145,.08)  32px,
        transparent             32px,  transparent             60px,
        rgba(90,100,115,.06)   60px,  rgba(90,100,115,.06)   62px
    );
    animation-duration: 70s;
}
.planet--forest .planet-sphere::after {
    box-shadow:
        inset 0 0 16px rgba(148,163,184,.14),
        inset 0 0 32px rgba(100,116,139,.07);
}



/* ─── CTA FINAL : EFFET "TROU NOIR" ───
   Section relevée d'un simple bloc de texte centré à un panneau "capsule"
   flottant au-dessus d'un trou noir : un disque d'accrétion (anneau
   conic-gradient blanc/bleu très pâle flouté) tourne lentement derrière
   le panneau, autour d'un horizon des événements totalement sombre en
   son centre. Le panneau lui-même est assombri et rendu plus opaque pour
   qu'il se détache nettement du halo, façon vaisseau au bord de
   l'horizon. Aucune icône décorative ici : par convention du site, la
   roquette n'apparaît que sur des éléments cliquables (cf. .capsule-cta,
   .divider-action, .planet-cta) — le CTA texte suffit.

   Le halo (::before/::after) est porté par .services-cta-halo, un
   conteneur qui n'enveloppe QUE .container et n'a lui-même aucun
   padding : sa boîte a donc exactement la même hauteur/centre vertical
   que .container. Le porter directement sur .services-cta (qui a un
   padding haut/bas asymétrique à cause de --footer-clearance) décalait
   le trou noir par rapport au panneau.

   padding-top : le disque d'accrétion peut atteindre 780px de diamètre
   (donc 390px de rayon depuis le centre du panneau) sur les grands
   écrans — avec seulement 100px de marge au-dessus de .services-cta-halo,
   .services-cta (overflow:hidden) tronquait le haut du disque. Le
   padding-top suit désormais le même clamp que le disque (avec une marge
   de sécurité) pour toujours lui laisser assez de place. */
.services-cta {
    text-align: center;
    padding: clamp(240px, 34vw, 420px) 20px var(--footer-clearance);
    position: relative;
    overflow: hidden;
}

.services-cta-halo {
    position: relative;
}

/* Disque d'accrétion : anneau conic-gradient flouté qui tourne en continu.
   Demande explicite ("le trou, et tous ceux de la page, doivent hériter
   de la couleur active") : la palette blanche/argentée fixe est
   remplacée par des teintes dérivées de --header-accent, même recette
   que .why-target-cta-halo/.hero-black-hole. */
.services-cta-halo::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(390px, 55vw, 690px);
    height: clamp(390px, 55vw, 690px);
    margin-top: -1px;
    border-radius: 50%;
    /* Bande horizontale déplacée sur ::after (demande explicite : elle ne
       doit pas tourner avec l'anneau — contrairement à ce calque animé par
       blackHoleSpin — cf. trou noir1.jpg où la lueur équatoriale reste
       fixe sur la face du disque pendant que l'anneau tourne autour). */
    background:
        conic-gradient(
            from -20deg,
            rgba(var(--header-accent),0)      0deg,
            rgba(var(--header-accent),.6)     38deg,
            rgba(var(--header-accent),.68)    68deg,
            rgba(var(--header-accent),.7)     92deg,
            rgba(var(--header-accent),.36)    118deg,
            rgba(var(--header-accent),0)      152deg,
            rgba(var(--header-accent),0)      222deg,
            rgba(var(--header-accent),.22)    250deg,
            rgba(var(--header-accent),.4)     282deg,
            rgba(var(--header-accent),.55)    302deg,
            rgba(var(--header-accent),.4)     320deg,
            rgba(var(--header-accent),0)      360deg
        );
    box-shadow: 0 0 clamp(41px, 5.8vw, 72px) clamp(12px, 1.8vw, 22px) rgba(var(--header-accent),.30);
    --hole-blur: 22px;
    animation:
        blackHoleSpin 22s linear infinite,
        blackHoleFlicker 6.5s ease-in-out infinite;
    pointer-events: none;
    z-index: 0;
}

/* Horizon des événements : cœur noir opaque qui masque le centre de
   l'anneau, avec une ombre portée large pour assombrir tout autour. */
.services-cta-halo::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(200px, 28vw, 350px);
    height: clamp(200px, 28vw, 350px);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    /* Version "réaliste" restaurée (demande explicite : "on avait obtenu un
       résultat très réaliste", plus de barre horizontale) : la bande
       linéaire equatoriale est retirée — un seul radial-gradient forme un
       cœur noir opaque avec un fin anneau photonique clair à 58-66%
       (l'horizon des événements, coloré --header-accent), plus proche
       d'une vraie photo de trou noir. Complété par un léger backdrop-filter
       (flou + saturation) sur le bord pour un rendu moins "à plat". */
    background:
        radial-gradient(circle, #000000 0%, #000000 58%, rgba(var(--header-accent),.85) 62%, #000000 66%, rgba(0,0,0,0) 76%);
    backdrop-filter: blur(2px) saturate(1.15);
    -webkit-backdrop-filter: blur(2px) saturate(1.15);
    box-shadow: 0 0 clamp(45px, 6.2vw, 78px) clamp(15px, 2.1vw, 26px) rgba(0,0,0,.85);
    animation: blackHolePulse 4.5s ease-in-out infinite;
    pointer-events: none;
    z-index: 1;
}

/* Rotation + "respiration" du disque : en plus de tourner, l'anneau se
   resserre puis se redéploie deux fois par tour (35%/85%, calés pile sur
   les mêmes angles de rotation 126deg/306deg = 360*.35 / 360*.85, donc la
   vitesse de rotation reste parfaitement linéaire malgré ces étapes
   intermédiaires) — donne l'impression que la matière est aspirée vers le
   centre puis relâchée, façon tourbillon, plutôt qu'un simple anneau figé
   qui tourne (demande explicite "effet d'aspiration/tourbillon autour de
   la lentille"). */
@keyframes blackHoleSpin {
    0%   { transform: translate(-50%, -50%) rotate(0deg)   scale(1); }
    35%  { transform: translate(-50%, -50%) rotate(126deg) scale(.88); }
    50%  { transform: translate(-50%, -50%) rotate(180deg) scale(1); }
    85%  { transform: translate(-50%, -50%) rotate(306deg) scale(.88); }
    100% { transform: translate(-50%, -50%) rotate(360deg) scale(1); }
}

/* Horizon des événements : léger gonflement synchronisé (scale) en plus du
   pulse d'opacité déjà présent — comme si le cœur noir "avalait" par
   à-coups la matière aspirée par le disque ci-dessus, sur un rythme plus
   rapide (4.5s) et volontairement désynchronisé des 22s du disque pour un
   mouvement plus organique/moins mécanique. */
@keyframes blackHolePulse {
    0%, 100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    50%      { opacity: 1; transform: translate(-50%, -50%) scale(1.06); }
}

/* Scintillement du disque d'accrétion (::before) : fait varier flou/luminosité
   via --hole-blur (posée par chaque instance) plutôt qu'un filter fixe,
   pour un rendu moins statique — restaurée avec la version "réaliste" du
   trou noir (cf. commentaire sur ::after ci-dessus). */
@keyframes blackHoleFlicker {
    0%, 100% { filter: blur(var(--hole-blur, 22px)) brightness(.94); }
    50%      { filter: blur(var(--hole-blur, 22px)) brightness(1.1); }
}

@media (prefers-reduced-motion: reduce) {
    .index-hero-black-hole::before,
    .index-hero-black-hole::after,
    .home-hero-halo::before,
    .home-hero-halo::after,
    .why-target-cta-halo::before,
    .why-target-cta-halo::after,
    .services-cta-halo::before,
    .services-cta-halo::after,
    .account-page::after,
    .hole-hotspot,
    .hole-hotspot::before {
        animation: none;
    }
}

.hole-anim-paused::before,
.hole-anim-paused::after,
.hole-anim-paused .hole-hotspot,
.hole-anim-paused .hole-hotspot::before {
    animation-play-state: paused !important;
}

/* ─── Point chaud en orbite (hole-hotspot) ───
   Petit point lumineux qui orbite autour de chaque trou noir (index.php,
   accueil.php x2 "home-hero-halo"/"why-target-cta-halo", services.php x2
   "hero-black-hole"/"services-cta-halo"), demande explicite lors du rendu
   "très réaliste" obtenu — simule un point d'accrétion particulièrement
   brillant qui tourne avec le disque plutôt qu'un anneau uniforme. Élément
   HTML dédié <span class="hole-hotspot"> déjà présent dans chaque page
   (cf. markup), 0x0 + position:absolute posé au même point d'ancrage que
   le trou noir parent, tout le rayon/mouvement se fait via ::before +
   transform sur l'élément lui-même (rotate en continu, cf.
   @keyframes holeHotspotOrbit) : évite de repositionner top/left en JS.
   --hotspot-radius/--hotspot-color redéfinis par instance ci-dessous (taille
   du disque + couleur cohérente avec l'anneau de chaque trou noir). */
.hole-hotspot {
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 0;
    pointer-events: none;
    z-index: 1;
    animation: holeHotspotOrbit 9s linear infinite;
}

.hole-hotspot::before {
    content: "";
    position: absolute;
    top: calc(var(--hotspot-radius, 160px) * -1);
    left: -5px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: radial-gradient(circle, #fff 0%, rgba(var(--hotspot-color, 200,225,255),.95) 45%, rgba(var(--hotspot-color, 200,225,255),0) 75%);
    box-shadow: 0 0 14px 4px rgba(var(--hotspot-color, 200,225,255),.85);
    animation: holeHotspotFlare 3.6s ease-in-out infinite;
}

@keyframes holeHotspotOrbit {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@keyframes holeHotspotFlare {
    0%, 100% { opacity: .3; transform: scale(.65); }
    45%      { opacity: 1;  transform: scale(1.2); }
    70%      { opacity: .45; transform: scale(.85); }
}

.index-hero-black-hole .hole-hotspot {
    --hotspot-radius: clamp(120px, 17vw, 215px);
    --hotspot-color: var(--hole-light, 200,225,255);
}

.home-hero-halo .hole-hotspot {
    --hotspot-radius: clamp(100px, 14vw, 185px);
    --hotspot-color: var(--hole-light, 200,225,255);
}

.why-target-cta-halo .hole-hotspot {
    --hotspot-radius: clamp(135px, 19vw, 240px);
    --hotspot-color: var(--header-accent);
    animation-delay: -3.1s;
}

.why-target-cta-halo .hole-hotspot::before {
    animation-delay: -1.8s;
}

.hero-black-hole .hole-hotspot {
    --hotspot-radius: clamp(120px, 17vw, 215px);
    --hotspot-color: var(--header-accent);
}

.services-cta-halo .hole-hotspot {
    --hotspot-radius: clamp(120px, 17vw, 215px);
    --hotspot-color: var(--header-accent);
    animation-delay: -3.1s;
}

.services-cta-halo .hole-hotspot::before {
    animation-delay: -1.8s;
}

.why-target-cta-halo.is-swallowing .hole-hotspot,
.services-cta-halo.is-swallowing .hole-hotspot {
    opacity: 0;
    transition: opacity .4s ease;
}

/* ─── Rockette en orbite autour du trou noir (services.php) ───
   Même traitement/technique que .why-target-cta-orbit (accueil.php
   #why-cta), simplement mis à l'échelle : le disque/anneau de
   .services-cta-halo est ~1.6x plus grand que celui de
   .why-target-cta-halo, l'orbite suit la même proportion. Réutilise les
   keyframes globales blackHoleOrbitSpin/blackHoleSwallowSpiral (déjà
   définies plus haut dans ce fichier) et le même gestionnaire de clic en
   JS (cf. main.js, bloc "CTA trou noir", généralisé aux deux halos). */
.services-cta-orbit {
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(310px, 45vw, 540px);
    height: clamp(310px, 45vw, 540px);
    transform: translate(-50%, -50%) rotate(0deg);
    z-index: 1;
    pointer-events: none;
    animation: blackHoleOrbitSpin 8s linear infinite;
}

.services-cta-orbit-rocket {
    position: absolute;
    top: 0;
    left: 50%;
    width: 36px;
    height: 36px;
    transform: translate(-50%, -50%) rotate(90deg);
    color: rgba(255,255,255,.85);
    filter: drop-shadow(0 0 6px rgba(139,197,255,.55));
    transition: opacity .3s ease;
}

.services-cta-orbit-trail {
    position: absolute;
    top: 0;
    left: 50%;
    width: 4px;
    height: 50px;
    transform-origin: 50% 0%;
    transform: translateX(-50%) rotate(90deg);
    background: linear-gradient(to bottom, rgba(139,197,255,.55) 0%, rgba(139,197,255,.18) 55%, rgba(139,197,255,0) 100%);
    border-radius: 2px;
    filter: blur(1.5px);
    pointer-events: none;
    transition: opacity .3s ease;
}

.services-cta-halo.is-swallowing .services-cta-orbit {
    /* Même ajustement que .why-target-cta-orbit (accueil.php) : linear +
       durée raccourcie, cf. commentaire là-bas. */
    animation: blackHoleSwallowSpiral 2.4s linear forwards;
}

.services-cta-halo.is-swallowing .services-cta-orbit-rocket,
.services-cta-halo.is-swallowing .services-cta-orbit-trail {
    opacity: 0;
    transition: opacity .35s ease 1.6s;
}

/* Plus de panneau/"boxe" : le texte flotte directement au-dessus du trou
   noir, sans fond/bordure/ombre/flou — seule la mise en page (largeur de
   lecture, centrage) est conservée. */
.services-cta .container {
    position: relative;
    z-index: 2;
    max-width: 720px;
    margin: 0 auto;
    padding: 0 20px;
}

.services-cta h2,
.services-cta .cta-text,
.services-cta .btn-accueil {
    position: relative;
    z-index: 1;
}

/* box-shadow: none — annule le halo générique "contour" posé sur tous les
   h2 du site (cf. règle h2{} globale) : ici le titre flotte sur le trou
   noir, sans contour rectangulaire autour du texte. */
.services-cta h2 {
    font-size: clamp(1.6rem, 3vw, 2.3rem);
    font-weight: 700;
    /* Décalage vers le bas (demande explicite, plusieurs ajustements
       successifs : texte+CTA trop hauts par rapport au centre du disque). */
    margin: 80px 0 16px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    box-shadow: none;
}

.services-cta .cta-text {
    color: rgba(255,255,255,.58);
    font-size: .98rem;
    max-width: 520px;
    margin: 0 auto 32px;
    line-height: 1.7;
}

@media (max-width: 640px) {
    .services-cta .container {
        padding: 44px 24px 36px;
        border-radius: 24px;
    }
}

/* Duplicata de la règle .btn-accueil de base (cf. plus haut, section
   index.php) — même correction (3ème teinte --accent-harmony-3, ton
   différent de la couleur principale), pour rester identique entre les 2
   déclarations. */
.btn-accueil {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 15px 44px;
    font-size: 1.05rem;
    font-weight: 600;
    border-radius: 999px;
    background: rgba(var(--accent-harmony-3), .14);
    border: 1px solid rgba(var(--accent-harmony-3), .32);
    color: #ffffff;
    text-decoration: none;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 0 24px rgba(var(--accent-harmony-3), .08), inset 0 1px 0 rgba(255,255,255,.07);
    transition: background .25s ease, box-shadow .25s ease, transform .25s ease;
}

.btn-accueil:hover {
    background: rgba(var(--accent-harmony-3), .22);
    box-shadow: 0 12px 36px rgba(var(--accent-harmony-3), .28);
    transform: translateY(-2px);
}






/* ─── ANIMATION D'ENTRÉE "PLANÈTE" (partagée par les 14 pages service) ───
   Demande explicite : "au début être au centre de l'écran (sans contenu de
   page) puis il y a un zoom sur la planète et alors le contenu de la page
   apparait en fondu". Classe .planet-entrance-page posée en dur dans le
   <main> de chaque page concernée (refonte/audit-site/hm/hebergement/
   maintenance/conseil/accompagnement/conseilaccompagnement/programmation/
   bot-discord/offres-site/sitevitrine/sitepro/surmesure), en plus de leur
   classe .page-X existante.
   Plutôt que de créer un 2e système de fondu qui entrerait en conflit avec
   le "SCROLL REVEAL" existant plus bas (.section-block/.is-visible — le
   hero, visible dès le chargement, y est déjà révélé en fondu par son
   propre IntersectionObserver), on se contente ici de FORCER tout le
   contenu direct du <main> à rester invisible tant que .bg-entrance est
   présent (zoom de la planète en cours, posé/retiré par main.js) — le
   !important est nécessaire pour passer devant .section-block.is-visible.
   Une fois .bg-entrance retiré (zoom terminé), ce forçage disparaît et
   chaque section retrouve son fondu normal déjà défini par le "SCROLL
   REVEAL" (hero révélé immédiatement, sections suivantes au scroll). */
.planet-entrance-page.bg-entrance > * {
    opacity: 0 !important;
}

/* ========================= offres-site.php ========================= */

/* ─── BACKGROUND FIXE ───
   TEST : Galaxy-web.png remplace bgsite.png comme fond de PAGE entier
   (fixed, comme les autres pages) au lieu d'être concentrée dans
   .offer-intro-block (cf. plus haut, pseudo-élément neutralisé) — même
   traitement (overlay noir .52 pour la lisibilité du texte) que
   bgsite.png ailleurs sur le site. À rebasculer sur bgsite.png si le
   rendu page entière ne convainc pas. */
.page-offers::before {
    content: "";
    position: fixed;
    inset: 0;
    /* Rideau dégradé en haut (0 à 90px opaque, fondu jusqu'à 260px) :
       masque le fond derrière le header flottant (top:20px +
       height:64px ≈ 84px). */
    background:
        linear-gradient(to bottom, rgba(3,5,14,.96) 0, rgba(3,5,14,.96) 90px, transparent 260px),
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Galaxie sur son propre calque (::after, peint par-dessus ::before) pour
   pouvoir lui appliquer un masque radial qui estompe son contour
   déchiqueté/tronqué en fondu, sans toucher au starfield bgsiteindex.png
   en dessous. */
.page-offers::after {
    content: "";
    position: fixed;
    inset: 0;
    background: url("../image/galaxie-web.png") center / 75% 60% no-repeat;
    /* Les % d'un radial-gradient explicite sont des RAYONS, pas des
       diamètres : "60% 55%" s'étendait donc jusqu'à 120%/110% de la
       largeur/hauteur — bien plus grand que l'image (75%/60%), donc le
       fondu n'atteignait la transparence totale que largement APRÈS le
       bord réel de l'image, qui restait quasi opaque (bordure visible).
       Rayons resserrés (28%/22%) pour que la transparence totale soit
       atteinte nettement AVANT le bord réel de l'image (75%/60%). */
    -webkit-mask-image: radial-gradient(ellipse 28% 22% at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(ellipse 28% 22% at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    /* Rétrécit + s'efface au scroll : --bg-scroll-scale/-opacity sont
       posées en JS (cf. main.js, bloc "DÉCOR DE FOND") sur .page-offers,
       dont ::after hérite. Valeurs par défaut (1) tant que le JS n'a pas
       encore tourné, pour éviter un flash au chargement. */
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}

/* Arrivée de page : demande explicite d'étendre l'animation d'entrée
   (planète centrée, contenu masqué, puis zoom) à offres-site.php, qui en
   était exclue jusqu'ici. Cf. .planet-entrance-page plus haut + main.js. */
.page-offers.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-offers > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-offers .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}

.page-offers .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── WRAPPER HERO + CARDS ─── */
.offer-intro-block {
    height: 80dvh;
    display: flex;
    flex-direction: column;
}

/* ─── HERO ─── */
.page-offers .offer-hero {
    padding-top: clamp(120px, 14dvh, 210px);
    padding-bottom: 5px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    max-width: 500px;
    margin: 0 auto;
    gap: 4px;
    flex-shrink: 0;
}

.offer-hero h1 {
    font-size: clamp(2rem, 4vw, 2.8rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    margin-bottom: 2px;
}

.offer-hero .intro {
    color: rgba(255,255,255,.68);
    font-size: .92rem;
    line-height: 1.6;
    max-width: 560px;
    margin-top: 2px;
}

/* ─── OFFER CARDS (LEVELS) ─── */
.offer-levels {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(16px, 2dvh, 28px);
    max-width: 1400px;
    width: 100%;
    margin: 0 auto;
    padding: 10px 20px 20px;
    flex: 1;
    align-content: center;
}

.page-offers .offer-card {
    padding: clamp(20px, 2.5dvh, 36px) 28px;
    display: flex;
    flex-direction: column;
    text-align: left;
    position: relative;
    border-radius: 20px;
    background:
        radial-gradient(circle at 15% 20%, rgba(255,255,255,.80) 0%, transparent .5%),
        radial-gradient(circle at 72% 8%,  rgba(255,255,255,.65) 0%, transparent .4%),
        radial-gradient(circle at 88% 55%, rgba(255,255,255,.72) 0%, transparent .45%),
        radial-gradient(circle at 30% 78%, rgba(255,255,255,.55) 0%, transparent .38%),
        radial-gradient(circle at 58% 34%, rgba(255,255,255,.60) 0%, transparent .35%),
        radial-gradient(circle at 90% 80%, rgba(255,255,255,.50) 0%, transparent .32%),
        radial-gradient(circle at 45% 90%, rgba(255,255,255,.45) 0%, transparent .30%),
        rgba(8,12,30,.72);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(255,255,255,.08);
    box-shadow: 0 15px 40px rgba(0,0,0,.45);
    color: #fff;
    text-decoration: none;
    overflow: hidden;
    transition: transform .35s ease, box-shadow .35s ease, border-color .35s ease;
}

.page-offers .offer-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    border-radius: 20px 20px 0 0;
    opacity: .7;
    transition: opacity .35s ease;
}

.page-offers .offer-card:hover {
    transform: translateY(-6px);
}

.page-offers .offer-card:hover::before {
    opacity: 1;
}

/* Tier colors — top accent + hover glow */
.page-offers .offer-card.essentiel::before {
    background: linear-gradient(90deg, rgba(59,130,246,.6), rgba(147,197,253,.9));
}
.page-offers .offer-card.essentiel:hover {
    border-color: rgba(59,130,246,.38);
    box-shadow: 0 20px 60px rgba(0,0,0,.55), 0 0 55px rgba(59,130,246,.28);
}

.page-offers .offer-card.pro::before {
    background: linear-gradient(90deg, rgba(251,191,36,.8), rgba(253,230,138,1));
}

/* ─── Offre Business mise en valeur par rapport à ses voisines (même
   logique que .service-capsule--featured sur services.php) : bordure et
   halo permanents (pas seulement au survol) + agrandissement léger sur
   desktop, où les 3 cartes sont côte à côte.
   Valeurs renforcées (bordure + halo + fond) : sur le fond galaxie plus
   clair implémenté depuis, le halo amber d'origine (.20/.28 d'opacité)
   se fondait trop dans l'arrière-plan et la carte ne ressortait plus
   assez de ses voisines. ─── */
.page-offers .offer-card.pro {
    border-width: 2px;
    border-color: rgba(251,191,36,.75);
    /* background-color seul (pas background-image) : la carte de base
       définit ses 7 halos décoratifs via background-image (shorthand) —
       on ne veut retoucher que la teinte de fond solide sous-jacente,
       pas remplacer/perdre ces halos. */
    background-color: rgba(58,38,4,.80);
    box-shadow: 0 18px 50px rgba(0,0,0,.6), 0 0 60px rgba(251,191,36,.40), inset 0 1px 0 rgba(255,255,255,.12);
}

.page-offers .offer-card.pro:hover {
    border-color: rgba(251,191,36,.85);
    box-shadow: 0 20px 60px rgba(0,0,0,.65), 0 0 80px rgba(251,191,36,.55), inset 0 1px 0 rgba(255,255,255,.16);
}

@media (min-width: 901px) {
    .page-offers .offer-card.pro {
        transform: scale(1.06);
        z-index: 2;
        animation: offerCardProGlow 3.4s ease-in-out infinite;
    }

    .page-offers .offer-card.pro:hover {
        transform: scale(1.06) translateY(-6px);
    }
}

@keyframes offerCardProGlow {
    0%, 100% { box-shadow: 0 18px 50px rgba(0,0,0,.5), 0 0 42px rgba(251,191,36,.20); }
    50%      { box-shadow: 0 22px 60px rgba(0,0,0,.5), 0 0 58px rgba(251,191,36,.34); }
}

.page-offers .offer-card.surmesure::before {
    background: linear-gradient(90deg, rgba(var(--header-accent),.7), rgba(147,197,253,.95));
}
.page-offers .offer-card.surmesure:hover {
    border-color: rgba(var(--header-accent),.36);
    box-shadow: 0 20px 60px rgba(0,0,0,.55), 0 0 55px rgba(var(--header-accent),.26);
}

.offer-card h2 {
    margin: 0 0 4px;
    font-size: clamp(1rem, 1.4vw, 1.25rem);
    line-height: 1.35;
    word-break: break-word;
}

.offer-card p {
    margin: 0;
    font-size: clamp(.8rem, 1vw, .92rem);
    line-height: 1.6;
    color: rgba(255,255,255,.80);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.offer-card .meta {
    margin-top: auto;
    padding-top: 12px;
    color: rgba(255,255,255,.45);
    font-size: .82rem;
}

.offer-card .price {
    display: inline-block;
    padding: 7px 16px;
    border-radius: 12px;
    font-size: 1.1rem;
    font-weight: 800;
    letter-spacing: -.01em;
    border: 1px solid rgba(255,255,255,.08);
    margin: 4px 0 6px;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

/* Demande explicite : le badge de prix Essentiel (900 CHF, section 1) doit
   avoir le même fond que celui du Premium (accent-following), pas un bleu
   fixe. */
.offer-card.essentiel .price { background: rgba(var(--header-accent),.18); border-color: rgba(var(--header-accent),.40); color: rgba(147,197,253,1); }
.offer-card.pro .price       { background: rgba(251,191,36,.18); border-color: rgba(251,191,36,.40); color: rgba(253,230,138,1); }
.offer-card.surmesure .price { background: rgba(var(--header-accent),.18); border-color: rgba(var(--header-accent),.40); color: rgba(147,197,253,1); }

/* OFFER PLANET THUMBNAIL */
.offer-planet {
    display: flex;
    justify-content: center;
    margin-bottom: clamp(10px, 1.5dvh, 18px);
}

.offer-planet img {
    width: clamp(60px, 7dvh, 80px);
    height: clamp(60px, 7dvh, 80px);
    border-radius: 50%;
    object-fit: cover;
    box-shadow: 0 0 22px rgba(255,255,255,.12);
    transition: transform .4s ease, box-shadow .4s ease;
}

.offer-card:hover .offer-planet img {
    transform: scale(1.08);
}

.offer-card.essentiel:hover .offer-planet img {
    box-shadow: 0 0 36px rgba(59,130,246,.45);
}

.offer-card.pro:hover .offer-planet img {
    box-shadow: 0 0 36px rgba(251,191,36,.45);
}

.offer-card.surmesure:hover .offer-planet img {
    box-shadow: 0 0 36px rgba(var(--header-accent),.45);
}

/* OFFER LINK */
.offer-link {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: 100%;
    text-decoration: none;
    color: inherit;
}

/* RIBBON */
.offer-ribbon {
    position: absolute;
    top: 12px;
    right: 12px;
    padding: 4px 12px;
    border-radius: 14px;
    font-size: .75rem;
    font-weight: 700;
    pointer-events: none;
    z-index: 2;
    /* Libellé plus long ("Réservé aux professionnels") : retour à la ligne
       borné plutôt qu'un débordement du badge hors de la carte offre. */
    max-width: 150px;
    white-space: normal;
    text-align: center;
    line-height: 1.2;
}

/* Les 3 rubans (essentiel / pro / sur mesure) partagent le même gabarit
   discret (contour + couleur de l'offre) — aucun des trois n'est mis en
   avant visuellement par rapport aux autres. */
/* Demande explicite (correction) : les rubans "Le choix des professionnels"
   (Business) et "Sur mesure" (Premium) ne doivent PAS dépendre de la
   couleur active — ils reviennent à des teintes fixes (ambre / violet,
   cohérent avec l'identité Business/Premium utilisée ailleurs sur le site).
   Seul le badge de PRIX (.offer-card .price, plus haut) suit désormais
   l'accent pour Essentiel ET Premium. */
.offer-ribbon.pro {
    background: rgba(251,191,36,.14);
    color: rgba(253,230,138,1);
    border: 1px solid rgba(251,191,36,.40);
}

.offer-ribbon.essentiel {
    background: rgba(59,130,246,.14);
    color: rgba(147,197,253,1);
    border: 1px solid rgba(59,130,246,.40);
}

.offer-ribbon.surmesure {
    background: rgba(139,92,246,.14);
    color: #c4b5fd;
    border: 1px solid rgba(139,92,246,.40);
}

/* ─── OPTIONS HEADER ─── */
.offer-options-header {
    text-align: center;
    max-width: 800px;
    margin: 0 auto;
    padding: 60px 20px 20px;
}

.offer-options-header h2 {
    font-size: clamp(1.6rem, 3vw, 2.2rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    background: linear-gradient(100deg, #ffffff 40%, rgba(122,92,255,.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    margin-bottom: 12px;
}

.offer-options-header p {
    color: rgba(255,255,255,.58);
    font-size: 1rem;
    line-height: 1.7;
}

/* ─── OPTIONS GRID ─── */
.options-section-header {
    grid-column: 1 / -1;
    position: relative;
    padding: 48px 0 20px;
    margin-top: 8px;
}

.options-section-header:first-child {
    padding-top: 0;
    margin-top: 0;
}

.options-section-header:not(:first-child)::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(var(--header-accent),.55) 25%,
        rgba(122,92,255,.35) 75%,
        transparent 100%
    );
    box-shadow: 0 0 14px rgba(var(--header-accent),.2);
}

.sect-header-content {
    display: flex;
    align-items: center;
    gap: 20px;
    background: linear-gradient(
        135deg,
        rgba(var(--header-accent),.06) 0%,
        rgba(122,92,255,.04) 100%
    );
    border: 1px solid rgba(var(--header-accent),.14);
    border-left: 3px solid rgba(var(--header-accent),.5);
    border-radius: 0 10px 10px 0;
    padding: 14px 20px 14px 18px;
    position: relative;
    overflow: hidden;
}

.sect-header-content::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 120px;
    height: 100%;
    background: linear-gradient(
        90deg,
        transparent,
        rgba(122,92,255,.04)
    );
    pointer-events: none;
}

.sect-num {
    font-size: 2.2rem;
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    color: rgba(var(--header-accent),.22);
    letter-spacing: -.03em;
    line-height: 1;
    flex-shrink: 0;
    font-family: monospace;
}

.sect-orb {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(var(--header-accent),.55);
    box-shadow: 0 0 10px rgba(var(--header-accent),.6), 0 0 24px rgba(var(--header-accent),.25);
    margin-left: auto;
    animation: orbPulse 3s ease-in-out infinite;
}

@keyframes orbPulse {
    0%, 100% { opacity: .6; box-shadow: 0 0 8px rgba(var(--header-accent),.5), 0 0 20px rgba(var(--header-accent),.2); }
    50%       { opacity: 1;  box-shadow: 0 0 14px rgba(var(--header-accent),.9), 0 0 32px rgba(var(--header-accent),.4); }
}

.options-section-header strong {
    display: block;
    font-size: .82rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: rgba(255,255,255,.82);
    margin-bottom: 4px;
}

.options-section-header p {
    font-size: .76rem;
    color: rgba(255,255,255,.38);
    line-height: 1.5;
    margin: 0;
}

.opt-cat-from {
    font-size: .68rem;
    font-weight: 500;
    color: rgba(255,255,255,.3);
    margin-left: 6px;
    vertical-align: middle;
    font-style: italic;
}

.opt-cat-from--devis {
    color: rgba(251,191,36,.7);
    font-style: normal;
    font-weight: 600;
}

/* ─── Prix des modules (2ᵉ colonne) ───
   Anciennement un flex "space-between" : le prix se retrouvait collé au
   bord droit de la carte, avec un bord GAUCHE en dents de scie (chaque
   libellé — "Offert", "Dès 80 CHF", "Dès 800 CHF"… — ayant une largeur
   différente). Passage à une grille 2 colonnes (cf. .options-category li
   plus bas) : la colonne prix a désormais une largeur fixe et le texte y
   est aligné à gauche, donc tous les prix démarrent à la même position
   verticale, sans être collés au bord droit de la carte. */
/* Demande explicite : les prix des modules ne doivent pas dépendre de la
   couleur sélectionnée, ils restent blancs (cf. 2ᵉ règle .opt-price plus
   bas dans la cascade, qui gagnait jusqu'ici avec rgb(var(--header-accent))). */
.opt-price {
    font-size: .75rem;
    font-weight: 600;
    color: rgba(255,255,255,.82);
    white-space: nowrap;
    text-align: left;
}

.opt-name {
    min-width: 0;
}

.options-section-divider {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 20px 0 8px;
}

.options-section-divider span {
    font-size: .75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: rgba(255,255,255,.45);
    white-space: nowrap;
}

.options-section-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: rgba(255,255,255,.08);
}

.offer-options {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 24px;
    max-width: 1100px;
    margin: 0 auto;
    padding: 40px 20px 60px;
    text-align: left;
}

.options-category {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.06);
    border-radius: 16px;
    padding: 20px 24px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 1.2s ease, transform 1.2s ease, border-color .3s ease, box-shadow .3s ease;
}

.options-category.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.options-category:hover {
    border-color: rgba(122,92,255,.22);
    box-shadow: 0 10px 30px rgba(0,0,0,.35);
}

/* ── Module mis en avant (offres-site.php) : Multilingue (offert avec
   Business) et Réservations & Agenda (offert avec Sur-mesure/Premium)
   isolés chacun sur leur propre ligne pleine largeur, séparés des autres
   modules du même groupe, avec un léger habillage de couleur et un badge
   « Module offert » accroché au titre. Les items restent en colonne,
   comme dans une carte de module normale. Couleur ambre = offert avec
   Business (Multilingue), couleur bleue = offert avec Sur-mesure/Premium
   (Réservations & Agenda), pour rester cohérent avec le code couleur déjà
   utilisé par .sur-adv-module-callout / .badge-offered--blue ailleurs. ── */
.options-category--featured {
    grid-column: 1 / -1;
    background: linear-gradient(135deg, rgba(251,191,36,.07) 0%, rgba(122,92,255,.05) 100%);
    border: 1px solid rgba(251,191,36,.28);
}

.options-category--featured:hover {
    border-color: rgba(251,191,36,.45);
    box-shadow: 0 10px 30px rgba(0,0,0,.35);
}

.options-category--featured h3 .badge-offered {
    margin-left: 8px;
    vertical-align: middle;
}

/* Demande explicite : le module "Réservations et agenda" (offert avec
   Sur-mesure/Premium) ne doit pas hériter de la couleur active — le
   commentaire ci-dessus documentait déjà "couleur bleue" pour ce module,
   contrairement au code qui suivait --header-accent par erreur. */
.options-category--featured--premium {
    background: linear-gradient(135deg, rgba(59,130,246,.08) 0%, rgba(99,102,241,.04) 100%);
    border-color: rgba(59,130,246,.28);
}

.options-category--featured--premium:hover {
    border-color: rgba(59,130,246,.45);
}

/* Demande explicite : sur surmesure.php, les modules offerts avec l'offre
   Premium doivent être violets (pas bleus comme sur offres-site.php). */
.page-sur .options-category--featured--premium {
    background: linear-gradient(135deg, rgba(139,92,246,.08) 0%, rgba(99,102,241,.04) 100%);
    border-color: rgba(139,92,246,.28);
}

.page-sur .options-category--featured--premium:hover {
    border-color: rgba(139,92,246,.45);
}

.option-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
}

.options-category h3 {
    font-size: 1rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255,255,255,.07);
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}

/* Icônes de catégorie remplaçant les emojis (offres-site.php / sitevitrine.php
   / sitepro.php / surmesure.php) : ligne sobre dans la teinte violette déjà
   utilisée pour les libellés h4 de cette même grille. */
.opt-cat-icon {
    width: 18px;
    height: 18px;
    margin-right: 8px;
    flex-shrink: 0;
    color: rgba(122,92,255,.85);
}

.options-category h4 {
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: rgba(122,92,255,.8);
    margin: 14px 0 6px;
}

.options-category ul {
    list-style: none;
    padding: 0;
    margin: 0 0 6px;
}

.options-category li {
    font-size: .88rem;
    color: rgba(255,255,255,.68);
    padding: 5px 0 5px 16px;
    position: relative;
    line-height: 1.5;
    display: grid;
    grid-template-columns: 1fr clamp(84px, 12vw, 108px);
    align-items: baseline;
    gap: 8px;
}

.options-category li::before {
    content: "▸";
    position: absolute;
    left: 0;
    color: rgba(122,92,255,.7);
    font-size: .75rem;
}

/* ─── TOOLTIP BADGES (div créé par JS) ─── */
.tooltip {
    position: fixed;
    background: rgba(10,15,40,.96);
    color: #fff;
    padding: 5px 11px;
    border-radius: 6px;
    font-size: .74rem;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity .15s ease;
    z-index: 9999;
    transform: translate(-50%, calc(-100% - 10px));
    border: 1px solid rgba(255,255,255,.10);
    box-shadow: 0 4px 16px rgba(0,0,0,.35);
}

/* ─── BADGES ─── */
.badge {
    display: inline-flex;
    align-items: center;
    font-size: .75rem;
    padding: 3px 10px;
    border-radius: 999px;
    font-weight: 600;
    letter-spacing: .02em;
    border: 1px solid transparent;
    white-space: nowrap;
}

.badge.essentiel {
    background: rgba(255,255,255,.06);
    color: rgba(255,255,255,.65);
    border-color: rgba(255,255,255,.10);
}

.badge.optional {
    background: rgba(251,191,36,.12);
    color: #fbbf24;
    border-color: rgba(251,191,36,.45);
    box-shadow: 0 0 8px rgba(251,191,36,.25), inset 0 0 6px rgba(251,191,36,.08);
    text-shadow: 0 0 8px rgba(251,191,36,.5);
}

/* ─── Badges des étapes "Comment je crée votre site internet" (accueil.php) ─── */
.badge.free {
    background: rgba(16,185,129,.12);
    color: #34d399;
    border-color: rgba(16,185,129,.4);
    box-shadow: 0 0 8px rgba(16,185,129,.2), inset 0 0 6px rgba(16,185,129,.08);
}

.badge.offered {
    background: rgba(139,92,246,.14);
    color: #c4b5fd;
    border-color: rgba(139,92,246,.4);
    box-shadow: 0 0 8px rgba(139,92,246,.2), inset 0 0 6px rgba(139,92,246,.08);
}

.badge.milestone {
    background: rgba(59,130,246,.12);
    color: #93c5fd;
    border-color: rgba(59,130,246,.4);
}

.badge.pro {
    background: rgba(251,191,36,.14);
    color: #fde68a;
    border-color: rgba(251,191,36,.38);
}

.badge.surmesure {
    background: rgba(59,130,246,.13);
    color: #93c5fd;
    border-color: rgba(59,130,246,.35);
}

/* .badge.intro : ancien bouton "Accéder aux offres" (bulle « » » anim.
   arrowSlideright) remplacé par .offers-hero-cta (.modules-cta-link) ci-dessous
   — son texte était uniquement dans un tooltip qui ne s'affichait jamais
   (aucune règle [data-tooltip]::after ne le reliait). */

.offers-hero-cta {
    margin-top: 10px;
}

.badge.suivante {
    font-size: 1.4rem;
    background: rgb(var(--header-accent));
    color: #fff;
    border-radius: 60%;
    border: none;
    margin-left: 20px;
    animation: arrowSlideleft 5s ease-in-out infinite;
    text-decoration: none;
}

.badge.precedente {
    font-size: 1.4rem;
    background: rgb(var(--header-accent));
    color: #fff;
    border-radius: 60%;
    border: none;
    margin-right: 20px;
    animation: arrowSlide1 5s ease-in-out infinite;
    text-decoration: none;
}

/* ─── TOOLTIPS ─── */
.tooltip-link {
    text-decoration: none;
    color: inherit;
}

.tooltip-icon {
    position: relative;
    display: inline-block;
    margin-left: 6px;
    cursor: pointer;
    font-size: 14px;
    color: rgba(255,255,255,.6);
    vertical-align: middle;
}

.tooltip-text {
    position: absolute;
    background: rgba(10,14,30,.96);
    border: 1px solid rgba(255,255,255,.10);
    color: #fff;
    border-radius: 8px;
    font-size: .75rem;
    font-weight: 500;
    white-space: nowrap;
    padding: 6px 12px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .2s ease, visibility .2s ease;
    z-index: 10;
}

.tooltip-icon .tooltip-text {
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
}

.tooltip-icon:hover .tooltip-text {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

/* ─── Tooltip directement au survol d'un bouton (pas d'icône séparée à côté) :
     ex. boutons "Enregistrer" de compte-profil.php. ─── */
.btn-tooltip { position: relative; }
.btn-tooltip::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(10,14,30,.96);
    border: 1px solid rgba(255,255,255,.10);
    color: #fff;
    border-radius: 8px;
    font-size: .75rem;
    font-weight: 500;
    white-space: nowrap;
    padding: 6px 12px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .2s ease, visibility .2s ease, transform .2s ease;
    z-index: 20;
}
.btn-tooltip:hover::after,
.btn-tooltip:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

/* ─── COMPARISON TABLE ─── */
.offer-comparison {
    max-width: 1600px;
    height: 85dvh;
    margin: 40px auto 0;
    margin-bottom: 60px;
    padding: 0 20px 60px;
}

.table-scroll-hint { display: none; }

.table-wrapper {
    border-radius: 16px;
    border: 1px solid rgba(255,255,255,.08);
    background:
        radial-gradient(circle at 8%  12%, rgba(255,255,255,.75) 0%, transparent .4%),
        radial-gradient(circle at 55% 5%,  rgba(255,255,255,.60) 0%, transparent .35%),
        radial-gradient(circle at 92% 18%, rgba(255,255,255,.70) 0%, transparent .42%),
        radial-gradient(circle at 22% 55%, rgba(255,255,255,.50) 0%, transparent .30%),
        radial-gradient(circle at 78% 42%, rgba(255,255,255,.55) 0%, transparent .33%),
        radial-gradient(circle at 40% 88%, rgba(255,255,255,.45) 0%, transparent .28%),
        radial-gradient(circle at 88% 78%, rgba(255,255,255,.48) 0%, transparent .30%),
        radial-gradient(circle at 14% 80%, rgba(255,255,255,.42) 0%, transparent .27%),
        rgba(6,8,20,.85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: 0 4px 60px rgba(0,0,0,.25);
    position: relative;
    padding-top: 14px;
    overflow: visible;
}



/* Sticky thead */
.offer-comparison thead {
    position: sticky;
    top: 0;
    z-index: 10;
}

.offer-comparison thead tr {
    background:
        radial-gradient(circle at 8%  12%, rgba(255,255,255,.75) 0%, transparent .4%),
        radial-gradient(circle at 55% 5%,  rgba(255,255,255,.60) 0%, transparent .35%),
        radial-gradient(circle at 92% 18%, rgba(255,255,255,.70) 0%, transparent .42%),
        rgba(6,8,20,.95);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}

.offer-comparison table {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
}

.offer-comparison tbody tr {
    border-bottom: 1px solid rgba(255,255,255,.055);
    transition: background .2s ease;
}

.offer-comparison tbody tr:last-child { border-bottom: none; }

.offer-comparison tbody tr:hover { background: rgba(255,255,255,.025); }

.offer-comparison tr.table-section-label td {
    font-size: .6rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .1em;
    color: rgba(255,255,255,.35);
    padding-top: 24px;
    padding-bottom: 6px;
    border-bottom: 1px solid rgba(255,255,255,.06);
    background: transparent !important;
    pointer-events: none;
}

.offer-comparison tr.table-section-label:hover { background: transparent !important; }

.offer-comparison td,
.offer-comparison th {
    padding: 15px 20px;
    text-align: center;
    line-height: 1.5;
    position: relative;
    vertical-align: middle;
}

.offer-comparison td {
    font-size: .78rem;
    word-wrap: break-word;
    overflow-wrap: break-word;
    color: rgba(255,255,255,.75);
}

.offer-comparison th {
    font-size: 0.8rem;
    font-weight: 700;
    color: #fff;
}

.offer-comparison td:first-child,
.offer-comparison th:first-child {
    width: 30%;
    text-align: left;
    font-weight: 500;
    color: rgba(255,255,255,.88);
    padding-left: 24px;
}

.offer-comparison td:not(:first-child),
.offer-comparison th:not(:first-child) {
    border-left: 1px solid rgba(255,255,255,.05);
}

/* Col 2 — Essentiel (cyan) */
.offer-comparison th:nth-child(2),
.offer-comparison td:nth-child(2) {
    background: rgba(59,130,246,.03);
}

/* Col 3 — Pro (recommended, amber) */
.offer-comparison th:nth-child(3),
.offer-comparison td:nth-child(3) {
    background: rgba(251,191,36,.06);
    border-left: 1px solid rgba(251,191,36,.20) !important;
    border-right: 1px solid rgba(251,191,36,.20);
}

.offer-comparison th:nth-child(3) {
    box-shadow: 0 6px 28px rgba(251,191,36,.14);
}

/* Col 4 — Sur mesure (blue) */
.offer-comparison th:nth-child(4),
.offer-comparison td:nth-child(4) {
    background: rgba(var(--header-accent),.04);
}

/* Row hover per column */
.offer-comparison tbody tr:hover td:nth-child(2) { background: rgba(59,130,246,.07); }
.offer-comparison tbody tr:hover td:nth-child(3) { background: rgba(251,191,36,.11); }
.offer-comparison tbody tr:hover td:nth-child(4) { background: rgba(var(--header-accent),.07); }

/* thead */
.offer-comparison thead th {
    font-weight: 800;
    padding-top: 28px;
    padding-bottom: 22px;
    font-size: 0.85rem;
    letter-spacing: .01em;
    border-bottom: 1px solid rgba(255,255,255,.07);
}

.offer-comparison thead th:first-child { border-radius: 16px 0 0 0; }
.offer-comparison thead th:last-child  { border-radius: 0 16px 0 0; }

.offer-comparison thead th:nth-child(2) { color: #93c5fd; }
.offer-comparison thead th:nth-child(3) { color: #fde68a; }
.offer-comparison thead th:nth-child(4) { color: #93c5fd; }


/* tfoot */
.offer-comparison tfoot tr {
    border-top: 1px solid rgba(255,255,255,.08);
}

.offer-comparison tfoot td {
    color: rgba(255,255,255,.45);
    font-size: .82rem;
    padding: 14px 20px;
}

.offer-comparison tfoot td:first-child { padding-left: 24px; }

/* Price row */
.offer-comparison .price-row {
    border-top: 1px solid rgba(255,255,255,.10) !important;
}

/* L'intitulé "Tarifs" avait été réduit et assombri (.74rem, opacité .55) par
   rapport aux autres libellés de ligne (Livraison, SEO, Pages…) : c'est ce qui
   rendait la ligne plus terne. On revient à la même mise en avant que les
   autres lignes. */
.offer-comparison .price-row td:first-child {
    font-weight: 500;
    color: rgba(255,255,255,.88);
}

.offer-comparison .price-row th {
    font-size: 1.0rem;
    font-weight: 800;
    color: #fff;
    padding-top: 22px;
    padding-bottom: 22px;
}

/* Couleurs alignées sur celles du thead (col2 = Essentiel/cyan, col3 =
   Business/or, col4 = Sur-mesure/bleu) : col2 et col4 étaient inversées, ce
   qui donnait un bleu pastel plus terne sur la colonne Essentiel au lieu du
   cyan vif utilisé partout ailleurs dans le tableau. */
.offer-comparison .price-row th:nth-child(2) { color: #93c5fd; }
.offer-comparison .price-row th:nth-child(3) { font-size: 1.4rem; color: #fde68a; }
.offer-comparison .price-row th:nth-child(4) { color: #93c5fd; }

/* Check / Cross coloring */
.offer-comparison .val-check { color: #4ade80; font-size: 1.1rem; font-weight: 700; }
/* Contraste relevé (.30 -> .42) : reste volontairement discret par rapport
   au ✓ vert (fonctionnalité non incluse), mais devait rester lisible en tant
   que symbole — demande explicite "améliore ce qui est visuellement fade". */
.offer-comparison .val-cross { color: rgba(255,255,255,.42); font-size: .9rem; letter-spacing: .05em; }



/* ─── OFFER CTA ─── */
/* .offer-cta suit maintenant la FAQ (padding-top réduit pour resserrer
   l'écart) et précède à son tour le formulaire de commande générique
   (.order-form-section, cf. plus bas dans le fichier) qui est désormais la
   vraie dernière section et réserve lui-même l'espace du footer flottant. */
.offer-cta {
    text-align: center;
    padding: 32px 20px 48px;
    max-width: 900px;
    margin: 0 auto;
}

.offer-cta h2 {
    font-size: clamp(1.6rem, 3vw, 2.2rem);
    font-weight: 800;
    margin-bottom: 40px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.cta-buttons {
    display: flex;
    gap: 16px;
    justify-content: center;
    flex-wrap: wrap;
    align-items: center;
}

.cta-btn {
    display: inline-block;
    padding: 12px 32px;
    border-radius: 999px;
    text-decoration: none;
    font-weight: 600;
    font-size: .95rem;
    color: #fff;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.12);
    transition: transform .3s ease, box-shadow .3s ease, background .3s ease, border-color .3s ease;
}

.cta-btn:hover {
    transform: translateY(-3px);
}

/* Essentiel (cyan) et Premium (bleu) : neutres par défaut, ne révèlent leur
   couleur qu'au survol — seule l'offre Business reste mise en avant en
   permanence (cf. .cta-btn--featured ci-dessous). */
.cta-btn--essentiel:hover {
    border-color: rgba(59,130,246,.6);
    box-shadow: 0 10px 25px rgba(59,130,246,.18);
    background: rgba(59,130,246,.10);
}

.cta-btn--premium:hover {
    border-color: rgba(var(--header-accent),.6);
    box-shadow: 0 10px 25px rgba(var(--header-accent),.18);
    background: rgba(var(--header-accent),.10);
}

/* Business (or) : couleur toujours visible, pas seulement au survol. */
.cta-btn--featured {
    background: rgba(251,191,36,.75);
    border-color: rgba(251,191,36,.55);
    transform: scale(1.06);
    box-shadow: 0 8px 24px rgba(251,191,36,.30);
}

.cta-btn--featured:hover {
    background: rgba(251,191,36,.90);
    box-shadow: 0 14px 34px rgba(251,191,36,.42);
    transform: scale(1.06) translateY(-3px);
}

/* ─── MODALITIES ─── */
.offer-modalities {
    max-width: 860px;
    margin: 0 auto;
    padding: 40px 20px var(--footer-clearance);
}

.offer-modalities h2 {
    text-align: center;
    font-size: clamp(1.4rem, 2.5vw, 1.9rem);
    font-weight: 700;
    margin-bottom: 28px;
    color: rgba(255,255,255,.9);
}

.modalities-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.modalities-list li {
    padding: 14px 20px 14px 44px;
    border-radius: 12px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.06);
    color: rgba(255,255,255,.70);
    font-size: .92rem;
    line-height: 1.6;
    position: relative;
    transition: border-color .25s ease, background .25s ease;
}

.modalities-list li::before {
    content: "✦";
    position: absolute;
    left: 18px;
    top: 50%;
    transform: translateY(-50%);
    font-size: .65rem;
    color: rgba(var(--header-accent),.65);
}

.modalities-list li:hover {
    background: rgba(255,255,255,.045);
    border-color: rgba(255,255,255,.10);
}

/* ========================= sitevitrine.php ========================= */

/* ─── BACKGROUND FIXE ─── */
.page-vitrine::before {
    content: "";
    position: fixed;
    inset: 0;
    /* Même traitement que hm.php/offres-site.php : rideau dégradé en haut
       (masque le fond derrière le header flottant) + bgsiteindex.png en
       fond de page entier. La planète-eau (ex .vitrine-hero-planet,
       retirée du hero) revient en ::after, cf. plus bas. */
    background:
        linear-gradient(to bottom, rgba(3,5,14,.96) 0, rgba(3,5,14,.96) 90px, transparent 260px),
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Planète-eau (offre Essentiel) sur son propre calque ::after, masquée en
   fondu radial — même principe que .page-offers::after / .page-hm::after. */
.page-vitrine::after {
    content: "";
    position: fixed;
    inset: 0;
    /* vmin (plus petit des 2 axes du viewport) au lieu de 75%/60% : garde
       une taille carrée quel que soit le format d'écran, pour que la
       planète reste ronde au lieu d'être étirée. Masque en cercle exact
       (unité vmin également) plutôt qu'ellipse en %, pour rester
       parfaitement rond lui aussi. */
    background: url("../image/planet-bleu.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    /* Rétrécit + s'efface au scroll, même mécanisme que .page-offers::after
       (cf. main.js, bloc "DÉCOR DE FOND"). */
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}

/* Arrivée de page : la planète part d'invisible/réduite et grandit jusqu'à
   sa taille pleine en 1s (cf. main.js, qui pose --bg-scroll-scale/-opacity à
   0 puis 1 juste après le chargement et retire .bg-entrance une fois
   l'animation terminée pour laisser le scroll reprendre la main avec sa
   transition rapide habituelle). */
.page-vitrine.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-vitrine > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-vitrine .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 2.5s ease .5s, transform 2.5s ease .5s;
}

.page-vitrine .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}


/* ─── HERO : taille réduite ─── */
.vitrine-hero {
    min-height: 60dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 180px 20px 60px;
    text-align: center;
    position: relative;
}


/* ─── NAVIGATION INTER-OFFRES : plus visible ─── */
.vitrine-offer-nav {
    position: absolute;
    top: clamp(90px, 12vh, 120px);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: min(860px, calc(100% - 40px));
}

.vitrine-nav-link {
    display: inline-flex;
    position: relative;
    align-items: center;
    gap: 10px;
    font-size: .95rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(255,255,255,.80);
    text-decoration: none;
    padding: 12px 28px;
    border-radius: 999px;
    background: rgba(var(--header-accent),.12);
    border: 1px solid rgba(var(--header-accent),.45);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow:
        0 0 18px rgba(var(--header-accent),.15),
        inset 0 1px 0 rgba(255,255,255,.08);
    transition:
        color .25s ease,
        background .25s ease,
        border-color .25s ease,
        box-shadow .25s ease,
        transform .25s ease;
}

.vitrine-nav-link:hover {
    color: #fff;
    background: rgba(var(--header-accent),.25);
    border-color: rgba(var(--header-accent),.75);
    box-shadow:
        0 0 32px rgba(var(--header-accent),.35),
        0 8px 20px rgba(var(--header-accent),.20),
        inset 0 1px 0 rgba(255,255,255,.12);
    transform: translateY(-2px);
}

.vitrine-nav-link--prev:hover {
    transform: translateY(-2px) translateX(-3px);
}

.vitrine-nav-link--next:hover {
    transform: translateY(-2px) translateX(3px);
}

.vitrine-nav-link svg {
    width: 18px;
    height: 18px;
    transition: transform .25s ease;
    flex-shrink: 0;
}

.vitrine-nav-link--prev:hover svg {
    transform: translateX(-3px);
}

.vitrine-nav-link--next:hover svg {
    transform: translateX(3px);
}

.vitrine-nav-link::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(-100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(10,14,30,.96);
    border: 1px solid rgba(255,255,255,.10);
    color: rgba(255,255,255,.85);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .04em;
    white-space: nowrap;
    padding: 5px 12px;
    border-radius: 6px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease, transform .2s ease;
    z-index: 10;
}

.vitrine-nav-link:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

.vitrine-track-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255,255,255,.22);
    border: 1px solid rgba(255,255,255,.18);
    flex-shrink: 0;
}

.vitrine-track-dot--active {
    width: 10px;
    height: 10px;
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.8);
    box-shadow: 0 0 10px rgba(var(--header-accent),.70);
}

.vitrine-track-line {
    width: 32px;
    height: 1px;
    background: rgba(255,255,255,.20);
}


/* ─── PLANÈTE DÉCORATIVE DERRIÈRE LA HERO (offre correspondante) ───
   Commune aux 3 pages d'offre (sitevitrine/sitepro/surmesure) : la planète
   de l'offre (déjà utilisée sur offres-site.php) est reprise en grand
   format, centrée derrière le bloc "offre / descriptif / prix / cta",
   sous la navigation inter-offres. Adoucie (opacité + flou + fondu radial)
   pour rester lisible en arrière-plan sans nuire au contraste du texte. */
.vitrine-hero-planet,
.pro-hero-planet,
.sur-hero-planet {
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(360px, 42vw, 620px);
    height: clamp(360px, 42vw, 620px);
    transform: translate(-50%, -50%);
    z-index: 0;
    pointer-events: none;
    opacity: .34;
    filter: blur(1px);
    mask-image: radial-gradient(circle, rgba(0,0,0,.9) 55%, transparent 78%);
    -webkit-mask-image: radial-gradient(circle, rgba(0,0,0,.9) 55%, transparent 78%);
}

.vitrine-hero-planet img,
.pro-hero-planet img,
.sur-hero-planet img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.vitrine-offer-nav,
.pro-offer-nav,
.sur-offer-nav {
    z-index: 2;
}

/* ─── HERO INNER ─── */
.vitrine-hero-inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    max-width: 700px;
}

/* Demande explicite : le badge "EXPRESS" (nom de l'offre Essentiel) reste
   bleu quelle que soit la couleur active — doit désormais en hériter. */
.vitrine-tier-label {
    display: inline-flex;
    align-items: center;
    padding: 4px 16px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgb(var(--header-accent));
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.28);
    box-shadow: 0 0 14px rgba(var(--header-accent),.12);
}

/* ─── Ruban d'offre (même logique que les cartes offres-site.php) ─── */
.vitrine-tier-row {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px;
}

/* Demande explicite : le badge "express" en haut du hero doit hériter de
   la couleur active. */
.vitrine-tier-ribbon {
    display: inline-flex;
    align-items: center;
    padding: 4px 14px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .04em;
    color: rgba(var(--header-accent),.9);
    background: rgba(var(--header-accent),.10);
    border: 1px dashed rgba(var(--header-accent),.35);
}

.vitrine-hero h1 {
    font-size: clamp(1.9rem, 4vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.vitrine-subtitle {
    color: rgba(255,255,255,.60);
    font-size: 1.05rem;
    line-height: 1.75;
    max-width: 560px;
    margin: 0;
}

.vitrine-price-block {
    margin: 4px 0;
}

.vitrine-price {
    /* Pastille adoucie : le dégradé plein + halo trop marqués attiraient
       trop l'œil sur le prix Essentiel par rapport au reste du hero.
       Demande explicite : ce badge de prix doit hériter de la couleur
       active plutôt que rester fixé en bleu/cyan. */
    display: inline-flex;
    align-items: baseline;
    gap: 9px;
    padding: 12px 28px;
    border-radius: 14px;
    color: rgba(255,255,255,.92);
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.28);
    box-shadow: 0 0 14px rgba(var(--header-accent),.12), inset 0 1px 0 rgba(255,255,255,.06);
}
.vitrine-price .price-amount { font-size: 1.9rem; font-weight: 800; letter-spacing: -.01em; }
.vitrine-price .price-currency { font-size: .92rem; font-weight: 700; opacity: .82; text-transform: uppercase; letter-spacing: .05em; }

/* ─── INCLUS + MODALITÉS ─── */
.vitrine-details {
    max-width: 1100px;
    margin: 0 auto;
    padding: 60px 20px;
}

.vitrine-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 28px;
}

.vitrine-card {
    padding: 32px 28px;
    border-radius: 20px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    position: relative;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease;
}

.vitrine-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.vitrine-card--includes::before {
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.70), transparent);
}

.vitrine-card--terms::before {
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.20), transparent);
}

.vitrine-card--includes:hover {
    border-color: rgba(59,130,246,.22);
    box-shadow: 0 10px 32px rgba(59,130,246,.09);
}

.vitrine-card h2 {
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 18px;
    padding-bottom: 12px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}

.vitrine-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.vitrine-list li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.05);
    color: rgba(255,255,255,.68);
    font-size: .88rem;
    line-height: 1.55;
    transition: background .2s ease, border-color .2s ease, color .2s ease;
}

/* Demande explicite : les symboles "validé" du tableau inclus doivent
   suivre la couleur active, pas un bleu fixe. */
.vitrine-list li::before {
    content: "✓";
    color: rgb(var(--header-accent));
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
    font-size: .85rem;
}

.vitrine-list--terms {
    counter-reset: modal-counter;
}

.vitrine-list--terms li {
    counter-increment: modal-counter;
}

.vitrine-list--terms li::before {
    content: counter(modal-counter, decimal-leading-zero) ".";
    color: rgba(59,130,246,.55);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    min-width: 22px;
    flex-shrink: 0;
}

.vitrine-card--includes .vitrine-list li:hover {
    background: rgba(59,130,246,.06);
    border-color: rgba(59,130,246,.16);
    color: rgba(255,255,255,.88);
}

/* ─── Feature offerte mise en évidence dans "Inclus" (même logique que
   .pro-list-highlight / .sur-list-highlight) : Formulaire de contact,
   offert avec Essentiel — cf. bannière .vit-adv-callout plus bas. ─── */
.vitrine-list-highlight {
    color: rgba(59,130,246,.95);
    font-weight: 600;
    background: rgba(59,130,246,.07);
    border-color: rgba(59,130,246,.2);
}

/* ─── OPTIONS ─── */
.vitrine-options {
    max-width: 1100px;
    margin: 0 auto;
    padding: 20px 20px 60px;
}

.vitrine-options-header {
    text-align: center;
    max-width: 680px;
    margin: 0 auto 36px;
}

.vitrine-options-header h2 {
    font-size: clamp(1.35rem, 2.5vw, 1.85rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.vitrine-options-header p {
    color: rgba(255,255,255,.50);
    font-size: .92rem;
    line-height: 1.7;
}

.vitrine-options-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 18px;
}

.vitrine-options-grid .option-card {
    grid-column: span 2;
}

.vitrine-options-grid .option-card:nth-child(7) {
    grid-column: 3 / 5;
}

.option-card {
    padding: 22px 20px;
    border-radius: 16px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    opacity: 0;
    transform: translateY(16px);
    transition:
        opacity .8s ease,
        transform .8s ease,
        border-color .3s ease,
        box-shadow .3s ease;
}

.option-card.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.option-card:nth-child(1) { transition-delay: .05s; }
.option-card:nth-child(2) { transition-delay: .12s; }
.option-card:nth-child(3) { transition-delay: .19s; }
.option-card:nth-child(4) { transition-delay: .26s; }
.option-card:nth-child(5) { transition-delay: .33s; }
.option-card:nth-child(6) { transition-delay: .40s; }
.option-card:nth-child(7) { transition-delay: .47s; }

/* Apparition plus lente sur sitevitrine/sitepro/surmesure uniquement (le
   reste du site garde .8s) : demandé pour accentuer l'effet d'arrivée sur
   ces 3 pages, en cohérence avec les 2.5s des .section-block ci-dessus. */
.page-vitrine .option-card,
.page-pro .option-card,
.page-sur .option-card {
    transition:
        opacity 2.5s ease .5s,
        transform 2.5s ease .5s,
        border-color .3s ease,
        box-shadow .3s ease;
}

.option-card:hover {
    border-color: rgba(var(--header-accent),.22);
    box-shadow: 0 8px 24px rgba(var(--header-accent),.08);
}

.option-card h3 {
    font-size: .92rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}

.option-card ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.option-card li {
    font-size: .83rem;
    color: rgba(255,255,255,.60);
    padding: 4px 0 4px 14px;
    position: relative;
    line-height: 1.5;
}

.option-card li::before {
    content: "▸";
    position: absolute;
    left: 0;
    color: rgba(var(--header-accent),.65);
    font-size: .72rem;
    top: 5px;
}

.option-card li.opt-item {
    padding-left: 0;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

.option-card li.opt-item::before {
    display: none;
}

.opt-item-name {
    flex: 1;
    color: rgba(255,255,255,.70);
    line-height: 1.5;
}

.opt-price {
    flex-shrink: 0;
    font-size: .78rem;
    font-weight: 600;
    color: rgba(255,255,255,.82);
    white-space: nowrap;
    margin-top: 1px;
}

/* ─── ADVANCED MODULES CALLOUT ─── */
.vit-adv-callout {
    grid-column: 1 / -1;
    max-width: 1100px;
    margin: 8px auto 0;
    padding: 0 20px 48px;
    width: 100%;
    box-sizing: border-box;
}

.vit-adv-callout-inner {
    display: flex;
    align-items: center;
    gap: 20px;
    background: linear-gradient(135deg, rgba(122,92,255,.07) 0%, rgba(var(--header-accent),.05) 100%);
    border: 1px solid rgba(122,92,255,.22);
    border-left: 3px solid rgba(122,92,255,.6);
    border-radius: 0 12px 12px 0;
    padding: 18px 24px;
    flex-wrap: wrap;
}

.vit-adv-callout-label {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: rgba(122,92,255,.9);
    white-space: nowrap;
    flex-shrink: 0;
}

.vit-adv-callout-text {
    flex: 1;
    font-size: .82rem;
    color: rgba(255,255,255,.5);
    line-height: 1.55;
    margin: 0;
    min-width: 200px;
}

.vit-adv-callout-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .8rem;
    font-weight: 600;
    color: rgba(122,92,255,.85);
    text-decoration: none;
    white-space: nowrap;
    flex-shrink: 0;
    transition: color .2s ease, gap .2s ease;
}

.vit-adv-callout-link svg {
    width: 14px;
    height: 14px;
    transition: transform .2s ease;
}

.vit-adv-callout-link:hover {
    color: rgba(122,92,255,1);
    gap: 10px;
}

.vit-adv-callout-link:hover svg {
    transform: translateX(3px);
}

.vit-adv-callout-inner + .vit-adv-callout-inner {
    margin-top: 10px;
}

.vit-adv-callout-inner--cyan {
    background: linear-gradient(135deg, rgba(59,130,246,.07) 0%, rgba(var(--header-accent),.04) 100%);
    border-color: rgba(59,130,246,.22);
    border-left-color: rgba(59,130,246,.6);
}

.vit-adv-callout-link--cyan {
    color: rgba(59,130,246,.85);
}

.vit-adv-callout-inner--cyan .vit-adv-callout-label {
    color: rgba(59,130,246,.9);
}

.vit-adv-callout-link--cyan:hover {
    color: rgba(59,130,246,1);
}

.vit-adv-callout-inner--green {
    background: linear-gradient(135deg, rgba(34,197,94,.07) 0%, rgba(16,185,129,.04) 100%);
    border-color: rgba(34,197,94,.22);
    border-left-color: rgba(34,197,94,.6);
}

.vit-adv-callout-link--green {
    color: rgba(34,197,94,.85);
}

.vit-adv-callout-inner--green .vit-adv-callout-label {
    color: rgba(34,197,94,.9);
}

.vit-adv-callout-link--green:hover {
    color: rgba(34,197,94,1);
}

/* ─── "Et après la livraison ?" : les bannières hébergement / conseil
   (auparavant deux chips compacts dans .vit-adv-callout) deviennent une
   vraie section à 2 blocs, sur sitevitrine.php / sitepro.php / surmesure.php.
   Le contenu (label/texte/lien) reprend tel quel vit_hm_callout_* et
   vit_conseil_callout_*. ─── */
.after-delivery {
    max-width: 1100px;
    margin: 0 auto;
    padding: 16px 20px 70px;
}

.after-delivery-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 28px;
}

.after-delivery-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 32px 30px;
    border-radius: 20px;
    background: linear-gradient(135deg, rgba(59,130,246,.08) 0%, rgba(var(--header-accent),.04) 100%);
    border: 1px solid rgba(59,130,246,.24);
    transition: border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}

.after-delivery-card:hover {
    border-color: rgba(59,130,246,.42);
    box-shadow: 0 14px 34px rgba(0,0,0,.3);
    transform: translateY(-3px);
}

.after-delivery-icon {
    font-size: 1.7rem;
    line-height: 1;
}

.after-delivery-card h3 {
    font-size: 1.15rem;
    font-weight: 800;
    color: #fff;
    margin: 0;
}

.after-delivery-card p {
    font-size: .9rem;
    color: rgba(255,255,255,.6);
    line-height: 1.6;
    margin: 0;
    flex: 1;
}

.after-delivery-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .88rem;
    font-weight: 700;
    color: rgba(59,130,246,.9);
    text-decoration: none;
    transition: color .2s ease, gap .2s ease;
}

.after-delivery-link svg {
    width: 15px;
    height: 15px;
    transition: transform .2s ease;
}

.after-delivery-link:hover {
    color: rgba(59,130,246,1);
    gap: 10px;
}

.after-delivery-link:hover svg {
    transform: translateX(3px);
}

/* ── Couleurs alignées sur la page de destination du lien, pas sur la page
   d'où l'on vient (sitevitrine/sitepro/surmesure partagent maintenant les
   mêmes couleurs) : « Le site livré, et ensuite ? » pointe vers hm.php
   (cyan, cf. $_header_accent_map dans partials/header.php) — c'est déjà la
   teinte par défaut de .after-delivery-card ci-dessus — et « Besoin d'un
   accompagnement ? » pointe vers conseil.php (violet). ── */
.after-delivery-card--conseil {
    background: linear-gradient(135deg, rgba(139,92,246,.08) 0%, rgba(99,102,241,.04) 100%);
    border-color: rgba(139,92,246,.24);
}

.after-delivery-card--conseil:hover {
    border-color: rgba(139,92,246,.42);
}

.after-delivery-card--conseil .after-delivery-link {
    color: rgba(139,92,246,.9);
}

.after-delivery-card--conseil .after-delivery-link:hover {
    color: rgba(139,92,246,1);
}

.pro-adv-module-callout {
    background: linear-gradient(135deg, rgba(251,191,36,.08) 0%, rgba(245,158,11,.04) 100%);
    border-color: rgba(251,191,36,.25);
    border-left-color: rgba(251,191,36,.65);
}

.pro-adv-module-callout .vit-adv-callout-label {
    color: rgba(251,191,36,.95);
}

/* ─── PAGE ESSENTIEL (sitevitrine.php) — bannière formulaire de contact offert ─── */
.vit-contact-offer-callout {
    background: linear-gradient(135deg, rgba(59,130,246,.08) 0%, rgba(var(--header-accent),.04) 100%);
    border-color: rgba(59,130,246,.25);
    border-left-color: rgba(59,130,246,.65);
}

.vit-contact-offer-callout .vit-adv-callout-label {
    color: rgba(59,130,246,.95);
}

.vit-adv-callout-link--amber {
    color: rgba(251,191,36,.85);
}

.vit-adv-callout-link--amber:hover {
    color: rgba(251,191,36,1);
}

.pro-list-highlight {
    color: rgba(251,191,36,.95);
    font-weight: 600;
    background: rgba(251,191,36,.06);
    border-color: rgba(251,191,36,.15);
}

/* ─── PAGE PREMIUM (surmesure.php) ─── */

.sur-adv-module-callout {
    background: linear-gradient(135deg, rgba(var(--header-accent),.08) 0%, rgba(99,102,241,.04) 100%);
    border-color: rgba(var(--header-accent),.25);
    border-left-color: rgba(var(--header-accent),.65);
}

.sur-adv-module-callout .vit-adv-callout-label {
    color: rgba(var(--header-accent),.95);
}

.vit-adv-callout-link--blue {
    color: rgba(var(--header-accent),.85);
}

.vit-adv-callout-link--blue:hover {
    color: rgba(var(--header-accent),1);
}

.sur-list-highlight {
    color: rgba(251,191,36,.95);
    font-weight: 600;
    background: rgba(251,191,36,.06);
    border-color: rgba(251,191,36,.15);
}

.sur-list-highlight--blue {
    color: rgba(var(--header-accent),.95);
    background: rgba(var(--header-accent),.06);
    border-color: rgba(var(--header-accent),.15);
}

.page-sur .sur-hero,
.page-sur .sur-details,
.page-sur .sur-options,
.page-sur .sur-cta {
    max-width: 1100px;
    margin-left: auto;
    margin-right: auto;
}

.sur-hero {
    padding-top: clamp(100px, 14vw, 160px);
    padding-bottom: 60px;
    text-align: center;
    position: relative;
}

.sur-offer-nav {
    position: absolute;
    top: clamp(90px, 12vh, 120px);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: min(860px, calc(100% - 40px));
}

.sur-nav-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: .95rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(255,255,255,.80);
    text-decoration: none;
    padding: 12px 28px;
    border-radius: 999px;
    background: rgba(var(--header-accent),.12);
    border: 1px solid rgba(var(--header-accent),.45);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow:
        0 0 18px rgba(var(--header-accent),.16),
        inset 0 1px 0 rgba(255,255,255,.08);
    transition:
        color .25s ease,
        background .25s ease,
        border-color .25s ease,
        box-shadow .25s ease,
        transform .25s ease;
}

.sur-nav-link:hover {
    color: #fff;
    background: rgba(var(--header-accent),.24);
    border-color: rgba(var(--header-accent),.75);
    box-shadow:
        0 0 36px rgba(var(--header-accent),.38),
        0 8px 20px rgba(var(--header-accent),.20),
        inset 0 1px 0 rgba(255,255,255,.12);
    transform: translateY(-2px);
}

.sur-nav-link--prev:hover { transform: translateY(-2px) translateX(-3px); }
.sur-nav-link--overview:hover { transform: translateY(-2px) translateX(3px); }

.sur-nav-link svg {
    width: 18px;
    height: 18px;
    transition: transform .25s ease;
    flex-shrink: 0;
}

.sur-nav-link--prev:hover svg { transform: translateX(-3px); }
.sur-nav-link--overview:hover svg { transform: translateX(3px); }

.sur-nav-link::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(-100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(10,14,30,.96);
    border: 1px solid rgba(255,255,255,.10);
    color: rgba(255,255,255,.85);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .04em;
    white-space: nowrap;
    padding: 5px 12px;
    border-radius: 6px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease, transform .2s ease;
    z-index: 10;
}

.sur-nav-link:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

.sur-tier-label {
    display: inline-block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.9);
    background: rgba(var(--header-accent),.1);
    border: 1px solid rgba(var(--header-accent),.25);
    border-radius: 20px;
    padding: 4px 14px;
}

/* ─── Ruban d'offre (même logique que les cartes offres-site.php) ─── */
.sur-tier-row {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 16px;
}

.sur-tier-ribbon {
    display: inline-flex;
    align-items: center;
    padding: 4px 14px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .04em;
    color: rgba(255,255,255,.75);
    background: rgba(255,255,255,.06);
    border: 1px dashed rgba(255,255,255,.22);
}

.sur-hero-inner {
    position: relative;
    z-index: 1;
}

.sur-hero-inner h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 800;
    margin: 0 0 12px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.sur-subtitle {
    color: rgba(255,255,255,.55);
    font-size: 1rem;
    line-height: 1.7;
    max-width: 540px;
    margin: 0 auto 28px;
}

.sur-price-block {
    margin-bottom: 28px;
}

.sur-price {
    /* Même style de pastille douce que .vitrine-price (sitevitrine.php),
       couleur bleue = accent de surmesure.php. */
    display: inline-flex;
    align-items: baseline;
    gap: 9px;
    padding: 13px 30px;
    border-radius: 14px;
    color: rgba(255,255,255,.92);
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(96,165,250,.30);
    box-shadow: 0 0 14px rgba(var(--header-accent),.14), inset 0 1px 0 rgba(255,255,255,.06);
}
.sur-price .price-amount { font-size: clamp(1.6rem, 3vw, 1.9rem); font-weight: 800; letter-spacing: -.01em; }
.sur-price .price-currency { font-size: .92rem; font-weight: 700; opacity: .82; text-transform: uppercase; letter-spacing: .05em; }

.sur-details {
    padding: 0 20px 48px;
}

.sur-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    max-width: 1100px;
    margin: 0 auto;
}

.sur-card {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    border-radius: 16px;
    padding: 28px 24px;
    position: relative;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease;
}

.sur-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.sur-card--includes::before {
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.80), transparent);
}

.sur-card--terms::before {
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.20), transparent);
}

.sur-card--includes:hover {
    border-color: rgba(var(--header-accent),.22);
    box-shadow: 0 10px 32px rgba(var(--header-accent),.09);
}

.sur-card h2 {
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 18px;
    padding-bottom: 12px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}

.sur-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.sur-list li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.05);
    font-size: .88rem;
    color: rgba(255,255,255,.68);
    line-height: 1.55;
    transition: background .2s ease, border-color .2s ease, color .2s ease;
}

.sur-list li::before {
    content: '✓';
    color: rgba(var(--header-accent),.8);
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
    font-size: .85rem;
}

.sur-card--includes .sur-list li:hover {
    background: rgba(var(--header-accent),.06);
    border-color: rgba(var(--header-accent),.16);
    color: rgba(255,255,255,.88);
}

.sur-list--terms {
    counter-reset: modal-counter;
}

.sur-list--terms li {
    counter-increment: modal-counter;
}

.sur-list--terms li::before {
    content: counter(modal-counter, decimal-leading-zero) ".";
    color: rgba(var(--header-accent),.55);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    min-width: 22px;
    flex-shrink: 0;
}

.badge-offered {
    display: inline-flex;
    align-items: center;
    margin-left: auto;
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    padding: 2px 9px;
    border-radius: 20px;
    flex-shrink: 0;
    line-height: 1.7;
}

.badge-offered--amber {
    background: rgba(251,191,36,.12);
    color: rgba(251,191,36,.95);
    border: 1px solid rgba(251,191,36,.28);
}

.badge-offered--blue {
    background: rgba(var(--header-accent),.12);
    color: rgba(var(--header-accent),.95);
    border: 1px solid rgba(var(--header-accent),.28);
}

/* Demande explicite : sur surmesure.php, les modules offerts avec l'offre
   Premium/Sur-mesure doivent être violets (identité Premium fixe), pas
   dépendants de la couleur active. */
.page-sur .badge-offered--blue {
    background: rgba(139,92,246,.12);
    color: rgba(139,92,246,.95);
    border: 1px solid rgba(139,92,246,.28);
}

.badge-offered--devis {
    background: rgba(255,255,255,.06);
    color: rgba(255,255,255,.50);
    border: 1px solid rgba(255,255,255,.12);
}

.highlight-anchor {
    color: inherit;
    text-decoration: none;
    flex: 1;
}

.highlight-anchor:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    text-decoration-color: currentColor;
    opacity: .85;
}

.sur-options {
    padding: 0 20px 48px;
}

.sur-cta {
    text-align: center;
    padding: 60px 20px var(--footer-clearance);
    max-width: 760px;
    margin: 0 auto;
}

.sur-cta h2 {
    font-size: clamp(1.45rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.sur-cta p {
    color: rgba(255,255,255,.55);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 560px;
    margin: 0 auto 28px;
}

@media (max-width: 768px) {
    .sur-cards {
        grid-template-columns: 1fr;
    }
}

/* ─── BACKGROUND FIXE ─── */
.page-sur::before {
    content: "";
    position: fixed;
    inset: 0;
    /* Même traitement que hm.php/offres-site.php : rideau dégradé en haut
       + bgsiteindex.png en fond de page entier. La planète-terre (ex
       .sur-hero-planet, retirée du hero) revient en ::after, cf. plus bas. */
    background:
        linear-gradient(to bottom, rgba(3,5,14,.96) 0, rgba(3,5,14,.96) 90px, transparent 260px),
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Planète-terre (offre Premium/sur-mesure) sur son propre calque ::after,
   masquée en fondu radial. */
.page-sur::after {
    content: "";
    position: fixed;
    inset: 0;
    /* vmin, même principe que .page-vitrine::after : planète ronde quel
       que soit le format d'écran. */
    background: url("../image/planet-terre.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    /* Rétrécit + s'efface au scroll, même mécanisme que .page-offers::after
       (cf. main.js, bloc "DÉCOR DE FOND"). */
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}

.page-sur.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-sur > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-sur .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 2.5s ease .5s, transform 2.5s ease .5s;
}

.page-sur .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── BTN PRIMARY OVERRIDE (tier Sur-mesure / "Démarrer mon projet") : seul
   bouton hero de tout le site à porter le double accent bleu (couleur de la
   page, cf. .sur-adv-module-callout) + liseré ambre (rappel du positionnement
   "Premium" de cette offre) — glow pulsé en continu + rockette (au lieu de la
   flèche générique "→" des autres pages) qui s'envole légèrement au survol. ─── */
.page-sur .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 17px 46px;
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    border-radius: 999px;
    color: #fff;
    text-decoration: none;
    /* demande explicite : "les boutons (couleur blanc) ne sont pas assez
       lisibles" — le dégradé qui montait jusqu'au blanc pur (mix ...#fff)
       rendait le texte blanc illisible avec l'accent "Blanc"/cyan ; on reste
       désormais toujours mélangé vers le noir (jamais plus clair que
       l'accent lui-même), comme la recette validée du hero accueil.php. */
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 30%, #000) 0%, color-mix(in srgb, rgb(var(--header-accent)) 48%, #000) 100%);
    /* demande explicite : "adapte les boutons [...] à la couleur
       sélectionnée" — bordure ambre figée alors que le fond suivait déjà
       --header-accent. */
    border: 1.5px solid rgba(var(--header-accent),.45);
    box-shadow:
        0 0 34px rgba(var(--header-accent),.35),
        0 10px 28px rgba(var(--header-accent),.28),
        inset 0 1px 0 rgba(255,255,255,.16);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition:
        background .3s ease,
        box-shadow .3s ease,
        transform .3s ease,
        border-color .3s ease;
    position: relative;
    overflow: hidden;
    animation: surCtaGlow 2.8s ease-in-out infinite;
}

.page-sur .btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%);
    border-radius: inherit;
    pointer-events: none;
}

.page-sur .btn-primary::after {
    content: none;
}

.page-sur .btn-primary .rocket-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    transition: transform .3s ease;
}

.page-sur .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 45%, #000) 0%, color-mix(in srgb, rgb(var(--header-accent)) 62%, #000) 100%);
    border-color: rgba(var(--header-accent),.75);
    box-shadow:
        0 0 56px rgba(var(--header-accent),.45),
        0 14px 36px rgba(var(--header-accent),.32),
        inset 0 1px 0 rgba(255,255,255,.20);
    transform: translateY(-3px);
}

.page-sur .btn-primary:hover .rocket-icon-wrap,
.page-sur .btn-primary:focus-visible .rocket-icon-wrap {
    transform: translate(3px, -3px) rotate(35deg) scale(1.1);
}

.page-sur .btn-primary:hover .rocket-icon-trail,
.page-sur .btn-primary:focus-visible .rocket-icon-trail {
    opacity: .85;
    height: 11px;
}

@keyframes surCtaGlow {
    0%, 100% {
        box-shadow:
            0 0 34px rgba(var(--header-accent),.35),
            0 10px 28px rgba(var(--header-accent),.28),
            inset 0 1px 0 rgba(255,255,255,.16);
    }
    50% {
        box-shadow:
            0 0 46px rgba(var(--accent-harmony-1),.22),
            0 10px 28px rgba(var(--header-accent),.28),
            inset 0 1px 0 rgba(255,255,255,.16);
    }
}

/* ─── CTA "Créer mon projet" (hero + CTA final), habillage "tech" ───
   Vient compléter .page-sur .btn-primary ci-dessus (glow, gradient), sans
   le remplacer : coins coupés façon panneau HUD, police monospace,
   balayage lumineux en boucle. Les 2 occurrences du bouton sur
   surmesure.php (hero + final) partagent cette classe. Spécificité
   (3 classes) > .page-sur .btn-primary (2 classes), donc ces règles
   gagnent sans !important.
   Demande explicite : l'effet "terminal de saisie" (prompt "> " + curseur
   clignotant "_" simulant une frappe) est retiré, mais la police monospace
   est conservée — cf. .sur-cta-tech-prompt/.sur-cta-tech-cursor plus bas,
   désormais orphelins (spans retirés du markup). Cette même formule
   (police + coins HUD + balayage, sans effet de frappe) est reprise sur
   sitevitrine.php et sitepro.php via les mêmes sélecteurs .sur-cta-tech
   étendus ci-dessous à .page-vitrine/.page-pro. */
.page-sur .btn-primary.sur-cta-tech,
.page-vitrine .btn-primary.sur-cta-tech,
.page-pro .btn-primary.sur-cta-tech {
    border-radius: 8px;
    clip-path: polygon(14px 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%, 0 14px);
    font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
    gap: 8px;
}

.sur-cta-tech-corner {
    position: absolute;
    width: 14px;
    height: 14px;
    pointer-events: none;
}
.sur-cta-tech-corner--tl {
    top: 4px;
    left: 4px;
    border-top: 2px solid rgba(255,255,255,.8);
    border-left: 2px solid rgba(255,255,255,.8);
}
.sur-cta-tech-corner--br {
    bottom: 4px;
    right: 4px;
    border-bottom: 2px solid rgba(255,255,255,.8);
    border-right: 2px solid rgba(255,255,255,.8);
}

.sur-cta-tech-prompt {
    color: rgba(56,189,248,.95);
    font-weight: 700;
}

.sur-cta-tech-cursor {
    display: inline-block;
    color: rgba(255,255,255,.85);
    animation: surCtaCursorBlink 1s steps(1) infinite;
}
@keyframes surCtaCursorBlink {
    0%, 49%  { opacity: 1; }
    50%, 100% { opacity: 0; }
}

/* Balayage lumineux en boucle — remplace le ::after neutralisé
   (content:none) sur .page-sur .btn-primary de base, uniquement pour cette
   variante "tech" (spécificité plus élevée, cf. note ci-dessus). */
.page-sur .btn-primary.sur-cta-tech::after,
.page-vitrine .btn-primary.sur-cta-tech::after,
.page-pro .btn-primary.sur-cta-tech::after {
    content: "";
    position: absolute;
    top: 0;
    left: -60%;
    width: 40%;
    height: 100%;
    background: linear-gradient(120deg, transparent, rgba(255,255,255,.4), transparent);
    transform: skewX(-20deg);
    animation: surCtaScan 3.2s ease-in-out infinite;
    pointer-events: none;
}
@keyframes surCtaScan {
    0%   { left: -60%; }
    55%  { left: 130%; }
    100% { left: 130%; }
}

/* ─── CTA FINAL ─── */
.vitrine-cta {
    text-align: center;
    padding: 60px 20px var(--footer-clearance);
    max-width: 760px;
    margin: 0 auto;
}

.vitrine-cta h2 {
    font-size: clamp(1.45rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.vitrine-cta p {
    color: rgba(255,255,255,.55);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 560px;
    margin: 0 auto 28px;
}

/* ─── BTN PRIMARY (tier Essentiel / "Créer mon projet") : même structure que
   .page-sur .btn-primary (référence), couleur cyan de la page à la place du
   bleu — glow pulsé en continu + rockette au lieu de la flèche "→". ─── */
.page-vitrine .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 17px 46px;
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    border-radius: 999px;
    color: #fff;
    text-decoration: none;
    /* demande explicite : "adapte les boutons [...] voir les choix faits
       [...] à accueil.php" — dégradé figé (bleu/cyan fixe) remplacé par la
       même recette accent-aware que .page-refonte/.page-programmation
       .btn-primary (rgb(var(--accent-harmony-1)) -> rgb(var(--header-accent))). */
    /* demande explicite : "les boutons (couleur blanc) ne sont pas assez
       lisibles" — dégradé toujours mélangé vers le noir (jamais la couleur
       d'accent pure), pour rester lisible avec le texte blanc même quand
       l'accent choisi est "Blanc"/cyan (quasi-blanc). */
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 40%, #000) 0%, color-mix(in srgb, rgb(var(--header-accent)) 48%, #000) 100%);
    border: 1.5px solid rgba(255,255,255,.40);
    box-shadow:
        0 0 34px rgba(var(--header-accent),.35),
        0 10px 28px rgba(var(--header-accent),.24),
        inset 0 1px 0 rgba(255,255,255,.16);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition:
        background .3s ease,
        box-shadow .3s ease,
        transform .3s ease,
        border-color .3s ease;
    position: relative;
    overflow: hidden;
    animation: vitCtaGlow 2.8s ease-in-out infinite;
}

.page-vitrine .btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%);
    border-radius: inherit;
    pointer-events: none;
}

.page-vitrine .btn-primary::after {
    content: none;
}

.page-vitrine .btn-primary .rocket-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    transition: transform .3s ease;
}

.page-vitrine .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 55%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-3)) 62%, #000) 100%);
    border-color: rgba(255,255,255,.70);
    box-shadow:
        0 0 56px rgba(var(--header-accent),.45),
        0 14px 36px rgba(var(--header-accent),.28),
        inset 0 1px 0 rgba(255,255,255,.20);
    transform: translateY(-3px);
}

.page-vitrine .btn-primary:hover .rocket-icon-wrap,
.page-vitrine .btn-primary:focus-visible .rocket-icon-wrap {
    transform: translate(3px, -3px) rotate(35deg) scale(1.1);
}

.page-vitrine .btn-primary:hover .rocket-icon-trail,
.page-vitrine .btn-primary:focus-visible .rocket-icon-trail {
    opacity: .85;
    height: 11px;
}

@keyframes vitCtaGlow {
    0%, 100% {
        box-shadow:
            0 0 34px rgba(var(--header-accent),.35),
            0 10px 28px rgba(var(--header-accent),.24),
            inset 0 1px 0 rgba(255,255,255,.16);
    }
    50% {
        box-shadow:
            0 0 46px rgba(var(--accent-harmony-1),.30),
            0 10px 28px rgba(var(--header-accent),.24),
            inset 0 1px 0 rgba(255,255,255,.16);
    }
}

.page-vitrine .section-block.is-visible .option-card {
    opacity: 1;
    transform: translateY(0);
}


/* ========================= sitepro.php ========================= */

/* ─── BACKGROUND FIXE ─── */
.page-pro::before {
    content: "";
    position: fixed;
    inset: 0;
    /* Même traitement que hm.php/offres-site.php : rideau dégradé en haut
       + bgsiteindex.png en fond de page entier. La planète-mars (ex
       .pro-hero-planet, retirée du hero) revient en ::after, cf. plus bas. */
    background:
        linear-gradient(to bottom, rgba(3,5,14,.96) 0, rgba(3,5,14,.96) 90px, transparent 260px),
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Planète-mars (offre Business) sur son propre calque ::after, masquée en
   fondu radial. */
.page-pro::after {
    content: "";
    position: fixed;
    inset: 0;
    /* vmin, même principe que .page-vitrine::after : planète ronde quel
       que soit le format d'écran. */
    background: url("../image/planet-orange.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    /* Rétrécit + s'efface au scroll, même mécanisme que .page-offers::after
       (cf. main.js, bloc "DÉCOR DE FOND"). */
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}

.page-pro.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-pro > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-pro .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 2.5s ease .5s, transform 2.5s ease .5s;
}

.page-pro .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── HERO ─── */
.pro-hero {
    min-height: 60dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 180px 20px 60px;
    text-align: center;
    position: relative;
}

/* ─── NAVIGATION INTER-OFFRES ─── */
.pro-offer-nav {
    position: absolute;
    top: clamp(90px, 12vh, 120px);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: min(860px, calc(100% - 40px));
}

.pro-nav-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: .95rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(255,255,255,.80);
    text-decoration: none;
    padding: 12px 28px;
    border-radius: 999px;
    background: rgba(var(--header-accent),.12);
    border: 1px solid rgba(var(--header-accent),.45);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow:
        0 0 18px rgba(var(--header-accent),.16),
        inset 0 1px 0 rgba(255,255,255,.08);
    transition:
        color .25s ease,
        background .25s ease,
        border-color .25s ease,
        box-shadow .25s ease,
        transform .25s ease;
}

.pro-nav-link:hover {
    color: #fff;
    background: rgba(var(--header-accent),.24);
    border-color: rgba(var(--header-accent),.75);
    box-shadow:
        0 0 36px rgba(var(--header-accent),.38),
        0 8px 20px rgba(var(--header-accent),.20),
        inset 0 1px 0 rgba(255,255,255,.12);
    transform: translateY(-2px);
}

.pro-nav-link--prev:hover { transform: translateY(-2px) translateX(-3px); }
.pro-nav-link--next:hover { transform: translateY(-2px) translateX(3px); }

.pro-nav-link svg {
    width: 18px;
    height: 18px;
    transition: transform .25s ease;
    flex-shrink: 0;
}

.pro-nav-link--prev:hover svg { transform: translateX(-3px); }
.pro-nav-link--next:hover svg { transform: translateX(3px); }

.pro-nav-link::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(-100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(10,14,30,.96);
    border: 1px solid rgba(255,255,255,.10);
    color: rgba(255,255,255,.85);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .04em;
    white-space: nowrap;
    padding: 5px 12px;
    border-radius: 6px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease, transform .2s ease;
    z-index: 10;
}

.pro-nav-link:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ─── HERO INNER ─── */
.pro-hero-inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    max-width: 700px;
}

.pro-tier-label {
    display: inline-flex;
    align-items: center;
    padding: 4px 16px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgb(var(--accent-harmony-1));
    background: rgba(var(--header-accent),.12);
    border: 1px solid rgba(var(--header-accent),.38);
    box-shadow:
        0 0 18px rgba(var(--header-accent),.20),
        inset 0 1px 0 rgba(255,255,255,.07);
}

/* ─── Ruban d'offre (même logique que les cartes offres-site.php) ─── */
.pro-tier-row {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 10px;
}

.pro-tier-ribbon {
    display: inline-flex;
    align-items: center;
    padding: 4px 14px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .04em;
    color: rgba(255,255,255,.75);
    background: rgba(255,255,255,.06);
    border: 1px dashed rgba(255,255,255,.22);
}

.pro-hero h1 {
    font-size: clamp(1.9rem, 4vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 35%, rgba(var(--header-accent),.95) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.pro-subtitle {
    color: rgba(255,255,255,.60);
    font-size: 1.05rem;
    line-height: 1.75;
    max-width: 560px;
    margin: 0;
}

.pro-price-block {
    margin: 4px 0;
}

.pro-price {
    /* Même style de pastille douce que .vitrine-price (sitevitrine.php),
       couleur ambre/or = accent de sitepro.php. */
    display: inline-flex;
    align-items: baseline;
    gap: 9px;
    padding: 12px 28px;
    border-radius: 14px;
    color: rgba(255,255,255,.92);
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.30);
    box-shadow: 0 0 14px rgba(var(--header-accent),.14), inset 0 1px 0 rgba(255,255,255,.06);
}
.pro-price .price-amount { font-size: 1.9rem; font-weight: 800; letter-spacing: -.01em; }
.pro-price .price-currency { font-size: .92rem; font-weight: 700; opacity: .82; text-transform: uppercase; letter-spacing: .05em; }

/* ─── INCLUS + MODALITÉS ─── */
.pro-details {
    max-width: 1100px;
    margin: 0 auto;
    padding: 60px 20px;
}

.pro-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 28px;
}

.pro-card {
    padding: 32px 28px;
    border-radius: 20px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    position: relative;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease;
}

.pro-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.pro-card--includes::before {
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.80), transparent);
}

.pro-card--terms::before {
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.20), transparent);
}

.pro-card--includes:hover {
    border-color: rgba(var(--header-accent),.25);
    box-shadow: 0 10px 32px rgba(var(--header-accent),.10);
}

.pro-card h2 {
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 18px;
    padding-bottom: 12px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}

.pro-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 9px;
}

.pro-list li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.05);
    color: rgba(255,255,255,.68);
    font-size: .88rem;
    line-height: 1.55;
    transition: background .2s ease, border-color .2s ease, color .2s ease;
}

.pro-list li::before {
    content: "✓";
    color: rgb(var(--header-accent));
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
    font-size: .85rem;
}

.pro-list--terms {
    counter-reset: modal-counter;
}

.pro-list--terms li {
    counter-increment: modal-counter;
}

.pro-list--terms li::before {
    content: counter(modal-counter, decimal-leading-zero) ".";
    color: rgba(var(--header-accent),.55);
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    min-width: 22px;
    flex-shrink: 0;
}

.pro-card--includes .pro-list li:hover {
    background: rgba(var(--header-accent),.07);
    border-color: rgba(var(--header-accent),.18);
    color: rgba(255,255,255,.88);
}

/* ─── OPTIONS ─── */
.pro-options {
    max-width: 1100px;
    margin: 0 auto;
    padding: 20px 20px 60px;
}

.pro-options-header {
    text-align: center;
    max-width: 680px;
    margin: 0 auto 36px;
}

.pro-options-header h2 {
    font-size: clamp(1.35rem, 2.5vw, 1.85rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #ffffff 35%, rgba(var(--header-accent),.95) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.pro-options-header p {
    color: rgba(255,255,255,.50);
    font-size: .92rem;
    line-height: 1.7;
}

.pro-options-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 18px;
}

.pro-options-grid .option-card            { grid-column: span 2; }
.pro-options-grid .option-card:nth-child(4) { grid-column: 2 / 4; }
.pro-options-grid .option-card:nth-child(5) { grid-column: 4 / 6; }

/* ─── CTA FINAL ─── */
.pro-cta {
    text-align: center;
    padding: 60px 20px var(--footer-clearance);
    max-width: 760px;
    margin: 0 auto;
}

.pro-cta h2 {
    font-size: clamp(1.45rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 35%, rgba(var(--header-accent),.95) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.pro-cta p {
    color: rgba(255,255,255,.55);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 560px;
    margin: 0 auto 28px;
}

/* ─── BTN PRIMARY (tier Business / "Créer mon projet") : même structure que
   .page-sur .btn-primary (référence), couleur ambre de la page à la place du
   bleu — glow pulsé en continu + rockette au lieu de la flèche "→". ─── */
.page-pro .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 17px 46px;
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: .05em;
    text-transform: uppercase;
    border-radius: 999px;
    color: #fff;
    text-decoration: none;
    /* demande explicite : "les boutons (couleur blanc) ne sont pas assez
       lisibles" — dégradé mélangé vers le noir plutôt que la couleur
       d'accent pure, pour rester lisible avec le texte blanc quel que soit
       l'accent (y compris "Blanc"/cyan, quasi-blanc). */
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-3)) 40%, #000) 0%, color-mix(in srgb, rgb(var(--header-accent)) 45%, #000) 50%, color-mix(in srgb, rgb(var(--accent-harmony-1)) 40%, #000) 100%);
    border: 1.5px solid rgba(255,255,255,.40);
    box-shadow:
        0 0 34px rgba(var(--header-accent),.35),
        0 10px 28px rgba(var(--header-accent),.24),
        inset 0 1px 0 rgba(255,255,255,.16);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: background .3s ease, box-shadow .3s ease, transform .3s ease, border-color .3s ease;
    position: relative;
    overflow: hidden;
    animation: proCtaGlow 2.8s ease-in-out infinite;
}

.page-pro .btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%);
    border-radius: inherit;
    pointer-events: none;
}

.page-pro .btn-primary::after {
    content: none;
}

.page-pro .btn-primary .rocket-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    transition: transform .3s ease;
}

.page-pro .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 55%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-1)) 60%, #000) 45%, color-mix(in srgb, rgb(var(--accent-harmony-1)) 45%, #000) 100%);
    border-color: rgba(255,255,255,.70);
    box-shadow:
        0 0 56px rgba(var(--header-accent),.45),
        0 14px 36px rgba(var(--header-accent),.28),
        inset 0 1px 0 rgba(255,255,255,.20);
    transform: translateY(-3px);
}

.page-pro .btn-primary:hover .rocket-icon-wrap,
.page-pro .btn-primary:focus-visible .rocket-icon-wrap {
    transform: translate(3px, -3px) rotate(35deg) scale(1.1);
}

.page-pro .btn-primary:hover .rocket-icon-trail,
.page-pro .btn-primary:focus-visible .rocket-icon-trail {
    opacity: .85;
    height: 11px;
}

@keyframes proCtaGlow {
    0%, 100% {
        box-shadow:
            0 0 34px rgba(var(--header-accent),.35),
            0 10px 28px rgba(var(--header-accent),.24),
            inset 0 1px 0 rgba(255,255,255,.16);
    }
    50% {
        box-shadow:
            0 0 46px rgba(var(--accent-harmony-1),.30),
            0 10px 28px rgba(var(--header-accent),.24),
            inset 0 1px 0 rgba(255,255,255,.16);
    }
}

.page-pro .section-block.is-visible .option-card {
    opacity: 1;
    transform: translateY(0);
}

/* ── Accents complémentaires sitepro.php : Exemples concrets et Commander
   utilisaient le bleu de marque générique (var(--brand-color)) au lieu de
   l'ambre/or propre à l'offre Business (cf. .pro-tier-label / .pro-price). ── */

/* Exemples concrets */
.page-pro .exemples-header .exemples-label {
    color: rgb(var(--header-accent));
    background: rgba(var(--header-accent),.10);
    border-color: rgba(var(--header-accent),.25);
}
.page-pro .exemple-card:hover {
    border-color: rgba(var(--header-accent),.4);
    box-shadow: 0 16px 40px rgba(var(--header-accent),.12);
}
.page-pro .exemple-card-price {
    color: rgb(var(--header-accent));
    background: rgba(var(--header-accent),.10);
    border-color: rgba(var(--header-accent),.25);
}
.page-pro .exemple-card-link { color: rgb(var(--header-accent)); }

/* Commander (le pill "Commander" partage déjà .exemples-label ci-dessus) :
   l'invitation à se connecter/créer un compte reste volontairement en bleu
   générique (pas la couleur de la page) ; seul le formulaire de commande une
   fois connecté (modules, cases à cocher) reprend l'accent or ci-dessous. */
.page-pro .account-checkbox-label input[type="checkbox"]:hover {
    border-color: rgba(var(--header-accent),.6);
}
.page-pro .account-checkbox-label input[type="checkbox"]:focus-visible {
    outline-color: rgb(var(--header-accent));
}
.page-pro .account-checkbox-label input[type="checkbox"]:checked {
    background: rgb(var(--header-accent));
    border-color: rgb(var(--header-accent));
}
.page-pro .account-module-card:has(input[type="checkbox"]:checked) {
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.08);
}
.page-pro .module-tier-badge--standard {
    color: rgb(var(--header-accent));
    background: rgba(var(--header-accent),.10);
    border-color: rgba(var(--header-accent),.3);
}



/* ========================= surmesure.php ========================= */
/* (bloc obsolète .page-custom / .custom-* supprimé — CSS orphelin datant
   d'avant le renommage de la page en "sur-*"/.page-sur, ne correspondait
   plus au markup actuel de surmesure.php ; cf. .page-sur/.sur-* plus haut,
   juste avant "sitevitrine.php", pour la version actuelle de cette page). */


/* ========================= refonte.php / audit-site.php ========================= */
/* Même traitement "galaxie plein fond" que sitevitrine.php/sitepro.php/
   surmesure.php ci-dessus (planète retirée du hero .cw-hero, cf. plus haut
   dans ce fichier, et redonnée en ::after plein écran, avec rétrécissement +
   fondu au scroll + grossissement à l'arrivée sur la page, cf. main.js bloc
   "DÉCOR DE FOND"). audit-site.php partage .page-refonte (posé sur <main>
   avec .page-audit-site en 2e classe, cf. plus haut) : la seule différence
   entre les 2 pages est la planète affichée (magma pour refonte.php,
   business pour audit-site.php — déjà la répartition utilisée par
   l'ancien .cw-hero::before ci-dessus). */

/* ─── BACKGROUND FIXE ─── */
.page-refonte::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(to bottom, rgba(3,5,14,.96) 0, rgba(3,5,14,.96) 90px, transparent 260px),
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Planète-magma (refonte.php) sur son propre calque ::after, masquée en
   fondu radial — même principe que .page-vitrine::after/.page-pro::after/
   .page-sur::after. audit-site.php reçoit sa propre planète (planet-business)
   via l'override juste en dessous. */
.page-refonte::after {
    content: "";
    position: fixed;
    inset: 0;
    /* vmin, même principe que .page-vitrine::after : planète ronde quel
       que soit le format d'écran. */
    background: url("../image/planet-rouge.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    /* Rétrécit + s'efface au scroll, même mécanisme que .page-offers::after
       (cf. main.js, bloc "DÉCOR DE FOND"). */
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}

/* Demande explicite : audit-site.php doit utiliser planet-orange, pas
   planet-jupiter. */
.page-audit-site::after {
    background-image: url("../image/planet-orange.webp");
}

.page-refonte.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-refonte > * {
    position: relative;
    z-index: 1;
}



/* ========================= hm.php ========================= */

/* ─── BACKGROUND FIXE ───
   TEST : galaxy-hm.png remplace bgsite.png comme fond de PAGE entier
   (fixed) au lieu d'être concentrée dans .hm-hero (cf. plus haut,
   background-image neutralisée). Même traitement (overlay noir .52) que
   bgsite.png ailleurs sur le site. À rebasculer sur bgsite.png si le
   rendu page entière ne convainc pas. */
.page-hm::before {
    content: "";
    position: fixed;
    inset: 0;
    /* Rideau dégradé en haut, même principe que .page-offers::before :
       masque le fond derrière le header flottant. */
    background:
        linear-gradient(to bottom, rgba(3,5,14,.96) 0, rgba(3,5,14,.96) 90px, transparent 260px),
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Galaxie sur son propre calque (::after), même principe que
   .page-offers::after : masque radial pour estomper le contour
   déchiqueté/tronqué en fondu, sans toucher au starfield en dessous. */
.page-hm::after {
    content: "";
    position: fixed;
    inset: 0;
    background: url("../image/galaxie-web.png") center / 75% 60% no-repeat;
    /* Même recalibrage que .page-offers::after (les % sont des rayons,
       pas des diamètres) pour que le fondu finisse avant le bord réel de
       l'image. */
    -webkit-mask-image: radial-gradient(ellipse 28% 22% at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(ellipse 28% 22% at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    /* Rétrécit + s'efface au scroll, même mécanisme que .page-offers::after
       (cf. main.js, bloc "DÉCOR DE FOND") — demande explicite : étendre
       l'effet déjà en place sur sitevitrine/sitepro/surmesure à hm.php. */
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}

/* Arrivée de page : demande explicite d'étendre l'animation d'entrée
   (planète centrée, contenu masqué, puis zoom) à hm.php, qui en était
   exclue jusqu'ici. Cf. .planet-entrance-page plus haut + main.js. */
.page-hm.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-hm > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-hm .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}

.page-hm .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── HERO ─── */
.hm-hero {
    min-height: 55dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 140px 20px 80px;
    text-align: center;
}

.hm-hero-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 22px;
    max-width: 760px;
}

.hm-page-label {
    display: inline-flex;
    align-items: center;
    padding: 4px 16px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    /* Demande explicite : "renforcer la lisibilité des badges section 1" —
       couleur bleue figée (ignorait l'accent) remplacée par la couleur
       sélectionnée, et fond translucide (.10) remplacé par un fond sombre
       bien plus opaque pour rester lisible sur un fond de planète clair. */
    color: rgba(var(--header-accent),.95);
    background: rgba(10,14,24,.65);
    border: 1px solid rgba(var(--header-accent),.55);
    box-shadow: 0 0 16px rgba(var(--header-accent),.25);
    text-shadow: 0 1px 3px rgba(0,0,0,.5);
}

.hm-hero h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* ─── PILLS FEATURES ─── */
.hm-features-pills {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 0;
}

/* Demande explicite (suite) : ces badges restaient "trop clairs/pas assez
   visibles" malgré le renfort déjà posé sur .hm-subtitle juste en dessous
   (même souci de fond de planète clair derrière) — le fond quasi
   transparent (.07) et le texte à 70% ne protégeaient pas assez. Fond bien
   plus opaque (même recette que .heberg-hero-cta-line) + texte quasi blanc +
   ombre portée, pour rester lisible quel que soit le fond. */
.hm-features-pills li {
    padding: 5px 14px;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 600;
    color: rgba(255,255,255,.92);
    background: rgba(10,14,24,.55);
    border: 1px solid rgba(59,130,246,.35);
    letter-spacing: .03em;
    text-shadow: 0 1px 3px rgba(0,0,0,.6);
}

/* Demande explicite : "le texte ... est très peu lisible" — opacité relevée
   + légère ombre portée pour rester lisible sur un fond de planète clair. */
.hm-subtitle {
    color: rgba(255,255,255,.85);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 580px;
    margin: 0;
    text-shadow: 0 1px 3px rgba(0,0,0,.75), 0 1px 10px rgba(0,0,0,.55);
}

/* ─── HERO CTA ─── */
.hm-hero-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    justify-content: center;
    margin-top: 4px;
}

.hm-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 14px 32px;
    font-size: 1rem;
    font-weight: 600;
    border-radius: 999px;
    color: rgba(255,255,255,.78);
    text-decoration: none;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.14);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: color .25s ease, background .25s ease, border-color .25s ease, transform .25s ease;
}

.hm-btn-secondary:hover {
    color: #fff;
    background: rgba(59,130,246,.10);
    border-color: rgba(59,130,246,.40);
    transform: translateY(-2px);
}

/* ─── BTN PRIMARY OVERRIDE (cyan) ─── */
.page-hm .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 14px 36px;
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .04em;
    border-radius: 999px;
    color: #fff;
    text-decoration: none;
    /* demande explicite : "adapte les boutons [...] voir les choix faits
       [...] à accueil.php" — dégradé bleu figé remplacé par la couleur
       d'accent sélectionnée. */
    /* demande explicite : "les boutons (couleur blanc) ne sont pas assez
       lisibles" — dégradé toujours mélangé vers le noir plutôt qu'une
       simple opacité de la couleur d'accent (qui laissait passer le fond
       clair et rendait le texte blanc illisible avec l'accent "Blanc"). */
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 42%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-3)) 38%, #000) 100%);
    border: 1px solid rgba(var(--header-accent),.45);
    box-shadow:
        0 0 28px rgba(var(--header-accent),.22),
        0 8px 20px rgba(var(--header-accent),.14),
        inset 0 1px 0 rgba(255,255,255,.10);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
    transition: background .3s ease, box-shadow .3s ease, transform .3s ease;
}

.page-hm .btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%);
    border-radius: inherit;
    pointer-events: none;
}

.page-hm .btn-primary::after {
    content: "→";
    font-size: .95rem;
    opacity: .7;
    transition: transform .3s ease, opacity .3s ease;
}

.page-hm .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 58%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-3)) 52%, #000) 100%);
    box-shadow:
        0 0 44px rgba(var(--header-accent),.40),
        0 12px 28px rgba(var(--header-accent),.22),
        inset 0 1px 0 rgba(255,255,255,.16);
    transform: translateY(-3px);
}

.page-hm .btn-primary:hover::after {
    transform: translateX(4px);
    opacity: 1;
}

/* ─── PLANS SECTION ─── */
.hm-plans {
    max-width: 1200px;
    margin: 0 auto;
    padding: 60px 20px 80px;
}

.hm-plans-header {
    text-align: center;
    max-width: 680px;
    margin: 0 auto 48px;
}

.hm-plans-header h2 {
    font-size: clamp(1.5rem, 3vw, 2.1rem);
    font-weight: 800;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.hm-plans-header p {
    color: rgba(255,255,255,.50);
    font-size: .95rem;
    line-height: 1.7;
}

/* ─── PLANS GRID ─── */
.hm-plans-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
    align-items: stretch;
}

/* ─── BANNIÈRE RABAIS FIDÉLITÉ ─── */
.hm-loyalty {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 24px;
    margin-top: 32px;
    padding: 28px 32px;
    border-radius: 18px;
    background: linear-gradient(135deg, rgba(59,130,246,.10), rgba(99,102,241,.06));
    border: 1px solid rgba(59,130,246,.22);
}

.hm-loyalty-text { max-width: 480px; }

.hm-loyalty-label {
    display: inline-block;
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(59,130,246,.90);
    background: rgba(59,130,246,.12);
    border: 1px solid rgba(59,130,246,.32);
    padding: 4px 12px;
    border-radius: 999px;
    margin-bottom: 10px;
}

.hm-loyalty-text h3 {
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 8px;
}

.hm-loyalty-text p {
    font-size: .86rem;
    color: rgba(255,255,255,.55);
    line-height: 1.6;
    margin: 0;
}

.hm-loyalty-stats {
    display: flex;
    gap: 16px;
    flex-shrink: 0;
}

.hm-loyalty-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-width: 92px;
    padding: 14px 18px;
    border-radius: 14px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(59,130,246,.24);
}

.hm-loyalty-discount {
    font-size: 1.5rem;
    font-weight: 800;
    color: #22d3ee;
    line-height: 1.1;
}

.hm-loyalty-period {
    font-size: .74rem;
    color: rgba(255,255,255,.50);
    text-transform: uppercase;
    letter-spacing: .04em;
}

@media (max-width: 640px) {
    .hm-loyalty { flex-direction: column; align-items: flex-start; padding: 24px; }
    .hm-loyalty-stats { width: 100%; justify-content: space-between; }
    .hm-loyalty-stat { flex: 1; min-width: 0; }
}

/* ─── PLAN CARD BASE ─── */
.hm-plan {
    display: flex;
    flex-direction: column;
    padding: 28px 24px 24px;
    border-radius: 20px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    position: relative;
    overflow: hidden;
    transition: transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}

.hm-plan::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.hm-plan:hover {
    transform: translateY(-6px);
}

/* ─── TIER COLORS ─── */
.hm-plan--basic::before {
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.25), transparent);
}
.hm-plan--basic:hover {
    border-color: rgba(255,255,255,.16);
    box-shadow: 0 16px 40px rgba(0,0,0,.30);
}

/* Demande explicite : l'offre Essentiel ne doit pas hériter de la couleur
   active, elle reste bleue fixe (comme Premium). */
.hm-plan--essentiel::before {
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.65), transparent);
}
.hm-plan--essentiel:hover {
    border-color: rgba(59,130,246,.28);
    box-shadow: 0 16px 40px rgba(59,130,246,.12);
}

.hm-plan--pro::before {
    background: linear-gradient(90deg, transparent, rgba(251,191,36,.85), transparent);
}
.hm-plan--pro {
    border-color: rgba(251,191,36,.20);
    box-shadow: 0 0 40px rgba(251,191,36,.08);
}
.hm-plan--pro:hover {
    border-color: rgba(251,191,36,.40);
    box-shadow: 0 16px 50px rgba(251,191,36,.18);
}

.hm-plan--premium::before {
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.70), transparent);
}
.hm-plan--premium:hover {
    border-color: rgba(59,130,246,.25);
    box-shadow: 0 16px 40px rgba(59,130,246,.10);
}

/* ─── RIBBON ─── */
.hm-plan-ribbon {
    position: absolute;
    top: 12px;
    right: 12px;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #fff;
    background: rgba(251,191,36,.75);
    border: 1px solid rgba(251,191,36,.48);
    box-shadow: 0 4px 14px rgba(251,191,36,.28);
}

/* ─── PLAN TOP ─── */
.hm-plan-top {
    margin-bottom: 20px;
}

/* Ligne Tier + Badge : largeur fixe pour le tier + hauteur FIXE (non min-height)
   pour la ligne entière, afin que le badge démarre toujours à la même
   position horizontale ET verticale, quelle que soit la longueur du mot
   (Basic / Essentiel / Business / Premium) ou du badge. Le texte du badge
   est contraint à une seule ligne (nowrap + ellipsis) : sans ça, un badge
   plus long passerait sur 2 lignes et ferait grandir la carte concernée
   uniquement, cassant l'alignement avec les 3 autres. */
.hm-plan-tier-row {
    display: flex;
    align-items: center;
    height: 24px;
    gap: 8px;
    margin-bottom: 8px;
}

.hm-plan-tier {
    display: inline-block;
    flex: 0 0 auto;
    min-width: 6.5em;
    font-size: .70rem;
    font-weight: 700;
    letter-spacing: .10em;
    text-transform: uppercase;
    margin-bottom: 0;
    white-space: nowrap;
}

.hm-plan--basic    .hm-plan-tier { color: rgba(255,255,255,.45); }
.hm-plan--essentiel .hm-plan-tier { color: #7aa2ff; }
.hm-plan--pro      .hm-plan-tier { color: #fde68a; }
.hm-plan--premium  .hm-plan-tier { color: #93c5fd; }

/* ─── BADGE DE POSITIONNEMENT (ex: "Sans maintenance", "Pour démarrer") ─── */
.hm-plan-badge {
    display: inline-block;
    flex: 1 1 auto;
    min-width: 0;
    font-size: .68rem;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 999px;
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.hm-plan--basic     .hm-plan-badge { color: rgba(255,255,255,.55); background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.14); }
.hm-plan--essentiel .hm-plan-badge { color: #7aa2ff; background: rgba(59,130,246,.12); border: 1px solid rgba(59,130,246,.28); }
.hm-plan--pro       .hm-plan-badge { color: #fde68a; background: rgba(251,191,36,.14); border: 1px solid rgba(251,191,36,.30); }
.hm-plan--premium   .hm-plan-badge { color: #93c5fd; background: rgba(59,130,246,.14); border: 1px solid rgba(59,130,246,.30); }

/* Nom du forfait : hauteur FIXE de 2 lignes (pas min-height) + troncature
   propre si un nom dépasse 2 lignes dans une langue donnée, pour garantir
   que le prix (et tout ce qui suit) démarre exactement à la même hauteur
   sur les 4 cartes. */
.hm-plan-top h3 {
    font-size: 1rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 14px;
    line-height: 1.3;
    height: 2.6em;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Mini-descriptif sous le prix (ex: "Idéal pour site vitrine") : hauteur
   fixe identique sur les 4 cartes, quel que soit le nombre de mots. */
.hm-plan-tagline {
    font-size: .80rem;
    /* Contraste relevé (.40 -> .65) : demande explicite "améliore ce qui est
       visuellement fade". */
    color: rgba(255,255,255,.65);
    margin: 6px 0 0;
    font-style: italic;
    height: 2.2em;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ─── PRIX ─── */
.hm-plan-price {
    display: flex;
    align-items: baseline;
    gap: 4px;
    padding: 10px 14px;
    border-radius: 10px;
    width: fit-content;
}

.hm-plan--basic    .hm-plan-price { background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08); }
.hm-plan--essentiel .hm-plan-price { background: rgba(59,130,246,.10);  border: 1px solid rgba(59,130,246,.20); }
.hm-plan--pro      .hm-plan-price { background: rgba(251,191,36,.12);  border: 1px solid rgba(251,191,36,.22); }
.hm-plan--premium  .hm-plan-price { background: rgba(59,130,246,.12);   border: 1px solid rgba(59,130,246,.22); }

/* Prix "Sur devis" (Premium) : texte plus long qu'un montant chiffré, taille réduite pour rester lisible dans la pastille. */
.hm-plan-price--quote .hm-price-amount { font-size: 1.05rem; }

.hm-price-prefix {
    font-size: .85rem;
    font-weight: 700;
    color: rgba(255,255,255,.50);
    align-self: baseline;
}

.hm-price-amount {
    font-size: 1.4rem;
    font-weight: 800;
    color: #fff;
    line-height: 1;
}

.hm-price-currency {
    font-size: .75rem;
    font-weight: 700;
    color: rgba(255,255,255,.55);
    margin-bottom: 2px;
}

.hm-price-period {
    font-size: .75rem;
    color: rgba(255,255,255,.40);
}

/* ─── PLAN LIST ─── */
.hm-plan-list {
    list-style: none;
    padding: 0;
    margin: 0 0 24px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
}

/* Hauteur FIXE + troncature propre (line-clamp) : chaque ligne d'item occupe
   exactement la même hauteur sur les 4 cartes, quelle que soit la longueur
   du texte (les descriptions détaillées type "Corrections de bugs simples
   (affichage, liens cassés...)" sont plus longues que "Support prioritaire
   (48h)"). Sans cette contrainte, un item plus long agrandit sa carte et
   décale tous les items suivants par rapport aux autres colonnes. La coche
   passe en position absolue (au lieu d'être un enfant flex) pour libérer le
   <li> et lui appliquer le modèle -webkit-box nécessaire au line-clamp. */
.hm-plan-list li {
    position: relative;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
    height: 90px;
    font-size: .78rem;
    color: rgba(255,255,255,.65);
    line-height: 1.45;
    padding: 8px 10px 8px 24px;
    border-radius: 8px;
    background: rgba(255,255,255,.02);
    border: 1px solid rgba(255,255,255,.04);
    transition: color .2s ease, background .2s ease;
}

.hm-plan-list li::before {
    content: "✓";
    position: absolute;
    left: 9px;
    top: 9px;
    font-size: .74rem;
    font-weight: 700;
}

.hm-plan--basic    .hm-plan-list li::before { color: rgba(255,255,255,.30); }
.hm-plan--essentiel .hm-plan-list li::before { color: #3b82f6; }
.hm-plan--pro      .hm-plan-list li::before { color: #fbbf24; }
.hm-plan--premium  .hm-plan-list li::before { color: #3b82f6; }

.hm-plan:hover .hm-plan-list li {
    color: rgba(255,255,255,.80);
}

/* ─── PLAN CTA ─── */
.hm-plan-cta {
    display: block;
    text-align: center;
    padding: 10px 20px;
    border-radius: 999px;
    font-size: .85rem;
    font-weight: 700;
    text-decoration: none;
    color: rgba(255,255,255,.75);
    border: 1px solid rgba(255,255,255,.12);
    background: rgba(255,255,255,.04);
    transition: color .25s ease, background .25s ease, border-color .25s ease, box-shadow .25s ease;
}

.hm-plan--pro .hm-plan-cta {
    color: #fff;
    background: rgba(251,191,36,.16);
    border-color: rgba(251,191,36,.40);
    box-shadow: 0 4px 16px rgba(251,191,36,.12);
}

.hm-plan-cta:hover {
    color: #fff;
    background: rgba(251,191,36,.20);
    border-color: rgba(251,191,36,.55);
    box-shadow: 0 6px 20px rgba(251,191,36,.20);
}

.hm-plan--basic    .hm-plan-cta:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.22); box-shadow: none; }
.hm-plan--essentiel .hm-plan-cta:hover { background: rgba(59,130,246,.14); border-color: rgba(59,130,246,.40); box-shadow: 0 6px 20px rgba(59,130,246,.12); }
.hm-plan--premium  .hm-plan-cta:hover { background: rgba(59,130,246,.14); border-color: rgba(59,130,246,.40); box-shadow: 0 6px 20px rgba(59,130,246,.12); }

/* Demande explicite : le badge lié au titre section 2 "Hébergement et
   Maintenance" doit hériter de la couleur active. */
.page-hm .hm-plans-header .cw-page-label {
    color: rgba(var(--header-accent),.9);
    border-color: rgba(var(--header-accent),.35);
    background: rgba(var(--header-accent),.10);
}

/* ─── LOGICIELS SUR-MESURE & BOTS DISCORD (offre "sur devis") ─── */
.hm-custom {
    padding-top: 20px;
}
.hm-custom-card {
    max-width: 880px;
    margin: 0 auto;
}
.hm-custom-price {
    font-size: 1.5rem;
}
.hm-custom-note {
    font-size: .8rem;
    color: rgba(255,255,255,.42);
    line-height: 1.6;
    margin: 0;
}

/* Demande explicite : "la vignette de prix pour sur-mesure ne doit pas être
   verte mais dépendre de la couleur sélectionnée" — l'émeraude fixe (calquée
   sur programmation.php/bot-discord.php) est remplacée par la couleur
   d'accent active de hm.php (rgba(var(--header-accent))). */
.page-hm .hm-custom .cw-page-label {
    color: rgba(var(--header-accent),.95);
    border-color: rgba(var(--header-accent),.38);
    background: rgba(var(--header-accent),.10);
}
.page-hm .hm-custom .cw-section-header h2 {
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.page-hm .hm-custom .cw-offer-card { border-color: rgba(var(--header-accent),.32); box-shadow: 0 0 40px rgba(var(--header-accent),.10); }
.page-hm .hm-custom .cw-offer-left { background: rgba(var(--header-accent),.10); border-right-color: rgba(var(--header-accent),.22); }
.page-hm .hm-custom .cw-offer-tier { color: rgba(var(--header-accent),.95); background: rgba(var(--header-accent),.16); border-color: rgba(var(--header-accent),.34); }
.page-hm .hm-custom .cw-offer-section-label { color: rgba(var(--header-accent),.78); }
.page-hm .hm-custom .btn-primary {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 42%, #000), color-mix(in srgb, rgb(var(--header-accent)) 38%, #000));
    box-shadow: 0 4px 20px rgba(var(--header-accent),.35);
}
.page-hm .hm-custom .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 58%, #000), color-mix(in srgb, rgb(var(--accent-harmony-3)) 52%, #000));
    box-shadow: 0 6px 28px rgba(var(--header-accent),.50);
}

/* ─── CTA FINAL ─── */
.hm-cta {
    text-align: center;
    padding: 60px 20px var(--footer-clearance);
    max-width: 720px;
    margin: 0 auto;
}

.hm-cta h2 {
    font-size: clamp(1.5rem, 2.8vw, 2.1rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.hm-cta p {
    color: rgba(255,255,255,.55);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 520px;
    margin: 0 auto 28px;
}

.hm-cta-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    justify-content: center;
}




/* ========================= hebergement.php ========================= */

/* ─── BACKGROUND FIXE ─── */
.page-heberg::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Planète-glace (hebergement.php) sur son propre calque ::after, masquée en
   fondu radial + rétrécie/effacée au scroll — même mécanisme que
   .page-vitrine::after/.page-refonte::after (cf. main.js, bloc "DÉCOR DE
   FOND") — demande explicite : étendre l'effet à toutes les pages offres. */
.page-heberg::after {
    content: "";
    position: fixed;
    inset: 0;
    background: url("../image/planet-blanc.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}
.page-heberg.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-heberg > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-heberg .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}

.page-heberg .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── LAYOUT INNER COMMUN ─── */
.heberg-section-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
}

/* ─── HERO ─── */
.heberg-hero {
    min-height: 55dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 140px 20px 80px;
    text-align: center;
}

.heberg-hero-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    max-width: 760px;
}

.heberg-page-label {
    display: inline-flex;
    align-items: center;
    padding: 4px 16px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    /* Demande explicite : "renforcer la lisibilité des badges section 1" —
       couleur bleue figée (ignorait l'accent) remplacée par la couleur
       sélectionnée, et fond translucide (.10) remplacé par un fond sombre
       bien plus opaque pour rester lisible sur un fond de planète clair. */
    color: rgba(var(--header-accent),.95);
    background: rgba(10,14,24,.65);
    border: 1px solid rgba(var(--header-accent),.55);
    box-shadow: 0 0 16px rgba(var(--header-accent),.25);
    text-shadow: 0 1px 3px rgba(0,0,0,.5);
}

.heberg-hero h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* Demande explicite : "le texte ... est très peu lisible" — opacité relevée
   + légère ombre portée pour rester lisible sur un fond de planète clair. */
.heberg-hero-sub {
    color: rgba(255,255,255,.85);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 620px;
    margin: 0;
    text-shadow: 0 1px 3px rgba(0,0,0,.75), 0 1px 10px rgba(0,0,0,.55);
}

.heberg-impact-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 0;
}

/* Demande explicite (suite) : ces badges restaient "trop clairs/pas assez
   visibles" malgré le renfort déjà posé sur .heberg-hero-cta-line juste en
   dessous (même souci de fond de planète clair derrière, cf. commentaire
   plus bas) — le fond quasi transparent (.04) et le texte à 68% ne
   protégeaient pas assez. Même recette que .heberg-hero-cta-line : fond bien
   plus opaque + texte quasi blanc + ombre portée. */
.heberg-impact-list li {
    padding: 6px 16px;
    border-radius: 999px;
    font-size: .82rem;
    font-weight: 600;
    color: rgba(255,255,255,.92);
    background: rgba(10,14,24,.55);
    border: 1px solid rgba(255,255,255,.18);
    text-shadow: 0 1px 3px rgba(0,0,0,.6);
}

/* Demande explicite : "le texte n'est pas assez lisible... ça se répète sur
   plusieurs pages (1ère section) qui ont pour bg une des planètes" — couleur
   bleue figée (ignorait l'accent) + fond quasi transparent (.06) qui ne
   protégeait pas assez du fond de planète derrière. Couleur accent-aware +
   fond sombre bien plus opaque pour rester lisible sur n'importe quel fond. */
.heberg-hero-cta-line {
    font-size: .92rem;
    font-weight: 600;
    color: rgba(var(--header-accent),.95);
    margin: 0;
    padding: 10px 20px;
    border-left: 2px solid rgba(var(--header-accent),.60);
    background: rgba(10,14,24,.55);
    border-radius: 0 8px 8px 0;
    text-align: left;
    text-shadow: 0 1px 4px rgba(0,0,0,.5);
}

/* ─── INFOMANIAK ─── */
.heberg-infomaniak {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.heberg-infomaniak .heberg-section-inner {
    display: flex;
    align-items: center;
    gap: 60px;
}

.heberg-section-text {
    flex: 1;
    min-width: 0;
}

.heberg-section-text h2 {
    font-size: clamp(1.3rem, 2.5vw, 1.85rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.heberg-section-text p {
    color: rgba(255,255,255,.55);
    font-size: .95rem;
    line-height: 1.75;
    margin: 0;
}

.heberg-infomaniak-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 18px;
    margin-top: 28px;
}

/* Boutons plus grands et plus affirmés que les CTA génériques de fin de page :
   c'est la première section de la page, elle mérite un appel à l'action
   plus visible. Spécificité (.page-heberg + 2 classes) volontairement plus
   forte que les règles génériques ".page-heberg .btn-primary" plus bas dans
   la feuille, pour ne pas se faire écraser malgré l'ordre des règles. */
.page-heberg .heberg-infomaniak-cta .btn-primary {
    padding: 17px 42px;
    font-size: 1.08rem;
    box-shadow:
        0 0 34px rgba(var(--header-accent),.28),
        0 10px 26px rgba(var(--header-accent),.18),
        inset 0 1px 0 rgba(255,255,255,.10);
}

.page-heberg .heberg-infomaniak-cta .btn-primary:hover {
    transform: translateY(-3px);
    box-shadow:
        0 0 42px rgba(var(--header-accent),.36),
        0 14px 32px rgba(var(--header-accent),.22),
        inset 0 1px 0 rgba(255,255,255,.12);
}

.page-heberg .heberg-infomaniak-cta .heberg-btn-secondary {
    padding: 17px 38px;
    font-size: 1.08rem;
    border-width: 1.5px;
}

@media (max-width: 640px) {
    .heberg-infomaniak-cta { flex-direction: column; }
    .heberg-infomaniak-cta .btn-primary,
    .heberg-infomaniak-cta .heberg-btn-secondary {
        width: 100%;
        justify-content: center;
    }
}

.heberg-badges {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    list-style: none;
    padding: 0;
    margin: 0;
    flex-shrink: 0;
    width: 340px;
}

.heberg-badge {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    border-radius: 12px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    font-size: .84rem;
    font-weight: 600;
    color: rgba(255,255,255,.72);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: border-color .25s ease, background .25s ease;
}

.heberg-badge:hover {
    background: rgba(59,130,246,.07);
    border-color: rgba(59,130,246,.22);
}

.heberg-badge-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 8px;
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .04em;
    flex-shrink: 0;
    background: rgba(var(--header-accent),.12);
    color: var(--brand-color);
    border: 1px solid rgba(var(--header-accent),.2);
}

.heberg-badge--swiss   .heberg-badge-icon { background: rgba(220,38,38,.10);  color: #f87171; border-color: rgba(220,38,38,.22); }
.heberg-badge--privacy .heberg-badge-icon { background: rgba(var(--header-accent),.12); color: #7aa2ff; border-color: rgba(var(--header-accent),.22); }
.heberg-badge--speed   .heberg-badge-icon { background: rgba(251,191,36,.10); color: #fbbf24; border-color: rgba(251,191,36,.22); }
.heberg-badge--eco     .heberg-badge-icon { background: rgba(34,197,94,.10);  color: #4ade80; border-color: rgba(34,197,94,.22); }

/* ─── SECTION HEADER COMMUN ─── */
.heberg-section-header {
    text-align: center;
    max-width: 680px;
    margin: 0 auto 40px;
}

.heberg-section-header h2 {
    font-size: clamp(1.4rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.heberg-section-header p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    line-height: 1.7;
}

/* ─── PILIERS ─── */
.heberg-pillars {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.heberg-pillars-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
}

.heberg-pillar {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    padding: 24px 22px;
    border-radius: 16px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    position: relative;
    overflow: hidden;
    transition: background .25s ease, border-color .25s ease, transform .25s ease;
}

.heberg-pillar::before {
    content: "";
    position: absolute;
    left: 0; top: 15%; bottom: 15%;
    width: 3px;
    border-radius: 0 2px 2px 0;
    opacity: .55;
    transition: opacity .25s ease, top .25s ease, bottom .25s ease;
}

/* Demande explicite : pilier 2 ne doit pas hériter de la couleur active
   (reste bleu fixe) ; pilier 3 ne doit pas être violet mais bleu fixe. */
.heberg-pillar--perf::before  { background: #3b82f6; }
.heberg-pillar--sec::before   { background: #3b82f6; }
.heberg-pillar--seo::before   { background: #3b82f6; }
.heberg-pillar--scale::before { background: #3b82f6; }

.heberg-pillar:hover {
    background: rgba(255,255,255,.048);
    border-color: rgba(255,255,255,.10);
    transform: translateX(5px);
}

.heberg-pillar:hover::before {
    opacity: 1;
    top: 6%;
    bottom: 6%;
}

.heberg-pillar-icon {
    font-size: 1.6rem;
    font-weight: 800;
    flex-shrink: 0;
    margin-top: 2px;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: rgba(59,130,246,.55);
}

.heberg-pillar--sec   .heberg-pillar-icon { color: rgba(59,130,246,.55); }
.heberg-pillar--seo   .heberg-pillar-icon { color: rgba(59,130,246,.55); }
.heberg-pillar--scale .heberg-pillar-icon { color: rgba(59,130,246,.55); }

.heberg-pillar-body h3 {
    font-size: .96rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 6px;
}

.heberg-pillar-body p {
    font-size: .86rem;
    color: rgba(255,255,255,.52);
    line-height: 1.65;
    margin: 0;
}

/* ─── INCLUS ─── */
.heberg-includes {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.heberg-includes-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
}

.heberg-inc-card {
    padding: 26px 22px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease, transform .3s ease;
}

.heberg-inc-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.55), transparent);
}

.heberg-inc-card:hover {
    border-color: rgba(59,130,246,.20);
    box-shadow: 0 10px 28px rgba(59,130,246,.08);
    transform: translateY(-4px);
}

.heberg-inc-icon {
    font-size: 2rem;
    font-weight: 800;
    margin-bottom: 12px;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: rgba(59,130,246,.45);
    display: block;
}

.heberg-inc-card h3 {
    font-size: .95rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}

.heberg-inc-card ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.heberg-inc-card li {
    font-size: .92rem;
    color: rgba(255,255,255,.78);
    padding: 6px 8px 6px 0;
    display: flex;
    align-items: flex-start;
    gap: 9px;
    line-height: 1.6;
}

.heberg-inc-card li::before {
    content: "✓";
    color: #22d3ee;
    font-size: .84rem;
    font-weight: 800;
    flex-shrink: 0;
    margin-top: 2px;
}

/* Distinction "garanti par Infomaniak" (infrastructure) vs "ma responsabilité"
   (ce que je configure/gère moi-même) : badge au-dessus de la liste, ou
   liste scindée en deux groupes pour les cartes mixtes (Performance, Sécurité). */
.heberg-owner-badge {
    display: inline-block;
    font-size: .64rem;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
    padding: 3px 10px;
    border-radius: 999px;
    margin: 0 0 10px;
}

.heberg-owner-badge--infomaniak {
    color: #4db8ff;
    background: rgba(0,152,255,.12);
    border: 1px solid rgba(0,152,255,.28);
}

.heberg-owner-badge--me {
    color: #34d399;
    background: rgba(16,185,129,.12);
    border: 1px solid rgba(16,185,129,.28);
}

.heberg-owner-group + .heberg-owner-group {
    margin-top: 14px;
}

.heberg-owner-group ul {
    margin: 0;
}

.heberg-inc-card-note {
    font-size: .78rem;
    color: rgba(255,255,255,.5);
    font-style: italic;
    line-height: 1.55;
    margin: 12px 0 0;
}

.heberg-inc-card-link {
    display: inline-block;
    font-size: .78rem;
    font-weight: 700;
    color: #34d399;
    margin: 6px 0 0;
    text-decoration: none;
}

.heberg-inc-card-link:hover {
    text-decoration: underline;
}

/* ─── PHILOSOPHIE ─── */
.heberg-philosophy {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.heberg-philosophy-card {
    max-width: 780px;
    margin: 0 auto;
    padding: 40px 36px;
    border-radius: 20px;
    background: rgba(255,255,255,.032);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    position: relative;
    overflow: hidden;
}

.heberg-philosophy-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(59,130,246,.55), rgba(var(--header-accent),.40), transparent);
}

.heberg-philosophy-card h2 {
    font-size: clamp(1.3rem, 2.2vw, 1.75rem);
    font-weight: 700;
    margin: 0 0 24px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.heberg-philo-points {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 24px;
}

.heberg-philo-point {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: .95rem;
    font-weight: 600;
    color: rgba(255,255,255,.85);
}

.heberg-philo-arrow {
    color: #3b82f6;
    font-weight: 700;
    flex-shrink: 0;
}

.heberg-philo-sub {
    font-size: .88rem;
    color: rgba(255,255,255,.40);
    margin: 0 0 12px;
    font-style: italic;
}

.heberg-philo-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.heberg-philo-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.55);
    padding: 8px 14px;
    border-radius: 8px;
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.05);
}

.heberg-philo-list li::before {
    content: "✕";
    color: rgba(239,68,68,.65);
    font-size: .75rem;
    font-weight: 700;
    flex-shrink: 0;
}

/* ─── MONITORING BONUS ─── */
.heberg-monitoring {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.heberg-monitoring-inner {
    display: flex;
    align-items: center;
    gap: 60px;
    padding: 36px 36px;
    border-radius: 20px;
    background: rgba(var(--header-accent),.05);
    border: 1px solid rgba(var(--header-accent),.16);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.heberg-monitoring-text {
    flex: 1;
    min-width: 0;
}

.heberg-monitoring-text h2 {
    font-size: clamp(1.2rem, 2vw, 1.6rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.heberg-monitoring-text p {
    color: rgba(255,255,255,.52);
    font-size: .92rem;
    line-height: 1.7;
    margin: 0;
}

/* Demande explicite : le texte et les badges restant bleus dans la section
   "Monitoring et amélioration continue" doivent hériter de la couleur
   active. */
.heberg-monitoring-premium-note {
    font-size: .82rem !important;
    color: rgba(var(--header-accent),.80) !important;
    font-style: italic;
    margin: 14px 0 0 !important;
}

.heberg-monitoring-cta {
    display: inline-block;
    margin-top: 16px;
}

.heberg-monitoring-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
    flex-shrink: 0;
    min-width: 260px;
}

.heberg-monitoring-list li {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: .88rem;
    font-weight: 600;
    color: rgba(255,255,255,.72);
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(var(--header-accent),.07);
    border: 1px solid rgba(var(--header-accent),.18);
}

.heberg-monitoring-list li::before {
    content: "→";
    color: rgb(var(--header-accent));
    font-weight: 700;
    flex-shrink: 0;
}

/* ─── CTA FINAL ─── */
.heberg-cta {
    padding: 70px 20px var(--footer-clearance);
    border-top: 1px solid rgba(255,255,255,.05);
}

.heberg-cta-inner {
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
}

.heberg-cta-inner h2 {
    font-size: clamp(1.5rem, 2.8vw, 2.1rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.heberg-cta-inner p {
    color: rgba(255,255,255,.55);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 520px;
    margin: 0 auto 28px;
}

.heberg-cta-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    justify-content: center;
}

.heberg-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 14px 32px;
    font-size: 1rem;
    font-weight: 600;
    border-radius: 999px;
    color: rgba(255,255,255,.78);
    text-decoration: none;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.14);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: color .25s ease, background .25s ease, border-color .25s ease, transform .25s ease;
}

.heberg-btn-secondary:hover {
    color: #fff;
    background: rgba(59,130,246,.10);
    border-color: rgba(59,130,246,.40);
    transform: translateY(-2px);
}

/* ─── BTN PRIMARY OVERRIDE ─── */
.page-heberg .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 14px 36px;
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .04em;
    border-radius: 999px;
    color: #fff;
    text-decoration: none;
    /* demande explicite : "adapte les boutons [...] voir les choix faits
       [...] à accueil.php" — dégradé bleu figé remplacé par la couleur
       d'accent sélectionnée. */
    /* demande explicite : "les boutons (couleur blanc) ne sont pas assez
       lisibles" — dégradé toujours mélangé vers le noir plutôt qu'une
       simple opacité de la couleur d'accent (qui laissait passer le fond
       clair et rendait le texte blanc illisible avec l'accent "Blanc"). */
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 42%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-3)) 38%, #000) 100%);
    border: 1px solid rgba(var(--header-accent),.45);
    box-shadow:
        0 0 28px rgba(var(--header-accent),.22),
        0 8px 20px rgba(var(--header-accent),.14),
        inset 0 1px 0 rgba(255,255,255,.10);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
    transition: background .3s ease, box-shadow .3s ease, transform .3s ease;
}

.page-heberg .btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%);
    border-radius: inherit;
    pointer-events: none;
}

.page-heberg .btn-primary::after {
    content: "→";
    font-size: .95rem;
    opacity: .7;
    transition: transform .3s ease, opacity .3s ease;
}

.page-heberg .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 58%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-3)) 52%, #000) 100%);
    box-shadow:
        0 0 44px rgba(var(--header-accent),.40),
        0 12px 28px rgba(var(--header-accent),.22),
        inset 0 1px 0 rgba(255,255,255,.16);
    transform: translateY(-3px);
}

.page-heberg .btn-primary:hover::after {
    transform: translateX(4px);
    opacity: 1;
}


/* ========================= maintenance.php ========================= */

/* ─── BACKGROUND FIXE ─── */
.page-maint::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Planète-custom (maintenance.php) sur son propre calque ::after, masquée en
   fondu radial + rétrécie/effacée au scroll — même mécanisme que
   .page-vitrine::after/.page-refonte::after (cf. main.js, bloc "DÉCOR DE
   FOND") — demande explicite : étendre l'effet à toutes les pages offres. */
.page-maint::after {
    content: "";
    position: fixed;
    inset: 0;
    background: url("../image/planet-blanc.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}
.page-maint.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-maint > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-maint .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}

.page-maint .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── LAYOUT INNER COMMUN ─── */
.maint-section-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
}

/* ─── SECTION HEADER ─── */
.maint-section-header {
    text-align: center;
    max-width: 680px;
    margin: 0 auto 40px;
}

.maint-section-header h2 {
    font-size: clamp(1.4rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.maint-section-header p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    line-height: 1.7;
}

/* ─── HERO ─── */
.maint-hero {
    min-height: 55dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 140px 20px 80px;
    text-align: center;
}

.maint-hero-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    max-width: 760px;
}

.maint-page-label {
    display: inline-flex;
    align-items: center;
    padding: 4px 16px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    /* Demande explicite : "renforcer la lisibilité des badges section 1" —
       couleur bleue figée (ignorait l'accent) remplacée par la couleur
       sélectionnée, et fond translucide (.10) remplacé par un fond sombre
       bien plus opaque pour rester lisible sur un fond de planète clair. */
    color: rgba(var(--header-accent),.95);
    background: rgba(10,14,24,.65);
    border: 1px solid rgba(var(--header-accent),.55);
    box-shadow: 0 0 16px rgba(var(--header-accent),.25);
    text-shadow: 0 1px 3px rgba(0,0,0,.5);
}

.maint-hero h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* Demande explicite : "le texte ... est très peu lisible" — opacité relevée
   + légère ombre portée pour rester lisible sur un fond de planète clair. */
.maint-hero-sub {
    color: rgba(255,255,255,.85);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 620px;
    margin: 0;
    text-shadow: 0 1px 3px rgba(0,0,0,.75), 0 1px 10px rgba(0,0,0,.55);
}

.maint-impact-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 0;
}

.maint-impact-list li {
    padding: 6px 16px;
    border-radius: 999px;
    font-size: .82rem;
    font-weight: 600;
    color: rgba(239,68,68,.80);
    background: rgba(239,68,68,.06);
    border: 1px solid rgba(239,68,68,.18);
}

/* Demande explicite : "le texte ... doit hériter de la couleur active" +
   "doit être plus lisible/visible" — même correctif que .heberg-hero-cta-line
   (couleur bleue figée + fond quasi transparent). */
.maint-hero-tagline {
    font-size: .92rem;
    font-weight: 600;
    color: rgba(var(--header-accent),.95);
    margin: 0;
    padding: 10px 20px;
    border-left: 2px solid rgba(var(--header-accent),.60);
    background: rgba(10,14,24,.55);
    border-radius: 0 8px 8px 0;
    text-align: left;
    text-shadow: 0 1px 4px rgba(0,0,0,.5);
}

/* ─── POURQUOI ─── */
.maint-why {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.maint-why-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.maint-why-card {
    padding: 28px 26px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
}

.maint-why-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.maint-why-card--reasons::before {
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.55), transparent);
}

.maint-why-card--risks::before {
    background: linear-gradient(90deg, transparent, rgba(239,68,68,.45), transparent);
}

.maint-why-card h3 {
    font-size: .96rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 16px;
}

.maint-tech-list,
.maint-risk-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.maint-tech-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.65);
    padding: 8px 12px;
    border-radius: 8px;
    background: rgba(59,130,246,.05);
    border: 1px solid rgba(59,130,246,.12);
}

.maint-tech-list li::before {
    content: "▸";
    color: #3b82f6;
    font-size: .72rem;
    flex-shrink: 0;
}

.maint-risk-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.62);
    padding: 8px 12px;
    border-radius: 8px;
    background: rgba(239,68,68,.04);
    border: 1px solid rgba(239,68,68,.10);
}

.maint-risk-list li::before {
    content: "✕";
    color: rgba(239,68,68,.70);
    font-size: .72rem;
    font-weight: 700;
    flex-shrink: 0;
}

.maint-why-tagline {
    margin-top: 16px;
    font-size: .86rem;
    font-weight: 600;
    color: rgba(239,68,68,.75);
    font-style: italic;
}

/* ─── PILIERS SÉCURITÉ + PERF ─── */
.maint-pillars {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.maint-pillars-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.maint-pillar {
    padding: 30px 26px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    gap: 16px;
    position: relative;
    overflow: hidden;
}

.maint-pillar::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.maint-pillar--sec::before {
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.65), transparent);
}

.maint-pillar--perf::before {
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.65), transparent);
}

.maint-pillar-head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.maint-pillar-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px 8px;
    border-radius: 7px;
    font-size: .65rem;
    font-weight: 800;
    letter-spacing: .06em;
    flex-shrink: 0;
    background: rgba(var(--header-accent),.10);
    color: var(--brand-color);
    border: 1px solid rgba(var(--header-accent),.20);
}

.maint-pillar--sec  .maint-pillar-icon { background: rgba(var(--header-accent),.10); color: #7aa2ff; border-color: rgba(var(--header-accent),.22); }
.maint-pillar--perf .maint-pillar-icon { background: rgba(251,191,36,.10); color: #fbbf24; border-color: rgba(251,191,36,.22); }

.maint-pillar-head h2 {
    font-size: clamp(1.1rem, 1.8vw, 1.4rem);
    font-weight: 700;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.maint-pillar > p {
    font-size: .90rem;
    color: rgba(255,255,255,.52);
    line-height: 1.7;
    margin: 0;
}

.maint-pillar-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.maint-pillar-list li {
    font-size: .86rem;
    color: rgba(255,255,255,.55);
    padding: 6px 10px 6px 0;
    display: flex;
    align-items: center;
    gap: 8px;
}

.maint-pillar-list li::before {
    content: "–";
    color: rgba(255,255,255,.25);
    flex-shrink: 0;
}

.maint-pillar-response {
    padding: 14px 16px;
    border-radius: 10px;
    background: rgba(59,130,246,.06);
    border: 1px solid rgba(59,130,246,.14);
}

.maint-pillar-response-label {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #3b82f6;
    margin-bottom: 10px;
}

.maint-pillar-response ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.maint-pillar-response li {
    font-size: .86rem;
    color: rgba(255,255,255,.68);
    display: flex;
    align-items: flex-start;
    gap: 7px;
}

.maint-pillar-response li::before {
    content: "✓";
    color: #3b82f6;
    font-size: .76rem;
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}

.maint-pillar-tagline {
    font-size: .88rem;
    font-weight: 600;
    color: rgba(59,130,246,.80);
    margin: 0;
    font-style: italic;
}

/* ─── INCLUS ─── */
.maint-includes {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.maint-includes-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
}

.maint-includes-cta {
    margin-top: 40px;
    text-align: center;
}

.maint-includes-cta p {
    font-size: .95rem;
    color: rgba(255,255,255,.65);
    margin: 0 0 16px;
}

.maint-inc-card {
    padding: 26px 22px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease, transform .3s ease;
}

.maint-inc-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.55), transparent);
}

.maint-inc-card:hover {
    border-color: rgba(59,130,246,.20);
    box-shadow: 0 10px 28px rgba(59,130,246,.08);
    transform: translateY(-4px);
}

.maint-inc-icon {
    font-size: 2rem;
    font-weight: 800;
    margin-bottom: 12px;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: rgba(59,130,246,.45);
    display: block;
}

.maint-inc-card h3 {
    font-size: .95rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}

.maint-inc-card ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.maint-inc-card li {
    font-size: .84rem;
    color: rgba(255,255,255,.58);
    display: flex;
    align-items: flex-start;
    gap: 8px;
    line-height: 1.5;
}

.maint-inc-card li::before {
    content: "✓";
    color: #3b82f6;
    font-size: .78rem;
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}

/* ─── APPROCHE ─── */
.maint-approach {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.maint-approach-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.maint-approach-card {
    padding: 32px 28px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    gap: 14px;
    position: relative;
    overflow: hidden;
}

.maint-approach-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.maint-approach-card--results::before {
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.55), transparent);
}

.maint-approach-card--hosting::before {
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.45), transparent);
}

.maint-approach-card h2 {
    font-size: clamp(1.1rem, 1.8vw, 1.4rem);
    font-weight: 700;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.maint-approach-card > p {
    font-size: .90rem;
    color: rgba(255,255,255,.52);
    line-height: 1.7;
    margin: 0;
}

.maint-approach-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.maint-approach-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.70);
    padding: 8px 12px;
    border-radius: 8px;
    background: rgba(59,130,246,.05);
    border: 1px solid rgba(59,130,246,.12);
}

.maint-approach-list li::before {
    content: "→";
    color: #3b82f6;
    font-weight: 700;
    flex-shrink: 0;
}

.maint-approach-tagline {
    font-size: .88rem;
    font-weight: 600;
    color: rgba(59,130,246,.80);
    margin: 0;
    font-style: italic;
}

.maint-hosting-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .88rem;
    font-weight: 600;
    color: #93c5fd;
    text-decoration: none;
    padding: 8px 16px;
    border-radius: 8px;
    border: 1px solid rgba(var(--header-accent),.28);
    background: rgba(var(--header-accent),.07);
    margin-top: 4px;
    transition: background .25s ease, border-color .25s ease, color .25s ease;
}

.maint-hosting-link::after {
    content: "→";
    font-size: .80rem;
}

.maint-hosting-link:hover {
    background: rgba(var(--header-accent),.14);
    border-color: rgba(var(--header-accent),.45);
    color: #fff;
}

/* ─── SÉRÉNITÉ ─── */
.maint-serenity {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.maint-serenity-inner {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.maint-serenity-block,
.maint-adapted-block {
    padding: 30px 26px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    gap: 14px;
    position: relative;
    overflow: hidden;
}

.maint-serenity-block::before,
.maint-adapted-block::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, rgba(59,130,246,.50), transparent);
}

.maint-serenity-block h2,
.maint-adapted-block h2 {
    font-size: clamp(1.1rem, 1.8vw, 1.4rem);
    font-weight: 700;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.maint-serenity-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.maint-serenity-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.68);
    padding: 9px 12px;
    border-radius: 8px;
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.05);
}

.maint-serenity-list li::before {
    content: "✓";
    color: #3b82f6;
    font-size: .76rem;
    font-weight: 700;
    flex-shrink: 0;
}

.maint-serenity-tagline {
    font-size: .88rem;
    font-weight: 600;
    color: rgba(59,130,246,.80);
    margin: 0;
    font-style: italic;
}

.maint-adapted-block > p {
    font-size: .90rem;
    color: rgba(255,255,255,.52);
    line-height: 1.7;
    margin: 0;
}

.maint-adapted-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.maint-adapted-list li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-size: .88rem;
    color: rgba(255,255,255,.62);
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.05);
    line-height: 1.5;
}

.maint-adapted-level {
    font-size: .70rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #3b82f6;
    background: rgba(59,130,246,.10);
    border: 1px solid rgba(59,130,246,.22);
    border-radius: 999px;
    padding: 2px 9px;
    white-space: nowrap;
    flex-shrink: 0;
    margin-top: 1px;
}

/* ─── BONUS ─── */
.maint-bonus {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.maint-bonus-card {
    max-width: 760px;
    margin: 0 auto;
    padding: 40px 36px;
    border-radius: 20px;
    background: rgba(59,130,246,.05);
    border: 1px solid rgba(59,130,246,.20);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    position: relative;
    overflow: hidden;
}

.maint-bonus-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(59,130,246,.75), rgba(37,99,235,.55), transparent);
}

.maint-bonus-badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 14px;
    border-radius: 999px;
    font-size: .70rem;
    font-weight: 700;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: #93c5fd;
    background: rgba(59,130,246,.12);
    border: 1px solid rgba(59,130,246,.35);
    box-shadow: 0 0 16px rgba(59,130,246,.15);
}

.maint-bonus-card h2 {
    font-size: clamp(1.2rem, 2vw, 1.6rem);
    font-weight: 700;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.maint-bonus-card > p {
    color: rgba(255,255,255,.52);
    font-size: .92rem;
    line-height: 1.7;
    max-width: 540px;
    margin: 0;
}

.maint-bonus-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    max-width: 480px;
    text-align: left;
}

.maint-bonus-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .90rem;
    font-weight: 500;
    color: rgba(255,255,255,.75);
    padding: 10px 16px;
    border-radius: 10px;
    background: rgba(59,130,246,.07);
    border: 1px solid rgba(59,130,246,.16);
}

.maint-bonus-list li::before {
    content: "→";
    color: #3b82f6;
    font-weight: 700;
    flex-shrink: 0;
}

.maint-bonus-tagline {
    font-size: .90rem;
    font-weight: 600;
    color: rgba(59,130,246,.85);
    margin: 0;
    font-style: italic;
}

/* ─── CTA FINAL ─── */
.maint-cta {
    padding: 70px 20px var(--footer-clearance);
    border-top: 1px solid rgba(255,255,255,.05);
}

.maint-cta-inner {
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
}

.maint-cta-inner h2 {
    font-size: clamp(1.5rem, 2.8vw, 2.1rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.maint-cta-inner p {
    color: rgba(255,255,255,.55);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 520px;
    margin: 0 auto 28px;
}

.maint-cta-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    justify-content: center;
}

.maint-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 14px 32px;
    font-size: 1rem;
    font-weight: 600;
    border-radius: 999px;
    color: rgba(255,255,255,.78);
    text-decoration: none;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.14);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: color .25s ease, background .25s ease, border-color .25s ease, transform .25s ease;
}

.maint-btn-secondary:hover {
    color: #fff;
    background: rgba(59,130,246,.10);
    border-color: rgba(59,130,246,.40);
    transform: translateY(-2px);
}

/* ─── BTN PRIMARY OVERRIDE ─── */
.page-maint .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 14px 36px;
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .04em;
    border-radius: 999px;
    color: #fff;
    text-decoration: none;
    /* demande explicite : "adapte les boutons [...] voir les choix faits
       [...] à accueil.php" — dégradé bleu figé remplacé par la couleur
       d'accent sélectionnée. */
    /* demande explicite : "les boutons (couleur blanc) ne sont pas assez
       lisibles" — dégradé toujours mélangé vers le noir plutôt qu'une
       simple opacité de la couleur d'accent (qui laissait passer le fond
       clair et rendait le texte blanc illisible avec l'accent "Blanc"). */
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 42%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-3)) 38%, #000) 100%);
    border: 1px solid rgba(var(--header-accent),.45);
    box-shadow:
        0 0 28px rgba(var(--header-accent),.22),
        0 8px 20px rgba(var(--header-accent),.14),
        inset 0 1px 0 rgba(255,255,255,.10);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
    transition: background .3s ease, box-shadow .3s ease, transform .3s ease;
}

.page-maint .btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%);
    border-radius: inherit;
    pointer-events: none;
}

.page-maint .btn-primary::after {
    content: "→";
    font-size: .95rem;
    opacity: .7;
    transition: transform .3s ease, opacity .3s ease;
}

.page-maint .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 58%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-3)) 52%, #000) 100%);
    box-shadow:
        0 0 44px rgba(var(--header-accent),.40),
        0 12px 28px rgba(var(--header-accent),.22),
        inset 0 1px 0 rgba(255,255,255,.16);
    transform: translateY(-3px);
}

.page-maint .btn-primary:hover::after {
    transform: translateX(4px);
    opacity: 1;
}

/* ========================= Navigation inter-pages HM ========================= */

/* ─── Position relative sur les 3 heroes ─── */
.hm-hero,
.heberg-hero,
.maint-hero {
    position: relative;
    padding-top: 200px;
}

/* ─── NAV ─── */
.hmg-nav {
    position: absolute;
    /* Remonté (90-120px -> 70-90px, demande explicite "tu peux les remonter
       étant donné qu'il n'y a plus de header au-dessus") : cet espacement
       datait de l'ancienne barre <header> horizontale, remplacée depuis par
       les vignettes HUD flottantes (Navigation/Mon compte, ancrées à
       top:22px) — plus besoin d'autant de marge en haut de page. */
    top: clamp(70px, 8vh, 90px);
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: min(680px, calc(100% - 40px));
    z-index: 2;
}

.hmg-nav-spacer {
    width: 120px;
    flex-shrink: 0;
}

/* ─── LIENS ─── */
.hmg-nav-link {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: rgba(255,255,255,.72);
    text-decoration: none;
    padding: 9px 18px;
    border-radius: 999px;
    border: 1px solid rgba(var(--header-accent),.38);
    background: rgba(var(--header-accent),.09);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: 0 0 14px rgba(var(--header-accent),.10);
    position: relative;
    transition: color .25s ease, border-color .25s ease, background .25s ease, box-shadow .25s ease, transform .25s ease;
}

.hmg-nav-link:hover {
    color: #fff;
    border-color: rgba(var(--header-accent),.68);
    background: rgba(var(--header-accent),.18);
    box-shadow: 0 0 24px rgba(var(--header-accent),.26);
}

.hmg-nav-link--prev:hover { transform: translateX(-3px); }
.hmg-nav-link--next:hover { transform: translateX(3px); }

.hmg-nav-link svg {
    transition: transform .25s ease;
    flex-shrink: 0;
}

.hmg-nav-link--prev:hover svg { transform: translateX(-2px); }
.hmg-nav-link--next:hover svg { transform: translateX(2px); }

/* ─── TOOLTIP ─── */
.hmg-nav-link::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(-100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(10,14,30,.96);
    border: 1px solid rgba(255,255,255,.10);
    color: rgba(255,255,255,.85);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .04em;
    white-space: nowrap;
    padding: 5px 12px;
    border-radius: 6px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease, transform .2s ease;
    z-index: 10;
}

.hmg-nav-link:hover::after {
    opacity: 1;
    transform: translateX(-50%) translateY(8px);
}

/* ─── TRACK ─── */
.hmg-offer-track {
    display: flex;
    align-items: center;
    gap: 6px;
}

.hmg-track-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255,255,255,.20);
    border: 1px solid rgba(255,255,255,.16);
    flex-shrink: 0;
}

.hmg-track-dot--active {
    width: 10px;
    height: 10px;
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.80);
    box-shadow: 0 0 10px rgba(var(--header-accent),.68);
}

.hmg-track-line {
    width: 28px;
    height: 1px;
    background: rgba(255,255,255,.18);
    flex-shrink: 0;
}




/* ─── HMG-NAV COULEUR INDIGO pour pages conseil ─── */
.page-conseil .hmg-nav-link {
    border-color: rgba(var(--header-accent),.38);
    background: rgba(var(--header-accent),.09);
    box-shadow: 0 0 14px rgba(var(--header-accent),.10);
}

.page-conseil .hmg-nav-link:hover {
    border-color: rgba(var(--header-accent),.68);
    background: rgba(var(--header-accent),.16);
    box-shadow: 0 0 20px rgba(var(--header-accent),.20);
}

.page-conseil .hmg-track-dot--active {
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.80);
    box-shadow: 0 0 10px rgba(var(--header-accent),.68);
}


/* ─── HMG-NAV COULEUR BLEUE pour la boucle Présentation
       (presentation.php → about.php → partenaires.php → livre-dor.php) ─── */
.page-presentation .hmg-nav-link,
.page-faq-site .hmg-nav-link,
.page-about .hmg-nav-link,
.page-partenaires .hmg-nav-link,
.page-projets-suivre .hmg-nav-link,
.page-livre-dor .hmg-nav-link {
    border-color: rgba(var(--header-accent),.38);
    background: rgba(var(--header-accent),.09);
    box-shadow: 0 0 14px rgba(var(--header-accent),.10);
}

.page-presentation .hmg-nav-link:hover,
.page-faq-site .hmg-nav-link:hover,
.page-about .hmg-nav-link:hover,
.page-partenaires .hmg-nav-link:hover,
.page-projets-suivre .hmg-nav-link:hover,
.page-livre-dor .hmg-nav-link:hover {
    border-color: rgba(var(--header-accent),.68);
    background: rgba(var(--header-accent),.16);
    box-shadow: 0 0 20px rgba(var(--header-accent),.20);
}

.page-presentation .hmg-track-dot--active,
.page-faq-site .hmg-track-dot--active,
.page-about .hmg-track-dot--active,
.page-partenaires .hmg-track-dot--active,
.page-projets-suivre .hmg-track-dot--active,
.page-livre-dor .hmg-track-dot--active {
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.80);
    box-shadow: 0 0 10px rgba(var(--header-accent),.68);
}

/* ─── HMG-NAV COULEUR BLEUE pour la boucle légale
       (cgv.php → mentions-legales.php → politique-confidentialite.php →
       politique-cookies.php) ─── partagent toutes .page-cgv, sans catégorie
       de service dédiée : même bleu neutre que la boucle Présentation. */
.page-cgv .hmg-nav-link {
    border-color: rgba(var(--header-accent),.38);
    background: rgba(var(--header-accent),.09);
    box-shadow: 0 0 14px rgba(var(--header-accent),.10);
}

.page-cgv .hmg-nav-link:hover {
    border-color: rgba(var(--header-accent),.68);
    background: rgba(var(--header-accent),.16);
    box-shadow: 0 0 20px rgba(var(--header-accent),.20);
}

.page-cgv .hmg-track-dot--active {
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.80);
    box-shadow: 0 0 10px rgba(var(--header-accent),.68);
}

/* ─── HMG-NAV — boucle Offres (sitevitrine.php → sitepro.php →
       surmesure.php), navigation adaptée au même système que les pages "à
       propos" (demande explicite), auparavant des classes dédiées
       (.vitrine-offer-nav, etc.) sans ligne de progression.
       Couleur adaptée à CHAQUE page plutôt qu'une seule couleur partagée
       (demande explicite) — reprise de l'accent déjà utilisé ailleurs sur
       chaque page :
       - sitevitrine.php : cyan — c'est déjà la couleur par défaut de
         .hmg-nav-link (cf. règles de base plus haut), donc aucune
         surcharge nécessaire ici.
       - sitepro.php : ambre/or (cf. .pro-price, .pro-hero h1).
       - surmesure.php : bleu (cf. .sur-price, .sur-hero h1). */
.page-pro .hmg-nav-link {
    border-color: rgba(var(--header-accent),.45);
    background: rgba(var(--header-accent),.12);
    box-shadow: 0 0 18px rgba(var(--header-accent),.15);
}

.page-pro .hmg-nav-link:hover {
    border-color: rgba(var(--header-accent),.75);
    background: rgba(var(--header-accent),.25);
    box-shadow: 0 0 28px rgba(var(--header-accent),.30);
}

.page-pro .hmg-track-dot--active {
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.80);
    box-shadow: 0 0 10px rgba(var(--header-accent),.70);
}

.page-sur .hmg-nav-link {
    border-color: rgba(var(--header-accent),.45);
    background: rgba(var(--header-accent),.12);
    box-shadow: 0 0 18px rgba(var(--header-accent),.15);
}

.page-sur .hmg-nav-link:hover {
    border-color: rgba(var(--header-accent),.75);
    background: rgba(var(--header-accent),.25);
    box-shadow: 0 0 28px rgba(var(--header-accent),.30);
}

.page-sur .hmg-track-dot--active {
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.80);
    box-shadow: 0 0 10px rgba(var(--header-accent),.70);
}

/* ─── Adaptation pour libellés plus longs (boucle légale) ───
   Même visuel que la boucle Présentation (aucun fond "verre" ni changement
   de taille des points — juste la couleur, cf. règles ci-dessus) : les
   libellés des pages légales sont simplement plus longs ("Conditions
   Générales de Vente", "Politique de confidentialité") que ceux de la
   boucle Présentation ("Avis", "Partenaires"...). Barre un peu plus large
   et texte légèrement réduit pour que les 2 liens + la piste de points
   restent sur une seule ligne sans se chevaucher. */
.page-cgv .hmg-nav {
    width: min(760px, calc(100% - 40px));
}

.page-cgv .hmg-nav-link {
    font-size: .74rem;
    padding: 9px 14px;
    letter-spacing: .03em;
}


/* ========================= conseil.php ========================= */

/* ─── BACKGROUND FIXE ─── */
.page-conseil::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Planète (conseil.php : planet-jupiter ; conseilaccompagnement.php, le hub,
   reprend sa planète de catégorie violette via l'override ci-dessous — même
   répartition que l'ancienne décoration de .cw-hero) sur son propre calque
   ::after, masquée en fondu radial + rétrécie/effacée au scroll — même
   mécanisme que .page-vitrine::after/.page-refonte::after (cf. main.js, bloc
   "DÉCOR DE FOND") — demande explicite : étendre l'effet à toutes les pages
   offres. */
.page-conseil::after {
    content: "";
    position: fixed;
    inset: 0;
    background: url("../image/planet-jupiter.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}
.page-conseil-hub::after {
    background-image: url("../image/planet-violet.webp");
}
.page-conseil.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-conseil > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-conseil .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}

.page-conseil .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── LAYOUT INNER COMMUN ─── */
.conseil-section-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 3vw, 2rem);
}

/* ─── SECTION HEADER ─── */
.conseil-section-header {
    text-align: center;
    max-width: 680px;
    margin: 0 auto 40px;
}

.conseil-section-header h2 {
    font-size: clamp(1.4rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.conseil-section-header p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    line-height: 1.7;
}

/* ─── HERO ─── */
.conseil-hero {
    min-height: 55dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 140px 20px 80px;
    text-align: center;
}

.conseil-hero-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    max-width: 760px;
    margin-top: 48px;
}

.conseil-page-label {
    display: inline-flex;
    align-items: center;
    padding: 4px 16px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: #a5b4fc;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.32);
    box-shadow: 0 0 16px rgba(var(--header-accent),.14);
}

.conseil-hero h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.15;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.conseil-hero-sub {
    color: rgba(255,255,255,.58);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 620px;
    margin: 0;
}

.conseil-impact-list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 0;
}

.conseil-impact-list li {
    padding: 6px 16px;
    border-radius: 999px;
    font-size: .82rem;
    font-weight: 600;
    color: rgba(165,180,252,.85);
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.22);
}

.conseil-hero-tagline {
    font-size: .92rem;
    font-weight: 600;
    color: rgba(var(--header-accent),.85);
    margin: 0;
    padding: 10px 20px;
    border-left: 2px solid rgba(var(--header-accent),.50);
    background: rgba(var(--header-accent),.06);
    border-radius: 0 8px 8px 0;
    text-align: left;
}

/* ─── REGARD EXPERT ─── */
.conseil-expert {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.conseil-expert-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.conseil-expert-card {
    padding: 28px 26px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
}

.conseil-expert-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.conseil-expert-card--situations::before {
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.55), transparent);
}

.conseil-expert-card--choices::before {
    background: linear-gradient(90deg, transparent, rgba(139,92,246,.50), transparent);
}

.conseil-expert-card h3 {
    font-size: .96rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 16px;
}

.conseil-expert-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.conseil-expert-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.65);
    padding: 8px 12px;
    border-radius: 8px;
    background: rgba(var(--header-accent),.05);
    border: 1px solid rgba(var(--header-accent),.10);
}

.conseil-expert-list li::before {
    content: "→";
    color: #818cf8;
    font-weight: 700;
    flex-shrink: 0;
}

.conseil-expert-list--choices li::before {
    content: "◆";
    color: rgba(139,92,246,.80);
    font-size: .6rem;
}

.conseil-expert-tagline {
    margin-top: 16px;
    font-size: .88rem;
    font-weight: 600;
    color: rgba(var(--header-accent),.85);
    font-style: italic;
}

/* ─── DOMAINES ─── */
.conseil-domains {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.conseil-domains-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
}

.conseil-domain {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    padding: 24px 22px;
    border-radius: 16px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    position: relative;
    overflow: hidden;
    transition: background .25s ease, border-color .25s ease, transform .25s ease;
}

.conseil-domain::before {
    content: "";
    position: absolute;
    left: 0; top: 15%; bottom: 15%;
    width: 3px;
    border-radius: 0 2px 2px 0;
    opacity: .55;
    transition: opacity .25s ease, top .25s ease, bottom .25s ease;
}

.conseil-domain--strategy::before { background: #6366f1; }
.conseil-domain--ux::before       { background: #8b5cf6; }
.conseil-domain--perf::before     { background: #6366f1; }
.conseil-domain--conv::before     { background: #8b5cf6; }

.conseil-domain:hover {
    background: rgba(255,255,255,.048);
    border-color: rgba(var(--header-accent),.16);
    transform: translateX(5px);
}

.conseil-domain:hover::before {
    opacity: 1;
    top: 6%;
    bottom: 6%;
}

.conseil-domain-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px 9px;
    border-radius: 7px;
    font-size: .64rem;
    font-weight: 800;
    letter-spacing: .06em;
    flex-shrink: 0;
    margin-top: 2px;
    background: rgba(var(--header-accent),.10);
    color: #a5b4fc;
    border: 1px solid rgba(var(--header-accent),.22);
}

.conseil-domain--strategy .conseil-domain-icon { background: rgba(139,92,246,.10); color: #c4b5fd; border-color: rgba(139,92,246,.22); }
.conseil-domain--ux       .conseil-domain-icon { background: rgba(99,102,241,.10); color: #a5b4fc; border-color: rgba(99,102,241,.22); }
.conseil-domain--perf     .conseil-domain-icon { background: rgba(251,191,36,.10); color: #fbbf24; border-color: rgba(251,191,36,.22); }
.conseil-domain--conv     .conseil-domain-icon { background: rgba(34,197,94,.10);  color: #4ade80; border-color: rgba(34,197,94,.22); }

.conseil-domain-body h3 {
    font-size: .96rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
}

.conseil-domain-body ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.conseil-domain-body li {
    font-size: .86rem;
    color: rgba(255,255,255,.55);
    padding: 4px 0 4px 14px;
    position: relative;
    line-height: 1.5;
}

.conseil-domain-body li::before {
    content: "▸";
    position: absolute;
    left: 0;
    color: rgba(var(--header-accent),.65);
    font-size: .72rem;
    top: 5px;
}

/* ─── APPROCHE ─── */
.conseil-approach {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.conseil-approach-card {
    max-width: 860px;
    margin: 0 auto;
    padding: 40px 36px;
    border-radius: 20px;
    background: rgba(255,255,255,.032);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.conseil-approach-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(var(--header-accent),.65), rgba(var(--accent-harmony-1),.45), transparent);
}

.conseil-approach-card h2 {
    font-size: clamp(1.3rem, 2.2vw, 1.75rem);
    font-weight: 700;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.conseil-approach-card > p {
    font-size: .92rem;
    color: rgba(255,255,255,.55);
    line-height: 1.75;
    margin: 0;
}

.conseil-approach-qualities {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.conseil-quality {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border-radius: 999px;
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.18);
    font-size: .88rem;
    font-weight: 600;
    color: rgba(255,255,255,.75);
}

.conseil-quality-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #818cf8;
    box-shadow: 0 0 8px rgba(var(--header-accent),.80);
    flex-shrink: 0;
}

.conseil-approach-results {
    padding: 18px 20px;
    border-radius: 12px;
    background: rgba(var(--header-accent),.06);
    border: 1px solid rgba(var(--header-accent),.16);
}

.conseil-approach-results-label {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #818cf8;
    margin-bottom: 12px;
}

.conseil-approach-results ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
}

.conseil-approach-results li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.70);
}

.conseil-approach-results li::before {
    content: "✓";
    color: #818cf8;
    font-size: .76rem;
    font-weight: 700;
    flex-shrink: 0;
}

/* ─── OFFRES ─── */
.conseil-offers {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.conseil-offers-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 18px;
    align-items: stretch;
}

.conseil-plan {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 26px 22px 22px;
    border-radius: 20px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    position: relative;
    overflow: hidden;
    transition: transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}

.conseil-plan::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
}

.conseil-plan:hover { transform: translateY(-6px); }

.conseil-plan--basic::before {
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.22), transparent);
}
.conseil-plan--basic:hover {
    border-color: rgba(255,255,255,.14);
    box-shadow: 0 16px 40px rgba(0,0,0,.28);
}

.conseil-plan--essential::before {
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.60), transparent);
}
.conseil-plan--essential:hover {
    border-color: rgba(var(--header-accent),.26);
    box-shadow: 0 16px 40px rgba(var(--header-accent),.10);
}

.conseil-plan--pro::before {
    background: linear-gradient(90deg, transparent, rgba(139,92,246,.80), transparent);
}
.conseil-plan--pro {
    border-color: rgba(139,92,246,.20);
    box-shadow: 0 0 40px rgba(139,92,246,.08);
}
.conseil-plan--pro:hover {
    border-color: rgba(139,92,246,.40);
    box-shadow: 0 16px 50px rgba(139,92,246,.18);
}

.conseil-plan--premium::before {
    background: linear-gradient(90deg, transparent, rgba(251,191,36,.60), transparent);
}
.conseil-plan--premium:hover {
    border-color: rgba(251,191,36,.24);
    box-shadow: 0 16px 40px rgba(251,191,36,.10);
}

.conseil-plan-ribbon {
    position: absolute;
    top: 12px;
    right: 12px;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #fff;
    background: rgba(139,92,246,.75);
    border: 1px solid rgba(139,92,246,.50);
    box-shadow: 0 4px 14px rgba(139,92,246,.30);
}

.conseil-plan-top { display: flex; flex-direction: column; gap: 8px; }

.conseil-plan-tier {
    display: inline-block;
    font-size: .70rem;
    font-weight: 700;
    letter-spacing: .10em;
    text-transform: uppercase;
}

.conseil-plan--basic    .conseil-plan-tier { color: rgba(255,255,255,.40); }
.conseil-plan--essential .conseil-plan-tier { color: #a5b4fc; }
.conseil-plan--pro      .conseil-plan-tier { color: #c4b5fd; }
.conseil-plan--premium  .conseil-plan-tier { color: #fcd34d; }

.conseil-plan-top h3 {
    font-size: .98rem;
    font-weight: 700;
    color: #fff;
    margin: 0;
    line-height: 1.3;
}

.conseil-plan-price {
    display: flex;
    align-items: baseline;
    gap: 4px;
    padding: 9px 12px;
    border-radius: 10px;
    width: fit-content;
}

.conseil-plan--basic    .conseil-plan-price { background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08); }
.conseil-plan--essential .conseil-plan-price { background: rgba(var(--header-accent),.10); border: 1px solid rgba(var(--header-accent),.20); }
.conseil-plan--pro      .conseil-plan-price { background: rgba(139,92,246,.12); border: 1px solid rgba(139,92,246,.24); }
.conseil-plan--premium  .conseil-plan-price { background: rgba(251,191,36,.10); border: 1px solid rgba(251,191,36,.22); }

.conseil-price-amount {
    font-size: 1.3rem;
    font-weight: 800;
    color: #fff;
    line-height: 1;
}

.conseil-price-currency {
    font-size: .75rem;
    font-weight: 700;
    color: rgba(255,255,255,.50);
    margin-bottom: 2px;
}

.conseil-price-period {
    font-size: .72rem;
    color: rgba(255,255,255,.38);
}

.conseil-plan-tagline {
    font-size: .80rem;
    color: rgba(255,255,255,.38);
    font-style: italic;
    margin: 0;
}

.conseil-plan-section { display: flex; flex-direction: column; gap: 8px; }

.conseil-plan-section-label {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: rgba(255,255,255,.35);
}

.conseil-plan-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
}

.conseil-plan-list li {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    font-size: .83rem;
    color: rgba(255,255,255,.65);
    line-height: 1.5;
    padding: 6px 8px;
    border-radius: 7px;
    background: rgba(255,255,255,.02);
    border: 1px solid rgba(255,255,255,.04);
    transition: color .2s ease;
}

.conseil-plan-list li::before {
    content: "✓";
    font-size: .76rem;
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}

.conseil-plan--basic    .conseil-plan-list li::before { color: rgba(255,255,255,.28); }
.conseil-plan--essential .conseil-plan-list li::before { color: #818cf8; }
.conseil-plan--pro      .conseil-plan-list li::before { color: #a78bfa; }
.conseil-plan--premium  .conseil-plan-list li::before { color: #fbbf24; }

.conseil-plan-list--ideal li::before { content: "→"; }

.conseil-plan:hover .conseil-plan-list li { color: rgba(255,255,255,.82); }

.conseil-plan-cta {
    display: block;
    text-align: center;
    padding: 10px 16px;
    border-radius: 999px;
    font-size: .84rem;
    font-weight: 700;
    text-decoration: none;
    color: rgba(255,255,255,.72);
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(255,255,255,.04);
    margin-top: auto;
    transition: color .25s ease, background .25s ease, border-color .25s ease, box-shadow .25s ease;
}

.conseil-plan--pro .conseil-plan-cta {
    color: #fff;
    background: rgba(139,92,246,.18);
    border-color: rgba(139,92,246,.42);
    box-shadow: 0 4px 16px rgba(139,92,246,.14);
}

.conseil-plan--basic    .conseil-plan-cta:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.20); }
.conseil-plan--essential .conseil-plan-cta:hover { background: rgba(var(--header-accent),.14); border-color: rgba(var(--header-accent),.40); box-shadow: 0 6px 20px rgba(var(--header-accent),.12); color: #fff; }
.conseil-plan--pro      .conseil-plan-cta:hover { background: rgba(139,92,246,.28); border-color: rgba(139,92,246,.60); box-shadow: 0 6px 20px rgba(139,92,246,.22); }
.conseil-plan--premium  .conseil-plan-cta:hover { background: rgba(251,191,36,.14); border-color: rgba(251,191,36,.38); box-shadow: 0 6px 20px rgba(251,191,36,.12); color: #fff; }

/* ─── PHILOSOPHIE ─── */
.conseil-philosophy {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.conseil-philosophy-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.conseil-philo-card {
    padding: 32px 28px;
    border-radius: 18px;
    background: rgba(255,255,255,.028);
    border: 1px solid rgba(255,255,255,.06);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    display: flex;
    flex-direction: column;
    gap: 16px;
    position: relative;
    overflow: hidden;
}

.conseil-philo-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.50), transparent);
}

.conseil-philo-card h2 {
    font-size: clamp(1.1rem, 1.8vw, 1.4rem);
    font-weight: 700;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.conseil-philo-card > p {
    font-size: .90rem;
    color: rgba(255,255,255,.52);
    line-height: 1.7;
    margin: 0;
}

.conseil-philo-steps {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.conseil-philo-steps li {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: .88rem;
    color: rgba(255,255,255,.70);
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(var(--header-accent),.06);
    border: 1px solid rgba(var(--header-accent),.12);
}

.conseil-step-num {
    font-family: "Space Grotesk", sans-serif;
    font-size: 1.1rem;
    font-weight: 800;
    color: #818cf8;
    opacity: .65;
    flex-shrink: 0;
    line-height: 1;
    width: 28px;
}

.conseil-philo-tagline {
    font-size: .88rem;
    font-weight: 600;
    color: rgba(var(--header-accent),.80);
    margin: 0;
    font-style: italic;
}

.conseil-partner-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.conseil-partner-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .88rem;
    color: rgba(255,255,255,.68);
    padding: 9px 12px;
    border-radius: 8px;
    background: rgba(255,255,255,.025);
    border: 1px solid rgba(255,255,255,.05);
}

.conseil-partner-list li::before {
    content: "→";
    color: #818cf8;
    font-weight: 700;
    flex-shrink: 0;
}

/* ─── BONUS ─── */
.conseil-bonus {
    padding: 70px 0;
    border-top: 1px solid rgba(255,255,255,.05);
}

.conseil-bonus-card {
    max-width: 760px;
    margin: 0 auto;
    padding: 40px 36px;
    border-radius: 20px;
    background: rgba(var(--header-accent),.05);
    border: 1px solid rgba(var(--header-accent),.20);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    position: relative;
    overflow: hidden;
}

.conseil-bonus-card::before {
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 2px;
    background: linear-gradient(to right, transparent, rgba(var(--header-accent),.75), rgba(var(--accent-harmony-1),.55), transparent);
}

.conseil-bonus-badge {
    display: inline-flex;
    align-items: center;
    padding: 4px 14px;
    border-radius: 999px;
    font-size: .70rem;
    font-weight: 700;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: #a5b4fc;
    background: rgba(var(--header-accent),.12);
    border: 1px solid rgba(var(--header-accent),.35);
    box-shadow: 0 0 16px rgba(var(--header-accent),.15);
}

.conseil-bonus-card h2 {
    font-size: clamp(1.2rem, 2vw, 1.6rem);
    font-weight: 700;
    margin: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.conseil-bonus-card > p {
    color: rgba(255,255,255,.52);
    font-size: .92rem;
    line-height: 1.7;
    max-width: 540px;
    margin: 0;
}

.conseil-bonus-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    max-width: 480px;
    text-align: left;
}

.conseil-bonus-list li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .90rem;
    font-weight: 500;
    color: rgba(255,255,255,.75);
    padding: 10px 16px;
    border-radius: 10px;
    background: rgba(var(--header-accent),.07);
    border: 1px solid rgba(var(--header-accent),.16);
}

.conseil-bonus-list li::before {
    content: "→";
    color: #818cf8;
    font-weight: 700;
    flex-shrink: 0;
}

.conseil-bonus-tagline {
    font-size: .90rem;
    font-weight: 600;
    color: rgba(var(--header-accent),.85);
    margin: 0;
    font-style: italic;
}

/* ─── CTA FINAL ─── */
.conseil-cta {
    padding: 70px 20px var(--footer-clearance);
    border-top: 1px solid rgba(255,255,255,.05);
}

.conseil-cta-inner {
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
}

.conseil-cta-inner h2 {
    font-size: clamp(1.5rem, 2.8vw, 2.1rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.conseil-cta-inner p {
    color: rgba(255,255,255,.55);
    font-size: .98rem;
    line-height: 1.75;
    max-width: 520px;
    margin: 0 auto 28px;
}

.conseil-cta-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    justify-content: center;
}

.conseil-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 14px 32px;
    font-size: 1rem;
    font-weight: 600;
    border-radius: 999px;
    color: rgba(255,255,255,.78);
    text-decoration: none;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.14);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: color .25s ease, background .25s ease, border-color .25s ease, transform .25s ease;
}

.conseil-btn-secondary:hover {
    color: #fff;
    background: rgba(var(--header-accent),.10);
    border-color: rgba(var(--header-accent),.40);
    transform: translateY(-2px);
}

/* ─── BTN PRIMARY OVERRIDE ─── */
.page-conseil .btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 14px 36px;
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .04em;
    border-radius: 999px;
    color: #fff;
    text-decoration: none;
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 42%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-1)) 38%, #000) 100%);
    border: 1px solid rgba(var(--header-accent),.45);
    box-shadow:
        0 0 28px rgba(var(--header-accent),.22),
        0 8px 20px rgba(var(--header-accent),.14),
        inset 0 1px 0 rgba(255,255,255,.10);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
    transition: background .3s ease, box-shadow .3s ease, transform .3s ease;
}

.page-conseil .btn-primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%);
    border-radius: inherit;
    pointer-events: none;
}

.page-conseil .btn-primary::after {
    content: "→";
    font-size: .95rem;
    opacity: .7;
    transition: transform .3s ease, opacity .3s ease;
}

.page-conseil .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 58%, #000) 0%, color-mix(in srgb, rgb(var(--accent-harmony-1)) 52%, #000) 100%);
    box-shadow:
        0 0 44px rgba(var(--header-accent),.40),
        0 12px 28px rgba(var(--header-accent),.22),
        inset 0 1px 0 rgba(255,255,255,.16);
    transform: translateY(-3px);
}

.page-conseil .btn-primary:hover::after {
    transform: translateX(4px);
    opacity: 1;
}


/* ========================= conseil.php (Conseil Web) ========================= */

/* ─── BACKGROUND FIXE ─── */
.page-conseil::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-conseil > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-conseil .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}
.page-conseil .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── btn-primary override ───
   Ce bloc, plus bas dans la cascade que ".page-conseil .btn-primary" défini
   plus haut (même sélecteur, même spécificité), est celui qui s'applique
   réellement : le dégradé violet/indigo était codé en dur (ignorait le
   sélecteur de couleur) et ne mélangeait jamais vers le noir, ce qui aurait
   aussi rendu le texte illisible avec un accent clair. Remplacé par la même
   recette accent-aware + toujours sombre que les autres pages offres. */
.page-conseil .btn-primary {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 42%, #000), color-mix(in srgb, rgb(var(--header-accent)) 38%, #000));
    box-shadow: 0 4px 20px rgba(var(--header-accent),.35);
}
.page-conseil .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 58%, #000), color-mix(in srgb, rgb(var(--accent-harmony-3)) 52%, #000));
    box-shadow: 0 6px 28px rgba(var(--header-accent),.50);
}

/* ─── SHARED ─── */
.cw-section-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 24px;
}

.cw-section-header {
    text-align: center;
    margin-bottom: 48px;
}
.cw-section-header h2 {
    font-size: clamp(1.4rem, 2.5vw, 1.9rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.cw-section-header p {
    color: rgba(255,255,255,.50);
    font-size: .95rem;
    max-width: 540px;
    margin: 0 auto;
}

/* ─── HERO ─── */
.cw-hero {
    min-height: 55dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 140px 24px 60px;
    text-align: center;
}
.cw-hero-inner {
    max-width: 760px;
    margin-top: 48px;
}
/* Demande explicite : "renforcer la lisibilité des badges section 1" — fond
   translucide accent (.10 d'opacité) laissait trop passer l'image de
   planète derrière sur certaines pages. Fond sombre bien plus opaque +
   ombre portée pour rester lisible quel que soit le fond. */
.cw-page-label {
    display: inline-block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.95);
    border: 1px solid rgba(var(--header-accent),.55);
    background: rgba(10,14,24,.65);
    padding: 5px 14px;
    border-radius: 999px;
    margin-bottom: 20px;
    text-shadow: 0 1px 3px rgba(0,0,0,.5);
}
.cw-hero h1 {
    font-size: clamp(1.9rem, 4vw, 3rem);
    font-weight: 800;
    line-height: 1.2;
    margin: 0 0 16px;
    background: linear-gradient(120deg, #fff 50%, rgba(var(--header-accent),.85) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
/* Demande explicite : "le texte ... est très peu lisible" (accompagnement.php,
   conseil.php notamment) — opacité relevée + légère ombre portée pour rester
   lisible sur un fond de planète clair. */
.cw-hero-sub {
    color: rgba(255,255,255,.85);
    font-size: 1rem;
    line-height: 1.7;
    max-width: 560px;
    margin: 0 auto 24px;
    text-shadow: 0 1px 3px rgba(0,0,0,.75), 0 1px 10px rgba(0,0,0,.55);
}
.cw-impact-list {
    list-style: none;
    padding: 0;
    margin: 0 auto 20px;
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}
/* Demande explicite (suite) : ces badges restaient "trop clairs/pas assez
   visibles" malgré le renfort déjà posé sur .cw-hero-tagline juste en
   dessous (même souci, cf. commentaire plus bas) — le fond teinté accent à
   12% et le texte à 80% ne protégeaient pas assez sur un fond de planète
   clair (refonte.php notamment). Fond bien plus opaque (même recette que
   .heberg-hero-cta-line) + texte quasi blanc + ombre portée, tout en gardant
   la bordure teintée accent comme identifiant visuel. */
.cw-impact-list li {
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .04em;
    padding: 6px 16px;
    border-radius: 999px;
    background: rgba(10,14,24,.55);
    border: 1px solid rgba(var(--header-accent),.40);
    color: rgba(255,255,255,.92);
    text-shadow: 0 1px 3px rgba(0,0,0,.6);
}
/* Demande explicite : "le texte n'est pas assez lisible... ça se répète sur
   plusieurs pages (1ère section) qui ont pour bg une des planètes" — 48%
   d'opacité blanche sans aucune ombre portée se fondait dans les hero au
   fond de planète clair (refonte.php notamment). Opacité relevée + légère
   ombre portée pour rester lisible quel que soit le fond. */
.cw-hero-tagline {
    font-size: .92rem;
    color: rgba(255,255,255,.85);
    font-style: italic;
    margin: 0;
    text-shadow: 0 1px 3px rgba(0,0,0,.75), 0 1px 10px rgba(0,0,0,.55);
}
.cw-hero-cta {
    display: inline-block;
    margin-top: 28px;
}

/* ─── WHY ─── */
.cw-why {
    padding: 80px 0;
}
.cw-why-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
}
/* Variante 1 seule carte (pas de carte "bénéfices" à côté) : centrée,
   largeur de lecture confortable plutôt qu'étirée sur toute la grille. */
.cw-why-grid--single {
    grid-template-columns: 1fr;
    max-width: 640px;
    margin: 0 auto;
}
.cw-why-card {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 16px;
    padding: 32px;
}
.cw-why-card--errors {
    border-color: rgba(239,68,68,.15);
}
.cw-why-card h2 {
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
}
.cw-why-card p {
    color: rgba(255,255,255,.50);
    font-size: .88rem;
    line-height: 1.6;
    margin: 0 0 16px;
}
.cw-why-list {
    list-style: none;
    padding: 0;
    margin: 0 0 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.cw-why-list li {
    font-size: .85rem;
    color: rgba(255,255,255,.60);
    padding-left: 18px;
    position: relative;
    line-height: 1.5;
}
.cw-why-list li::before {
    content: "✕";
    position: absolute;
    left: 0;
    color: rgba(239,68,68,.75);
    font-size: .72rem;
    top: 3px;
}
.cw-why-tagline {
    font-size: .85rem;
    color: rgba(239,68,68,.70);
    font-weight: 600;
    margin: 0;
    font-style: italic;
}
.cw-why-card--benefits h3 {
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: rgba(255,255,255,.55);
    margin: 0 0 16px;
}
.cw-benefits-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.cw-benefits-list li {
    font-size: .88rem;
    color: rgba(255,255,255,.75);
    padding: 10px 14px 10px 42px;
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.14);
    border-radius: 8px;
    position: relative;
}
.cw-benefits-list li::before {
    content: "✓";
    position: absolute;
    left: 14px;
    color: rgba(var(--header-accent),.9);
    font-weight: 800;
}

/* ─── APPROCHE ─── */
.cw-approach {
    padding: 80px 0;
}
.cw-approach-inner {
    max-width: 640px;
    margin: 0 auto;
    text-align: center;
}
.cw-approach-inner h2 {
    font-size: clamp(1.3rem, 2.5vw, 1.8rem);
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.cw-approach-inner > p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    margin: 0 0 36px;
}
.cw-approach-steps {
    list-style: none;
    padding: 0;
    margin: 0 0 24px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    text-align: left;
}
.cw-approach-steps li {
    display: flex;
    align-items: center;
    gap: 16px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(var(--header-accent),.15);
    border-radius: 10px;
    padding: 16px 20px;
    font-size: .92rem;
    color: rgba(255,255,255,.80);
    transition: border-color .25s, background .25s;
}
.cw-approach-steps li:hover {
    border-color: rgba(var(--header-accent),.30);
    background: rgba(var(--header-accent),.07);
}
.cw-step-num {
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .10em;
    color: rgba(var(--header-accent),.9);
    background: rgba(var(--header-accent),.14);
    border: 1px solid rgba(var(--header-accent),.28);
    border-radius: 6px;
    padding: 4px 9px;
    flex-shrink: 0;
}
.cw-approach-tagline {
    font-size: .88rem;
    color: rgba(255,255,255,.40);
    font-style: italic;
    margin: 0;
}

/* ─── DOMAINS ─── */
.cw-domains {
    padding: 80px 0;
}
.cw-domains-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
}
.cw-domain {
    display: flex;
    gap: 14px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 14px;
    padding: 24px;
    transition: border-color .25s, box-shadow .25s;
}
.cw-domain:hover {
    border-color: rgba(var(--header-accent),.22);
    box-shadow: 0 6px 20px rgba(var(--header-accent),.08);
}
.cw-domain-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px 9px;
    border-radius: 7px;
    font-size: .64rem;
    font-weight: 800;
    letter-spacing: .06em;
    flex-shrink: 0;
    margin-top: 2px;
    background: rgba(var(--header-accent),.10);
    color: #a5b4fc;
    border: 1px solid rgba(var(--header-accent),.22);
}

.cw-domain--structure .cw-domain-icon { background: rgba(139,92,246,.10); color: #c4b5fd; border-color: rgba(139,92,246,.22); }
.cw-domain--ux        .cw-domain-icon { background: rgba(99,102,241,.10); color: #a5b4fc; border-color: rgba(99,102,241,.22); }
.cw-domain--content   .cw-domain-icon { background: rgba(251,191,36,.10); color: #fbbf24; border-color: rgba(251,191,36,.22); }
.cw-domain--perf      .cw-domain-icon { background: rgba(251,191,36,.10); color: #fbbf24; border-color: rgba(251,191,36,.22); }
.cw-domain--conv      .cw-domain-icon { background: rgba(34,197,94,.10);  color: #4ade80; border-color: rgba(34,197,94,.22); }
.cw-domain-body h3 {
    font-size: .85rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}
.cw-domain-body ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.cw-domain-body li {
    font-size: .80rem;
    color: rgba(255,255,255,.55);
    padding-left: 12px;
    position: relative;
    line-height: 1.5;
}
.cw-domain-body li::before {
    content: "▸";
    position: absolute;
    left: 0;
    color: rgba(var(--header-accent),.65);
    font-size: .68rem;
    top: 4px;
}

/* ─── WHEN ─── */
.cw-when {
    padding: 80px 0;
}
.cw-when-inner {
    max-width: 640px;
    margin: 0 auto;
    text-align: center;
}
.cw-when-inner h2 {
    font-size: clamp(1.3rem, 2.5vw, 1.8rem);
    font-weight: 700;
    margin: 0 0 28px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.cw-when-list {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.cw-when-list li {
    font-size: .90rem;
    color: rgba(255,255,255,.72);
    padding: 11px 16px 11px 46px;
    background: rgba(var(--header-accent),.06);
    border: 1px solid rgba(var(--header-accent),.12);
    border-radius: 8px;
    position: relative;
    text-align: left;
    transition: background .2s, border-color .2s;
}
.cw-when-list li:hover {
    background: rgba(var(--header-accent),.11);
    border-color: rgba(var(--header-accent),.22);
}
.cw-when-list li::before {
    content: "→";
    position: absolute;
    left: 16px;
    color: rgba(var(--header-accent),.75);
    font-weight: 700;
}
.cw-when-tagline {
    font-size: .90rem;
    color: rgba(var(--header-accent),.82);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}

/* ─── OFFER ─── */
.cw-offer {
    padding: 80px 0;
}
.cw-offer-card {
    display: grid;
    grid-template-columns: 280px 1fr;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(var(--header-accent),.30);
    border-radius: 20px;
    overflow: hidden;
    box-shadow: 0 0 40px rgba(var(--header-accent),.10);
}
.cw-offer-left {
    background: rgba(var(--header-accent),.10);
    border-right: 1px solid rgba(var(--header-accent),.20);
    padding: 36px 28px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.cw-offer-tier {
    display: inline-block;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.9);
    background: rgba(var(--header-accent),.15);
    border: 1px solid rgba(var(--header-accent),.32);
    padding: 4px 10px;
    border-radius: 999px;
    align-self: flex-start;
}
.cw-offer-left h3 {
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    margin: 0;
    line-height: 1.35;
}
.cw-offer-tagline {
    font-size: .82rem;
    color: rgba(255,255,255,.48);
    margin: 0;
    line-height: 1.55;
}
.cw-offer-price {
    display: flex;
    align-items: baseline;
    gap: 5px;
    margin: 8px 0;
}
/* Préfixe "Dès" placé AVANT le montant (cf. refonte.php) : sans lui, le mot
   "dès" finissait relégué dans le petit texte de fin de ligne
   (".cw-price-period"), loin du prix qu'il est censé qualifier — on lisait
   "1200 CHF dès, projet unique", pas franchement clair. */
.cw-price-prefix {
    font-size: 1.1rem;
    font-weight: 700;
    color: rgba(255,255,255,.55);
    align-self: baseline;
}
.cw-price-amount {
    font-size: 2rem;
    font-weight: 800;
    color: #fff;
    line-height: 1;
}
.cw-price-currency {
    font-size: .85rem;
    font-weight: 700;
    color: rgba(255,255,255,.45);
}
.cw-price-period {
    font-size: .78rem;
    color: rgba(255,255,255,.35);
}
.cw-offer-right {
    padding: 36px 32px;
    display: flex;
    flex-direction: column;
    gap: 26px;
}
.cw-offer-section {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.cw-offer-section-label {
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.72);
}
.cw-offer-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
}
.cw-offer-list li {
    font-size: .82rem;
    color: rgba(255,255,255,.78);
    padding: 5px 13px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.09);
    border-radius: 6px;
}
.cw-offer-list--ideal li {
    background: rgba(var(--header-accent),.08);
    border-color: rgba(var(--header-accent),.18);
    color: rgba(255,255,255,.65);
}

/* ─── BENEFITS ─── */
.cw-benefits {
    padding: 80px 0;
}
.cw-benefits-inner {
    max-width: 680px;
    margin: 0 auto;
    text-align: center;
}
.cw-benefits-inner h2 {
    font-size: clamp(1.3rem, 2.5vw, 1.8rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.cw-benefits-inner > p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    margin: 0 0 28px;
}
.cw-benefits-pills {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    display: flex;
    gap: 12px;
    justify-content: center;
    flex-wrap: wrap;
}
.cw-benefits-pills li {
    font-size: .88rem;
    color: rgba(255,255,255,.78);
    padding: 9px 20px;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.26);
    border-radius: 999px;
}
.cw-benefits-tagline {
    font-size: .90rem;
    color: rgba(var(--header-accent),.82);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}

/* ─── CONSEIL VS ACCOMPAGNEMENT ─── */
.cw-vs {
    padding: 80px 0;
}
.cw-vs-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    max-width: 900px;
    margin: 0 auto;
}
.cw-vs-card {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 16px;
    padding: 30px 32px;
}
.cw-vs-card h3 {
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: rgba(255,255,255,.55);
    margin: 0 0 16px;
}
.cw-vs-card ul {
    list-style: none;
    padding: 0;
    margin: 0 0 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.cw-vs-card li {
    font-size: .88rem;
    color: rgba(255,255,255,.72);
    padding: 6px 14px;
    background: rgba(255,255,255,.03);
    border-radius: 6px;
}
.cw-vs-card--conseil {
    border-color: rgba(var(--header-accent),.25);
}
.cw-vs-card--conseil li {
    background: rgba(var(--header-accent),.07);
    border: 1px solid rgba(var(--header-accent),.12);
}
.cw-vs-card p {
    font-size: .85rem;
    color: rgba(255,255,255,.42);
    margin: 0 0 12px;
}
.cw-vs-tagline {
    font-size: .85rem;
    color: rgba(var(--header-accent),.80) !important;
    font-weight: 600;
    font-style: italic;
}

/* ─── EXPERTISE ─── */
.cw-expertise {
    padding: 80px 0;
}
.cw-expertise-card {
    max-width: 600px;
    margin: 0 auto;
    text-align: center;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    border-radius: 20px;
    padding: 48px 36px;
}
.cw-expertise-card h2 {
    font-size: clamp(1.25rem, 2vw, 1.65rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.cw-expertise-card > p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    margin: 0 0 28px;
}
.cw-exp-list {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}
.cw-exp-list li {
    font-size: .88rem;
    color: rgba(255,255,255,.78);
    padding: 9px 20px;
    background: rgba(var(--header-accent),.09);
    border: 1px solid rgba(var(--header-accent),.22);
    border-radius: 8px;
}
.cw-exp-tagline {
    font-size: .88rem;
    color: rgba(var(--header-accent),.80);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}

/* ─── BONUS ─── */
.cw-bonus {
    padding: 80px 0;
}
.cw-bonus-card {
    max-width: 720px;
    margin: 0 auto;
    background: linear-gradient(135deg, rgba(var(--header-accent),.12), rgba(var(--accent-harmony-1),.09));
    border: 1px solid rgba(var(--header-accent),.30);
    border-radius: 20px;
    padding: 44px 40px;
    text-align: center;
}
.cw-bonus-badge {
    display: inline-block;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.9);
    background: rgba(var(--header-accent),.15);
    border: 1px solid rgba(var(--header-accent),.35);
    padding: 4px 12px;
    border-radius: 999px;
    margin-bottom: 16px;
}
.cw-bonus-card h2 {
    font-size: 1.25rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 24px;
}
.cw-bonus-list {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    display: flex;
    gap: 12px;
    justify-content: center;
    flex-wrap: wrap;
}
.cw-bonus-list li {
    font-size: .85rem;
    color: rgba(255,255,255,.78);
    padding: 8px 18px;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.26);
    border-radius: 999px;
}
.cw-bonus-tagline {
    font-size: .88rem;
    color: rgba(var(--header-accent),.85);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}

/* ─── HÉBERGEMENT / MAINTENANCE ─── */
.cw-hosting {
    padding: 80px 0;
}
.cw-hosting-card {
    max-width: 720px;
    margin: 0 auto;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    border-radius: 20px;
    padding: 44px 40px;
    text-align: center;
}
.cw-hosting-card h2 {
    font-size: 1.25rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
}
.cw-hosting-card > p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    margin: 0 0 24px;
}
.cw-hosting-list {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    display: flex;
    gap: 12px;
    justify-content: center;
    flex-wrap: wrap;
}
.cw-hosting-list li {
    font-size: .85rem;
    color: rgba(255,255,255,.78);
    padding: 8px 18px;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.26);
    border-radius: 999px;
}
.cw-hosting-tagline {
    font-size: .88rem;
    color: rgba(var(--header-accent),.85);
    font-weight: 600;
    font-style: italic;
    margin: 12px 0 0;
}
.cw-hosting-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 22px;
    font-size: .92rem;
    font-weight: 700;
    letter-spacing: .02em;
    color: #fff;
    text-decoration: none;
    padding: 12px 28px;
    border-radius: 999px;
    background: linear-gradient(135deg, rgba(var(--header-accent),.85) 0%, rgba(var(--accent-harmony-1),.75) 100%);
    border: 1px solid rgba(139,146,246,.55);
    box-shadow:
        0 0 24px rgba(var(--header-accent),.30),
        0 8px 20px rgba(var(--header-accent),.18),
        inset 0 1px 0 rgba(255,255,255,.12);
    transition: transform .2s ease, box-shadow .2s ease, background .2s ease;
}
.cw-hosting-link::after {
    content: "→";
    transition: transform .2s ease;
}
.cw-hosting-link:hover {
    transform: translateY(-2px);
    background: linear-gradient(135deg, rgba(129,140,248,.95) 0%, rgba(167,139,250,.85) 100%);
    box-shadow:
        0 0 32px rgba(var(--header-accent),.45),
        0 12px 28px rgba(var(--header-accent),.28),
        inset 0 1px 0 rgba(255,255,255,.16);
}
.cw-hosting-link:hover::after {
    transform: translateX(3px);
}

/* ─── CTA FINAL ───
   Redevenue la dernière section de la page (easter egg #autopilote retiré,
   cf. conseilaccompagnement.php) : porte donc à nouveau le padding-bottom
   réservé au footer flottant (var(--footer-clearance)). */
.cw-cta {
    padding: 80px 0 var(--footer-clearance);
    text-align: center;
}
.cw-cta-inner {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 24px;
}
.cw-cta h2 {
    font-size: clamp(1.45rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.cw-cta p {
    color: rgba(255,255,255,.52);
    font-size: .98rem;
    line-height: 1.75;
    margin: 0 auto 28px;
}
.cw-cta-buttons {
    display: flex;
    gap: 14px;
    justify-content: center;
    flex-wrap: wrap;
}
.cw-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 28px;
    border-radius: 999px;
    border: 1px solid rgba(var(--header-accent),.35);
    background: rgba(var(--header-accent),.08);
    color: rgba(255,255,255,.78);
    font-size: .90rem;
    font-weight: 600;
    text-decoration: none;
    transition: background .25s, border-color .25s, color .25s;
}
.cw-btn-secondary:hover {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.55);
    color: #fff;
}

/* ─── HUB DE SERVICES (conseilaccompagnement.php) ─── */
.hub-services {
    padding: 80px 0;
}
.hub-services-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
}
.hub-service-card {
    display: flex;
    gap: 16px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 16px;
    padding: 28px;
    transition: border-color .25s, box-shadow .25s, transform .25s;
}
.hub-service-card:hover {
    transform: translateY(-2px);
}
.hub-service-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 10px;
    font-size: .6rem;
    font-weight: 800;
    letter-spacing: .04em;
    flex-shrink: 0;
}
.hub-service-tag {
    display: block;
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    font-weight: 700;
    color: rgba(255,255,255,.4);
    margin-bottom: 4px;
}
.hub-service-body h3 {
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 8px;
}
.hub-service-body p {
    font-size: .85rem;
    color: rgba(255,255,255,.58);
    line-height: 1.6;
    margin: 0 0 12px;
}
.hub-service-body ul {
    list-style: none;
    padding: 0;
    margin: 0 0 14px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.hub-service-body li {
    font-size: .78rem;
    color: rgba(255,255,255,.55);
    padding-left: 13px;
    position: relative;
    line-height: 1.5;
}
.hub-service-body li::before {
    content: "▸";
    position: absolute;
    left: 0;
    font-size: .66rem;
    top: 3px;
}
.hub-service-link {
    font-size: .82rem;
    font-weight: 700;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.hub-service-link:hover {
    text-decoration: underline;
}

.hub-service-card--conseil .hub-service-icon,
.hub-service-card--accomp .hub-service-icon {
    background: rgba(139,92,246,.12); color: #c4b5fd; border: 1px solid rgba(139,92,246,.25);
}
.hub-service-card--conseil .hub-service-link,
.hub-service-card--accomp .hub-service-link { color: #c4b5fd; }
.hub-service-card--conseil .hub-service-body li::before,
.hub-service-card--accomp .hub-service-body li::before { color: rgba(139,92,246,.7); }

/* Demande explicite : "le badge WEB ne doit pas hériter de la couleur active,
   toujours bleu" — comme les autres cartes du hub (violet/ambre/émeraude
   fixes), la carte "Création de site" garde son identité bleue fixe. */
.hub-service-card--creation .hub-service-icon {
    background: rgba(59,130,246,.12); color: #7db2ff; border: 1px solid rgba(59,130,246,.25);
}
.hub-service-card--creation .hub-service-link { color: #7db2ff; }
.hub-service-card--creation .hub-service-body li::before { color: rgba(59,130,246,.7); }

.hub-service-card--audit .hub-service-icon,
.hub-service-card--refonte .hub-service-icon {
    background: rgba(245,158,11,.12); color: #fbbf24; border: 1px solid rgba(245,158,11,.25);
}
.hub-service-card--audit .hub-service-link,
.hub-service-card--refonte .hub-service-link { color: #fbbf24; }
.hub-service-card--audit .hub-service-body li::before,
.hub-service-card--refonte .hub-service-body li::before { color: rgba(245,158,11,.7); }

.hub-service-card--prog .hub-service-icon {
    background: rgba(16,185,129,.12); color: #34d399; border: 1px solid rgba(16,185,129,.25);
}
.hub-service-card--prog .hub-service-link { color: #34d399; }
.hub-service-card--prog .hub-service-body li::before { color: rgba(16,185,129,.7); }


/* ─── HMG-NAV COULEUR INDIGO pour pages accompagnement ─── */
.page-accomp .hmg-nav-link {
    border-color: rgba(var(--header-accent),.38);
    background: rgba(var(--header-accent),.09);
    box-shadow: 0 0 14px rgba(var(--header-accent),.10);
}

.page-accomp .hmg-nav-link:hover {
    border-color: rgba(var(--header-accent),.68);
    background: rgba(var(--header-accent),.16);
    box-shadow: 0 0 20px rgba(var(--header-accent),.20);
}

.page-accomp .hmg-track-dot--active {
    background: rgb(var(--header-accent));
    border-color: rgba(var(--header-accent),.80);
    box-shadow: 0 0 10px rgba(var(--header-accent),.68);
}


/* ========================= accompagnement.php ========================= */

/* ─── BACKGROUND FIXE ─── */
.page-accomp::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

/* Lune (accompagnement.php) sur son propre calque ::after, masquée en fondu
   radial + rétrécie/effacée au scroll — même mécanisme que
   .page-vitrine::after/.page-refonte::after (cf. main.js, bloc "DÉCOR DE
   FOND") — demande explicite : étendre l'effet à toutes les pages offres. */
.page-accomp::after {
    content: "";
    position: fixed;
    inset: 0;
    background: url("../image/lune.png") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}
.page-accomp.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}

.page-accomp > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-accomp .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}
.page-accomp .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── btn-primary override ───
   Dégradé toujours mélangé vers le noir (jamais la couleur d'accent pure) —
   demande explicite : "les boutons (couleur blanc) ne sont pas assez
   lisibles", le texte du bouton restant blanc quel que soit l'accent. */
.page-accomp .btn-primary {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 42%, #000), color-mix(in srgb, rgb(var(--header-accent)) 38%, #000));
    box-shadow: 0 4px 20px rgba(var(--header-accent),.35);
}
.page-accomp .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 58%, #000), color-mix(in srgb, rgb(var(--accent-harmony-3)) 52%, #000));
    box-shadow: 0 6px 28px rgba(var(--header-accent),.50);
}

/* ─── SHARED ─── */
.acmp-section-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 24px;
}

.acmp-section-header {
    text-align: center;
    margin-bottom: 48px;
}
.acmp-section-header h2 {
    font-size: clamp(1.4rem, 2.5vw, 1.9rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.acmp-section-header p {
    color: rgba(255,255,255,.50);
    font-size: .95rem;
    max-width: 540px;
    margin: 0 auto;
}

/* ─── HERO ─── */
.acmp-hero {
    min-height: 55dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 140px 24px 60px;
    text-align: center;
}
.acmp-hero-inner {
    max-width: 780px;
    margin-top: 48px;
}
.acmp-page-label {
    display: inline-block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.9);
    border: 1px solid rgba(var(--header-accent),.35);
    background: rgba(var(--header-accent),.10);
    padding: 5px 14px;
    border-radius: 999px;
    margin-bottom: 20px;
}
.acmp-hero h1 {
    font-size: clamp(1.9rem, 4vw, 3rem);
    font-weight: 800;
    line-height: 1.2;
    margin: 0 0 16px;
    background: linear-gradient(120deg, #fff 50%, rgba(var(--header-accent),.85) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.acmp-hero-sub {
    color: rgba(255,255,255,.58);
    font-size: 1rem;
    line-height: 1.7;
    max-width: 600px;
    margin: 0 auto 24px;
}
.acmp-impact-list {
    list-style: none;
    padding: 0;
    margin: 0 auto 20px;
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
}
.acmp-impact-list li {
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .04em;
    padding: 6px 16px;
    border-radius: 999px;
    background: rgba(var(--header-accent),.12);
    border: 1px solid rgba(var(--header-accent),.30);
    color: rgba(255,255,255,.80);
}
.acmp-hero-tagline {
    font-size: .92rem;
    color: rgba(255,255,255,.48);
    font-style: italic;
    margin: 0;
}

/* ─── WHY ─── */
.acmp-why {
    padding: 80px 0;
}
.acmp-why-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
}
.acmp-why-card {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 16px;
    padding: 32px;
}
.acmp-why-card--problems {
    border-color: rgba(239,68,68,.15);
}
.acmp-why-card h2 {
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
}
.acmp-why-card p {
    color: rgba(255,255,255,.50);
    font-size: .88rem;
    line-height: 1.6;
    margin: 0 0 16px;
}
.acmp-why-list {
    list-style: none;
    padding: 0;
    margin: 0 0 14px;
    display: flex;
    flex-direction: column;
    gap: 7px;
}
.acmp-why-list li {
    font-size: .85rem;
    color: rgba(255,255,255,.58);
    padding-left: 18px;
    position: relative;
    line-height: 1.5;
}
.acmp-why-list li::before {
    content: "✕";
    position: absolute;
    left: 0;
    color: rgba(239,68,68,.72);
    font-size: .72rem;
    top: 3px;
}
.acmp-why-result {
    font-size: .85rem;
    color: rgba(239,68,68,.65);
    font-style: italic;
    font-weight: 600;
    margin: 0;
}
.acmp-why-card--benefits h3 {
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: rgba(255,255,255,.52);
    margin: 0 0 16px;
}
.acmp-benefits-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.acmp-benefits-list li {
    font-size: .88rem;
    color: rgba(255,255,255,.78);
    padding: 10px 14px 10px 42px;
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.14);
    border-radius: 8px;
    position: relative;
}
.acmp-benefits-list li::before {
    content: "✓";
    position: absolute;
    left: 14px;
    color: rgba(var(--header-accent),.9);
    font-weight: 800;
}

/* ─── APPROCHE ─── */
.acmp-approach {
    padding: 80px 0;
}
.acmp-approach-inner {
    max-width: 860px;
    margin: 0 auto;
    text-align: center;
}
.acmp-approach-inner h2 {
    font-size: clamp(1.3rem, 2.5vw, 1.8rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.acmp-approach-inner > p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    margin: 0 0 36px;
}
.acmp-cycle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 24px;
}
.acmp-cycle-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.22);
    border-radius: 12px;
    padding: 16px 20px;
    min-width: 130px;
    transition: background .25s, border-color .25s;
}
.acmp-cycle-step:hover {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.38);
}
.acmp-cycle-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px 8px;
    border-radius: 7px;
    font-size: .62rem;
    font-weight: 800;
    letter-spacing: .06em;
    background: rgba(var(--header-accent),.10);
    color: #a5b4fc;
    border: 1px solid rgba(var(--header-accent),.22);
}

.acmp-cycle-icon--aud  { background: rgba(139,92,246,.10); color: #c4b5fd; border-color: rgba(139,92,246,.22); }
.acmp-cycle-icon--opt  { background: rgba(var(--header-accent),.10); color: #7aa2ff; border-color: rgba(var(--header-accent),.22); }
.acmp-cycle-icon--perf { background: rgba(251,191,36,.10); color: #fbbf24; border-color: rgba(251,191,36,.22); }
.acmp-cycle-icon--conv { background: rgba(34,197,94,.10);  color: #4ade80; border-color: rgba(34,197,94,.22); }
.acmp-cycle-step span:last-child {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: rgba(255,255,255,.72);
}
.acmp-cycle-arrow {
    font-size: 1.2rem;
    color: rgba(var(--header-accent),.55);
    font-weight: 700;
}
.acmp-approach-tagline {
    font-size: .88rem;
    color: rgba(255,255,255,.40);
    font-style: italic;
    margin: 0;
}

/* ─── INCLUDES ─── */
.acmp-includes {
    padding: 80px 0;
}
.acmp-includes-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
}
.acmp-inc-card {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 14px;
    padding: 26px 24px;
    transition: border-color .25s, box-shadow .25s;
}
.acmp-inc-card:hover {
    border-color: rgba(var(--header-accent),.22);
    box-shadow: 0 6px 20px rgba(var(--header-accent),.08);
}
.acmp-inc-icon {
    font-size: 2rem;
    font-weight: 800;
    margin-bottom: 12px;
    line-height: 1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: rgba(var(--header-accent),.45);
    display: block;
}
.acmp-inc-card h3 {
    font-size: .85rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255,255,255,.07);
}
.acmp-inc-card ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.acmp-inc-card li {
    font-size: .80rem;
    color: rgba(255,255,255,.55);
    padding-left: 12px;
    position: relative;
    line-height: 1.5;
}
.acmp-inc-card li::before {
    content: "▸";
    position: absolute;
    left: 0;
    color: rgba(var(--header-accent),.65);
    font-size: .68rem;
    top: 4px;
}

/* ─── PROGRESSION ─── */
.acmp-progress {
    padding: 80px 0;
}
.acmp-progress-inner {
    max-width: 680px;
    margin: 0 auto;
    text-align: center;
}
.acmp-progress-inner h2 {
    font-size: clamp(1.3rem, 2.5vw, 1.8rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.acmp-progress-inner > p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    margin: 0 0 28px;
}
.acmp-progress-pills {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: 12px;
    justify-content: center;
    flex-wrap: wrap;
}
.acmp-progress-pills li {
    font-size: .88rem;
    color: rgba(255,255,255,.78);
    padding: 9px 20px;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.26);
    border-radius: 999px;
}

/* ─── OFFERS ─── */
.acmp-offers {
    padding: 80px 0;
}
.acmp-offers-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    align-items: stretch;
}
.acmp-plan {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.09);
    border-radius: 18px;
    padding: 32px 28px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    position: relative;
    transition: border-color .25s, box-shadow .25s;
}
.acmp-plan:hover {
    border-color: rgba(var(--header-accent),.22);
    box-shadow: 0 8px 28px rgba(var(--header-accent),.08);
}
.acmp-plan--pro {
    border-color: rgba(var(--header-accent),.35);
    background: rgba(var(--header-accent),.08);
    box-shadow: 0 0 40px rgba(var(--header-accent),.12);
}
.acmp-plan-ribbon {
    position: absolute;
    top: -1px;
    right: 24px;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    background: linear-gradient(135deg, #6366f1, #818cf8);
    color: #fff;
    padding: 5px 14px;
    border-radius: 0 0 8px 8px;
}
.acmp-plan-top {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.acmp-plan-tier {
    display: inline-block;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.9);
    background: rgba(var(--header-accent),.14);
    border: 1px solid rgba(var(--header-accent),.28);
    padding: 3px 10px;
    border-radius: 999px;
    align-self: flex-start;
}
.acmp-plan-top h3 {
    font-size: 1rem;
    font-weight: 700;
    color: #fff;
    margin: 0;
    line-height: 1.3;
}
.acmp-plan-price {
    display: flex;
    align-items: baseline;
    gap: 5px;
}
.acmp-price-amount {
    font-size: 1.75rem;
    font-weight: 800;
    color: #fff;
    line-height: 1;
}
.acmp-price-currency {
    font-size: .82rem;
    font-weight: 700;
    color: rgba(255,255,255,.42);
}
/* Prix "Sur devis" (Premium) : texte plus long qu'un montant chiffré, taille réduite pour rester lisible dans la pastille. */
.acmp-plan-price--quote .acmp-price-amount { font-size: 1.05rem; }

.acmp-price-period {
    font-size: .75rem;
    color: rgba(255,255,255,.32);
}
.acmp-plan-tagline {
    font-size: .80rem;
    color: rgba(255,255,255,.45);
    margin: 0;
    line-height: 1.5;
}
.acmp-plan-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
    flex: 1;
}
.acmp-plan-list li {
    font-size: .82rem;
    color: rgba(255,255,255,.68);
    padding: 6px 10px 6px 28px;
    position: relative;
    line-height: 1.5;
}
.acmp-plan-list li::before {
    content: "✓";
    position: absolute;
    left: 8px;
    color: rgba(var(--header-accent),.80);
    font-weight: 700;
    font-size: .80rem;
}
.acmp-plan--pro .acmp-plan-list li::before {
    color: rgba(129,140,248,.90);
}
.acmp-plan-note {
    margin: 0;
}
.acmp-plan-note-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .78rem;
    font-weight: 700;
    color: rgba(129,140,248,.95);
    text-decoration: none;
    line-height: 1.4;
}
.acmp-plan-note-link:hover {
    text-decoration: underline;
}
.acmp-plan-ideal {
    font-size: .82rem;
    color: rgba(var(--header-accent),.78);
    font-style: italic;
    font-weight: 600;
    margin: 0;
    padding-top: 4px;
    border-top: 1px solid rgba(255,255,255,.06);
}
.acmp-plan-cta {
    display: block;
    text-align: center;
    padding: 11px 20px;
    border-radius: 999px;
    border: 1px solid rgba(var(--header-accent),.35);
    background: rgba(var(--header-accent),.10);
    color: rgba(255,255,255,.85);
    font-size: .85rem;
    font-weight: 600;
    text-decoration: none;
    margin-top: auto;
    transition: background .25s, border-color .25s, color .25s;
}
.acmp-plan-cta:hover {
    background: rgba(var(--header-accent),.22);
    border-color: rgba(var(--header-accent),.55);
    color: #fff;
}
/* Demande explicite : le bouton "Commencer" de l'offre "Accompagnement
   stratégique continu" doit être stylisé à la couleur de la page active,
   pas un indigo fixe. Recette dark color-mix déjà utilisée ailleurs pour
   rester lisible avec le texte blanc quel que soit l'accent (y compris
   "Blanc"/cyan, quasi-blanc). */
.acmp-plan--pro .acmp-plan-cta {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 55%, #000) 0%, color-mix(in srgb, rgb(var(--header-accent)) 75%, #000) 100%);
    border-color: transparent;
    color: #fff;
    box-shadow: 0 4px 16px rgba(var(--header-accent),.30);
}
.acmp-plan--pro .acmp-plan-cta:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--header-accent)) 70%, #000) 0%, color-mix(in srgb, rgb(var(--header-accent)) 88%, #000) 100%);
    box-shadow: 0 6px 22px rgba(var(--header-accent),.45);
}

/* ─── PHILOSOPHY ─── */
.acmp-philosophy {
    padding: 80px 0;
}
.acmp-philosophy-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
}
.acmp-philo-card {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 16px;
    padding: 32px;
}
.acmp-philo-card h2 {
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.acmp-philo-card p {
    color: rgba(255,255,255,.48);
    font-size: .88rem;
    line-height: 1.6;
    margin: 0 0 16px;
}
.acmp-partner-list {
    list-style: none;
    padding: 0;
    margin: 0 0 14px;
    display: flex;
    flex-direction: column;
    gap: 9px;
}
.acmp-partner-list li {
    font-size: .88rem;
    color: rgba(255,255,255,.72);
    padding: 8px 12px 8px 32px;
    background: rgba(var(--header-accent),.07);
    border-radius: 7px;
    position: relative;
}
.acmp-partner-list li::before {
    content: "→";
    position: absolute;
    left: 10px;
    color: rgba(var(--header-accent),.72);
    font-weight: 700;
}
.acmp-philo-tagline {
    font-size: .85rem;
    color: rgba(var(--header-accent),.80);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}
.acmp-vs-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
    margin-bottom: 14px;
}
.acmp-vs-col {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.acmp-vs-label {
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .10em;
    text-transform: uppercase;
    color: rgba(255,255,255,.45);
    margin-bottom: 4px;
}
.acmp-vs-col ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.acmp-vs-col li {
    font-size: .82rem;
    color: rgba(255,255,255,.60);
    padding: 5px 10px;
    background: rgba(255,255,255,.03);
    border-radius: 5px;
}
.acmp-vs-col--active li {
    color: rgba(255,255,255,.80);
    background: rgba(var(--header-accent),.09);
    border: 1px solid rgba(var(--header-accent),.16);
}
.acmp-vs-tagline {
    font-size: .85rem;
    color: rgba(var(--header-accent),.78);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}

/* ─── GROWTH ─── */
.acmp-growth {
    padding: 80px 0;
}
.acmp-growth-card {
    max-width: 680px;
    margin: 0 auto;
    text-align: center;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    border-radius: 20px;
    padding: 48px 36px;
}
.acmp-growth-card h2 {
    font-size: clamp(1.25rem, 2vw, 1.65rem);
    font-weight: 700;
    margin: 0 0 10px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.9) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.acmp-growth-card > p {
    color: rgba(255,255,255,.48);
    font-size: .92rem;
    margin: 0 0 26px;
}
.acmp-growth-list {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    text-align: left;
}
.acmp-growth-list li {
    font-size: .88rem;
    color: rgba(255,255,255,.72);
    padding: 9px 14px 9px 38px;
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.14);
    border-radius: 7px;
    position: relative;
}
.acmp-growth-list li::before {
    content: "↗";
    position: absolute;
    left: 12px;
    color: rgba(var(--header-accent),.80);
    font-weight: 700;
}
.acmp-growth-tagline {
    font-size: .90rem;
    color: rgba(var(--header-accent),.82);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}

/* ─── BONUS ─── */
.acmp-bonus {
    padding: 80px 0;
}
.acmp-bonus-card {
    max-width: 720px;
    margin: 0 auto;
    background: linear-gradient(135deg, rgba(var(--header-accent),.12), rgba(129,140,248,.09));
    border: 1px solid rgba(var(--header-accent),.30);
    border-radius: 20px;
    padding: 44px 40px;
    text-align: center;
}
.acmp-bonus-badge {
    display: inline-block;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: rgba(var(--header-accent),.9);
    background: rgba(var(--header-accent),.15);
    border: 1px solid rgba(var(--header-accent),.35);
    padding: 4px 12px;
    border-radius: 999px;
    margin-bottom: 16px;
}
.acmp-bonus-card h2 {
    font-size: 1.25rem;
    font-weight: 700;
    color: #fff;
    margin: 0 0 24px;
}
.acmp-bonus-list {
    list-style: none;
    padding: 0;
    margin: 0 0 20px;
    display: flex;
    gap: 12px;
    justify-content: center;
    flex-wrap: wrap;
}
.acmp-bonus-list li {
    font-size: .85rem;
    color: rgba(255,255,255,.78);
    padding: 8px 18px;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.26);
    border-radius: 999px;
}
.acmp-bonus-tagline {
    font-size: .88rem;
    color: rgba(var(--header-accent),.85);
    font-weight: 600;
    font-style: italic;
    margin: 0;
}

/* ─── CTA FINAL ─── */
.acmp-cta {
    padding: 80px 0 var(--footer-clearance);
    text-align: center;
}
.acmp-cta-inner {
    max-width: 680px;
    margin: 0 auto;
    padding: 0 24px;
}
.acmp-cta h2 {
    font-size: clamp(1.45rem, 2.5vw, 2rem);
    font-weight: 700;
    margin: 0 0 14px;
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.acmp-cta p {
    color: rgba(255,255,255,.52);
    font-size: .98rem;
    line-height: 1.75;
    margin: 0 auto 28px;
}
.acmp-cta-buttons {
    display: flex;
    gap: 14px;
    justify-content: center;
    flex-wrap: wrap;
}
.acmp-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 28px;
    border-radius: 999px;
    border: 1px solid rgba(var(--header-accent),.35);
    background: rgba(var(--header-accent),.08);
    color: rgba(255,255,255,.78);
    font-size: .90rem;
    font-weight: 600;
    text-decoration: none;
    transition: background .25s, border-color .25s, color .25s;
}
.acmp-btn-secondary:hover {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.55);
    color: #fff;
}




/* ========================= presentation.php ========================= */

/* ─── BACKGROUND (identique à about.php / partenaires.php) ─── */
.page-presentation::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-presentation > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-presentation .section-block {
    opacity: 0;
    transform: translateY(44px);
    transition:
        opacity 0.85s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.95s cubic-bezier(0.16, 1, 0.3, 1);
}

.page-presentation .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.about-hero.presentation-hero {
    padding-bottom: 40px;
}

/* ─── GRILLE DES ACCÈS PRÉSENTATION (réutilise les capsules de services.php) ─── */
.presentation-grid {
    max-width: 1180px;
    margin: 0 auto;
}

.presentation-grid .service-capsule {
    max-width: 360px;
}

/* ─── Vignette "Livre d'or" : effet brillant dans sa propre couleur ───
   var(--capsule-color)/--capsule-soft sont déjà définis par la variante
   .service-capsule--refonte (ambre) portée par cette carte — l'effet
   suit donc automatiquement sa couleur. Implémenté via un élément dédié
   (.capsule-shine, ajouté uniquement sur cette carte) plutôt qu'en
   détournant .service-capsule::before/::after (déjà utilisés pour la
   grille pointillée et le liseré bas), et scopé par
   .presentation-card-shine (pas par --refonte) pour ne pas affecter la
   vignette "Refonte de site" de services.php, qui partage la même classe
   de variante de couleur. */
.presentation-card-shine .capsule-shine {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    overflow: hidden;
    border-radius: inherit;
}

.presentation-card-shine .capsule-shine::before {
    content: "";
    position: absolute;
    inset: -40% -10%;
    background: linear-gradient(115deg,
        transparent 38%,
        color-mix(in srgb, var(--capsule-color) 38%, transparent) 48%,
        color-mix(in srgb, var(--capsule-color) 16%, transparent) 53%,
        transparent 62%);
    transform: translateX(-60%);
    mix-blend-mode: screen;
    animation: presentationCardSheen 3.8s ease-in-out infinite;
}

@keyframes presentationCardSheen {
    0%, 15%   { transform: translateX(-60%); }
    65%, 100% { transform: translateX(60%); }
}

@media (prefers-reduced-motion: reduce) {
    .presentation-card-shine .capsule-shine::before { animation: none; }
}


/* ========================= about.php ========================= */

/* ─── BACKGROUND ─── */
.page-about::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-about > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-about .section-block {
    opacity: 0;
    transform: translateY(44px);
    transition:
        opacity 0.85s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.95s cubic-bezier(0.16, 1, 0.3, 1);
}

.page-about .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── HERO ─── */
/* padding-top porté à 200px (au lieu de 140px) pour laisser la place à la
   navigation inter-pages Présentation (positionnée en absolute au-dessus
   du contenu, comme pour les chaînes hm/heberg/maint et conseil). */
.about-hero {
    padding: 200px 20px 80px;
}

.about-hero .container {
    max-width: 1100px;
    margin: 0 auto;
}

.about-hero-layout {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 60px;
}

.about-hero-content {
    flex: 1 1 0;
    min-width: 0;
}

.about-hero-content h1 {
    font-size: clamp(2.2rem, 4vw, 3.2rem);
    font-weight: 800;
    line-height: 1.15;
    margin-bottom: 22px;
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent),.90) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.about-subtitle {
    color: rgba(255,255,255,.65);
    line-height: 1.88;
    font-size: 1.05rem;
    max-width: 560px;
}

/* ─── PHOTO ───
   Discrète mais pas minuscule : un portrait rond façon "byline", assez
   présent pour se voir clairement à côté du texte sans redevenir le point
   focal de la page (fini la carte rectangulaire avec halo lumineux). */
.about-hero-image {
    flex: 0 0 180px;
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
}

.about-hero-image img {
    position: relative;
    z-index: 1;
    width: 160px;
    height: 160px;
    object-fit: cover;
    border-radius: 50%;
    display: block;
    filter: grayscale(25%);
    border: 2px solid rgba(255,255,255,.12);
    box-shadow: 0 12px 30px rgba(0,0,0,.35);
}

/* Badge discret sous l'avatar (remplace le texte gris plat d'origine) */
.about-image-caption {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: 14px;
    padding: 7px 16px;
    border-radius: 999px;
    background: rgba(255,255,255,.035);
    border: 1px solid rgba(255,255,255,.08);
    font-size: .72rem;
    color: rgba(255,255,255,.55);
    text-align: center;
    letter-spacing: .02em;
    white-space: nowrap;
}

.about-image-caption-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    flex-shrink: 0;
    background: rgba(16,185,129,.85);
    box-shadow: 0 0 8px rgba(16,185,129,.55);
}

/* ─── RÉSEAUX (dans .about-hero-content, sous le sous-titre) ───
   Réutilise les classes .contact-social-heading / .contact-social-links /
   .contact-social-link de contact.php (déjà génériques, non scopées à une
   page en particulier). */
.about-social-heading {
    margin-top: 26px;
}

/* ─── SECTIONS ─── */
.about-section {
    padding: 80px 20px;
}

.about-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 28px;
    max-width: 1100px;
    margin: 0 auto;
}

/* ─── CARDS ─── */
.about-card,
.about-single {
    padding: 34px 38px;
    border-radius: 18px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    position: relative;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease;
}

.about-card::before,
.about-single::before {
    content: "";
    position: absolute;
    top: 0;
    left: 10%;
    right: 10%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.50), transparent);
}

.about-card:hover,
.about-single:hover {
    border-color: rgba(var(--header-accent),.16);
    box-shadow: 0 22px 55px rgba(0,0,0,.22), 0 0 30px rgba(var(--header-accent),.05);
}

.about-card h2,
.about-single h2 {
    font-size: 1.55rem;
    font-weight: 700;
    margin-bottom: 18px;
    line-height: 1.3;
    background: linear-gradient(100deg, #ffffff 40%, rgba(148,163,184,.80) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.about-single {
    max-width: 900px;
    margin: 0 auto;
}

/* ─── LISIBILITÉ "Ma vision du web" ───
   6 paragraphes denses sans règle dédiée héritaient juste des styles par
   défaut du navigateur (line-height ~1.2, taille 16px) : trop compact sur
   fond sombre. On leur donne un traitement proche de celui déjà utilisé
   ailleurs sur about.php (.about-partners-text, .about-list li). */
#vision .about-card p {
    font-size: .95rem;
    line-height: 1.8;
    color: rgba(255,255,255,.68);
    margin-bottom: 16px;
}

#vision .about-card p:last-child {
    margin-bottom: 0;
}

/* ─── COMPARATIF "solution générique" vs "mon approche" ───
   Remplace la simple liste à puces de la différenciation par un parallèle
   visuel entre une approche générique (neutre, jamais nommée) et mon
   approche personnalisée — sans jamais critiquer un concurrent précis. */
.about-compare {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.about-compare-row {
    display: grid;
    grid-template-columns: minmax(0, 100px) minmax(0, 1fr) minmax(0, 1fr);
    gap: 10px;
    align-items: stretch;
    padding: 10px 0;
    border-bottom: 1px solid rgba(255,255,255,.055);
}

.about-compare-row:last-child {
    border-bottom: none;
}

.about-compare-row--header {
    padding-bottom: 8px;
    border-bottom: 1px solid rgba(255,255,255,.10);
}

.about-compare-label {
    min-width: 0;
    font-size: .70rem;
    font-weight: 700;
    color: rgba(255,255,255,.42);
    text-transform: uppercase;
    letter-spacing: .04em;
    display: flex;
    align-items: center;
    line-height: 1.3;
    overflow-wrap: break-word;
    word-break: break-word;
    hyphens: auto;
}

.about-compare-col {
    min-width: 0;
    font-size: .84rem;
    line-height: 1.55;
    padding: 8px 12px;
    border-radius: 10px;
    overflow-wrap: break-word;
    word-break: break-word;
}

.about-compare-row--header .about-compare-col {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    padding: 4px 12px;
    background: none;
    border: none;
}

.about-compare-col--generic {
    color: rgba(255,255,255,.42);
    background: rgba(255,255,255,.02);
    border: 1px solid rgba(255,255,255,.05);
}

.about-compare-row--header .about-compare-col--generic {
    color: rgba(255,255,255,.38);
}

.about-compare-col--custom {
    color: rgba(255,255,255,.85);
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.18);
}

.about-compare-row--header .about-compare-col--custom {
    color: rgba(120,170,255,.95);
}

.about-partners-teaser {
    text-align: center;
}

.about-partners-teaser .about-partners-text {
    color: rgba(255,255,255,.65);
    line-height: 1.8;
    max-width: 620px;
    margin: 0 auto 24px;
}

/* ─── LISTES ─── */
.about-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 10px;
}

.about-list li {
    padding: 14px 18px 14px 46px;
    border-radius: 12px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.055);
    color: rgba(255,255,255,.70);
    line-height: 1.68;
    position: relative;
    transition: background .25s ease, border-color .25s ease, color .25s ease;
}

.about-list li::before {
    content: "▸";
    position: absolute;
    left: 18px;
    top: 15px;
    color: rgba(var(--header-accent),.75);
    font-size: .82rem;
    line-height: 1;
}

.about-list li:hover {
    background: rgba(var(--header-accent),.06);
    border-color: rgba(var(--header-accent),.16);
    color: rgba(255,255,255,.88);
}

/* Liste numérotée (méthode) */
.about-list--numbered {
    counter-reset: method-counter;
}

.about-list--numbered li {
    counter-increment: method-counter;
}

.about-list--numbered li::before {
    content: counter(method-counter, decimal-leading-zero);
    font-size: .70rem;
    font-weight: 700;
    letter-spacing: .04em;
    top: 50%;
    transform: translateY(-50%);
    color: rgba(var(--header-accent),.65);
}

/* ─── Lien vers la section "méthode" de accueil.php (#method) ─── */
.about-method-link {
    margin-top: 24px;
    display: flex;
    justify-content: center;
}

/* ─── CTA "devis sur mesure" en bas de la section #forwho ─── */
.about-forwho-cta {
    margin-top: 28px;
    padding-top: 28px;
    border-top: 1px solid rgba(255,255,255,.08);
    text-align: center;
}

.about-forwho-cta h3 {
    font-size: 1.15rem;
    font-weight: 700;
    color: #fff;
    margin-bottom: 8px;
}

.about-forwho-cta p {
    color: rgba(255,255,255,.62);
    line-height: 1.7;
    max-width: 520px;
    margin: 0 auto 20px;
}

/* ─── PHILOSOPHIE ─── */
.about-philosophy {
    padding: 80px 20px;
    text-align: center;
}

.about-philosophy .container {
    max-width: 980px;
    margin: 0 auto;
}

.about-philosophy h2 {
    font-size: 1.8rem;
    font-weight: 700;
    margin-bottom: 0;
    background: linear-gradient(100deg, #ffffff 40%, rgba(148,163,184,.80) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.philosophy-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 18px;
    margin: 30px auto 0;
}

.philosophy-item {
    padding: 26px 22px;
    border-radius: 16px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    border-top-width: 2px;
    color: rgba(255,255,255,.68);
    line-height: 1.75;
    font-size: .96rem;
    transition: transform .3s ease, box-shadow .3s ease, color .25s ease;
}

.philosophy-item:hover {
    transform: translateY(-3px);
    color: rgba(255,255,255,.88);
}

.philosophy-item:nth-child(1) { border-top-color: rgba(var(--header-accent),.65); }
.philosophy-item:nth-child(2) { border-top-color: rgba(59,130,246,.65); }
.philosophy-item:nth-child(3) { border-top-color: rgba(139,92,246,.65); }
.philosophy-item:nth-child(4) { border-top-color: rgba(16,185,129,.65); }

.philosophy-item:nth-child(1):hover { box-shadow: 0 14px 38px rgba(var(--header-accent),.10); }
.philosophy-item:nth-child(2):hover { box-shadow: 0 14px 38px rgba(59,130,246,.10); }
.philosophy-item:nth-child(3):hover { box-shadow: 0 14px 38px rgba(139,92,246,.10); }
.philosophy-item:nth-child(4):hover { box-shadow: 0 14px 38px rgba(16,185,129,.10); }

/* ─── MINI FAQ DE RÉASSURANCE (n'est plus la dernière section de
       presentation.php depuis l'ajout du CTA "projets à suivre" juste
       après : c'est ce nouveau bloc qui réserve désormais l'espace du
       footer flottant, cf. #presentation-projets-cta plus bas). ─── */
.presentation-faq {
    padding: 20px 20px 80px;
}

.presentation-faq .container {
    max-width: 760px;
    margin: 0 auto;
}

/* ─── CTA ─── */
.about-cta {
    padding: 100px 20px var(--footer-clearance);
    text-align: center;
}

/* Sur presentation.php, le CTA précède désormais la mini FAQ : il n'est
   plus la dernière section, donc plus besoin d'y réserver l'espace du
   footer flottant (repris par #presentation-projets-cta, la nouvelle
   dernière section de la page). */
#presentation-cta {
    padding-bottom: 80px;
}

.about-cta .container {
    max-width: 680px;
    margin: 0 auto;
}

.about-cta h2 {
    font-size: clamp(1.8rem, 3vw, 2.4rem);
    font-weight: 700;
    margin-bottom: 18px;
    background: linear-gradient(100deg, #ffffff 35%, rgba(var(--header-accent),.88) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.about-cta p {
    color: rgba(255,255,255,.60);
    line-height: 1.88;
    margin: 0 auto 34px;
    font-size: 1rem;
}

.presentation-cta-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    justify-content: center;
    align-items: center;
}

/* .btn-accueil porte un margin-bottom:130px hérité de son usage en hero
   (voir règle générale plus haut) : neutralisé ici pour éviter qu'il
   n'étire le bouton secondaire voisin (align-items: stretch par défaut
   aurait sinon calqué sa hauteur sur celle, artificiellement agrandie,
   du bouton "Me contacter"). */
.presentation-cta-buttons .btn-accueil {
    margin-bottom: 0;
}

.presentation-btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 14px 32px;
    font-size: 1rem;
    font-weight: 600;
    border-radius: 999px;
    color: rgba(255,255,255,.78);
    text-decoration: none;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.14);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: color .25s ease, background .25s ease, border-color .25s ease, transform .25s ease;
}

.presentation-btn-secondary:hover {
    color: #fff;
    background: rgba(var(--header-accent),.10);
    border-color: rgba(var(--header-accent),.40);
    transform: translateY(-2px);
}


/* ========================= partenaires.php ========================= */

/* ─── BACKGROUND (identique à about.php) ─── */
.page-partenaires::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-partenaires > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-partenaires .section-block {
    opacity: 0;
    transform: translateY(44px);
    transition:
        opacity 0.85s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.95s cubic-bezier(0.16, 1, 0.3, 1);
}

.page-partenaires .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── HERO (centrée, sans photo) ─── */
/* Cette hero n'a pas de photo (contrairement à about.php qui réutilise
   .about-hero) : son contenu est plus court, donc le même padding que sur
   about.php (200px haut / 80px bas + 80px haut de section suivante) laissait
   un vide disproportionné avant la première section. On resserre ici,
   uniquement sur cette page. */
#partners-hero.about-hero { padding-bottom: 40px; }
#partner-official.about-section { padding-top: 40px; }

.partners-hero-layout {
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
}

.partners-hero-layout h1 {
    font-size: clamp(2.2rem, 4vw, 3.2rem);
    font-weight: 800;
    line-height: 1.15;
    margin-bottom: 22px;
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent),.90) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.partners-hero-layout .about-subtitle {
    margin: 0 auto;
}

/* ─── GRILLE DES PARTENAIRES ─── */
.partners-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 28px;
    max-width: 950px;
    margin: 0 auto;
}
/* Variante 1 seule carte (réseau partenaire réduit à Atelier.Tech) :
   centrée, largeur de lecture confortable plutôt qu'étirée sur toute la
   grille (même logique que .cw-why-grid--single plus bas). */
.partners-grid--single {
    grid-template-columns: 1fr;
    max-width: 480px;
    margin: 0 auto;
}

.partner-card-domain {
    display: inline-block;
    align-self: flex-start;
    margin-bottom: 14px;
    padding: 5px 12px;
    border-radius: 999px;
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .03em;
    text-transform: uppercase;
    color: rgb(var(--header-accent));
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.28);
}

.partner-card {
    display: flex;
    flex-direction: column;
}

.partner-card-link {
    margin-top: 22px;
    align-self: flex-start;
    padding: 10px 20px;
    font-size: .85rem;
}

/* Les 2 cartes d'une même rangée ont la même hauteur (grid stretch par
   défaut), mais un texte descriptif plus long que l'autre décalait le
   bouton "Découvrir le projet" vers le bas d'une carte par rapport à
   l'autre. En poussant le bouton en bas de la colonne flex (.partner-card),
   les deux boutons se retrouvent alignés sur la même ligne quelle que soit
   la longueur du texte. */
#partners-watch .partner-card-link {
    margin-top: auto;
}

.partner-card-link .rocket-icon {
    width: 18px;
    height: 18px;
}

.about-card h3,
.partner-card h3 {
    font-size: 1.55rem;
    font-weight: 700;
    margin-bottom: 18px;
    line-height: 1.3;
    background: linear-gradient(100deg, #ffffff 40%, rgba(148,163,184,.80) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* ─── TITRES DE CATÉGORIE (Partenaire / Réseau partenaire) ─── */
.partners-category-title {
    text-align: center;
    font-size: clamp(1.5rem, 2.6vw, 2rem);
    font-weight: 800;
    margin: 0 auto 30px;
    max-width: 720px;
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent),.90) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.partners-network-subtitle {
    text-align: center;
    margin: -10px auto 36px;
}

/* ─── PARTENAIRE OFFICIEL (Infomaniak) ─── */
.partner-featured {
    max-width: 560px;
    margin: 0 auto;
    align-items: flex-start;
}

.partner-featured .modules-cta-link {
    margin-top: 6px;
    align-self: flex-start;
}


/* ========================= projets-a-suivre.php ========================= */

/* ─── BACKGROUND (identique à about.php / partenaires.php) : cette page
   n'avait jamais reçu son bloc .page-projets-suivre::before, elle restait
   donc sans l'image de fond fixe du reste du site. ─── */
.page-projets-suivre::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-projets-suivre > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-projets-suivre .section-block {
    opacity: 0;
    transform: translateY(44px);
    transition:
        opacity 0.85s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.95s cubic-bezier(0.16, 1, 0.3, 1);
}

.page-projets-suivre .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* Chaque projet a sa propre section pleine largeur (au lieu de partager une
   grille avec l'autre projet) ; la 2e section reçoit un léger fond distinct
   pour bien les séparer visuellement, comme les autres pages du site
   alternent parfois le fond entre sections (cf. reviews-section--accueil). */
.projet-section--tinted {
    background: rgba(255,255,255,.02);
    border-top: 1px solid rgba(255,255,255,.05);
    border-bottom: 1px solid rgba(255,255,255,.05);
}

.projet-showcase {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 44px;
    align-items: center;
    max-width: 1000px;
    margin: 0 auto;
}

.projet-showcase--reverse .projet-showcase-preview { order: 2; }
.projet-showcase--reverse .projet-showcase-info    { order: 1; }

.projet-showcase-info .partner-card-domain {
    margin-bottom: 14px;
}

.projet-showcase-info h2 {
    font-size: 1.55rem;
    font-weight: 700;
    margin-bottom: 16px;
    line-height: 1.3;
    background: linear-gradient(100deg, #ffffff 40%, rgba(148,163,184,.80) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.projet-showcase-info p {
    color: rgba(255,255,255,.65);
    line-height: 1.75;
    margin-bottom: 24px;
}

.projet-showcase-preview .browser-chrome,
.projet-showcase-preview .browser-preview {
    border-radius: 0;
}

/* ─── Carousel "Projets à suivre" (surmesure.php) ─── */
.projet-carousel {
    max-width: 1000px;
    margin: 0 auto;
}

.projet-carousel-viewport {
    position: relative;
    display: grid;
}

/* Les 2 slides occupent la même cellule de grille (empilées), pour un fondu
   enchaîné fluide entre elles au lieu d'un simple basculement instantané. */
.projet-carousel-slide {
    grid-area: 1 / 1 / -1 / -1;
    opacity: 0;
    pointer-events: none;
    transition: opacity .9s ease;
}

.projet-carousel-slide.is-active {
    opacity: 1;
    pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
    .projet-carousel-slide {
        transition: none;
    }
}

.projet-carousel-nav {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 28px;
}

.projet-carousel-dot {
    width: 10px;
    height: 10px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255,255,255,.2);
    cursor: pointer;
    transition: background .2s, transform .2s;
}

.projet-carousel-dot:hover {
    background: rgba(255,255,255,.4);
}

.projet-carousel-dot.is-active {
    background: rgb(var(--header-accent));
    transform: scale(1.3);
}

.projet-showcase-preview {
    border-radius: 16px;
    overflow: hidden;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(255,255,255,.03);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
}

.browser-preview--soon {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: rgba(255,255,255,.02);
    color: rgba(255,255,255,.32);
}

.browser-preview--soon svg {
    width: 30px;
    height: 30px;
    opacity: .6;
}

.browser-preview--soon span {
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.projet-maquette-btn--soon {
    opacity: .5;
    cursor: default;
    pointer-events: none;
    border-style: dashed;
}

.projet-maquette-btn--soon:hover {
    transform: none;
    box-shadow: none;
}


/* ========================= contact.php ========================= */

/* ─── BACKGROUND ─── */
.page-contact::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-contact > * {
    position: relative;
    z-index: 1;
}

/* ─── SCROLL REVEAL ─── */
.page-contact .section-block {
    opacity: 0;
    transform: translateY(44px);
    transition:
        opacity 0.85s cubic-bezier(0.16, 1, 0.3, 1),
        transform 0.95s cubic-bezier(0.16, 1, 0.3, 1);
}

.page-contact .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── SECTION ─── */
.contact {
    /* La section newsletter (ajoutée après) est désormais la dernière de la
       page et porte elle-même var(--footer-clearance) : .contact n'a donc
       plus qu'un espacement de bas de section normal. */
    padding: 140px 20px 60px;
}

.contact .container {
    max-width: 1100px;
    margin: 0 auto;
}

/* ─── HEADER ─── */
.contact-header {
    text-align: center;
    margin-bottom: 56px;
}

.contact-header h1 {
    font-size: clamp(2.2rem, 4vw, 3rem);
    font-weight: 800;
    line-height: 1.15;
    margin-bottom: 14px;
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent),.90) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.contact-header p {
    color: rgba(255,255,255,.58);
    font-size: 1.05rem;
    line-height: 1.78;
    max-width: 540px;
    margin: 0 auto;
}

.form-group {
    display: flex;
    flex-direction: column;
    text-align: left;
    gap: 8px;
    /* Évite qu'un input avec une largeur intrinsèque (ex: dans une grille à
       2 colonnes comme .auth-row-split) ne force la colonne à s'élargir
       au-delà de l'espace disponible et à déborder de sa carte. */
    min-width: 0;
}
/* Bug réel trouvé ici : l'attribut HTML [hidden] est censé masquer un élément
   via la règle par défaut du navigateur "[hidden] { display: none }", mais
   celle-ci a la même spécificité que ".form-group { display: flex }"
   ci-dessus — et une règle d'auteur l'emporte toujours sur celle du
   navigateur à spécificité égale. Résultat : un .form-group avec l'attribut
   hidden restait visible (ex : "Précisez votre nom de domaine" / "Votre site
   est-il déjà en ligne ?" affichés même en cas de réponse "Non" sur
   compte-projets.php). Cette règle, plus spécifique, rétablit le masquage. */
.form-group[hidden] { display: none; }

.form-group label {
    font-size: .76rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: rgba(255,255,255,.45);
}

/* Mention "(facultatif)" accolée à un label (ex : "Pourquoi choisir
   CroisierWeb ?" sur compte-creer-site.php, demande explicite : "doit être
   facultatif") — plus discrète que le reste du label déjà très atténué. */
.field-optional-hint {
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    color: rgba(255,255,255,.30);
}

.form-group input,
.form-group textarea {
    width: 100%;
    box-sizing: border-box;
    min-width: 0;
    padding: 13px 16px;
    border-radius: 11px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(0,0,0,.28);
    color: #fff;
    font-size: .95rem;
    font-family: inherit;
    outline: none;
    resize: vertical;
    transition: border-color .25s ease, box-shadow .25s ease, background .25s ease;
}

.form-group input::placeholder,
.form-group textarea::placeholder {
    color: rgba(255,255,255,.20);
}

.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus {
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.05);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.10), 0 0 20px rgba(var(--header-accent),.08);
}

/* Icône calendrier des champs date (demande explicite : "l'icône calendrier
   soit plus visible... la manière de choisir la date sans effort") — l'icône
   native ::-webkit-calendar-picker-indicator est minuscule et quasi invisible
   sur fond sombre par défaut. Remplacée par notre propre pictogramme blanc
   (même langage visuel que le chevron de .form-group select ci-dessous),
   agrandie et surlignée au survol dans la couleur d'accent de la page pour
   bien signaler qu'elle est cliquable. color-scheme:dark fait en sorte que le
   popup natif du calendrier s'ouvre lui aussi en thème sombre plutôt qu'en
   blanc cru. Uniquement Chrome/Edge/Safari (WebKit/Blink) : Firefox ne permet
   pas de personnaliser cette icône, elle y garde son apparence native. */
.form-group input[type="date"] {
    color-scheme: dark;
    cursor: pointer;
    /* Bug signalé ("les box des filtres ne sont pas belles, il faut les
       harmoniser") : sans appearance:none, Chromium continue de dessiner le
       bouton natif "effacer" (x) et les flèches de spin par-dessus notre
       fond sombre — 2 petits pavés clairs qui, combinés au texte "dd/mm/yyyy"
       en gris clair, donnaient l'impression d'une case restée blanche par
       endroits à côté du champ texte pleinement stylé. appearance:none
       retire ces résidus visuels natifs pour un rendu uniforme avec le reste
       du formulaire (fond, bordure, rayon identiques à .form-group input). */
    -webkit-appearance: none;
    appearance: none;
}
.form-group input[type="date"]::-webkit-clear-button,
.form-group input[type="date"]::-webkit-inner-spin-button {
    display: none;
}
.form-group input[type="date"]::-webkit-calendar-picker-indicator {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='5' width='18' height='16' rx='2'/><line x1='16' y1='3' x2='16' y2='7'/><line x1='8' y1='3' x2='8' y2='7'/><line x1='3' y1='10' x2='21' y2='10'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 18px;
    width: 30px;
    height: 30px;
    padding: 6px;
    margin-right: -6px;
    border-radius: 8px;
    opacity: 1;
    cursor: pointer;
    transition: background-color .2s ease;
}
.form-group input[type="date"]::-webkit-calendar-picker-indicator:hover,
.form-group input[type="date"]::-webkit-calendar-picker-indicator:focus {
    background-color: rgba(var(--header-accent), .22);
}

/* Repère visuel sur les champs date d'échéance d'admin-sites.php (demande
   explicite : "orange à partir de 30 jours avant l'échéance et rouge 7 jours
   avant") — classe posée côté PHP selon le nombre de jours restants (cf.
   site_expiry_class() dans pages/admin-sites.php), même vocabulaire de
   couleur que le reste du site (--warning orange/--danger rouge, cf.
   .account-site-warning--warning/--danger). */
.form-group input.date-expiry-warning {
    background: rgba(245,158,11,.12);
    border-color: rgba(245,158,11,.5);
    color: #fcd34d;
}
.form-group input.date-expiry-danger {
    background: rgba(239,68,68,.12);
    border-color: rgba(239,68,68,.55);
    color: #fca5a5;
}

.form-group select {
    width: 100%;
    box-sizing: border-box;
    min-width: 0;
    padding: 13px 40px 13px 16px;
    border-radius: 11px;
    border: 1px solid rgba(255,255,255,.08);
    background-color: rgba(0,0,0,.28);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff99' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 14px;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    color: #fff;
    font-size: .95rem;
    font-family: inherit;
    outline: none;
    cursor: pointer;
    transition: border-color .25s ease, box-shadow .25s ease, background .25s ease;
}

.form-group select option {
    background: #10141f;
    color: #fff;
}

/* ─── CHANNEL SELECTOR ─── */
.channel-radio-group {
    display: flex;
    gap: 10px;
}

.channel-option {
    flex: 1;
    cursor: pointer;
}

.channel-option input[type="radio"] {
    display: none;
}

.channel-label {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 11px 16px;
    border-radius: 11px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(0,0,0,.28);
    color: rgba(255,255,255,.40);
    font-size: .90rem;
    font-family: inherit;
    cursor: pointer;
    transition: border-color .25s ease, background .25s ease,
                color .25s ease, box-shadow .25s ease;
}

.channel-label svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.channel-option input:checked + .channel-label {
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.12);
    color: #ffffff;
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.10), 0 0 18px rgba(var(--header-accent),.08);
}

.channel-option:hover .channel-label {
    border-color: rgba(255,255,255,.14);
    color: rgba(255,255,255,.65);
}

/* Sélecteur de langue (pages/compte-profil.php, #langue) : 4 options à
   flex:1 sur une seule ligne (règle desktop ci-dessus) — sur mobile, ça
   écrasait chaque libellé ("Français", "English"...) dans une largeur trop
   étroite, texte tronqué/débordant (demande explicite : "le choix de la
   langue est tronqué, le contenu déborde"). Passe en grille 2 colonnes ×
   2 lignes au lieu d'1 ligne de 4 : chaque option garde assez de place pour
   son icône + son libellé complet. Le groupe "Style d'affichage" (2 options
   seulement, même classe .channel-radio-group plus bas sur la même page)
   n'est pas impacté négativement : 2 colonnes pour 2 éléments reste 1 seule
   ligne, identique visuellement à la version desktop. */
@media (max-width: 600px) {
    .channel-radio-group {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 10px;
    }
    .channel-option { flex: none; }
    .channel-label {
        padding: 10px 8px;
        font-size: .82rem;
    }
}

/* ─── BOUTON ENVOI ─── */
/* Recoloré sur la paire harmonisante --accent-harmony-1/-2 (demande
   explicite : "la couleur secondaire [...] utilisée sur tous les boutons
   en fonction du choix" — bug réel trouvé ici) : ce bouton était resté
   figé en bleu littéral (rgba(var(--header-accent),...)/rgba(var(--header-accent),...)),
   ignorant totalement la couleur choisie en Mon profil, sur TOUTES les
   pages qui l'utilisent (login.php, register.php, verify-2fa.php,
   oauth-link.php, reset-password.php, forgot-password.php). Dégradé
   translucide (pas plein comme .livre-dor-cta-btn) pour rester fidèle à
   l'habillage vitré d'origine — seule la teinte suit désormais l'accent. */
.btn-contact {
    align-self: flex-start;
    padding: 13px 38px;
    border-radius: 999px;
    border: 1px solid rgba(var(--accent-harmony-1), .35);
    background: linear-gradient(135deg, rgba(var(--accent-harmony-1), .22), rgba(var(--accent-harmony-2), .22));
    color: var(--accent-harmony-contrast, #fff);
    font-size: 1rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    letter-spacing: .02em;
    transition: background .25s ease, box-shadow .25s ease, transform .25s ease;
}

.btn-contact:hover {
    background: linear-gradient(135deg, rgba(var(--accent-harmony-1), .34), rgba(var(--accent-harmony-2), .34));
    box-shadow: 0 10px 30px rgba(var(--accent-harmony-1), .22);
    transform: translateY(-2px);
}

.btn-contact:active {
    transform: translateY(0);
}

/* ─── SUCCESS / ERROR ─── */
.contact-success {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 16px;
    padding: 56px 32px;
    background: rgba(16, 185, 129, 0.08);
    border: 1px solid rgba(16, 185, 129, 0.25);
    border-radius: 20px;
    margin-bottom: 48px;
}

.contact-success-icon {
    width: 64px;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(16, 185, 129, 0.15);
    border-radius: 50%;
    color: #10b981;
}

.contact-success-icon svg {
    width: 32px;
    height: 32px;
}

.contact-success h2 {
    font-size: 1.6rem;
    font-weight: 700;
    color: #10b981;
    margin: 0;
}

.contact-success p {
    font-size: 1rem;
    color: rgba(255,255,255,.72);
    margin: 0;
    max-width: 460px;
}

.contact-error {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 20px;
    background: rgba(239, 68, 68, 0.10);
    border: 1px solid rgba(239, 68, 68, 0.30);
    border-radius: 12px;
    color: #f87171;
    font-size: .93rem;
    font-weight: 500;
    margin-bottom: 28px;
}

.contact-error svg {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

/* ─── livre-dor.php ──────────────────────────────────────────── */

/* ─── BACKGROUND FIXE ─── */
.page-livre-dor::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}
.page-livre-dor > * {
    position: relative;
    z-index: 1;
}
.page-livre-dor .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}
.page-livre-dor .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* pages/portfolio.php : la dernière section de la page (diaporama
   "maquettes", cf. #portfolio-maquettes dans pages/portfolio.php) doit
   réserver l'espace du footer flottant — même mécanisme que
   var(--footer-clearance) déjà utilisé en fin de page ailleurs sur le site
   (demande explicite : "il faut rajouter un padding bot pour le footer
   flottant"). Le diaporama "réalisations" (#portfolio-realises) passe
   désormais avant les maquettes (demande explicite) et n'est donc plus la
   dernière section : pas besoin d'y réserver cet espace. */
#portfolio-maquettes {
    padding-bottom: var(--footer-clearance);
}

/* Comme sur les autres pages (.contact .container, .about-hero .container, etc.),
   le conteneur doit être plafonné en largeur : sans cette règle, le formulaire et
   la liste d'avis s'étirent sur 100% de la largeur de l'écran, ce qui n'est pas
   ergonomique sur les grands moniteurs. */
.page-livre-dor .container {
    max-width: 1100px;
    margin: 0 auto;
}

.page-livre-dor .livre-dor-hero {
    text-align: center;
    /* 200px : place pour le sous-menu Présentation ET pour la nouvelle
       navigation inter-pages (boucle presentation/about/partenaires/livre-dor). */
    padding: 200px 20px 80px;
}

.page-livre-dor .livre-dor-hero h1 {
    font-size: clamp(2.2rem, 4vw, 3.2rem);
    font-weight: 800;
    line-height: 1.15;
    margin-bottom: 22px;
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent),.90) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.page-livre-dor .livre-dor-hero .intro {
    color: rgba(255,255,255,.65);
    line-height: 1.88;
    font-size: 1.05rem;
    max-width: 560px;
    margin: 0 auto;
}

/* Le bouton "Découvrir nos services" (.cgv-back-link) suit désormais cette
   section et devient la dernière de la page : c'est donc lui qui réserve
   l'espace du footer flottant, plus cette section-ci. */
.page-livre-dor .livre-dor-body {
    padding: 0 20px 60px;
}

/* Empile toujours .livre-dor-summary puis .ldo-first-review-cta l'un sous
   l'autre : sans ce wrapper en colonne, deux inline-flex se retrouvent
   côte à côte tant qu'il reste de la place sur la ligne. */
.livre-dor-summary-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    margin: 28px auto 0;
    width: fit-content;
}

.livre-dor-summary {
    display: inline-flex;
    align-items: center;
    gap: 16px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 14px;
    padding: 14px 24px;
}

.livre-dor-avg-num {
    font-family: var(--font-title);
    font-size: 2.4rem;
    font-weight: 800;
    color: #fff;
    line-height: 1;
}

.livre-dor-avg-stars { color: #fbbf24; font-size: 1.1rem; margin-bottom: 4px; }

/* ─── CTA "Déposer mon avis" ───
   Toujours affiché sous .livre-dor-summary (via .livre-dor-summary-block en
   colonne), quel que soit le nombre d'avis clients — mène à la bannière
   "Laisser un avis" plus bas sur cette page. */
.ldo-first-review-cta {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.28);
    border-radius: 14px;
    padding: 14px 24px;
    color: #fff;
    font-weight: 700;
    font-size: .95rem;
    text-decoration: none;
    transition: background .2s ease, border-color .2s ease, transform .2s ease;
}

.ldo-first-review-cta svg {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
}

.ldo-first-review-cta:hover {
    background: rgba(var(--header-accent),.16);
    border-color: rgba(var(--header-accent),.5);
    transform: translateY(-2px);
}
.livre-dor-avg-label { font-size: .78rem; color: var(--text-muted); }

.livre-dor-layout {
    display: grid;
    grid-template-columns: 380px 1fr;
    gap: 36px;
    align-items: start;
}

.livre-dor-form-card {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 28px;
    position: sticky;
    top: 100px;
}

.livre-dor-form-card h2 {
    font-family: var(--font-title);
    font-size: 1.1rem;
    color: #fff;
    margin-bottom: 18px;
}

.required { color: #f87171; }

.review-honeypot { position: absolute; left: -9999px; top: -9999px; width: 1px; height: 1px; overflow: hidden; }

.star-picker { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }

.star-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 26px;
    line-height: 1;
    color: rgba(255,255,255,.18);
    padding: 2px;
    transition: color .15s, transform .1s;
}

.star-btn:hover { transform: scale(1.15); }
.star-btn.selected, .star-btn.hovered { color: #fbbf24; }
.star-btn:focus-visible {
    outline: 2px solid rgba(var(--header-accent),.7);
    outline-offset: 2px;
    border-radius: 4px;
}

.star-label { font-size: .78rem; color: var(--text-muted); margin-left: 6px; }

/* ─── "Mes avis publiés" (pages/compte-avis.php) ───
   Liste des avis déjà publiés par le client, chacun modifiable via un
   formulaire replié par défaut (cf. .review-edit-toggle / .review-edit-form,
   basculés en JS sans rechargement de page). */
.review-mine-card {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 18px 20px;
    margin-bottom: 14px;
}
.review-mine-card:last-child { margin-bottom: 0; }

.review-mine-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}

.review-mine-stars { color: #fbbf24; font-size: .95rem; letter-spacing: 1px; }

/* opacity:.75 retiré : se cumulait avec --text-muted (déjà une rgba avec son
   propre alpha, .85 dans le contexte .account-page) pour retomber sous ~.64
   de contraste effectif — demande explicite "améliore ce qui est
   visuellement fade". */
.review-mine-date { font-size: .74rem; color: var(--text-muted); white-space: nowrap; }

.review-mine-message {
    font-size: .88rem;
    color: var(--text-muted);
    line-height: 1.6;
    white-space: pre-line;
    margin-bottom: 14px;
}

.review-mine-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.review-mine-actions form { display: inline-flex; }

.review-edit-form {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid rgba(255,255,255,.08);
}

/* Espace le bouton "Enregistrer les modifications" du champ texte juste
   au-dessus (sans ce gap, ils étaient collés l'un à l'autre). */
.review-edit-form form { display: flex; flex-direction: column; gap: 16px; }

/* Hauteur ajustée automatiquement en JS (cf. script de pages/compte-avis.php)
   à l'ouverture du formulaire d'édition, pour que tout le message existant
   soit visible sans scroll — overflow:hidden évite un flash de scrollbar
   pendant le recalcul, resize:vertical laisse le client l'agrandir encore. */
.review-edit-textarea {
    min-height: 90px;
    overflow: hidden;
    resize: vertical;
}

.livre-dor-empty { text-align: center; padding: 60px 24px; color: var(--text-muted); }

.livre-dor-grid { display: flex; flex-direction: column; gap: 14px; }

.review-card {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 20px 22px;
    transition: border-color .2s, box-shadow .4s ease;
}

.review-card:hover { border-color: rgba(var(--header-accent),.35); }

/* Repère temporaire quand on arrive sur un avis précis depuis le diaporama
   ou l'aperçu index.php/accueil.php (cf. #review-ID + JS de livre-dor.php). */
.review-card--highlighted {
    border-color: rgba(251,191,36,.55);
    box-shadow: 0 0 0 3px rgba(251,191,36,.18);
}

.review-card-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}

.review-card-avatar {
    width: 40px; height: 40px; border-radius: 50%;
    /* Fond TOUJOURS blanc (demande explicite : "le fond de l'avatar s'adapte
       à la couleur active. Il doit toujours être blanc !") — avant, le fond
       suivait --brand-color (couleur de thème active, cf. pastille "Couleur"
       du widget flottant). L'initiale (repli quand l'utilisateur n'a pas de
       photo, cf. review_avatar_html()) reprend --brand-color en couleur de
       texte à la place, pour rester lisible et garder un lien avec la
       couleur active sans dépendre du fond. */
    background: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 1rem; font-weight: 800; color: var(--brand-color);
    flex-shrink: 0;
    font-family: var(--font-title);
}

.review-card-meta { flex: 1; }
.review-card-name { font-size: .92rem; font-weight: 700; color: #fff; }
.review-card-date { font-size: .75rem; color: var(--text-muted); margin-top: 2px; }
.review-card-stars { margin-left: auto; color: #fbbf24; font-size: .95rem; }

.review-card-message {
    font-size: .9rem;
    color: var(--text-muted);
    line-height: 1.7;
    border-left: 2px solid rgba(var(--header-accent),.35);
    padding-left: 14px;
    margin: 0;
    /* Les retours à la ligne saisis dans le formulaire (textarea) sont de
       vrais caractères \n dans le texte : sans ceci, le HTML les ignore et
       les affiche comme un simple espace. pre-line les respecte tout en
       laissant le texte s'enrouler normalement (pas de scroll horizontal). */
    white-space: pre-line;
}

/* ─── Avis au-delà de $reviewsVisibleLimit : masqués tant que la liste
       n'est pas dépliée via le bouton "Voir plus d'avis". ─── */
.review-card--extra { display: none; }
.livre-dor-grid.is-expanded .review-card--extra { display: block; }

.review-toggle-wrap {
    display: flex;
    justify-content: center;
    margin-top: 20px;
}

.review-toggle-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 24px;
    font-size: .85rem;
    font-weight: 600;
    border-radius: 999px;
    color: rgba(255,255,255,.78);
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.14);
    cursor: pointer;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: color .25s ease, background .25s ease, border-color .25s ease;
}

.review-toggle-btn:hover {
    color: #fff;
    background: rgba(var(--header-accent),.10);
    border-color: rgba(var(--header-accent),.40);
}

/* Sans width/height explicite sur le <svg> (viewBox seul ne suffit pas),
   certains navigateurs retombent sur la taille par défaut d'un élément
   remplacé (300x150px) et cassent visuellement le bouton — la taille est
   donc aussi verrouillée ici en CSS, en plus des attributs sur la balise. */
.review-toggle-chevron { width: 14px; height: 14px; transition: transform .25s ease; flex-shrink: 0; }
.review-toggle-btn[aria-expanded="true"] .review-toggle-chevron { transform: rotate(180deg); }

.pagination-wrap { margin-top: 28px; }

.pagination { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; }

.page-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 8px;
    border-radius: 8px;
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.1);
    color: var(--text-muted);
    text-decoration: none;
    font-size: .85rem;
    font-weight: 600;
    transition: background .15s, color .15s, border-color .15s;
}

.page-btn:hover { background: rgba(var(--header-accent),.12); color: #fff; }
.page-btn.active { background: var(--brand-color); color: var(--brand-color-contrast, #fff); border-color: var(--brand-color); }

@media (max-width: 860px) {
    .livre-dor-layout { grid-template-columns: 1fr; }
    .livre-dor-form-card { position: static; }
}

/* ─── Diaporama des avis 5 étoiles (automatique, cf. pages/livre-dor.php) —
       au-dessus du catalogue complet. ─── */
.livre-dor-featured-title {
    font-family: var(--font-title);
    font-size: 1.3rem;
    color: #fff;
    margin-bottom: 20px;
    text-align: center;
}

/* Diaporama infini (.reviews-slider-wrap / .reviews-track / .review-item) :
   classes partagées avec index.php et accueil.php, définies plus bas dans ce
   fichier. Sur ces 2 autres pages, un bloc .reviews-footer (margin-top:36px)
   suit le slider et crée l'espace avant la section suivante — livre-dor.php
   n'a pas ce bloc (le CTA "Laisser un avis" suit directement), d'où ce
   margin-bottom dédié pour ne pas les coller l'un à l'autre. */
.livre-dor-featured .reviews-slider-wrap {
    margin-bottom: 36px;
}

/* ─── Bannière CTA "Laisser un avis" (remplace l'ancien formulaire
       inline, désormais externalisé sur pages/compte-avis.php). ─── */
.livre-dor-cta-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    background: linear-gradient(135deg, color-mix(in srgb, var(--brand-color) 10%, rgba(255,255,255,.03)), rgba(255,255,255,.03));
    border: 1px solid color-mix(in srgb, var(--brand-color) 25%, rgba(255,255,255,.08));
    border-radius: var(--radius);
    padding: 26px 30px;
    margin-bottom: 36px;
}

.livre-dor-cta-banner h2 {
    font-family: var(--font-title);
    font-size: 1.1rem;
    color: #fff;
    margin: 0 0 4px;
}

.livre-dor-cta-banner p { margin: 0; font-size: .88rem; color: var(--text-muted); }
.livre-dor-cta-banner-actions { display: flex; gap: 12px; flex-wrap: wrap; }

/* Bouton dédié à cette bannière (page publique) : le langage visuel du
   dashboard client (.btn-account) n'a pas sa place ici, on reprend plutôt
   le style pilule/dégradé/glow des CTA publics du site (cf. .btn-contact).
   Dégradé en --accent-harmony-1/-2 (demande explicite) plutôt que
   var(--brand-color) directement : la couleur brute de l'accent choisi
   "jurait" trop répétée partout — la paire harmonisante (cf. .accent-* en
   tête de fichier) offre un accord de couleurs plutôt qu'un simple décalque. */
.livre-dor-cta-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 13px 30px;
    border-radius: 999px;
    background: linear-gradient(135deg, rgb(var(--accent-harmony-1)), rgb(var(--accent-harmony-2)));
    border: 1px solid transparent;
    color: var(--accent-harmony-contrast, #fff);
    text-shadow: 0 1px 3px rgba(0,0,0,.3);
    font-size: .92rem;
    font-weight: 700;
    font-family: inherit;
    text-decoration: none;
    letter-spacing: .01em;
    box-shadow: 0 8px 24px rgba(var(--accent-harmony-1), .35);
    transition: transform .2s ease, box-shadow .2s ease, filter .2s ease;
}

.livre-dor-cta-btn:hover {
    transform: translateY(-2px);
    filter: brightness(1.08);
    box-shadow: 0 12px 32px rgba(var(--accent-harmony-1), .48);
}

.livre-dor-cta-btn:active { transform: translateY(0); }

/* "Se connecter" (visiteur déjà inscrit) : restait figé en gris neutre,
   aucune adaptation à la couleur choisie (demande explicite : "reste... à
   adapter en fonction du choix sélectionné"). Reprend la même paire
   harmonisante que le bouton plein ci-dessus, en version discrète/outline. */
.livre-dor-cta-btn--outline {
    background: rgba(var(--accent-harmony-2), .1);
    border-color: rgba(var(--accent-harmony-2), .4);
    color: #fff;
    box-shadow: none;
}

.livre-dor-cta-btn--outline:hover {
    background: rgba(var(--accent-harmony-2), .18);
    border-color: rgba(var(--accent-harmony-2), .65);
    filter: none;
    box-shadow: none;
}

/* ══════════════════════════════════════════════════════════════
   FAQ — accordéon réutilisable (page-faq-site.php, blocs "FAQ
   spécialisée" sur accueil.php / offres-site.php / sitevitrine.php /
   sitepro.php / surmesure.php, et page compte faq.php).
   ══════════════════════════════════════════════════════════════ */
.faq-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.faq-item {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 14px;
    overflow: hidden;
    transition: border-color .2s;
}

.faq-item:hover { border-color: rgba(var(--header-accent),.3); }
.faq-item[open] { border-color: rgba(var(--header-accent),.4); }

.faq-question {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 18px 22px;
    cursor: pointer;
    font-weight: 700;
    color: #fff;
    font-size: .95rem;
    list-style: none;
}

.faq-question::-webkit-details-marker { display: none; }

.faq-chevron {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--brand-color);
    transition: transform .25s;
}

.faq-item[open] .faq-chevron { transform: rotate(180deg); }

.faq-answer {
    padding: 0 22px 20px;
    color: var(--text-muted);
    font-size: .88rem;
    line-height: 1.7;
}

.faq-answer a {
    display: flex;
    align-items: center;
    gap: 6px;
    width: fit-content;
    margin-top: 10px;
    color: var(--brand-color);
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid rgba(var(--header-accent),.35);
    transition: border-color .2s ease, transform .2s ease;
}

.faq-answer a:hover,
.faq-answer a:focus-visible {
    border-color: var(--brand-color);
    transform: translateX(3px);
}

.faq-answer a + a { margin-top: 6px; }

/* ─── Blocs "FAQ spécialisée" intégrés en bas de page ─── */
/* Ce bloc est la dernière section sur accueil.php : c'est donc lui qui doit
   réserver l'espace pour le footer flottant (var(--footer-clearance)). */
.faq-preview-section {
    padding: 80px 20px var(--footer-clearance);
    position: relative;
}

/* Sur offres-site.php, la FAQ n'est plus la dernière section : le CTA final
   (.offer-cta) a été déplacé après elle et réserve désormais lui-même
   l'espace du footer flottant. Un padding-bottom normal suffit donc ici,
   sinon les deux espacements s'additionnaient et créaient un vide énorme
   entre la FAQ et le CTA. */
.page-offers .faq-preview-section {
    padding-bottom: 80px;
}

/* ─── accueil.php : FAQ + Newsletter regroupées dans une seule section.
   Plus de fond dédié ici : le bgsite.png fixe posé sur .site-main::before
   (même logique que le reste du site) suffit, comme sur les autres pages
   où la dernière section n'a pas de background propre. Padding-top
   légèrement réduit pour remonter le contenu en haut de section. ─── */
.faq-preview-section--bg {
    overflow: hidden;
    /* demande explicite : réduction de largeur -10%/côté (dernière section
       "dans le vaisseau"), cf. commentaire détaillé sur .method plus haut.
       La bande métallique de fin (.metal-plate-band--bottom, enfant direct
       de cette section) suit automatiquement cette largeur puisqu'elle est
       positionnée en absolute left:0/right:0 relativement à cette boîte —
       aucun réglage séparé n'est nécessaire pour "adapter la barre de la
       dernière section". */
    width: 90%;
    margin-left: auto;
    margin-right: auto;
    /* Écart avec le haut de la section augmenté (demande explicite) pour
       laisser respirer le badge + titre, plutôt que les coller juste sous
       le divider qui précède. */
    padding-top: 110px;
    /* demande explicite : "uniformise le bg [des 7 sections de la fusée] à
       la façon des sites évolutifs construits autour de modules" — reprend
       exactement le fond de main .modules (au lieu du fond bgsiteindex.png
       repris précédemment de .home-service-section--hebergement), cf.
       commentaire détaillé sur .method plus haut. */
    background:
        radial-gradient(ellipse at 0% 100%,   rgba(var(--header-accent),.18) 0%, transparent 45%),
        radial-gradient(ellipse at 100% 0%,   rgba(var(--header-accent),.10) 0%, transparent 45%),
        radial-gradient(ellipse at 50% 50%,   rgba(var(--header-accent),.05) 0%, transparent 65%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.025) 0,
            rgba(255,255,255,.025) 1px,
            transparent 1px,
            transparent 44px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.018) 0,
            rgba(255,255,255,.018) 1px,
            transparent 1px,
            transparent 44px
        ),
        rgba(7,10,18,.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-top: 1px solid rgba(var(--header-accent),.14);
    border-bottom: 1px solid rgba(var(--header-accent),.14);
}

/* accueil.php : la FAQ n'est plus la dernière section de la page (suite à
   la permutation avec "continuer la visite") — un padding-bottom normal
   suffit désormais, c'est .home-service-section--hebergement qui réserve
   l'espace du footer flottant (cf. plus bas dans ce fichier), même
   principe que .page-offers .faq-preview-section ci-dessus. */
.site-main .faq-preview-section--bg {
    padding-bottom: 80px;
}

/* accueil.php : demande explicite — donner à la section FAQ l'impression
   d'être "remplie d'essence" / immergée. Nappe teintée (couleur du thème
   sélectionné) occupant la moitié basse de la section, surmontée d'une
   ligne de surface ondulée qui dérive en continu, façon liquide dans une
   cuve. Purement décoratif (aria-hidden), posé en tout premier enfant de
   la section donc sous le sas/coques/contenu. */
.faq-fuel-immersion {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

.faq-fuel-immersion::before {
    content: "";
    position: absolute;
    left: -5%;
    right: -5%;
    top: 18%;
    bottom: 0;
    background:
        linear-gradient(180deg,
            rgba(var(--header-accent), .10) 0%,
            rgba(var(--header-accent), .20) 35%,
            rgba(var(--header-accent), .34) 100%),
        repeating-linear-gradient(115deg,
            rgba(255,255,255,.03) 0,
            rgba(255,255,255,.03) 2px,
            transparent 2px,
            transparent 30px);
    animation: faqFuelShimmer 10s ease-in-out infinite alternate;
}

.faq-fuel-immersion::after {
    content: "";
    position: absolute;
    left: -10%;
    right: -10%;
    top: calc(18% - 15px);
    height: 30px;
    background-image:
        radial-gradient(ellipse 70px 15px at 35px 15px, rgba(255,255,255,.18) 0%, transparent 72%),
        radial-gradient(ellipse 70px 15px at 105px 15px, rgba(255,255,255,.18) 0%, transparent 72%),
        linear-gradient(180deg, transparent 0%, rgba(var(--header-accent),.14) 100%);
    background-size: 140px 30px, 140px 30px, 100% 30px;
    background-repeat: repeat-x, repeat-x, no-repeat;
    animation: faqFuelWaveDrift 9s linear infinite;
}

@keyframes faqFuelShimmer {
    from { opacity: .85; }
    to   { opacity: 1; }
}

@keyframes faqFuelWaveDrift {
    from { background-position: 0 0, 0 0, 0 0; }
    to   { background-position: -140px 0, -140px 0, 0 0; }
}

.faq-preview-section .container {
    max-width: 800px;
    margin: 0 auto;
    position: relative;
    z-index: 1;
}

/* accueil.php : newsletter en section indépendante, DERNIÈRE section de la
   page (réserve l'espace du footer flottant). Demande explicite : "il ne
   doit y avoir que le bg de la page de visible" — plus de fond ni de voile
   propres à cette section, ni de border-top (qui traverserait tout l'écran
   puisque cette section n'a pas la largeur réduite des sections fusée) :
   transparente, seul le fond fixe .site-main::before reste visible, comme
   pour .why-cta-section ci-dessus. */
.newsletter-home-section {
    padding: 80px 20px var(--footer-clearance);
    position: relative;
    overflow: hidden;
}
.newsletter-home-section .container {
    max-width: 640px;
    margin: 0 auto;
    position: relative;
    z-index: 1;
}

.faq-preview-header {
    text-align: center;
    margin-bottom: 36px;
}

.faq-preview-header .reviews-eyebrow { margin-bottom: 16px; }

.faq-preview-header h2 {
    font-family: var(--font-title);
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    color: #fff;
    margin-bottom: 10px;
}

.faq-preview-header p {
    color: var(--text-muted);
    max-width: 480px;
    margin: 0 auto;
}

.faq-preview-footer {
    text-align: center;
    margin-top: 28px;
}

/* ─── Cartes "Modalités" devenues FAQ sur les pages d'offre
   (sitevitrine.php / sitepro.php / surmesure.php) : même emplacement
   dans la grille à 2 colonnes, le contenu passe juste d'une liste à
   un accordéon. ─── */
.faq-card-footer {
    margin-top: 16px;
}

/* Lien "Voir toute la FAQ" : transformé en pill bien visible (au lieu
   d'un simple lien souligné gris) pour inciter au clic vers faq-site.php. */
.faq-card-footer .reviews-see-all-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .82rem;
    font-weight: 700;
    color: rgba(var(--header-accent),.95);
    text-decoration: none;
    padding: 9px 18px;
    border-radius: 999px;
    background: rgba(var(--header-accent),.09);
    border: 1px solid rgba(var(--header-accent),.28);
    transition: background .2s ease, border-color .2s ease, color .2s ease, gap .2s ease;
}

.faq-card-footer .reviews-see-all-link:hover {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.45);
    color: #fff;
    gap: 10px;
}

/* Couleur à la teinte active de chaque page d'offre (sitevitrine = cyan,
   sitepro = or/gold ; surmesure reste bleu, déjà la couleur de base). */
.page-vitrine .faq-card-footer .reviews-see-all-link {
    color: rgba(var(--header-accent),.95);
    background: rgba(var(--header-accent),.09);
    border-color: rgba(var(--header-accent),.28);
}
.page-vitrine .faq-card-footer .reviews-see-all-link:hover {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.45);
    color: #fff;
}

.page-pro .faq-card-footer .reviews-see-all-link {
    color: rgba(var(--header-accent),.95);
    background: rgba(var(--header-accent),.09);
    border-color: rgba(var(--header-accent),.28);
}
.page-pro .faq-card-footer .reviews-see-all-link:hover {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.45);
    color: #fff;
}

/* sitepro.php : le survol/ouverture des questions FAQ gardait le reflet
   bleu générique au lieu de l'or de la page. */
.page-pro .faq-item:hover { border-color: rgba(var(--header-accent),.3); }
.page-pro .faq-item[open] { border-color: rgba(var(--header-accent),.4); }

/* sitevitrine.php : même correctif, le reflet des questions FAQ restait
   bleu générique au lieu du cyan de la page. */
.page-vitrine .faq-item:hover { border-color: rgba(var(--header-accent),.3); }
.page-vitrine .faq-item[open] { border-color: rgba(var(--header-accent),.4); }

/* La flèche déroulante (.faq-chevron) reprend var(--brand-color), bleu
   générique, sur toutes les pages. À la couleur active pour sitevitrine
   (cyan) et sitepro (or) ; surmesure reste bleu, déjà la bonne couleur. */
.page-vitrine .faq-chevron { color: rgba(var(--header-accent),.95); }
.page-pro .faq-chevron { color: rgb(var(--header-accent)); }

/* ─── Page FAQ complète (faq-site.php) ─── */
.page-faq-site::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}
.page-faq-site > * {
    position: relative;
    z-index: 1;
}
.page-faq-site .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}
.page-faq-site .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.page-faq-site .container {
    max-width: 1100px;
    margin: 0 auto;
}

.faq-site-hero {
    text-align: center;
    padding: 140px 20px 60px;
}

.faq-site-hero h1 {
    font-size: clamp(2.2rem, 4vw, 3.2rem);
    font-weight: 800;
    line-height: 1.15;
    margin-bottom: 22px;
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent),.90) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.faq-site-hero p {
    color: rgba(255,255,255,.65);
    line-height: 1.88;
    font-size: 1.05rem;
    max-width: 560px;
    margin: 0 auto;
}

.faq-site-body {
    padding: 0 20px var(--footer-clearance);
    max-width: 800px;
    margin: 0 auto;
}

.faq-category { margin-bottom: 40px; }
.faq-category:last-child { margin-bottom: 0; }

.faq-category-title {
    font-family: var(--font-title);
    font-size: 1.05rem;
    color: var(--brand-color);
    margin-bottom: 16px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(255,255,255,.08);
}

/* ─── CTA de fin de page : renvoi vers le support de l'espace client ─── */
.faq-cta {
    margin-top: 56px;
    padding-top: 40px;
    border-top: 1px solid rgba(255,255,255,.08);
    text-align: center;
}

.faq-cta-title {
    font-family: var(--font-title);
    font-size: 1.2rem;
    font-weight: 700;
    color: #fff;
    margin-bottom: 8px;
}

.faq-cta-text {
    color: var(--text-muted);
    font-size: .92rem;
    line-height: 1.7;
    max-width: 480px;
    margin: 0 auto 22px;
}

@media (max-width: 700px) {
    .faq-site-hero { padding: 120px 20px 40px; }
}

/* ─── INFO CARDS ─── */
.contact-info {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    margin-bottom: 48px;
}

.info-card {
    padding: 22px 22px 22px 26px;
    border-radius: 16px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    border-left-width: 2px;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: box-shadow .3s ease;
}

.info-card h3 {
    font-size: .76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    margin-bottom: 8px;
}

.info-card p {
    color: rgba(255,255,255,.62);
    font-size: .92rem;
    line-height: 1.65;
}

.info-card .info-card-hint {
    color: rgba(255,255,255,.45);
    font-size: .78rem;
    line-height: 1.5;
    margin-top: 2px;
}

/* ─── LIENS SOCIAUX (card Email) ───
   Boutons ronds assez grands (40px) pour rester faciles à toucher au pouce
   sur mobile ; les liens LinkedIn/Discord ouvrent l'app native en un tap
   là où elle est installée (comportement natif des liens universels,
   rien à faire côté site une fois les vraies URLs renseignées). */
.info-card h3.contact-social-heading {
    margin-top: 14px;
}

.contact-social-links {
    display: flex;
    gap: 10px;
    margin-top: 12px;
}

.contact-social-link {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    color: rgba(255,255,255,.65);
    border: 1px solid rgba(255,255,255,.14);
    background: rgba(255,255,255,.04);
    transition: color .2s ease, border-color .2s ease, background .2s ease, transform .2s ease;
}

.contact-social-link svg {
    width: 18px;
    height: 18px;
}

.contact-social-link:hover {
    color: #fff;
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.16);
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(var(--header-accent),.22);
}

.info-card--blue   { border-left-color: rgba(var(--header-accent),.70); }
.info-card--cyan   { border-left-color: rgba(59,130,246,.70); }
.info-card--purple { border-left-color: rgba(139,92,246,.70); }
.info-card--green  { border-left-color: rgba(16,185,129,.70); }

.info-card--blue   h3 { color: rgba(99,160,255,.90); }
.info-card--cyan   h3 { color: rgba(34,211,238,.90); }
.info-card--purple h3 { color: rgba(167,139,250,.90); }
.info-card--green  h3 { color: rgba(52,211,153,.90); }

.info-card--blue:hover   { box-shadow: 0 12px 32px rgba(var(--header-accent),.08); }
.info-card--cyan:hover   { box-shadow: 0 12px 32px rgba(59,130,246,.08); }
.info-card--purple:hover { box-shadow: 0 12px 32px rgba(139,92,246,.08); }
.info-card--green:hover  { box-shadow: 0 12px 32px rgba(16,185,129,.08); }

/* ─── BOUTON "APPELER" (facilite l'appel en un tap sur mobile) ─── */
.contact-call-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 12px;
    padding: 10px 20px;
    border-radius: 999px;
    border: 1px solid rgba(16,185,129,.35);
    background: rgba(16,185,129,.12);
    color: #fff;
    text-decoration: none;
    font-size: .86rem;
    font-weight: 600;
    letter-spacing: .01em;
    transition: background .25s ease, transform .25s ease, box-shadow .25s ease;
}

.contact-call-btn svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
}

.contact-call-btn:hover {
    background: rgba(16,185,129,.22);
    border-color: rgba(16,185,129,.55);
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(16,185,129,.18);
    color: #fff;
}

.contact-call-btn:active {
    transform: translateY(0);
}

/* ─── ESPACE CLIENT (liens vers les formulaires du dashboard) ─── */
.contact-client {
    margin-top: 64px;
    padding-top: 48px;
    border-top: 1px solid rgba(255,255,255,.08);
}

.contact-client-header {
    text-align: center;
    max-width: 620px;
    margin: 0 auto 32px;
}

.contact-client-subtitle {
    color: rgba(255,255,255,.60);
    font-size: .98rem;
    line-height: 1.8;
    margin-top: 10px;
}

.contact-client-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
}

.contact-client-card {
    padding: 28px 24px;
    border-radius: 16px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    border-top-width: 2px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
    transition: transform .3s ease, box-shadow .3s ease;
}

.contact-client-card:hover {
    transform: translateY(-3px);
}

.contact-client-card h3 {
    font-size: 1.02rem;
    font-weight: 700;
    margin: 0;
}

.contact-client-card p {
    color: rgba(255,255,255,.62);
    font-size: .90rem;
    line-height: 1.65;
    flex: 1;
}

.contact-client-card .contact-client-card-hint {
    flex: 0 0 auto;
    color: rgba(255,255,255,.42);
    font-size: .78rem;
    line-height: 1.5;
    margin-top: -6px;
}

.contact-client-card .modules-cta-link {
    margin-top: 6px;
    padding: 10px 22px;
    font-size: .88rem;
}

.contact-client-card--blue   { border-top-color: rgba(var(--header-accent),.65); }
.contact-client-card--cyan   { border-top-color: rgba(59,130,246,.65); }
.contact-client-card--purple { border-top-color: rgba(139,92,246,.65); }

.contact-client-card--blue   h3 { color: rgba(99,160,255,.90); }
.contact-client-card--cyan   h3 { color: rgba(34,211,238,.90); }
.contact-client-card--purple h3 { color: rgba(167,139,250,.90); }

.contact-client-card--blue:hover   { box-shadow: 0 14px 38px rgba(var(--header-accent),.08); }
.contact-client-card--cyan:hover   { box-shadow: 0 14px 38px rgba(59,130,246,.08); }
.contact-client-card--purple:hover { box-shadow: 0 14px 38px rgba(139,92,246,.08); }


/* ═══════════════════════════════════════════════════════
   SECTION EXEMPLES — browser mockup + iframe preview
   ═══════════════════════════════════════════════════════ */

.exemples-section {
    padding: 80px 24px;
    max-width: 1100px;
    margin: 0 auto;
}

.exemples-header {
    text-align: center;
    margin-bottom: 56px;
}

.exemples-header .exemples-label {
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--brand-color);
    background: var(--brand-color-soft);
    border: 1px solid rgba(var(--header-accent),.25);
    border-radius: 999px;
    padding: 4px 14px;
    margin-bottom: 16px;
}

.exemples-header h2 {
    font-family: var(--font-title);
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    color: #fff;
    margin-bottom: 12px;
    background: none;
    box-shadow: none;
}

/* Demande explicite : le titre "Prêt à lancer votre projet ?" du
   formulaire de commande (sitevitrine/sitepro/surmesure, partials/
   order-form.php) doit hériter de la couleur active, comme les autres
   titres de section (même recette que .vitrine-cta h2) — scopé à
   .order-form-section pour ne pas toucher l'autre usage de
   .exemples-header ("Exemples concrets", resté blanc uni). */
.order-form-section .exemples-header h2 {
    background: linear-gradient(100deg, #ffffff 40%, rgba(var(--header-accent),.88) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.exemples-header p {
    color: var(--text-muted);
    font-size: 1rem;
    max-width: 520px;
    margin: 0 auto;
}

/* ─── Section #commande générique (cf. partials/account-invite.php) ───
   Demande explicite : "chaque page ait un bouton qui ramène au bas de page
   (créer un compte)" — réutilise .exemples-header pour le titre/texte (même
   composant que les autres CTA du site), seule cette rangée de boutons est
   propre à ce bloc.
   Cette section est la toute dernière avant le footer sur refonte.php,
   audit-site.php, hebergement.php, maintenance.php, programmation.php,
   bot-discord.php, accompagnement.php et conseil.php (demande explicite :
   "il manque un léger écart bas de page pour le footer") — sans ce
   padding-bottom, elle ne réservait pas l'espace du footer flottant
   (var(--footer-clearance), même mécanisme que .order-form-section utilisé
   sur sitevitrine/sitepro/surmesure). */
.account-invite-section {
    padding: 60px 24px var(--footer-clearance);
}

/* Demande explicite : suppression du CTA "créer un compte" séparé
   (partials/account-invite.php) sur refonte/audit-site/programmation/
   bot-discord/accompagnement/conseil — leur propre "CTA FINAL" (.cw-cta)
   devient la toute dernière section de la page et doit donc désormais
   réserver lui-même l'espace du footer flottant (var(--footer-clearance)),
   ce que .cw-cta ne fait pas par défaut (utilisé aussi sur des pages où il
   n'est pas la dernière section, ex. conseilaccompagnement.php). Ciblé par
   id plutôt que par classe pour ne pas affecter ces autres usages. */
#rf-cta-final,
#au-cta-final,
#pg-cta-final,
#bd-cta-final,
#acc-cta-final,
#conseil-cta-final {
    padding-bottom: var(--footer-clearance);
}

/* ─── Bouton hero "service-hero-cta" (refonte/audit-site/hebergement/
   maintenance/programmation/bot-discord/accompagnement/conseil) ───
   Demande explicite : "styliser les boutons là pas beau" + "pour le style
   des boutons reprends le style de accueil.php" — sans cette classe,
   l'icône fusée utilisait par défaut .rocket-icon (64x64px, pensée pour le
   hero d'accueil.php), ce qui rendait ce bouton disproportionné. Forme/typo
   repris du CTA hero d'accueil.php (.hero-cta-row .btn-primary : majuscules,
   letter-spacing, petit rayon de bordure) plutôt que le gros bouton pilule
   utilisé sur les offres (essentiel/pro/surmesure). */
.service-hero-cta {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    border-radius: 8px;
    font-family: var(--font-title);
    font-weight: 700;
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: .06em;
}
.service-hero-cta .rocket-icon-wrap {
    display: inline-flex;
}
.service-hero-cta .rocket-icon {
    width: 18px;
    height: 18px;
}

/* Demande explicite : "le texte est collé au dessus du bouton, il faut créer
   un écart" (refonte/audit-site/programmation/bot-discord/accompagnement/
   conseil) — .cw-hero-tagline a margin:0, donc rien ne séparait le texte du
   bouton hero juste en dessous. Ciblé uniquement quand le bouton suit
   directement ce tagline (ne touche pas hebergement.php/maintenance.php, où
   le bouton suit .heberg-hero-cta-line, déjà bien espacé par son padding). */
.cw-hero-tagline + .service-hero-cta {
    margin-top: 24px;
}

.account-invite-actions {
    display: flex;
    justify-content: center;
    gap: 14px;
    flex-wrap: wrap;
}

@keyframes slide-exemples {
    from { transform: translateX(0); }
    to   { transform: translateX(calc(-100% / var(--sets, 2))); }
}

.exemples-slider-wrap {
    overflow: hidden;
    mask-image: linear-gradient(to right, transparent 0%, black 8%, black 92%, transparent 100%);
    -webkit-mask-image: linear-gradient(to right, transparent 0%, black 8%, black 92%, transparent 100%);
}

.exemples-track {
    display: flex;
    gap: 32px;
    width: max-content;
    animation: slide-exemples var(--slider-speed, 30s) linear infinite;
}

.exemples-track:hover { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
    .exemples-track { animation: none; }
}

/* ─── Bouton "Accélérer le diaporama" ───
   Style "fonctionnel" (même logique que .btn-account--functional /
   .footer-cta : sobre, bordure fine, fond quasi transparent, typo
   majuscule) plutôt qu'un CTA marketing — c'est une commande, pas une
   invitation à naviguer. Pas d'icône fusée : par convention du site elle
   est réservée aux liens cliquables, pas aux boutons d'action. */
.exemples-controls {
    display: flex;
    justify-content: center;
    margin: 28px 0 0;
}

/* Couleur pilotée par --header-accent (pas --brand-color, demande explicite,
   bug signalé : "en couleur auto, le bouton accélérer le diaporama est bleu
   au lieu d'orange") — --header-accent est TOUJOURS posé selon la couleur
   par défaut de la page active (cf. $_header_accent_map dans
   partials/header.php, 'amber' pour sitepro.php), y compris en "Couleur
   auto" (aucune préférence explicite du visiteur). --brand-color, lui, n'est
   posé que lorsqu'un visiteur a choisi une couleur explicite (cf. classes
   .user-accent-* dans header.php) : en mode auto, ce bouton retombait donc
   sur le bleu par défaut de :root au lieu de suivre l'ambre de la page. */
.exemples-speed-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 18px;
    border-radius: 999px;
    background: rgba(255,255,255,.03);
    border: 1px solid color-mix(in srgb, rgb(var(--header-accent)) 40%, rgba(255,255,255,.16));
    color: rgb(var(--header-accent));
    font-family: var(--font-title);
    font-weight: 600;
    font-size: .74rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
    touch-action: manipulation;
    transition: background .15s ease, border-color .15s ease, color .15s ease, transform .15s ease;
}

.exemples-speed-icon {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    transition: transform .15s ease;
}

.exemples-speed-btn:hover {
    background: color-mix(in srgb, rgb(var(--header-accent)) 12%, transparent);
    border-color: rgb(var(--header-accent));
    color: #fff;
}

/* État "maintenu" (clic prolongé / touche enfoncée) : le diaporama tourne
   réellement plus vite (cf. main.js), le bouton le confirme visuellement. */
.exemples-speed-btn.is-active {
    background: color-mix(in srgb, rgb(var(--header-accent)) 22%, transparent);
    border-color: rgb(var(--header-accent));
    color: #fff;
    transform: scale(.96);
}

.exemples-speed-btn.is-active .exemples-speed-icon {
    transform: translateX(2px);
}

.exemple-card {
    width: 340px;
    flex-shrink: 0;
    border-radius: 16px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    overflow: hidden;
    transition: border-color .25s, box-shadow .25s, transform .25s;
}

.exemple-card:hover {
    border-color: rgba(var(--header-accent),.4);
    box-shadow: 0 16px 40px rgba(var(--header-accent),.12);
    transform: translateY(-4px);
}

.browser-chrome {
    background: rgba(255,255,255,.06);
    border-bottom: 1px solid rgba(255,255,255,.07);
    padding: 10px 14px;
    display: flex;
    align-items: center;
    gap: 12px;
}

.browser-dots {
    display: flex;
    gap: 5px;
    flex-shrink: 0;
}

.browser-dots span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    display: block;
}

.browser-dots span:nth-child(1) { background: #ff5f57; }
.browser-dots span:nth-child(2) { background: #ffbd2e; }
.browser-dots span:nth-child(3) { background: #28c840; }

.browser-url {
    flex: 1;
    background: rgba(255,255,255,.06);
    border-radius: 6px;
    padding: 4px 10px;
    font-size: 0.72rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-family: monospace;
}

.browser-preview {
    width: 100%;
    height: 260px;
    overflow: hidden;
    position: relative;
    background: #fff;
}

.browser-preview iframe {
    width: 400%;
    height: 400%;
    border: none;
    transform: scale(0.25);
    transform-origin: top left;
    pointer-events: none;
}

.exemple-card-meta {
    padding: 14px 20px 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.exemple-card-price {
    display: inline-block;
    align-self: flex-start;
    font-family: var(--font-title);
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--brand-color);
    background: var(--brand-color-soft);
    border: 1px solid rgba(var(--header-accent),.25);
    border-radius: 999px;
    padding: 3px 12px;
}

.exemple-card-modules {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.exemple-module-tag {
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--text-muted);
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 6px;
    padding: 3px 9px;
    white-space: nowrap;
}

.exemple-card-footer {
    padding: 16px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.exemple-card-info h3 {
    font-family: var(--font-title);
    font-size: 1rem;
    font-weight: 600;
    color: #fff;
    margin-bottom: 2px;
}

.exemple-card-info span {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.exemple-card-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--brand-color);
    text-decoration: none;
    white-space: nowrap;
    transition: gap .2s;
}

.exemple-card-link:hover { gap: 10px; }


/* ─── Avis clients (accueil.php) ─────────────────────────────── */
.reviews-section { padding: 80px 24px var(--footer-clearance); position: relative; }
/* min-width:0 : .reviews-inner est un flex item (parent display:flex en
   colonne sur accueil.php/.reviews-section--accueil). Sans ça, sa taille
   minimale automatique se cale sur le min-content de .reviews-track
   (width:max-content, plusieurs cartes de 340px) MALGRÉ le overflow:hidden
   de .reviews-slider-wrap — un classique de flexbox. Résultat sur mobile :
   .reviews-inner est forcé plus large que l'écran, et comme html a
   overflow-x:clip (pas de scroll horizontal possible), le titre et le
   bouton "livre d'or" qu'il contient se retrouvent simplement invisibles,
   hors-champ à droite, sans aucun moyen d'y accéder. */
.reviews-inner { max-width: 1100px; width: 100%; min-width: 0; margin: 0 auto; text-align: center; position: relative; z-index: 1; }

/* ─── accueil.php : fond assorti au reste de la page ─── */
/* Le bloc FAQ ajouté après cette section est maintenant la dernière
   section de la page (voir .faq-preview-section) : c'est donc lui qui
   réserve l'espace du footer flottant, pas cette section-ci. Sans cette
   surcharge de padding-bottom, l'espace réservé se retrouvait au milieu
   de la page, entre les avis et la FAQ, au lieu d'être tout en bas. */
.reviews-section--accueil {
    /* 100dvh (demande explicite), même logique que .why-cta-section :
       min-height + flex column + centrage vertical du contenu. */
    min-height: 100dvh;
    /* demande explicite : réduction de largeur -10%/côté, cf. commentaire
       détaillé sur .method plus haut. */
    width: 90%;
    margin-left: auto;
    margin-right: auto;
    display: flex;
    flex-direction: column;
    /* flex-end (et non plus center) : demande explicite de décaler le
       contenu vers le bas de la section plutôt que de le centrer
       verticalement. */
    justify-content: flex-end;
    /* padding-top passé de 30px à la même échelle que les autres sections
       "dans le vaisseau" (demande explicite : "contenu trop collé en
       haut") : avec justify-content:flex-end, un contenu plus haut que la
       section ne bénéficie d'aucun centrage automatique — seul ce
       padding-top garantit une vraie respiration sous le nouveau bandeau
       .section-sas. */
    padding-top: clamp(90px, 10vh, 120px);
    padding-bottom: 80px;
    overflow: hidden;
    /* demande explicite : "uniformise le bg [des 7 sections de la fusée] à
       la façon des sites évolutifs construits autour de modules" — reprend
       exactement le fond de main .modules, cf. commentaire détaillé sur
       .method plus haut. */
    background:
        radial-gradient(ellipse at 0% 100%,   rgba(var(--header-accent),.18) 0%, transparent 45%),
        radial-gradient(ellipse at 100% 0%,   rgba(var(--header-accent),.10) 0%, transparent 45%),
        radial-gradient(ellipse at 50% 50%,   rgba(var(--header-accent),.05) 0%, transparent 65%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.025) 0,
            rgba(255,255,255,.025) 1px,
            transparent 1px,
            transparent 44px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.018) 0,
            rgba(255,255,255,.018) 1px,
            transparent 1px,
            transparent 44px
        ),
        rgba(7,10,18,.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-top: 1px solid rgba(var(--header-accent),.14);
    border-bottom: 1px solid rgba(var(--header-accent),.14);
}

.reviews-section--accueil::before {
    content: "";
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(
        0deg,
        transparent 0,
        transparent 3px,
        rgba(0,0,0,.03) 3px,
        rgba(0,0,0,.03) 4px
    );
    pointer-events: none;
    z-index: 0;
}

/* ===================== RESPONSIVE MOBILE : FUSÉE PLEINE LARGEUR =====================
   Demande explicite : "sur mobile, il faudrait que la fusée colle les bords
   du téléphone... adapter la capsule du haut de la fusée en fonction. Le but
   est de gagner de l'espace pour le contenu des sections."
   Les 7 sections "dans le vaisseau" (#method-heading -> #faq-preview, cf.
   commentaire détaillé sur .method plus haut) sont réduites à 90% de largeur
   en permanence (10% de marge répartie de chaque côté) pour donner
   l'impression que la fusée flotte dans l'espace — un bel effet sur grand
   écran, mais qui coûte ~20% de largeur de contenu en trop sur un téléphone,
   où chaque pixel compte. Repassées à 100% sous ce breakpoint (fusée collée
   aux bords de l'écran, comme demandé) :
   - .metal-plate-dome-cap (la capsule, hors section, cf. commentaire détaillé
     plus haut) suit avec left/right:0 pour rester exactement alignée avec le
     haut de la coque désormais pleine largeur, au lieu de "flotter" en
     retrait par rapport à des sections qui ne le sont plus.
   - .rocket-hull-edge (coques latérales) et .section-sas (bandeau du sas)
     n'ont besoin d'AUCUN ajustement : déjà en position absolute left/right:0
     à l'intérieur de chaque section, ils suivent automatiquement la nouvelle
     largeur — ils se retrouvent donc collés aux bords réels de l'écran
     plutôt qu'à 10% de marge, exactement l'effet recherché, sans perdre le
     visuel "coque de vaisseau" qui délimite chaque section. */
@media (max-width: 640px) {
    .sol-off,
    .problem,
    .method,
    .why-target,
    main .modules,
    .reviews-section--accueil,
    .faq-preview-section--bg {
        width: 100%;
        margin-left: 0;
        margin-right: 0;
    }

    .metal-plate-dome-cap {
        left: 0;
        right: 0;
    }
}


/* ─── index.php : la section newsletter ajoutée après les avis devient la
   dernière section de la page ; c'est donc elle qui réserve l'espace du
   footer flottant (même principe que reviews-section--accueil ci-dessus,
   pour accueil.php/faq-preview-section). ─── */
.reviews-section--index { padding-bottom: 80px; }

/* Halo de fond accent-aware (demande explicite : "livre d'or et newsletter
   [...] il s'agit de l'ensemble : la couleur d'écriture, le fond (halo),
   les // etc" — ces 2 sections d'index.php n'avaient jusqu'ici AUCUN fond
   dédié, contrairement à .reviews-section--accueil (accueil.php) qui a
   déjà ce même radial-gradient rgba(var(--header-accent)) depuis un tour
   précédent. Même halo ici, réutilisé tel quel pour rester cohérent avec
   le reste du site. */
.reviews-section--index {
    background: radial-gradient(ellipse at 50% 0%, rgba(var(--header-accent), .12) 0%, transparent 55%);
}

/* demande explicite : "enlève le reflet en haut de section [newsletter],
   je veux que le bg soit juste l'image de la page" — .newsletter-section
   partageait jusqu'ici le même halo que .reviews-section--index ci-dessus ;
   il ne doit plus avoir aucun fond propre, seul le fond fixe générique
   .site-main::before (bgsite.png) doit transparaître. */
.newsletter-section {
    background: none;
}

.reviews-eyebrow, .newsletter-eyebrow {
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--brand-color);
    background: var(--brand-color-soft);
    border: 1px solid rgba(var(--header-accent),.25);
    border-radius: 999px;
    padding: 4px 14px;
    margin-bottom: 16px;
}

/* color:#fff en dur -> rgb(var(--title-accent)) (demande explicite
   ci-dessus, "la couleur d'écriture" du titre lui-même, pas seulement le
   petit "//" devant lui, cf. h2::before tout en haut de ce fichier, déjà
   accent-aware) : --title-accent est la variable dédiée aux titres
   (cf. h1/h2, .accent-* tout en haut), déjà recalculée pour les 6
   couleurs. text-shadow ajouté en plus pour un léger halo lumineux
   directement sur le texte, assorti au fond ci-dessus. */
.reviews-title, .newsletter-title {
    font-family: var(--font-title);
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    color: rgb(var(--title-accent));
    text-shadow: 0 0 24px rgba(var(--title-accent), .35);
    margin-bottom: 0;
    transition: color .4s ease, text-shadow .4s ease;
}

@keyframes slide-reviews {
    from { transform: translateX(0); }
    to   { transform: translateX(calc(-100% / var(--sets, 2))); }
}

.reviews-slider-wrap {
    overflow: hidden;
    margin-top: 44px;
    mask-image: linear-gradient(to right, transparent 0%, black 8%, black 92%, transparent 100%);
    -webkit-mask-image: linear-gradient(to right, transparent 0%, black 8%, black 92%, transparent 100%);
}

.reviews-track {
    display: flex;
    gap: 20px;
    width: max-content;
    animation: slide-reviews var(--slider-speed, 36s) linear infinite;
}

.reviews-track:hover { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
    .reviews-track { animation: none; }
}

.review-item {
    width: 340px;
    height: 324px;
    flex-shrink: 0;
    text-align: left;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 16px;
    padding: 28px 26px 24px;
    position: relative;
    overflow: hidden;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    transition: border-color .25s, box-shadow .25s;
    display: flex;
    flex-direction: column;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

.review-item::before {
    content: '\201C';
    position: absolute;
    top: 6px; right: 18px;
    font-size: 80px;
    font-family: Georgia, serif;
    line-height: 1;
    color: var(--brand-color);
    opacity: 0.12;
    pointer-events: none;
}

/* Pas de transform ici volontairement : combiné à -webkit-line-clamp sur
   .review-message (message tronqué à taille fixe), un translateY/scale au
   survol faisait réapparaître le texte "agrandi" hors de sa zone tronquée
   (bug de rendu webkit line-clamp + transform). Le lift visuel se fait donc
   uniquement via bordure/ombre, sans déplacer/transformer la carte. */
.review-item:hover {
    border-color: rgba(var(--header-accent),.4);
    box-shadow: 0 16px 40px rgba(var(--header-accent),.12);
}

.review-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 6px;
    gap: 10px;
}

.review-author { display: flex; align-items: center; gap: 10px; }

.review-avatar {
    width: 36px; height: 36px; flex-shrink: 0;
    border-radius: 50%;
    /* Fond TOUJOURS blanc (demande explicite, même correctif que
       .review-card-avatar ci-dessus) — l'initiale reprend --brand-color en
       couleur de texte plutôt que le fond. */
    background: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 14px; font-weight: 700; color: var(--brand-color);
    text-transform: uppercase;
}

.review-name { font-size: 14px; font-weight: 700; color: #fff; }

.review-rating {
    color: #fbbf24;
    font-size: 15px;
    flex-shrink: 0;
    letter-spacing: 1px;
}

.review-date { font-size: 11px; color: var(--text-muted); margin-bottom: 14px; opacity: .7; }

/* Repère discret "avis modifié" (icône crayon + tooltip), accolé à la date
   d'un avis via review_edited_badge() (cf. includes/reviews_bootstrap.php) —
   n'apparaît que si l'auteur a édité son avis depuis compte-avis.php. */
.review-edited-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: 6px;
    color: rgba(255,255,255,.4);
    position: relative;
    cursor: help;
    vertical-align: middle;
}
.review-edited-badge:hover,
.review-edited-badge:focus-visible { color: rgba(255,255,255,.75); outline: none; }
.review-edited-badge::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    background: #10131a;
    border: 1px solid rgba(255,255,255,.12);
    color: #fff;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    padding: 5px 10px;
    border-radius: 8px;
    opacity: 0;
    visibility: hidden;
    transition: opacity .15s ease;
    pointer-events: none;
    z-index: 20;
}
.review-edited-badge:hover::after,
.review-edited-badge:focus-visible::after { opacity: 1; visibility: visible; }

.review-message {
    font-size: .88rem;
    color: var(--text-muted);
    line-height: 1.65;
    border-top: 1px solid rgba(255,255,255,.06);
    padding-top: 14px;
    margin-top: 2px;
    /* Même correctif que .review-card-message (livre-dor.php) : préserve les
       retours à la ligne saisis dans le formulaire d'avis. */
    white-space: pre-line;
    /* Box de taille standardisée (.review-item a une hauteur fixe) : le
       message est tronqué à 5 lignes quel que soit sa longueur (même logique
       que le diaporama de livre-dor.php) — l'ellipse "…" apparaît
       naturellement si ça continue, et toute la carte reste cliquable pour
       lire l'avis complet dans le catalogue.
       max-height (8.25em = 5 lignes à line-height:1.65) est nécessaire EN PLUS
       de -webkit-line-clamp : cet élément est aussi un enfant flex (flex:1)
       de .review-item, et flex:1 étire sa hauteur pour remplir tout l'espace
       restant de la carte, bien au-delà des 5 lignes — sur certains avis
       longs, ce conflit flex/line-clamp laissait le texte réel déborder
       ("hors zone") sous l'ellipse au lieu d'être masqué.
       box-sizing: content-box est indispensable ici : le reset global du
       site pose box-sizing:border-box partout (cf. début de ce fichier), ce
       qui aurait inclus padding-top (14px) + border-top (1px) DANS les
       8.25em de max-height, laissant ~15px de moins que les 5 lignes réelles
       — la boîte coupait alors une partie de la 5e ligne / laissait un bout
       de ligne suivante à moitié visible sous l'ellipse. En content-box,
       max-height ne porte que sur le texte lui-même (padding/bordure
       s'ajoutent par-dessus), ce qui fait exactement correspondre la
       limite dure avec les 5 lignes que -webkit-line-clamp calcule en
       interne, sans aucun bout de ligne visible en trop. */
    box-sizing: content-box;
    max-height: 8.25em;
    flex: 1;
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Indique explicitement que la carte est cliquable et amène à l'avis complet
   dans le catalogue du livre d'or (cf. ?page=X#review-ID) — sans ce repère,
   rien ne signalait qu'un clic ouvrait la suite du message tronqué. */
.review-readmore {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-top: 8px;
    font-size: .74rem;
    font-weight: 600;
    color: var(--brand-color);
    opacity: .85;
    flex-shrink: 0;
    transition: opacity .15s ease, transform .15s ease;
}

.review-readmore svg { flex-shrink: 0; }

.review-item:hover .review-readmore { opacity: 1; transform: translateX(3px); }

.reviews-footer { margin-top: 36px; }

.reviews-all-btn { display: inline-flex; }

/* Écart réduit entre le bouton "livre d'or" et le divider rockette juste
   en dessous (demande explicite, ajustement répété : le premier passage à
   4px restait encore trop grand) : surcharge le margin-top générique
   .site-main .section-divider (clamp(18px,3vh,32px), pensé pour les
   dividers ENTRE deux sections bien distinctes) qui donnait ici un écart
   trop grand entre un bouton et le divider de SA PROPRE section. On retire
   aussi le padding-top propre au rocket-wrapper (10px, hérité de la règle
   générique .site-main .section-divider .rocket-wrapper) qui ajoutait
   encore de l'espace au-dessus de la fusée. */
.site-main .section-divider--faq {
    margin-top: -10px;
}

.site-main .section-divider--faq .rocket-wrapper {
    padding-top: 0;
}

.reviews-cta {
    max-width: 560px;
    margin-left: auto;
    margin-right: auto;
    padding-top: 8px;
}

.reviews-cta-text {
    font-size: .95rem;
    color: var(--text-muted);
    line-height: 1.6;
    margin-bottom: 20px;
}

.reviews-cta-actions {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}

.reviews-cta-btn { display: inline-flex; }

/* ─── index.php : section "Newsletter" (après les avis) ─── */
.newsletter-section { padding: 80px 24px var(--footer-clearance); position: relative; }
.newsletter-inner { max-width: 640px; margin: 0 auto; text-align: center; position: relative; z-index: 1; }
.newsletter-text { font-size: .95rem; color: var(--text-muted); line-height: 1.6; margin: 18px auto 26px; max-width: 520px; }
.newsletter-form { display: flex; justify-content: center; }
.newsletter-hint { font-size: .85rem; color: var(--text-muted); margin-top: 16px; }
.newsletter-hint a { color: var(--brand-color); font-weight: 600; text-decoration: none; }
.newsletter-hint a:hover { text-decoration: underline; }
.newsletter-hint--active { color: #34d399; display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; }
.newsletter-hint--active svg { flex-shrink: 0; }

.reviews-see-all-link {
    font-size: .82rem;
    color: var(--text-muted);
    text-decoration: underline;
    text-underline-offset: 3px;
    transition: color .2s;
}

.reviews-see-all-link:hover { color: var(--brand-color); }

@media (max-width: 700px) {
    .review-item { width: 260px; }
}


/* ─── Formulaire de commande (pages d'offres) ────────────────── */
/* padding-bottom généreux : la page se termine ici, il faut laisser la
   place au footer flottant (variable --footer-clearance, cf. plus haut)
   sans qu'il ne recouvre le bouton "Générer mon devis". */
.order-form-section { padding: 60px 24px var(--footer-clearance); }
.order-form-section .container { max-width: 1100px; margin: 0 auto; }

/* ─── Espace compte / admin ──────────────────────────────────── */
/* Même remarque : ces pages se terminent souvent juste après une carte/table,
   il faut réserver assez d'espace pour que le footer flottant ne recouvre
   jamais le dernier bouton/lien visible en bas de page.
   padding-top ramené de 100px à 32px : ce 100px réservait la place du
   header flottant (toujours visible en haut de page auparavant). Depuis que
   le header reste masqué à l'arrivée sur .account-page et ne réapparaît
   qu'au scroll (cf. body:has(main.page-service, main.account-page)
   .site-header:not(.visible) plus haut), cette réserve n'a plus lieu
   d'être — 32px ne sert plus qu'à garder un peu d'air en haut du titre. */
.account-page { padding: 32px 24px var(--footer-clearance); }

/* Pages compte-*.php (dashboard utilisateur) : header ET mini-footer classique
   (sitemap/logo/réseaux sociaux) restent entièrement désactivés (cf.
   partials/header.php $_isUserAccountPage), MAIS les widgets flottants
   Couleur/Langue, eux, y sont désormais visibles au même titre que sur
   admin-*.php (demande explicite : "les sélecteurs de langue et de couleur
   en bas de page" sur les pages utilisateur ET admin) — la réserve
   var(--footer-clearance) de la règle .account-page ci-dessus reste donc
   nécessaire ici aussi (ancien override à 40px retiré, il aurait laissé ces
   2 widgets recouvrir le bas du contenu). */

/* ─── Lisibilité renforcée sur tout l'espace compte/admin (textes, liens, boutons) ───
   --text-muted est redéfini localement (hérité par tous les descendants de
   .account-page) sans toucher sa valeur globale utilisée ailleurs sur le site. */
.account-page { --text-muted: rgba(255,255,255,.85); }

/* Liens "bruts" dans les textes (hints, empty states, alertes) : pas de classe
   dédiée, donc ils héritaient sinon de la couleur de lien par défaut du
   navigateur — peu lisible et peu cohérent avec la charte. */
.account-page a:not([class]) {
    color: #7cb8ff;
    font-weight: 600;
    text-decoration: underline;
    text-decoration-color: rgba(124,184,255,.45);
    text-underline-offset: 2px;
    transition: color .15s ease;
}
.account-page a:not([class]):hover { color: #fff; text-decoration-color: currentColor; }

/* Boutons "outline" : bordure et fond trop discrets sur fond sombre. */
.btn-account--outline {
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.34);
    color: #fff;
}
.btn-account--outline:hover {
    background: rgba(255,255,255,.10);
    border-color: rgba(255,255,255,.55);
}

/* Liens de la navigation latérale (compte/admin) : légèrement plus lisibles
   à l'état inactif, sans changer la logique de surbrillance de l'état actif. */
.account-sidenav-link { color: rgba(255,255,255,.82); }
.account-sidenav-link:hover { color: #fff; }

/* ─── BACKGROUND FIXE (même image que le reste du site) ───
   var(--space-bg) plutôt que bgsite.png en dur : ce calque, propre aux
   dashboards (.account-page, compte-*.php ET admin-*.php), est peint
   PAR-DESSUS .site-main::before (même z-index:0, mais .account-page est
   descendant de .site-main dans le DOM donc peint après) — c'est en réalité
   LUI qui déterminait le fond visible sur les dashboards, pas
   .site-main::before : le corriger séparément était nécessaire pour que le
   fond y suive aussi la couleur choisie en Mon profil. */
.account-page::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
    /* pointer-events:none AJOUTÉ (correctif) : cette couche décorative fixe
       couvre TOUTE la page (inset:0) — contrairement à .account-page::after
       juste en dessous (le trou noir), qui l'a déjà, celle-ci ne l'avait
       jamais eu. Un pseudo-élément fixed sans pointer-events:none reste
       cliquable/tactile par défaut : posé par-dessus toute la page, il
       pouvait intercepter des gestes de glissement avant qu'ils n'atteignent
       les éléments réels en dessous (ex. le scroll tactile des bandes de
       nav du dashboard), tout en laissant passer les simples taps selon le
       moteur de rendu — cohérent avec le bug remonté ("le tap marche, pas
       le swipe"). Aucun changement visuel : purement décoratif, ne doit de
       toute façon jamais intercepter d'interaction. */
    pointer-events: none;
}

/* ─── Trou noir de fond, dashboards admin + utilisateur (demande explicite :
   "je veux bien un trou noir en fond dépendant de la couleur sélectionnée, en
   position fixe peu importe le scroll") ───
   Même habillage que .index-hero-black-hole (disque d'accrétion conique
   tournant + cœur noir/horizon des événements) et mêmes variables de couleur
   --hole-light/-mid/-soft/-base/-glow (déjà posées par .img-accent-* sur
   <body> selon la préférence choisie en Mon profil, cf. partials/header.php
   $_imgAccentColor — repli bleu par défaut si aucune préférence explicite),
   mais posé ici en un seul pseudo-élément ::after (::before est déjà pris par
   le fond étoilé ci-dessus) combinant l'anneau ET le cœur noir dans les
   mêmes calques de background, et SANS l'animation d'entrée (dézoom lié à
   --reveal-delay) propre aux heros publics : toujours visible dès le
   chargement, en continu. position:fixed (comme .account-page::before,
   PAS absolute) : reste bien à l'écran quel que soit le défilement, plutôt
   que de défiler avec le contenu. z-index:0, même contexte d'empilement que
   .account-page::before (peint APRÈS lui grâce à l'ordre before/after, donc
   visible par-dessus le fond étoilé) et toujours sous le contenu réel
   (.account-page > *, z-index:1 plus haut). Discret (alpha réduit sur
   chaque calque, PAS de opacity: .5 sur l'élément) : sert d'ambiance de
   fond permanente, ne doit jamais gêner la lecture des formulaires/tableaux
   par-dessus.
   Bug signalé ("le trou noir n'est pas noir, problème d'opacité") : un
   `opacity: .5` posé directement sur cet ::after diminuait TOUT l'élément
   d'un coup, y compris le cœur radial-gradient(#000...) censé être un vrai
   noir plein (horizon des événements) — composité à 50% d'opacité sur le
   fond étoilé déjà sombre, il rendait comme un gris/bleu-noir plutôt qu'un
   vrai noir. Fix : opacity retirée, alpha de chaque stop du conic-gradient
   (l'anneau) ET du box-shadow (la lueur) divisé par 2 pour conserver EXACTEMENT
   la même luminosité visible qu'avant (alpha × opacity .5 == alpha/2 × opacity 1)
   — seul le cœur #000 (jamais concerné par ces alpha) redevient un noir plein. */
.account-page::after {
    content: "";
    position: fixed;
    top: 50vh;
    left: 50vw;
    width: clamp(390px, 42vw, 620px);
    height: clamp(390px, 42vw, 620px);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(circle, #000 0%, #000 40%, rgba(0,0,0,0) 50%),
        conic-gradient(
            from -20deg,
            rgba(255,255,255,0)                     0deg,
            rgba(var(--hole-mid, 140,190,255),.3)   38deg,
            rgba(var(--hole-base, 60,150,255),.34)  68deg,
            rgba(var(--hole-light, 200,225,255),.35) 92deg,
            rgba(var(--hole-soft, 110,180,255),.18) 118deg,
            rgba(255,255,255,0)                     152deg,
            rgba(255,255,255,0)                     222deg,
            rgba(var(--hole-soft, 90,170,255),.11)  250deg,
            rgba(var(--hole-soft, 90,170,255),.2)   282deg,
            rgba(var(--hole-light, 200,225,255),.275) 302deg,
            rgba(var(--hole-base, 50,150,255),.2)   320deg,
            rgba(255,255,255,0)                     360deg
        );
    box-shadow: 0 0 70px 22px rgba(var(--hole-glow, 80,150,255),.11);
    filter: blur(20px);
    animation: blackHoleSpin 26s linear infinite;
}

.account-page > * {
    position: relative;
    z-index: 1;
}

.account-hero { max-width: 1180px; margin: 0 auto 32px; text-align: center; }
.account-hero h1 { font-family: var(--font-title); font-size: clamp(1.5rem, 3vw, 2rem); color: #fff; margin-bottom: 8px; }
.account-hero p { color: var(--text-muted); }

/* ─── Bandeau d'en-tête des pages du dashboard client (compte-*.php +
     faq.php) — remplace le titre/sous-titre centrés "flottants" par un
     bandeau encadré aligné à gauche, avec une icône reprenant celle du menu
     latéral (cf. partials/account-nav.php), pour donner plus de présence
     visuelle qu'un simple h1/p. Recolorable via var(--brand-color) /
     --brand-color-soft / --brand-color-glow (couleur choisie par le client,
     cf. .user-accent-* plus haut dans ce fichier) — même mécanique que le
     reste du site pour cette personnalisation.
     Sélecteur combiné .account-hero.account-hero--banner (2 classes sur le
     même élément) pour garantir la priorité sur .account-hero de base, quel
     que soit l'ordre des règles dans ce fichier (cf. le bug de spécificité
     rencontré plus tôt cette session avec .section-divider). ─── */
.account-hero.account-hero--banner {
    display: flex;
    align-items: center;
    gap: 20px;
    text-align: left;
    background: linear-gradient(135deg, var(--brand-color-soft), rgba(255,255,255,.03));
    border: 1px solid var(--brand-color-soft);
    border-radius: 18px;
    padding: 24px 28px;
    box-shadow: 0 20px 45px -28px var(--brand-color-glow);
}
.account-hero--banner .account-hero-icon {
    flex-shrink: 0;
    width: 52px;
    height: 52px;
    border-radius: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--brand-color-soft);
    border: 1px solid var(--brand-color-glow);
    color: var(--brand-color);
}
.account-hero--banner .account-hero-icon svg { width: 26px; height: 26px; }
/* pages/compte-creer-site.php : icône planète Terre (assets/image/planet-terre.png)
   à la place d'un pictogramme SVG générique (demande explicite) — même
   traitement circulaire que .offer-planet img sur offres-site.php. */
.account-hero--banner .account-hero-icon img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }
.account-hero--banner .account-hero-text { min-width: 0; }
.account-hero--banner h1 { text-align: left; margin-bottom: 6px; }
.account-hero--banner p { text-align: left; margin: 0; }

@media (max-width: 640px) {
    .account-hero.account-hero--banner { flex-direction: column; align-items: flex-start; padding: 20px; }
}

/* Menu compte/admin splitté en 2 colonnes (gauche + droite), demande
   explicite : "travail" à gauche (Tableau de bord/Mes projets côté client,
   CroisierWeb/Gestion projets/Outils côté admin), "compte"/gestion à droite
   — plus de place par colonne pour agrandir les liens (meilleure
   lisibilité). Colonnes agrandies une 1ère fois (220px -> 280px à gauche /
   240px à droite, demande explicite "surtout celle travail"), puis une 2e
   fois (280px -> 310px à gauche / 240px -> 260px, demande explicite
   "agrandit encore la navigation") pour accompagner l'agrandissement des
   liens eux-mêmes (.account-sidenav-link) — largeur totale augmentée
   d'autant à chaque fois pour que la section centrale (.account-content) ne
   rétrécisse pas (reste à 1024px).
   Demande explicite suivante : les 2 boutons de la barre du haut
   (partials/account-topbar.php) doivent être au même niveau que le titre
   de page (.account-hero--banner), à gauche et à droite de celui-ci, et
   non plus au-dessus des 2 colonnes de nav. Or .account-hero et
   .account-layout sont deux éléments frères directs de <main
   class="account-page"> (cf. structure commune à toutes les pages
   compte-*.php / admin-*.php) : pour que les boutons (contenus dans
   .account-layout > partial > .account-topbar) et le titre (.account-hero,
   frère de .account-layout) partagent la même ligne de grille, c'est
   .account-page lui-même qui doit devenir l'hôte de la grille — .account-layout
   ET .account-topbar passent en display:contents (à toutes les tailles
   d'écran désormais, plus seulement en mobile comme avant) pour que leurs
   descendants (colonnes de nav, contenu, boutons) deviennent des enfants de
   grille directs de .account-page, placés explicitement via grid-column/
   grid-row plutôt que via l'ordre du DOM. */
.account-page {
    max-width: 1650px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 310px 1fr 260px;
    grid-template-rows: auto auto;
    gap: 28px;
    align-items: start;
    /* Distance entre le bord de l'écran et le bord de la grille (demande
       explicite : "la NAV reste fixe... peu importe le scroll", boutons du
       haut y compris) — la nav et les 2 boutons passent de sticky/grid à
       position:fixed ci-dessous, il faut donc recalculer À LA MAIN la
       coordonnée horizontale qu'ils occupaient jusqu'ici implicitement via
       la grille centrée (max-width:1650px + margin:auto + padding 24px de
       .account-page, cf. plus bas dans ce fichier). max() retombe sur 24px
       (le padding de .account-page) tant que l'écran fait moins de 1650px
       de large, et suit ensuite la marge de centrage réelle au-delà —
       reproduisant exactement la position gauche/droite qu'avait la grille,
       désormais en position:fixed. */
    --dash-edge: max(24px, calc((100vw - 1650px) / 2 + 24px));
}
.account-layout { display: contents; }

/* .account-layout passant en display:contents ci-dessus À TOUTE TAILLE
   D'ÉCRAN (et non plus seulement en mobile), ses enfants ne sont plus
   sélectionnés par ".account-page > *" (qui ne vise que les enfants
   DIRECTS dans l'arbre DOM) et perdent le position:relative + z-index:1
   qui les faisait passer au-dessus du fond fixe .account-page::before —
   réappliqué explicitement ci-dessous (.account-sidenav-col,
   .account-content) et sur .account-topbar-btn plus bas.
   grid-column/grid-row ci-dessous n'ont plus d'effet réel depuis le passage
   de .account-sidenav-col--left/--right en position:fixed (cf. plus bas) —
   un élément hors-flux ignore son placement de grille — mais restent posés
   pour documenter la colonne d'origine ; c'est désormais left/right (via
   var(--dash-edge)) qui fixe leur position horizontale. */
.account-sidenav-col--left  { grid-column: 1; grid-row: 2; }
.account-content            { grid-column: 2; grid-row: 2; position: relative; z-index: 1; }
.account-sidenav-col--right { grid-column: 3; grid-row: 2; }

/* Le titre de page (.account-hero--banner) reste un enfant direct de
   .account-page (jamais passé en display:contents) : il occupe la colonne
   centrale de la 1ère ligne de grille, entre les 2 boutons de la barre du
   haut. .max-width/.margin de la règle de base .account-hero (centrage en
   bloc classique) sont annulés ici : dans une grille, la largeur/position
   sont pilotées par la colonne, pas par des marges automatiques. */
.account-hero.account-hero--banner {
    grid-column: 2;
    grid-row: 1;
    max-width: none;
    margin: 0;
}

/* Barre du haut (partials/account-topbar.php) : "Accueil" à gauche, "Mon
   profil" à droite — raccourcis en plus des liens déjà présents dans les
   colonnes (demande explicite), pas un remplacement.
   display:contents ici aussi (desktop) : ses 2 boutons deviennent des
   enfants de grille indépendants de .account-page, placés chacun de part
   et d'autre du titre (colonnes 1 et 3, même ligne que le titre). Redevient
   un vrai conteneur flex en mobile (cf. media query plus bas), où les 2
   boutons doivent rester groupés au-dessus du menu. */
.account-topbar { display: contents; }
/* Même habillage "vaisseau spatial" que .account-sidenav ci-dessous et que
   les widgets flottants Couleur/Langue (demande explicite : améliorer le
   visuel de ces 2 boutons, sans toucher à leur position haut-gauche/
   haut-droite ni à leur fonction). background-image/-color remplacent
   l'ancien aplat "background" unique — IMPORTANT : :hover/:focus-visible
   ci-dessous utilisent donc background-color (pas le raccourci "background")
   pour ne pas effacer cette vignette au survol. */
/* position:fixed (demande explicite : "2 boutons y compris" restent fixes
   peu importe le scroll) — top:22px reprend le même repère que les autres
   éléments flottants "vaisseau spatial" du site (cf. .hud-widget--nav/
   --account, top:22px sur les pages publiques). left/right via
   var(--dash-edge) (cf. .account-page plus haut) : reproduit la position
   horizontale qu'avait la grille (grid-column:1/3 + justify-self start/end),
   devenue sans effet sur un élément désormais hors-flux. */
.account-topbar-btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 16px 28px;
    border-radius: 999px;
    background-image:
        linear-gradient(rgba(var(--header-accent),.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(var(--header-accent),.05) 1px, transparent 1px);
    background-size: 14px 14px;
    background-color: rgba(var(--header-accent),.035);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(var(--header-accent),.16);
    color: #fff;
    font-size: 1.02rem;
    font-weight: 700;
    text-decoration: none;
    position: fixed;
    top: 22px;
    z-index: 5;
    box-shadow: 0 10px 26px -18px rgba(0,0,0,.65), 0 0 20px -12px rgba(var(--header-accent),.35);
    transition: background-color .15s ease, border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.account-topbar-btn--home    { left: var(--dash-edge); }
.account-topbar-btn--profile { right: var(--dash-edge); }
/* Icône en chip, même traitement que .account-sidenav-link svg ci-dessous. */
.account-topbar-btn svg {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    padding: 4px;
    box-sizing: content-box;
    border-radius: 50%;
    background: rgba(var(--header-accent),.12);
    transition: background .15s ease;
}
.account-topbar-btn:hover {
    border-color: rgba(var(--header-accent),.4);
    background-color: var(--brand-color-soft);
    box-shadow: 0 10px 26px -16px rgba(var(--header-accent),.55), 0 0 0 1px rgba(var(--header-accent),.15);
    transform: translateY(-1px);
}
.account-topbar-btn:hover svg { background: rgba(var(--header-accent),.22); }
.account-topbar-btn:focus-visible {
    outline: 2px solid rgba(var(--header-accent),.7);
    outline-offset: 2px;
    border-color: rgba(var(--header-accent),.4);
    background-color: var(--brand-color-soft);
}

/* ─── partials/account-topbar.php : switch admin <-> compte utilisateur
     (demande explicite) — remplace le bouton "Mon profil" seul UNIQUEMENT
     pour un compte admin, dans le même emplacement de grille
     (.account-topbar-btn--profile, cf. règle grid-column:3 plus haut,
     réutilisée telle quelle sur ce nouveau conteneur).
     "position: relative; z-index: 1;" indispensable ici (bug identifié :
     bouton invisible, ou visible une fraction de seconde puis masqué) :
     .account-topbar-switch est un descendant de .account-layout, passé en
     display:contents (cf. plus haut), donc PAS un enfant DIRECT de
     .account-page — le sélecteur ".account-page > *" qui élève tout le
     reste au-dessus du fond fixe .account-page::before (position:fixed,
     z-index:0) ne le vise donc pas. .account-topbar-btn (l'ancien bouton
     "Mon profil" seul, remplacé par ce switch pour un compte admin)
     réapplique déjà cette élévation explicitement plus haut — il manquait
     ici sur son remplaçant. ─── */
/* Même vignette/flou que .account-topbar-btn ci-dessus, pour rester cohérent
   visuellement puisque ce switch occupe le même emplacement (compte admin
   uniquement) — box-shadow inset d'origine conservée (creuse le fond pour
   loger les 2 options), glow externe ajouté en plus. */
.account-topbar-switch {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    border-radius: 999px;
    background-image:
        linear-gradient(rgba(var(--header-accent),.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(var(--header-accent),.05) 1px, transparent 1px);
    background-size: 14px 14px;
    background-color: rgba(var(--header-accent),.035);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(var(--header-accent),.16);
    box-shadow: inset 0 1px 2px rgba(0,0,0,.25), 0 10px 26px -18px rgba(0,0,0,.65), 0 0 20px -12px rgba(var(--header-accent),.35);
    /* position:fixed explicite ici aussi (et non hérité de .account-topbar-btn
       --profile, qui porte déjà "right: var(--dash-edge)" via sa propre
       classe partagée sur cet élément, cf. partials/account-topbar.php) —
       évite tout risque d'écrasement par l'ordre des règles dans ce fichier :
       top/position doivent rester "fixed"/22px même si cette règle est lue
       après celle de .account-topbar-btn. */
    position: fixed;
    top: 22px;
    z-index: 5;
}
.account-topbar-switch-opt {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 12px 20px;
    border-radius: 999px;
    font-weight: 700;
    font-size: .92rem;
    color: rgba(255,255,255,.55);
    text-decoration: none;
    transition: background .18s ease, color .18s ease, box-shadow .18s ease, transform .12s ease;
}
.account-topbar-switch-opt svg { width: 16px; height: 16px; flex-shrink: 0; opacity: .85; }
.account-topbar-switch-opt:hover {
    color: #fff;
    background: rgba(var(--header-accent),.14);
}
.account-topbar-switch-opt:active { transform: scale(.96); }
.account-topbar-switch-opt.active {
    background: var(--brand-color);
    color: var(--brand-color-contrast, #fff);
    box-shadow: 0 2px 10px rgba(var(--header-accent),.45);
}
.account-topbar-switch-opt.active svg { opacity: 1; }
.account-topbar-switch-opt:focus-visible {
    outline: 2px solid rgba(var(--header-accent),.7);
    outline-offset: 2px;
}

/* Habillage "vaisseau spatial" (demande explicite : améliorer le visuel de
   la nav, contenu/fonctions/positions inchangés) — même recette que les
   widgets flottants Couleur/Langue (cf. .hud-widget) : léger quadrillage en
   fond + flou de verre, pour donner de la profondeur à un panneau qui était
   jusqu'ici un simple aplat semi-transparent. Padding/gap/border-radius
   INCHANGÉS : seule l'habillage visuel change, pas la mise en page.
   Teinté à la couleur d'accent choisie (demande explicite suivante :
   "ajoutons-y un peu de couleur, en fonction de la sélectionnée") —
   rgba(var(--header-accent),...) plutôt que du blanc neutre, comme partout
   ailleurs sur ces pages (cf. .account-sidenav-stat, .account-sidenav-cta) ;
   dosage volontairement léger ("un peu") pour rester un panneau sombre
   discret, pas une carte colorée. */
.account-sidenav {
    background-image:
        linear-gradient(rgba(var(--header-accent),.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(var(--header-accent),.05) 1px, transparent 1px);
    background-size: 16px 16px;
    background-color: rgba(var(--header-accent),.035);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(var(--header-accent),.16);
    border-radius: var(--radius);
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 1px;
    box-shadow: 0 0 0 1px rgba(0,0,0,.25), 0 18px 40px -26px rgba(0,0,0,.65), 0 0 24px -12px rgba(var(--header-accent),.35);
}

/* Colonne "travail" (gauche) — ajusté suite au retour explicite : le gap
   uniforme de 9px (précédent tour) créait trop d'espace À L'INTÉRIEUR même
   de la nav travail (entre "Tableau de bord", l'étiquette "Mes projets" et
   ses 4 liens), alors que l'écart voulu était surtout celui ENTRE les
   grandes sections (stats croisierweb -> nav travail -> boutons de
   demande). Remis à un gap serré (4px, proche de l'original 1px) pour
   l'intérieur de la liste ; l'écart avant le bloc "nav travail" est
   recréé À PART juste en dessous, via un margin-top ciblé sur
   .account-sidenav-link--big ("Tableau de bord", 1er élément du bloc) —
   les écarts stats-banner/CTA (margins déjà posés séparément, hors de ce
   conteneur flex) restent inchangés. Seule la colonne de droite (identité/
   à propos) garde le gap:1px d'origine, non concernée par la demande. */
.account-sidenav-col--left .account-sidenav { gap: 4px; }

/* Nav gauche/droite en position:fixed (demande explicite : "la NAV reste
   fixe... peu importe le scroll de l'utilisateur") — remplace l'ancien
   position:sticky, qui pouvait se détacher près du bas de page (cf.
   l'ancienne règle body.footer-revealed ci-dessous, supprimée : elle
   contredirait maintenant ce comportement). left/right posés séparément sur
   .account-sidenav-col--left/--right (cf. plus haut, var(--dash-edge)) pour
   reproduire la même position horizontale qu'avant, width explicite
   nécessaire (un élément fixed ne reprend plus la largeur de sa colonne de
   grille d'origine). top:96px sous les boutons du haut (eux aussi fixed
   désormais, cf. .account-topbar-btn plus bas) ; bottom:130px réserve la
   place des widgets flottants Couleur/Langue (position:fixed, bottom:22px,
   cf. partials/footer.php) — demande explicite "prévoit la place pour les 2
   sélecteurs du bas" — top+bottom posés ensemble dimensionnent
   automatiquement la hauteur disponible, overflow-y gère le cas où le menu
   est plus grand qu'elle. */
.account-sidenav-col {
    position: fixed;
    /* top augmenté 96px -> 114px (demande explicite : "toujours trop tassé...
       Bouton / Ecart / Stats CroisierWeb / Petit écart / Nav travail" — l'écart
       sous le bouton "Retour au site"/"Mon profil" était quasi nul). Rendu
       possible sans repasser en débordement par la suppression des 2 pastilles
       de stats personnelles juste au-dessus (cf. partials/account-nav.php,
       demande explicite précédente) : le budget de hauteur libéré par leur
       retrait est réinvesti ici plutôt que simplement laissé vide. */
    top: 114px;
    bottom: 130px;
    z-index: 5;
    overflow-y: auto;
    overflow-x: hidden;
}
.account-sidenav-col--left  { left: var(--dash-edge);  width: 310px; }
.account-sidenav-col--right { right: var(--dash-edge); width: 260px; }

/* Taille des liens augmentée (.87rem -> .95rem -> 1.05rem, padding + icône
   agrandis en conséquence, demandes explicites successives "agrandit
   grandement... les 2 barres de nav" puis "agrandit encore la navigation")
   — boost supplémentaire pour la colonne gauche ("travail") plus bas via
   .account-sidenav-col--left .account-sidenav-link. */
.account-sidenav-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: 8px;
    font-size: 1.05rem;
    font-weight: 500;
    color: var(--text-muted);
    text-decoration: none;
    border: 1px solid transparent;
    position: relative;
    transition: background .15s ease, color .15s ease, border-color .15s ease, transform .15s ease;
}

/* Icône en "chip" (petit fond arrondi autour du pictogramme, demande
   explicite d'amélioration visuelle) — padding+box-sizing:content-box pour
   ne pas réduire la taille visuelle de l'icône elle-même (width/height
   ci-dessous, et surchargés plus bas pour la colonne de gauche, restent la
   taille du TRAIT, le padding s'ajoute autour). */
.account-sidenav-link svg {
    width: 21px;
    height: 21px;
    flex-shrink: 0;
    padding: 5px;
    box-sizing: content-box;
    border-radius: 8px;
    background: rgba(var(--header-accent),.10);
    transition: background .15s ease;
}
/* Survol également teinté (demande explicite "un peu de couleur, en fonction
   de la sélectionnée") — remplace les tons blancs neutres d'origine. */
.account-sidenav-link:hover { background: rgba(var(--header-accent),.08); color: #fff; transform: translateX(2px); }
.account-sidenav-link:hover svg { background: rgba(var(--header-accent),.18); }
/* Etat actif : fond teinté existant conservé, + une fine barre d'accent à
   gauche et un léger halo (même langage que les cartes de demande
   colorées/.account-sidenav-cta) pour repérer la page courante d'un coup
   d'oeil, plus nettement qu'un simple changement de fond. */
.account-sidenav-link.active {
    background: var(--brand-color-soft);
    color: #fff;
    border-color: rgba(var(--header-accent),.3);
    box-shadow: inset 0 0 0 1px rgba(var(--header-accent),.12), 0 6px 18px -12px rgba(var(--header-accent),.7);
}
.account-sidenav-link.active svg { background: rgba(var(--header-accent),.24); }
.account-sidenav-link.active::before {
    content: "";
    position: absolute;
    left: -1px;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 3px;
    background: var(--brand-color);
    box-shadow: 0 0 8px var(--brand-color-glow);
}
/* Navigation clavier (Tab) — même logique que .btn-account:focus-visible
   ci-dessus, appliquée au menu latéral compte/admin. */
.account-sidenav-link:focus-visible {
    outline: 2px solid rgba(var(--header-accent),.7);
    outline-offset: 2px;
    background: rgba(255,255,255,.05);
    color: #fff;
}

/* Boost supplémentaire pour la colonne de gauche ("travail" : Tableau de
   bord/Mes projets côté client, CroisierWeb/Gestion projets/Outils côté
   admin) — demande explicite "surtout celle travail". Sélecteur combiné
   (0,0,2,0) plus spécifique que .account-sidenav-link seul (0,0,1,0) :
   l'emporte sans dépendre de l'ordre des règles dans ce fichier.
   Revu à la baisse (demande explicite suivante : "adapter la taille de la
   NAV travail pour qu'elle ne soit pas trop grande") — depuis son passage
   en position:fixed (hauteur d'écran limitée, cf. .account-sidenav-col),
   l'agrandissement précédent (1.14rem/16px) la faisait déborder et
   nécessiter un défilement interne trop important. Reste malgré tout
   légèrement au-dessus de la base (.account-sidenav-link, 1.05rem/14px 16px)
   pour conserver un peu de la mise en avant demandée à l'origine. */
.account-sidenav-col--left .account-sidenav-link {
    font-size: 1.02rem;
    padding: 10px 14px;
}
.account-sidenav-col--left .account-sidenav-link svg { width: 20px; height: 20px; }
.account-sidenav-link--logout { margin-top: 6px; border-top: 1px solid rgba(255,255,255,.08); padding-top: 12px; }

/* Harmonisation nav ADMIN gauche/droite (demande explicite : "elle doivent
   avoir la meme taille de police (harmonise a la plus petite des 2)") — la
   gauche utilisait 1.02rem (liens, règle ci-dessus) / .7rem (étiquettes de
   catégorie, taille de base de .account-sidenav-group-label) contre .88rem /
   .64rem à droite (cf. .account-sidenav-col--right plus bas) ; on aligne la
   gauche sur la droite, la plus petite des deux. Scopé à
   .account-sidenav--admin (posé uniquement sur les <nav> de
   partials/admin-nav.php, cf. commentaire associé) pour ne pas retoucher le
   dashboard CLIENT (partials/account-nav.php), qui partage les mêmes classes
   de colonne mais n'était pas concerné par la demande. Spécificité (0,0,3,0)
   volontairement supérieure à la règle 1.02rem ci-dessus (0,0,2,0) pour
   l'emporter sans dépendre de l'ordre des règles dans ce fichier. */
.account-sidenav-col--left .account-sidenav--admin .account-sidenav-link {
    font-size: .88rem;
}
.account-sidenav-col--left .account-sidenav--admin .account-sidenav-group-label {
    font-size: .64rem;
}

/* Réduction supplémentaire, légère (demande explicite : "réduis très
   légèrement la taille de la nav de gauche, elle est un petit poil trop
   grande sur Chrome") — depuis le retrait du pliage/dépliage des catégories
   (cf. commentaire _admin_nav_label, partials/admin-nav.php), toutes les
   catégories restent dépliées en permanence, ce qui allonge le menu et
   nécessite un défilement interne sur certains écrans. La colonne gauche
   héritait encore du padding/de la taille d'icône "boost" (10px 14px, icône
   20px) de .account-sidenav-col--left .account-sidenav-link ci-dessus,
   au-delà de la simple taille de police déjà harmonisée sur la droite —
   resserré ici pour l'admin uniquement (même sélecteur scopé que
   ci-dessus), sans toucher le dashboard CLIENT qui garde son gabarit actuel. */
.account-sidenav-col--left .account-sidenav--admin .account-sidenav-link {
    padding: 8px 12px;
    gap: 10px;
}
.account-sidenav-col--left .account-sidenav--admin .account-sidenav-link svg {
    width: 17px;
    height: 17px;
}

/* Colonne de DROITE réduite (demande explicite : "il faudra réduire sa taille
   globale pour qu'elle reste visible sur tout les navigateurs entièrement sur
   une seule hauteur d'écran") — cette colonne porte presque 2 fois plus de
   liens que celle de gauche (profil/abonnements/devis/factures/avis +
   livre d'or/à propos/FAQ/CGV + déconnexion), avec la taille de base
   (1.05rem/14px 16px) elle dépassait la hauteur disponible sur les écrans
   courants et ne restait lisible qu'en scrollant À L'INTÉRIEUR du menu (cf.
   overflow-y sur .account-sidenav-col). Resserré nettement plus que la
   colonne de gauche (qui n'a que 5 liens) pour tenir sur un seul écran. */
.account-sidenav-col--right .account-sidenav-link {
    font-size: .88rem;
    padding: 8px 12px;
    gap: 10px;
}
.account-sidenav-col--right .account-sidenav-link svg {
    width: 16px;
    height: 16px;
    padding: 4px;
}
.account-sidenav-col--right .account-sidenav-group-label {
    font-size: .64rem;
    padding: 6px 10px 2px;
}
.account-sidenav-col--right .account-sidenav-divider { margin: 3px 6px; }

/* Enveloppe transparente sur desktop : les liens restent des enfants directs
   de la colonne .account-sidenav (mise en page en colonne inchangée). Devient
   une vraie bande défilable horizontalement en dessous de 860px. */
.account-sidenav-links { display: contents; }

.account-content { min-width: 0; }

.account-card {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 26px 28px;
    margin-bottom: 24px;
}

/* Zone de danger (suppression de compte) : même rouge que status-badge--unpaid. */
.account-card--danger {
    border-color: rgba(239,68,68,.28);
}
.account-card--danger h2 {
    color: #f87171;
}

/* Confirmation "Vider une table" (pages/admin-tools.php) — corrige un bug où
   le formulaire de confirmation restait TOUJOURS visible (demande explicite :
   "la confirmation d'action est buggée elle est toujours visible") : le
   formulaire portait à la fois l'attribut [hidden] ET un style inline
   "display:flex", qui prenait le pas sur la règle [hidden]{display:none} du
   navigateur. Le style inline a été retiré du HTML et déplacé ici, appliqué
   uniquement quand [hidden] est absent (donc uniquement après clic sur
   "Vider", piloté par le script en fin de page).
*/
.db-tool-confirm:not([hidden]) {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.account-card h2 {
    font-family: var(--font-title);
    font-size: 1.1rem;
    color: #fff;
    margin-bottom: 16px;
}

.account-card-hint {
    font-size: .85rem;
    color: var(--text-muted);
    line-height: 1.6;
    margin: -6px 0 16px;
}

/* ─── COULEUR DE HEADER (Mon profil) ─── */
.color-swatch-group { display: flex; gap: 16px; flex-wrap: wrap; }
.color-swatch-option {
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}
.color-swatch-option input[type="radio"] { display: none; }
.color-swatch-dot {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,.12);
    box-shadow: 0 0 0 3px transparent;
    transition: box-shadow .2s ease, border-color .2s ease, transform .15s ease;
}
/* ─── pastilles "planète" (demande explicite) : chaque couleur devient une
     mini sphère texturée (mêmes visuels que la galaxie d'offres-site.php),
     plutôt qu'un simple rond de couleur plat. Ordre affiché : Eau, Terre,
     Verte, Violette, Mars, Magma. ─── */
.color-swatch-dot--planet {
    width: 44px;
    height: 44px;
    background-size: cover;
    background-position: center;
    border-color: rgba(255,255,255,.18);
    box-shadow: 0 2px 8px rgba(0,0,0,.5), inset -8px -8px 16px rgba(0,0,0,.55);
}
.color-swatch-dot--planet-eau      { background-image: url('../image/planet-bleu.webp'); }
.color-swatch-dot--planet-blanc    { background-image: url('../image/planet-blanc.webp'); }
.color-swatch-dot--planet-verte    { background-image: url('../image/planet-vert.webp'); }
.color-swatch-dot--planet-violette { background-image: url('../image/planet-violet.webp'); }
.color-swatch-dot--planet-orange   { background-image: url('../image/planet-orange.webp'); }
.color-swatch-dot--planet-rouge    { background-image: url('../image/planet-rouge.webp'); }
.color-swatch-option:hover .color-swatch-dot { transform: scale(1.08); }
/* Couleur sélectionnée : anneau blanc net + glow + coche, pour qu'elle soit
   identifiable en un coup d'œil. Piloté par ":checked" (pas une classe
   ajoutée par PHP) pour que l'effet suive immédiatement le clic de
   l'utilisateur — y compris AVANT d'enregistrer, sur la couleur qu'il vient
   de sélectionner, et pas seulement sur celle déjà enregistrée en base. */
.color-swatch-option input:checked ~ .color-swatch-dot {
    border-color: #fff;
    box-shadow: 0 0 0 3px rgba(255,255,255,.25), 0 0 14px rgba(255,255,255,.35);
}
.color-swatch-check {
    width: 16px;
    height: 16px;
    color: #fff;
    opacity: 0;
    transform: scale(.4);
    transition: opacity .15s ease, transform .15s ease;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,.6));
}
.color-swatch-option input:checked ~ .color-swatch-dot .color-swatch-check { opacity: 1; transform: scale(1); }
.color-swatch-name { font-size: .68rem; color: var(--text-muted); transition: color .15s ease, font-weight .15s ease; }
.color-swatch-option input:checked ~ .color-swatch-name { color: #fff; font-weight: 700; }
/* BUG TROUVÉ (demande explicite : "changer les pastilles de couleur par les
   images de planète correspondantes, voir sélecteur de couleur en bas à
   gauche des pages" — cf. .hud-color-option/.hud-widget--color dans
   partials/footer.php, qui lui affiche bien les planètes) : ces 6 règles
   posaient "background" en RACCOURCI, qui réinitialise TOUJOURS
   background-image à "none" même quand seule une couleur est précisée — et
   avec 2 classes (.color-swatch-option--<couleur> .color-swatch-dot), leur
   spécificité l'emportait sur .color-swatch-dot--planet-* (1 seule classe,
   cf. plus haut), qui pose justement le background-image de la mini-planète.
   Résultat : cette page (Mon profil) affichait des pastilles de couleur unie
   au lieu des planètes, contrairement au widget bas-gauche qui n'a jamais ce
   wrapper "--<couleur>" et n'était donc pas touché. "background-color" (au
   lieu de "background") ne touche QUE la couleur : la planète reprend la
   main sur background-image, cette couleur unie ne reste visible qu'en
   arrière-plan (utile si l'image tarde à charger / échoue). */
.color-swatch-option--blue    .color-swatch-dot { background-color: rgb(10,88,202); }
.color-swatch-option--amber   .color-swatch-dot { background-color: rgb(245,158,11); }
.color-swatch-option--emerald .color-swatch-dot { background-color: rgb(16,185,129); }
.color-swatch-option--cyan    .color-swatch-dot { background-color: rgb(232,237,245); }
.color-swatch-option--gold    .color-swatch-dot { background-color: rgb(24,8,8); }
.color-swatch-option--violet  .color-swatch-dot { background-color: rgb(139,92,246); }

/* ─── Pastille "Automatique" (demande explicite : "rajouter une couleur par
   défaut (pastille vide)... pour choisir la couleur selon la page pour les
   utilisateurs n'ayant pas eux-même choisi une préférence") — contrairement
   aux mini-planètes ci-dessus (image de fond), CE disque reste
   volontairement creux/transparent (aucune couleur ni texture), pour se
   distinguer visuellement au premier coup d'œil comme "aucune couleur
   choisie" plutôt qu'une 7e couleur comme les autres. Bordure en tirets
   (dashed) plutôt que pleine : renforce cette lecture "vide/neutre".
   Utilisée à la fois par la grille Mon profil (.color-swatch-option--auto)
   et le widget flottant public (.hud-color-option), les deux réutilisant le
   même .color-swatch-dot de base (cf. règles génériques plus haut). ─── */
.color-swatch-dot--empty {
    background: transparent;
    border: 2px dashed rgba(255,255,255,.45);
    box-shadow: none;
}
.color-swatch-option:hover .color-swatch-dot--empty,
.hud-color-option:hover .color-swatch-dot--empty {
    border-color: rgba(255,255,255,.7);
}
.color-swatch-option input:checked ~ .color-swatch-dot--empty,
.hud-color-option.is-active .color-swatch-dot--empty {
    border-style: solid;
}

/* ─── A2F (double authentification) — Mon profil ─── */
.totp-setup-box {
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
    background: rgba(0,0,0,.22);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 16px;
    margin-top: 8px;
}
.totp-qr { width: 176px; height: 176px; flex-shrink: 0; background: #fff; border-radius: 10px; padding: 8px; box-sizing: border-box; }
.totp-manual-key { display: flex; flex-direction: column; gap: 6px; }
.totp-manual-key code {
    font-size: .82rem;
    background: rgba(0,0,0,.35);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 8px;
    padding: 8px 10px;
    color: #fff;
    word-break: break-all;
}
.recovery-codes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 10px;
    margin-bottom: 18px;
}
.recovery-code {
    display: block;
    text-align: center;
    background: rgba(0,0,0,.35);
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 8px;
    padding: 10px;
    font-size: .88rem;
    letter-spacing: .04em;
    color: #fff;
}

/* ─── Bannière "confirmez votre email" — barre horizontale centrée en haut,
     non bloquante. Historique de positionnement (demande explicite,
     plusieurs itérations) : d'abord coin bas-droit (chevauchait le widget
     flottant Langue, cf. .hud-widget--lang, même coin), puis bas centré,
     puis enfin ICI — barre horizontale fixée en haut, centrée entre les
     widgets Navigation (haut-gauche) et Mon compte (haut-droite, cf.
     .hud-widget--nav/--account), au même top:22px qu'eux pour rester sur
     leur ligne. Contenu condensé sur une seule ligne (icône + texte court +
     bouton + fermeture) pour tenir dans cet espace, plutôt que la carte
     verticale (titre + 3 paragraphes) utilisée quand la bannière visait un
     coin — même esprit horizontal que .cookie-banner-inner plus bas dans ce
     fichier, transposé dans une pilule flottante plutôt qu'une bande
     pleine largeur. */
.email-verify-banner {
    position: fixed;
    top: 22px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 90;
    display: flex;
    align-items: center;
    gap: 14px;
    max-width: calc(100% - 420px);
    background: rgba(18, 20, 28, .94);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid rgba(255,255,255,.10);
    border-top: 3px solid var(--brand-color);
    border-radius: 14px;
    padding: 12px 16px;
    box-shadow: 0 16px 40px rgba(0,0,0,.45);
}
/* Le logo (fichier PNG noir ou blanc) rendait mal sur le fond sombre de la
   bannière quel que soit le traitement CSS (filtre, médaillon...) — remplacé
   par l'icône roquette (déjà utilisée comme identité sur le site) dans un
   badge dégradé couleur de marque, plus simple et net à cette petite taille. */
.email-verify-banner-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    border-radius: 9px;
    background: linear-gradient(135deg, var(--brand-color), color-mix(in srgb, var(--brand-color) 70%, #000));
    box-shadow: 0 3px 10px color-mix(in srgb, var(--brand-color) 40%, transparent);
    color: var(--brand-color-contrast, #fff);
}
.email-verify-banner-icon svg { width: 16px; height: 16px; }
.email-verify-banner-text {
    font-size: .82rem;
    color: rgba(255,255,255,.85);
    line-height: 1.4;
    margin: 0;
    white-space: nowrap;
}
/* Bouton dédié (plutôt que le .btn-account générique) : dégradé couleur de
   marque, légère élévation au survol — pour un CTA plus soigné dans cette
   pilule sombre. Compact (largeur au contenu, pas 100% comme dans l'ancienne
   carte verticale) pour rester sur une seule ligne avec le texte. */
.email-verify-banner-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 8px 14px;
    border-radius: 8px;
    background: linear-gradient(135deg, var(--brand-color), color-mix(in srgb, var(--brand-color) 75%, #fff));
    color: var(--brand-color-contrast, #fff);
    font-size: .78rem;
    font-weight: 600;
    text-decoration: none;
    letter-spacing: .01em;
    white-space: nowrap;
    box-shadow: 0 6px 18px color-mix(in srgb, var(--brand-color) 35%, transparent);
    transition: transform .18s ease, box-shadow .18s ease, filter .18s ease;
}
.email-verify-banner-btn svg { width: 13px; height: 13px; transition: transform .25s ease; }
.email-verify-banner-btn:hover {
    transform: translateY(-1px);
    filter: brightness(1.08);
    box-shadow: 0 8px 22px color-mix(in srgb, var(--brand-color) 45%, transparent);
}
.email-verify-banner-btn:hover svg { transform: translate(3px, -3px) rotate(45deg); }
.email-verify-banner-close {
    flex-shrink: 0;
    background: none;
    border: none;
    color: rgba(255,255,255,.35);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px;
}
.email-verify-banner-close:hover { color: rgba(255,255,255,.75); }
@media (max-width: 900px) {
    /* En dessous de ~900px, plus assez de place pour tenir centrée entre
       Navigation et Mon compte sans les chevaucher (cf. max-width ci-dessus,
       calculé pour un desktop large) : repasse sous les 2 widgets du haut,
       toujours horizontale mais sur toute la largeur disponible. */
    .email-verify-banner { top: auto; bottom: 20px; left: 16px; right: 16px; transform: none; max-width: none; }
    .email-verify-banner-text { white-space: normal; }
}
@media (max-width: 480px) {
    .email-verify-banner { flex-wrap: wrap; padding: 12px 14px; }
}

/* ─── Bannière de rappel "Ajouter une photo de profil" (partials/header.php)
       — même style flottant que .email-verify-banner ci-dessus (jamais
       affichées ensemble : la vérification d'email est prioritaire). ─── */
.avatar-reminder-banner {
    position: fixed;
    top: 22px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 90;
    display: flex;
    align-items: center;
    gap: 14px;
    max-width: calc(100% - 420px);
    background: rgba(18, 20, 28, .94);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid rgba(255,255,255,.10);
    border-top: 3px solid var(--brand-color);
    border-radius: 14px;
    padding: 12px 16px;
    box-shadow: 0 16px 40px rgba(0,0,0,.45);
}
.avatar-reminder-banner-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    border-radius: 9px;
    background: linear-gradient(135deg, var(--brand-color), color-mix(in srgb, var(--brand-color) 70%, #000));
    box-shadow: 0 3px 10px color-mix(in srgb, var(--brand-color) 40%, transparent);
    color: var(--brand-color-contrast, #fff);
}
.avatar-reminder-banner-icon svg { width: 16px; height: 16px; }
.avatar-reminder-banner-text {
    font-size: .82rem;
    color: rgba(255,255,255,.85);
    line-height: 1.4;
    margin: 0;
    white-space: nowrap;
}
.avatar-reminder-banner-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 8px 14px;
    border-radius: 8px;
    background: linear-gradient(135deg, var(--brand-color), color-mix(in srgb, var(--brand-color) 75%, #fff));
    color: var(--brand-color-contrast, #fff);
    font-size: .78rem;
    font-weight: 600;
    text-decoration: none;
    letter-spacing: .01em;
    white-space: nowrap;
    box-shadow: 0 6px 18px color-mix(in srgb, var(--brand-color) 35%, transparent);
    transition: transform .18s ease, box-shadow .18s ease, filter .18s ease;
}
.avatar-reminder-banner-btn svg { width: 13px; height: 13px; transition: transform .25s ease; }
.avatar-reminder-banner-btn:hover {
    transform: translateY(-1px);
    filter: brightness(1.08);
    box-shadow: 0 8px 22px color-mix(in srgb, var(--brand-color) 45%, transparent);
}
.avatar-reminder-banner-btn:hover svg { transform: translate(3px, -3px) rotate(45deg); }
.avatar-reminder-banner-close {
    flex-shrink: 0;
    background: none;
    border: none;
    color: rgba(255,255,255,.35);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px;
}
.avatar-reminder-banner-close:hover { color: rgba(255,255,255,.75); }
@media (max-width: 900px) {
    .avatar-reminder-banner { top: auto; bottom: 20px; left: 16px; right: 16px; transform: none; max-width: none; }
    .avatar-reminder-banner-text { white-space: normal; }
}
@media (max-width: 480px) {
    .avatar-reminder-banner { flex-wrap: wrap; padding: 12px 14px; }
}

.account-kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 18px;
    margin-bottom: 24px;
}

.account-kpi-card {
    position: relative;
    overflow: hidden;
    display: block;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 20px 22px;
    text-decoration: none;
    color: inherit;
    transition: border-color .2s ease, background .2s ease, box-shadow .2s ease, transform .15s ease;
}
.account-kpi-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 26px -16px rgba(0,0,0,.6);
}

/* Reflet lumineux qui balaie la carte au survol (même langage que
   .btn-account, cf. plus haut). */
.account-kpi-card::after {
    content: "";
    position: absolute;
    top: 0;
    left: -75%;
    width: 45%;
    height: 100%;
    z-index: 1;
    background: linear-gradient(115deg, transparent 0%, rgba(var(--header-accent),.35) 45%, rgba(var(--header-accent),.6) 50%, rgba(var(--header-accent),.35) 55%, transparent 100%);
    transform: skewX(-20deg);
    pointer-events: none;
}
.account-kpi-card:hover::after {
    animation: kpiCardShine 1.5s ease-in-out infinite;
}
@keyframes kpiCardShine {
    0%   { left: -75%; }
    100% { left: 130%; }
}
@media (prefers-reduced-motion: reduce) {
    .account-kpi-card:hover::after { animation: none; }
}

/* Petite rockette qui apparaît au survol, en coin bas-droit — reprend le
   même esprit "tech/spatial" que .btn-account. */
.account-kpi-rocket {
    position: absolute;
    right: 16px;
    bottom: 14px;
    width: 20px;
    height: 20px;
    z-index: 2;
    color: rgb(var(--header-accent));
    opacity: 0;
    transform: translate(7px, 9px) rotate(-45deg) scale(.4);
    transition: opacity .3s ease, transform .45s cubic-bezier(.34,1.56,.64,1);
    pointer-events: none;
}
.account-kpi-rocket svg { display: block; width: 100%; height: 100%; }
.account-kpi-card:hover .account-kpi-rocket {
    opacity: 1;
    transform: translate(0, 0) rotate(-45deg) scale(1);
}
@media (prefers-reduced-motion: reduce) {
    .account-kpi-rocket { transform: rotate(-45deg); transition: opacity .2s ease; }
    .account-kpi-card:hover .account-kpi-rocket { transform: rotate(-45deg); }
}

.account-kpi-card--profile { display: flex; align-items: center; gap: 14px; }
.account-kpi-card--profile .account-kpi-value { font-size: 1.05rem; }
.account-kpi-card--secondary {
    border-color: rgba(var(--accent-harmony-2),.4);
    background: rgba(var(--accent-harmony-2),.07);
    box-shadow: 0 0 24px rgba(var(--accent-harmony-2),.12);
}

/* ─── Reflets de couleur conditionnels (compte-dashboard.php) : signalent en
     un coup d'œil un état qui mérite l'attention du client — rouge pour une
     facture impayée, vert pour un site actif, bleu pour un abonnement actif,
     orange pour un devis en attente. ─── */
.account-kpi-card--danger {
    border-color: rgba(239,68,68,.4);
    background: rgba(239,68,68,.07);
    box-shadow: 0 0 24px rgba(239,68,68,.12);
}
.account-kpi-card--success {
    border-color: rgba(16,185,129,.4);
    background: rgba(16,185,129,.07);
    box-shadow: 0 0 24px rgba(16,185,129,.12);
}
.account-kpi-card--info {
    border-color: rgba(var(--header-accent),.4);
    background: rgba(var(--header-accent),.07);
    box-shadow: 0 0 24px rgba(var(--header-accent),.12);
}
.account-kpi-card--warning {
    border-color: rgba(245,158,11,.4);
    background: rgba(245,158,11,.07);
    box-shadow: 0 0 24px rgba(245,158,11,.12);
}

.account-kpi-value { font-family: var(--font-title); font-size: 1.7rem; font-weight: 700; color: #fff; }
.account-kpi-label { font-size: .78rem; color: var(--text-muted); margin-top: 4px; }
.account-kpi-hint { font-size: .68rem; color: var(--text-muted); opacity: .75; margin-top: 6px; }

.data-table { width: 100%; border-collapse: collapse; font-size: .88rem; }
.data-table th {
    text-align: left;
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--text-muted);
    padding: 10px 14px;
    border-bottom: 1px solid rgba(255,255,255,.1);
}
.data-table td { padding: 14px; border-bottom: 1px solid rgba(255,255,255,.06); color: #fff; vertical-align: middle; }
.data-table tr:last-child td { border-bottom: none; }
.data-table .muted { color: var(--text-muted); }

/* Défilement horizontal pour un tableau particulièrement large (ex :
   pages/admin-apporteurs.php, 14 colonnes) — sur les autres tableaux du
   site (moins de colonnes), pas de wrapper posé donc aucun changement de
   comportement ; règle volontairement scopée à .data-table-scroll plutôt
   que .data-table directement, pour ne rien changer ailleurs. Complète la
   règle mobile existante plus bas (@media max-width:860px), qui ne
   s'applique qu'en dessous de 860px : ici le scroll est actif à TOUTE
   largeur d'écran dès que le tableau dépasse min-width. */
.data-table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: 10px;
}
.data-table-scroll .data-table { min-width: 1100px; }

/* Aperçu tronqué + "Voir tout" pour une colonne "Message" pouvant contenir
   un texte long (candidatures apporteurs) — évite qu'une seule ligne
   n'étire toute la hauteur du tableau. Fermé par défaut, même composant
   visuel que .account-request-details ailleurs sur le site. */
.data-table-message-preview { max-width: 220px; }
.data-table-message-preview summary {
    cursor: pointer;
    color: var(--text-muted);
    font-size: .82rem;
}
.data-table-message-preview[open] summary { color: #fff; }
.data-table-message-preview div { margin-top: 6px; white-space: normal; }

.status-badge {
    display: inline-block;
    font-size: .72rem;
    font-weight: 700;
    padding: 3px 11px;
    border-radius: 999px;
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
}
.status-badge--active,  .status-badge--paid,     .status-badge--accepted, .status-badge--approved { background: rgba(16,185,129,.14); color: #34d399; }
.status-badge--pending, .status-badge--sent,     .status-badge--deploying { background: rgba(251,191,36,.14); color: #fbbf24; }
.status-badge--unpaid,  .status-badge--declined, .status-badge--overdue, .status-badge--rejected { background: rgba(239,68,68,.14); color: #f87171; }
.status-badge--invoiced,.status-badge--cancelled,.status-badge--offline,.status-badge--maintenance { background: rgba(255,255,255,.08); color: var(--text-muted); }

/* ─── pages/compte-devis.php + pages/compte-factures.php : "meilleure
     présentation" (demande explicite) ───
     Remplace le balisage jusqu'ici entièrement en style inline (mêmes 2
     pages, code dupliqué) par des classes réutilisables : bande de
     statistiques en tête de page (même langage visuel que .account-kpi-card
     du dashboard, en version non-cliquable/statique) + carte de document
     avec liseré de couleur à gauche reprenant le code couleur déjà en place
     sur .status-badge (vert=payé/accepté, orange=en attente, rouge=impayé/
     refusé, gris=neutre) — repérage au coup d'oeil sans avoir à lire le
     badge de statut. ─── */
.doc-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 12px;
    margin-bottom: 20px;
}
/* Même carte que .account-kpi-card (fond quadrillé + accent couleur) mais
   sans les affordances de lien (pas de hover-translate ni de fusée) : ces
   cartes sont purement informatives, pas cliquables. */
.doc-stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 14px 16px;
    border-radius: var(--radius);
    background-image:
        linear-gradient(rgba(var(--header-accent),.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(var(--header-accent),.05) 1px, transparent 1px);
    background-size: 16px 16px;
    background-color: rgba(var(--header-accent),.035);
    border: 1px solid rgba(var(--header-accent),.16);
}
.doc-stat-value { font-size: 1.5rem; font-weight: 700; color: #fff; line-height: 1.15; }
.doc-stat-label { font-size: .78rem; color: var(--text-muted); }
.doc-stat--warning { border-color: rgba(251,191,36,.35); background-color: rgba(251,191,36,.06); }
.doc-stat--warning .doc-stat-value { color: #fbbf24; }
.doc-stat--danger  { border-color: rgba(239,68,68,.35); background-color: rgba(239,68,68,.06); }
.doc-stat--danger  .doc-stat-value { color: #f87171; }
.doc-stat--success { border-color: rgba(16,185,129,.35); background-color: rgba(16,185,129,.06); }
.doc-stat--success .doc-stat-value { color: #34d399; }
.doc-stat--info    { border-color: rgba(96,165,250,.35); background-color: rgba(96,165,250,.08); }
.doc-stat--info    .doc-stat-value { color: #60a5fa; }

/* ─── pages/admin-custom-quotes.php : bloc d'actions secondaires repliable
     (demande explicite, tâche #33 : "simplifier le formulaire/affichage")
     — regroupe les actions les moins fréquentes/plus sensibles (transformer
     en projet, annuler, supprimer) derrière un simple <details>, pour que
     la carte de demande affiche par défaut l'essentiel (contenu de la
     demande + changement de statut + notes) sans la noyer sous 4 formulaires
     empilés. Même esprit que .account-request-details déjà utilisé côté
     client, décliné ici pour l'admin. ─── */
.doc-card-more { margin-top: 14px; border-top: 1px solid rgba(255,255,255,.08); padding-top: 10px; }
.doc-card-more summary {
    cursor: pointer;
    font-size: .82rem;
    font-weight: 600;
    color: var(--text-muted);
    list-style: none;
    display: flex;
    align-items: center;
    gap: 6px;
}
.doc-card-more summary::-webkit-details-marker { display: none; }
.doc-card-more summary::before {
    content: "";
    width: 7px;
    height: 7px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    transition: transform .15s ease;
    flex-shrink: 0;
}
.doc-card-more[open] summary::before { transform: rotate(45deg); }
.doc-card-more summary:hover { color: #fff; }
.doc-card-more-body { margin-top: 12px; display: flex; flex-direction: column; gap: 12px; }

.doc-card--info::before { background: #60a5fa; }

.doc-card {
    position: relative;
    background: rgba(255,255,255,.02);
    border-radius: var(--radius);
    margin-bottom: 14px;
    padding: 20px 22px 20px 26px;
    /* Liseré de statut : posé en ::before plutôt qu'un border-left direct,
       pour garder le border-radius intact sur les 4 coins (un border-left
       classique casse l'arrondi du coin haut/bas-gauche). */
    overflow: hidden;
}
.doc-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 4px;
    background: rgba(255,255,255,.15);
}
.doc-card--success::before { background: #34d399; }
.doc-card--warning::before { background: #fbbf24; }
.doc-card--danger::before  { background: #f87171; }
.doc-card--muted   { opacity: .85; }
.doc-card-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 10px;
}
.doc-card-ref { color: #fff; font-size: 1.02rem; }
.doc-card-badges { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.doc-card-items { margin-bottom: 10px; }
.doc-card-foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}
.doc-card-foot--sm { font-size: .9rem; }
.doc-card-total { color: #fff; }
.doc-card-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.doc-card-extra {
    margin-top: 14px;
    border-top: 1px solid rgba(255,255,255,.08);
    padding-top: 14px;
}

/* Cartes "Demandes clients" (pages/admin-custom-quotes.php, demande
   explicite : "rends les demandes plus visibles pour que les infos
   essentiels soient lisibles facilement") — le titre du projet passait
   inaperçu (simple <p><strong>, même gabarit que le reste du texte) et les
   infos clé (budget, domaine, contenu fourni, type de projet, créneau...)
   s'empilaient en lignes de texte fines et peu contrastées, difficiles à
   distinguer les unes des autres. Le titre devient un vrai <h3> nettement
   plus grand ; les infos clé deviennent des puces (fond + bordure, label
   discret + valeur blanche en gras) affichées en ligne, qui se détachent
   clairement du reste de la carte. */
.quote-card-title {
    margin: 2px 0 12px;
    color: #fff;
    font-size: 1.18rem;
    font-weight: 700;
    line-height: 1.3;
}
.quote-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
}
.quote-card-meta-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 6px 12px;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 8px;
    font-size: .82rem;
    line-height: 1.3;
}
.quote-card-meta-chip-label { color: var(--text-muted); }
.quote-card-meta-chip-value { color: #fff; font-weight: 600; }
/* Message du client : mis dans un encart dédié (fond légèrement plus clair
   que la carte) pour le distinguer visuellement des infos structurées
   ci-dessus, plutôt qu'un simple paragraphe qui se fondait avec le reste. */
.quote-card-message {
    padding: 12px 14px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.06);
    border-radius: 10px;
    color: rgba(255,255,255,.82);
    white-space: pre-line;
    line-height: 1.5;
    margin-bottom: 12px;
}
.quote-card-message--empty {
    font-style: italic;
    color: var(--text-muted);
    background: none;
    border: none;
    padding: 0;
}
.quote-card-date { font-size: .78rem; color: var(--text-muted); margin-bottom: 14px; }

/* Formulaire de confirmation d'annulation (bug corrigé : un style inline
   "display:flex" posé directement sur le <form> gagnait TOUJOURS contre la
   règle [hidden] { display:none } du navigateur, quel que soit l'état de
   l'attribut "hidden" basculé par le JS — le formulaire restait donc visible
   en permanence). [hidden] doit rester APRÈS la règle de base pour la
   surcharger via l'ordre + la spécificité combinée (classe + attribut). */
.quote-cancel-form {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 8px;
}
.quote-cancel-form[hidden] { display: none; }

/* ─── admin-custom-quotes.php : bandeau de filtre "type de demande" / "date
     de la demande" (demande explicite), même principe que .admin-site-
     filters sur pages/admin-sites.php. ─── */
.quote-filters { padding: 18px 22px; }
.quote-filters-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 14px;
}
.quote-filters-row .form-group { flex: 1; min-width: 180px; margin-bottom: 0; }
.quote-filters-row .form-group input,
.quote-filters-row .form-group select {
    height: 44px;
    box-sizing: border-box;
}
.quote-filters-actions { display: flex; gap: 10px; flex-shrink: 0; }

/* Étiquette de type de demande (demande explicite : "indiquer clairement le
   type de demande en haut... plus visible qu'un simple badge, une couleur
   différente selon la demande — Créer site (bleu) sur mesure (vert) rdv
   (violet) hébergement (blanc) nom de domaine (jaune)") — remplace le petit
   badge discret qui se fondait avec le badge de statut voisin par une puce
   nettement plus grande, en tout premier sur la carte, avec un point de
   couleur pleine (pas juste un texte teinté) pour un repérage rapide même en
   parcourant la liste sans lire chaque libellé. Complétée d'un liseré de la
   même couleur en haut de carte (cf. .doc-card--type-* plus bas) : le code
   couleur reste visible même en défilant, avant que la puce elle-même soit
   lue. */
.quote-type-tag {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 16px;
    border-radius: 999px;
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .01em;
    margin-bottom: 12px;
}
.quote-type-tag-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}
.quote-type-tag--site       { background: #3b82f6; color: #fff; }
.quote-type-tag--custom-dev { background: #22c55e; color: #fff; }
.quote-type-tag--conseil    { background: #8b5cf6; color: #fff; }
.quote-type-tag--hosting    { background: #ffffff; color: #0f172a; }
.quote-type-tag--domain     { background: #facc15; color: #1a1400; }
.quote-type-tag--default    { background: rgba(255,255,255,.10); color: #fff; border: 1px solid rgba(255,255,255,.22); }

.doc-card--type-site       { border-top: 3px solid #3b82f6; }
.doc-card--type-custom-dev { border-top: 3px solid #22c55e; }
.doc-card--type-conseil    { border-top: 3px solid #8b5cf6; }
.doc-card--type-hosting    { border-top: 3px solid #ffffff; }
.doc-card--type-domain     { border-top: 3px solid #facc15; }

/* ─── Repère de couleur sur un message (pages/admin-messages.php,
     pages/compte-messages.php) : simple point coloré (--dot-color défini
     inline par le PHP), avec tooltip au survol expliquant sa signification
     (même mécanique que .btn-tooltip). ─── */
.message-color-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--dot-color, #999);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--dot-color, #999) 25%, transparent);
    flex-shrink: 0;
}
.message-color-dot--tooltip { position: relative; cursor: help; }
.message-color-dot--tooltip::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    background: rgba(10,14,30,.96);
    border: 1px solid rgba(255,255,255,.10);
    color: #fff;
    border-radius: 8px;
    font-size: .72rem;
    font-weight: 500;
    white-space: nowrap;
    padding: 5px 10px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .2s ease, visibility .2s ease, transform .2s ease;
    z-index: 20;
}
.message-color-dot--tooltip:hover::after,
.message-color-dot--tooltip:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

/* Avatar réel du client dans les avis publics (index.php/accueil.php,
   livre-dor.php catalogue + diaporama) quand son compte en a un — sinon
   l'initiale reste affichée comme avant. Un seul style suffit, ces classes
   sont toutes des ronds pleins avec du texte centré. */
.review-avatar img,
.review-card-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}

/* ─── Avatar de profil (pages/compte-profil.php + pages/admin-avatars.php) :
       photo si envoyée et approuvée, sinon rond d'initiales — même
       principe visuel que .review-card-avatar / .comment-avatar. ─── */
.profile-avatar-row { display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap; }

.profile-avatar-img {
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    border: 1px solid rgba(255,255,255,.12);
}

.profile-avatar-initials {
    border-radius: 50%;
    background: var(--brand-color);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    color: var(--brand-color-contrast, #fff);
    font-family: var(--font-title);
    flex-shrink: 0;
}

.profile-avatar-actions { flex: 1; min-width: 220px; }

.profile-avatar-pending-preview {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 10px 0;
    padding: 10px 12px;
    background: rgba(251,191,36,.06);
    border: 1px solid rgba(251,191,36,.2);
    border-radius: 10px;
}

/* Aperçu local (FileReader) de la nouvelle photo avant publication —
   pages/compte-profil.php, cf. assets/js/main.js. */
.avatar-upload-preview {
    position: relative;
    display: inline-flex;
    flex-shrink: 0;
}
.avatar-upload-preview img {
    width: 52px;
    height: 52px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--brand-color);
}
.avatar-upload-clear {
    position: absolute;
    top: -4px;
    right: -4px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #fff;
    border: 1px solid rgba(0,0,0,.15);
    color: #c0392b;
    font-size: .68rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 4px rgba(0,0,0,.2);
    padding: 0;
}
.avatar-upload-picker {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
}
.btn-account:disabled {
    opacity: .45;
    cursor: not-allowed;
    pointer-events: none;
}

/* Petit indicateur ajouté par main.js dans le bouton au moment de l'envoi
   d'un formulaire (cf. "RETOUR VISUEL PENDANT L'ENVOI D'UN FORMULAIRE") —
   currentColor pour rester lisible aussi bien sur .btn-account (fond plein)
   que sur .btn-account--outline (fond transparent). */
.btn-spinner {
    width: 13px;
    height: 13px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    display: inline-block;
    opacity: .8;
    animation: btn-spinner-spin .6s linear infinite;
    flex-shrink: 0;
}
@keyframes btn-spinner-spin {
    to { transform: rotate(360deg); }
}
/* "Prendre une photo" (capture caméra) : réservé au mobile, un appareil de
   bureau n'a généralement pas cet usage — cf. pages/compte-profil.php. */
.avatar-upload-camera { display: none; }
@media (max-width: 768px) {
    .avatar-upload-camera { display: inline-flex; }
}

/* Galerie de choix rapide (avatars récents + avatars CroisierWeb proposés)
   sous le formulaire d'envoi — pages/compte-profil.php. */
.avatar-gallery-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.avatar-gallery-thumb {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    padding: 0;
    border: 2px solid transparent;
    background: rgba(255,255,255,.04);
    cursor: pointer;
    overflow: hidden;
    flex-shrink: 0;
    transition: border-color .15s ease, transform .15s ease;
}
.avatar-gallery-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.avatar-gallery-thumb:hover {
    border-color: rgba(255,255,255,.35);
    transform: translateY(-2px);
}
.avatar-gallery-thumb.is-selected {
    border-color: var(--brand-color);
}

.account-empty { text-align: center; padding: 48px 24px; color: var(--text-muted); }

/* ─── compte-projets.php : bouton "Annuler" d'une demande en cours (table
     "Mes demandes en cours") — discret par défaut, s'affirme en rouge au
     survol pour bien signaler l'action destructive sans l'imposer visuellement
     dans le tableau. ─── */
.btn-account-cancel-request {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 8px;
    background: transparent;
    border: 1px solid rgba(239,68,68,.3);
    color: #f87171;
    font-size: .74rem;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.btn-account-cancel-request:hover {
    background: rgba(239,68,68,.14);
    border-color: rgba(239,68,68,.5);
    color: #fca5a5;
}
.btn-account-cancel-request:focus-visible {
    outline: 2px solid rgba(239,68,68,.6);
    outline-offset: 2px;
    background: rgba(239,68,68,.14);
    border-color: rgba(239,68,68,.5);
    color: #fca5a5;
}

/* ─── Box de confirmation personnalisée (ex : annulation d'une demande sur
     compte-projets.php) — remplace le confirm() natif du navigateur par une
     modale au style du site. ─── */
.confirm-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: rgba(6,8,16,.72);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.confirm-modal-overlay[hidden] { display: none; }
.confirm-modal {
    width: 100%;
    max-width: 400px;
    background: #14161e;
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 14px;
    padding: 26px 28px;
    box-shadow: 0 24px 60px rgba(0,0,0,.5);
}
.confirm-modal h3 {
    font-family: var(--font-title);
    font-size: 1rem;
    color: #fff;
    margin: 0 0 12px;
}
.confirm-modal p {
    font-size: .86rem;
    color: var(--text-muted);
    line-height: 1.55;
    margin: 0 0 22px;
}
.confirm-modal p strong { color: #fff; }
.confirm-modal-actions {
    display: flex;
    gap: 10px;
    justify-content: flex-end;
    flex-wrap: wrap;
}
/* Case à cocher obligatoire avant validation (pages/compte-projets.php —
   demande explicite : "cette validation doit faire office de signature
   officielle", donc un choix conscient plutôt qu'un simple clic) — le bouton
   "Confirmer" reste désactivé (cf. .confirm-modal-actions button[disabled]
   ci-dessous) tant qu'elle n'est pas cochée. */
.confirm-modal-ack {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: -8px 0 20px;
    font-size: .82rem;
    color: var(--text-muted);
    line-height: 1.5;
    cursor: pointer;
}
.confirm-modal-ack input[type="checkbox"] {
    margin-top: 3px;
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    accent-color: var(--brand-color);
    cursor: pointer;
}
.confirm-modal-actions button[disabled] {
    opacity: .4;
    cursor: not-allowed;
}

/* ─── Empty state avec action (ex : "Mes derniers devis" du dashboard) ─── */
.account-empty--action { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.account-empty--action p { margin: 0; }
.account-empty-hint { font-size: .82rem; color: var(--text-muted); }
.account-empty-hint a { color: var(--brand-color); font-weight: 600; text-decoration: none; }
.account-empty-hint a:hover { text-decoration: underline; }

.account-alert {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 20px;
    border-radius: 12px;
    font-size: .88rem;
    margin-bottom: 20px;
}
.account-alert--success { background: rgba(16,185,129,.10); border: 1px solid rgba(16,185,129,.3); color: #34d399; }
.account-alert--error   { background: rgba(239,68,68,.10);  border: 1px solid rgba(239,68,68,.3);  color: #f87171; }
.account-alert--info    { background: var(--brand-color-soft); border: 1px solid rgba(var(--header-accent),.3); color: #93c5fd; }

.btn-account {
    position: relative;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 22px;
    border-radius: 10px;
    background: var(--brand-color);
    color: var(--brand-color-contrast, #fff);
    font-weight: 600;
    font-size: .85rem;
    border: none;
    cursor: pointer;
    text-decoration: none;
    transition: opacity .2s, transform .15s, box-shadow .2s ease;
}
/* "Esprit tech, navigation spatiale" (demande explicite, appliquée à TOUS les
   boutons dashboard utilisateur ET admin puisque .btn-account est la classe
   de base partagée par toutes les variantes ci-dessous — aucune page n'a
   besoin d'être modifiée individuellement pour en bénéficier) : un reflet
   lumineux façon "scan" balaie le bouton au survol (::before, transform
   uniquement — coût de rendu négligeable), et un léger halo coloré vient
   souligner l'action au survol/focus, comme un panneau de contrôle qui
   s'illumine. */
.btn-account::before {
    content: '';
    position: absolute;
    top: 0;
    left: -60%;
    width: 40%;
    height: 100%;
    background: linear-gradient(115deg, transparent, rgba(255,255,255,.35), transparent);
    transform: skewX(-20deg);
    transition: left .55s ease;
    pointer-events: none;
}
.btn-account:hover::before { left: 130%; }
.btn-account:hover {
    opacity: .9;
    transform: translateY(-1px);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand-color) 55%, transparent), 0 6px 18px color-mix(in srgb, var(--brand-color) 30%, transparent);
}
/* Navigation clavier (Tab) : jusqu'ici seuls les boutons/liens du site
   vitrine avaient un vrai style de focus (cf. .services-hero-refresh
   :focus-visible plus haut) — le dashboard, pourtant utilisé au quotidien,
   retombait sur le contour par défaut du navigateur. Même mécanique
   (outline coloré via --header-accent) reprise ici. */
.btn-account:focus-visible {
    outline: 2px solid rgba(var(--header-accent),.7);
    outline-offset: 2px;
}
.btn-account--outline { background: transparent; border: 1px solid rgba(255,255,255,.2); color: #fff; }
.btn-account--danger  { background: rgba(239,68,68,.9); }
/* "Esprit spatial/tech" (demande explicite, 2e passe : "comme pour les
   boutons vu précédemment" — un simple halo de couleur, cf. tentative
   précédente ci-dessus dans l'historique des commits, ne suffisait pas ;
   il fallait le même registre franchement "spatial" que .nav-services-
   featured sur le site vitrine : semis d'étoiles + lueur de nébuleuse, pas
   juste un contour lumineux). Repris à l'identique dans son PRINCIPE (étoiles
   neutres en rgba(255,255,255,...) + lueur teintée) mais SANS les couleurs
   de fond fixes (#04070f/#0d2a5c/#1f0f3d) de ce bouton-là : .btn-account--
   primary est utilisé sur toutes les pages compte/admin avec la couleur de
   marque choisie par le client (cf. bug déjà corrigé une fois plus haut,
   .btn-account--tech-brand : "la couleur du bouton ne va pas du tout, y
   avait que pour le bouton bleu") — le fond reste donc var(--brand-color)
   (hérité de .btn-account), seuls les points lumineux (neutres) et la
   lueur (rgba(var(--header-accent),...)) s'ajoutent par-dessus. */
.btn-account--primary {
    background-image:
        radial-gradient(1px 1px at 18% 30%, rgba(255,255,255,.8), transparent 100%),
        radial-gradient(1px 1px at 40% 75%, rgba(255,255,255,.55), transparent 100%),
        radial-gradient(1.3px 1.3px at 62% 20%, rgba(255,255,255,.85), transparent 100%),
        radial-gradient(1px 1px at 82% 65%, rgba(255,255,255,.5), transparent 100%),
        radial-gradient(1px 1px at 92% 30%, rgba(255,255,255,.65), transparent 100%);
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.18),
        0 0 0 1px rgba(255,255,255,.14),
        0 0 14px color-mix(in srgb, var(--brand-color) 35%, transparent),
        0 0 28px rgba(var(--header-accent),.22);
}
.btn-account--primary:hover {
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.25),
        0 0 0 1px rgba(255,255,255,.22),
        0 0 20px color-mix(in srgb, var(--brand-color) 45%, transparent),
        0 0 40px rgba(var(--header-accent),.32);
}

/* ─── Variantes "tech" à accent coloré distinct (demande explicite,
     pages/compte-sites.php : "donner plus de style aux boutons, les
     différencier légèrement" — appliquées aux boutons d'action par site :
     Voir le site / Accéder à la dashboard / Demander un module / Mettre en
     arrêt) — même structure que .btn-account--outline (fond transparent,
     bordure fine) mais teintée par rôle, façon boutons de commande d'un
     tableau de bord où chaque fonction a sa propre couleur repère. Classes
     génériques (pas scopées à compte-sites.php) : réutilisables partout où
     un même besoin de différenciation par rôle se présente. ─── */
.btn-account--tech-cyan {
    background: rgba(34,211,238,.08);
    border: 1px solid rgba(34,211,238,.4);
    color: #67e8f9;
}
.btn-account--tech-cyan:hover { background: rgba(34,211,238,.18); border-color: rgba(34,211,238,.7); }
.btn-account--tech-emerald {
    background: rgba(16,185,129,.08);
    border: 1px solid rgba(16,185,129,.4);
    color: #6ee7b7;
}
.btn-account--tech-emerald:hover { background: rgba(16,185,129,.18); border-color: rgba(16,185,129,.7); }
.btn-account--tech-amber {
    background: rgba(251,191,36,.08);
    border: 1px solid rgba(251,191,36,.4);
    color: #fcd34d;
}
.btn-account--tech-amber:hover { background: rgba(251,191,36,.18); border-color: rgba(251,191,36,.7); }
.btn-account--tech-violet {
    background: rgba(139,92,246,.08);
    border: 1px solid rgba(139,92,246,.4);
    color: #c4b5fd;
}
.btn-account--tech-violet:hover { background: rgba(139,92,246,.18); border-color: rgba(139,92,246,.7); }
/* Variante "tech" liée au thème actif (demande explicite, bug signalé : "la
   couleur du bouton ne va pas du tout, y avait que pour le bouton bleu" —
   contrairement aux 4 couleurs de rôle FIXES ci-dessus (cyan/emerald/amber/
   violet, volontairement identiques pour tout le monde quel que soit le
   thème), "Voir le site" doit garder le même comportement que l'ancien
   .btn-account--primary : suivre var(--brand-color), donc la préférence de
   couleur du client (widget "couleur"/Mon profil), au lieu d'une teinte
   fixe qui ne correspond à rien pour la plupart des clients. Même structure
   translucide que les variantes ci-dessus, juste paramétrée par la couleur
   active au lieu d'une couleur figée. */
.btn-account--tech-brand {
    background: color-mix(in srgb, var(--brand-color) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--brand-color) 40%, transparent);
    color: var(--brand-color);
}
.btn-account--tech-brand:hover {
    background: color-mix(in srgb, var(--brand-color) 18%, transparent);
    border-color: color-mix(in srgb, var(--brand-color) 70%, transparent);
}
/* Variante "outline" teintée rouge pour les actions destructives mais
   secondaires (demande explicite : "améliore le visuel des boutons") — au
   lieu d'un simple bouton --outline neutre indiscernable des autres actions,
   signale visuellement qu'il s'agit d'une suppression, sans le poids visuel
   d'un --danger plein (réservé aux actions les plus critiques). */
.btn-account--outline-danger {
    background: transparent;
    border: 1px solid rgba(239,68,68,.4);
    color: #f87171;
}
.btn-account--outline-danger:hover {
    background: rgba(239,68,68,.12);
    border-color: rgba(239,68,68,.7);
}
.btn-account--sm { padding: 6px 14px; font-size: .78rem; }

/* ─── Bouton "fonctionnel" (action technique : envoyer un formulaire, une
     demande de support…) — volontairement sobre, pas un CTA marketing.
     Réutilisable partout (contrairement à la variante scopée de
     compte-profil.php). ─── */
.btn-account--functional {
    background: rgba(255,255,255,.04);
    border: 1px solid color-mix(in srgb, var(--brand-color) 40%, rgba(255,255,255,.16));
    color: var(--brand-color);
    box-shadow: none;
    border-radius: 6px;
    font-family: var(--font-title);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.btn-account--functional.btn-account--sm { font-size: .68rem; }
.btn-account--functional:hover {
    opacity: 1;
    transform: none;
    background: color-mix(in srgb, var(--brand-color) 16%, transparent);
    border-color: var(--brand-color);
    color: #fff;
}
.btn-account--functional:active { transform: none; }

/* ─── Bouton CTA (invitation à l'action : lancer un projet, prendre rendez-
     vous…) — dégradé + relief, à l'opposé du bouton "fonctionnel" ci-dessus. ─── */
.btn-account--cta {
    background: linear-gradient(135deg, var(--brand-color), color-mix(in srgb, var(--brand-color) 70%, #000));
    box-shadow: 0 4px 14px color-mix(in srgb, var(--brand-color) 32%, transparent);
    transition: transform .18s ease, box-shadow .18s ease, filter .18s ease;
}
.btn-account--cta:hover {
    opacity: 1;
    transform: translateY(-2px);
    filter: brightness(1.08);
    box-shadow: 0 8px 22px color-mix(in srgb, var(--brand-color) 45%, transparent);
}
.btn-account--cta:active { transform: translateY(0); }

/* ─── CTA "vedette" des états vides (demande explicite : "moins fade" pour
     les boutons "Faire une demande" (compte-projets.php) et "Demander un
     entretien" (compte-rendez-vous.php)) — scopé à ce modificateur précis
     plutôt qu'au générique .btn-account--cta.btn-account--sm (réutilisé tel
     quel ailleurs pour des CTA plus discrets, ex. "Voir les tarifs" sur
     compte-abonnements.php, qu'on ne veut pas changer ici) : remplace --sm
     sur ces 2 boutons seulement, avec un gabarit nettement plus grand et un
     dégradé/glow plus marqué pour qu'ils ressortent dans le grand espace
     vide de la carte "état vide" qui les entoure. ─── */
.btn-account--cta-hero {
    padding: 15px 34px;
    font-size: 1rem;
    font-weight: 700;
    border-radius: 12px;
    box-shadow: 0 10px 28px color-mix(in srgb, var(--brand-color) 50%, transparent);
}
.btn-account--cta-hero:hover {
    box-shadow: 0 16px 38px color-mix(in srgb, var(--brand-color) 62%, transparent);
}

/* ─── pages/compte-profil.php : boutons volontairement sobres, façon
     "contrôle technique" (fond plat, bordure, monospace, majuscules) plutôt
     que des CTA marketing (fini le dégradé/glow/lift — ce sont des actions de
     gestion de compte, pas des invitations à cliquer) — scopé à cette page
     via .account-content--profile-buttons. ─── */
.account-content--profile-buttons .btn-account {
    background: rgba(255,255,255,.04);
    border: 1px solid color-mix(in srgb, var(--brand-color) 40%, rgba(255,255,255,.16));
    color: var(--brand-color);
    box-shadow: none;
    border-radius: 6px;
    padding: 9px 16px;
    font-family: var(--font-title);
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.account-content--profile-buttons .btn-account:hover {
    opacity: 1;
    transform: none;
    background: color-mix(in srgb, var(--brand-color) 16%, transparent);
    border-color: var(--brand-color);
    color: #fff;
}
.account-content--profile-buttons .btn-account:active { transform: none; }
.account-content--profile-buttons .btn-account--outline {
    background: transparent;
    border: 1px solid rgba(255,255,255,.16);
    color: var(--text-muted);
    box-shadow: none;
}
.account-content--profile-buttons .btn-account--outline:hover {
    background: rgba(255,255,255,.05);
    border-color: rgba(255,255,255,.32);
    color: #fff;
}
.account-content--profile-buttons .btn-account--danger {
    background: transparent;
    border: 1px solid rgba(239,68,68,.4);
    color: #f87171;
    box-shadow: none;
}
.account-content--profile-buttons .btn-account--danger:hover {
    background: rgba(239,68,68,.12);
    border-color: #ef4444;
    color: #fca5a5;
}

.account-module-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 14px;
}

.account-module-card {
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 12px;
    padding: 16px 18px;
    transition: border-color .15s ease, background .15s ease, transform .15s ease, box-shadow .15s ease;
}
.account-module-card:hover {
    border-color: rgba(255,255,255,.18);
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0,0,0,.18);
}

.account-module-card h4 { font-size: .92rem; color: #fff; margin-bottom: 4px; }
.account-module-card .price { font-size: .8rem; color: var(--brand-color); font-weight: 700; margin-bottom: 10px; }

/* Case à cocher personnalisée (modules, formulaires de commande) */
.account-checkbox-label {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: .85rem;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
    transition: color .15s ease;
}

.account-checkbox-label:hover { color: #fff; }

.account-checkbox-label input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    width: 21px;
    height: 21px;
    margin: 0;
    flex-shrink: 0;
    border-radius: 6px;
    border: 2px solid rgba(255,255,255,.28);
    background: rgba(255,255,255,.04);
    position: relative;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, transform .1s ease;
}

.account-checkbox-label input[type="checkbox"]:hover {
    border-color: rgba(var(--header-accent),.6);
}

.account-checkbox-label input[type="checkbox"]:active {
    transform: scale(.92);
}

.account-checkbox-label input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--brand-color);
    outline-offset: 2px;
}

.account-checkbox-label input[type="checkbox"]:checked {
    background: var(--brand-color);
    border-color: var(--brand-color);
}

.account-checkbox-label input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    left: 6px;
    top: 2px;
    width: 6px;
    height: 11px;
    border: solid var(--brand-color-contrast, #fff);
    border-width: 0 2.5px 2.5px 0;
    transform: rotate(45deg);
}

/* Met en valeur toute la carte module quand son option est sélectionnée */
.account-module-card:has(input[type="checkbox"]:checked) {
    border-color: rgba(var(--header-accent),.55);
    background: var(--brand-color-soft);
}

/* Badges palier standard/avancé + badge "Offert" (formulaire de commande) */
.module-card-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
}

.module-tier-badge {
    display: inline-block;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    padding: 3px 8px;
    border-radius: 999px;
    border: 1px solid transparent;
}

.module-tier-badge--standard {
    color: var(--brand-color);
    background: var(--brand-color-soft);
    border-color: rgba(var(--header-accent),.3);
}

.module-tier-badge--avance {
    color: #ffb84d;
    background: rgba(255,184,77,.12);
    border-color: rgba(255,184,77,.3);
}

.module-free-badge {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: #4ade80;
    background: rgba(74,222,128,.12);
    border: 1px solid rgba(74,222,128,.35);
    padding: 3px 8px;
    border-radius: 999px;
}

.account-module-card.is-free {
    border-color: rgba(74,222,128,.55) !important;
    background: rgba(74,222,128,.08) !important;
}

/* ─── pages/admin-modules.php : vue d'ensemble 2×2 (une carte cliquable par
   section) + détail d'une section. ─── */
.admin-section-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 18px;
    margin-bottom: 32px;
}
@media (max-width: 720px) {
    .admin-section-grid { grid-template-columns: 1fr; }
}

.admin-section-card {
    display: block;
    padding: 26px 28px;
    border-radius: 16px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.09);
    text-decoration: none;
    color: inherit;
    transition: border-color .18s ease, background .18s ease, transform .18s ease, box-shadow .18s ease;
}
.admin-section-card:hover {
    border-color: rgba(var(--header-accent),.45);
    background: rgba(var(--header-accent),.06);
    transform: translateY(-3px);
    box-shadow: 0 14px 32px rgba(0,0,0,.25);
}
.admin-section-card-num {
    display: inline-block;
    font-family: var(--font-title);
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .1em;
    color: var(--brand-color);
    margin-bottom: 10px;
}
.admin-section-card h3 {
    font-size: 1.2rem;
    color: #fff;
    margin: 0 0 8px;
}
.admin-section-card p {
    font-size: .88rem;
    color: var(--text-muted);
    line-height: 1.6;
    margin: 0 0 16px;
}
.admin-section-card-count {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .78rem;
    font-weight: 600;
    color: rgba(255,255,255,.55);
}
.admin-section-card-arrow {
    float: right;
    font-size: 1.3rem;
    color: var(--brand-color);
    transition: transform .18s ease;
}
.admin-section-card:hover .admin-section-card-arrow {
    transform: translateX(4px);
}

.admin-back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: .85rem;
    font-weight: 600;
    color: var(--text-muted);
    text-decoration: none;
    margin-bottom: 18px;
    transition: color .15s ease;
}
.admin-back-link:hover { color: #fff; }

/* Regroupe visuellement les 3 lignes de badges + la ligne "mise en avant"
   dans le formulaire catégorie, avec plus d'air qu'un simple form-group. */
.admin-form-fieldset {
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 14px;
    padding: 18px 20px 20px;
    margin: 18px 0 22px;
    background: rgba(255,255,255,.015);
}
.admin-form-fieldset > .admin-fieldset-title {
    display: block;
    font-size: .8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: rgba(255,255,255,.55);
    margin: 0 0 4px;
}
.admin-form-fieldset > .account-card-hint {
    margin: 0 0 16px;
}
.admin-badge-row {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    padding: 10px 0;
}
.admin-badge-row + .admin-badge-row {
    border-top: 1px solid rgba(255,255,255,.06);
}
.admin-badge-row select {
    flex: 1;
    min-width: 220px;
}

/* Chip à cocher personnalisée (remplace la case à cocher navigateur brute
   pour essentiel / business / premium / mise en avant). */
.admin-badge-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border-radius: 999px;
    border: 1.5px solid rgba(255,255,255,.14);
    background: rgba(255,255,255,.03);
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
    font-size: .85rem;
    font-weight: 700;
    white-space: nowrap;
    min-width: 150px;
    transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.admin-badge-toggle input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.admin-badge-toggle::before {
    content: "";
    width: 14px;
    height: 14px;
    border-radius: 4px;
    flex-shrink: 0;
    border: 1.5px solid rgba(255,255,255,.3);
    transition: background .15s ease, border-color .15s ease;
}
.admin-badge-toggle:hover { border-color: rgba(255,255,255,.32); }
.admin-badge-toggle:has(input:checked) { color: #fff; }
.admin-badge-toggle:has(input:checked)::before {
    background: currentColor;
    border-color: currentColor;
}
.admin-badge-toggle--essentiel:has(input:checked) {
    background: rgba(255,255,255,.10);
    border-color: rgba(255,255,255,.4);
}
.admin-badge-toggle--pro:has(input:checked) {
    background: rgba(251,191,36,.16);
    border-color: rgba(251,191,36,.55);
    color: #fde68a;
}
.admin-badge-toggle--surmesure:has(input:checked) {
    background: rgba(59,130,246,.16);
    border-color: rgba(59,130,246,.55);
    color: #93c5fd;
}
.admin-badge-toggle--featured:has(input:checked) {
    background: rgba(167,139,250,.16);
    border-color: rgba(167,139,250,.55);
    color: #c4b5fd;
}

/* ─── admin-modules.php : "Ajouter une catégorie" (déplacée en tête de page) ─── */
.admin-add-category summary {
    cursor: pointer;
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 10px;
}
.admin-add-category summary::-webkit-details-marker { display: none; }
.admin-add-category summary::after {
    content: "";
    width: 9px;
    height: 9px;
    border-right: 2px solid var(--brand-color);
    border-bottom: 2px solid var(--brand-color);
    transform: rotate(-45deg);
    transition: transform .18s ease;
    margin-left: auto;
}
.admin-add-category[open] summary::after { transform: rotate(45deg); }
.admin-add-category > .account-card-hint { margin: 16px 0 0; }
.admin-add-category form { margin-top: 20px; }
.admin-add-category .form-group + .form-group,
.admin-add-category .admin-form-fieldset + .form-group { margin-top: 18px; }

/* Segmented control (2-3 choix exclusifs) — remplace les <select> nus pour
   "disponible/inclus" et la couleur de mise en avant, même logique visuelle
   que .admin-badge-toggle (case native masquée + :has(:checked)). */
.admin-segmented {
    display: inline-flex;
    border-radius: 999px;
    border: 1.5px solid rgba(255,255,255,.14);
    background: rgba(255,255,255,.03);
    overflow: hidden;
}
.admin-segmented label {
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    font-size: .8rem;
    font-weight: 600;
    color: var(--text-muted);
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s ease, color .15s ease;
}
.admin-segmented label:not(:first-child) { border-left: 1.5px solid rgba(255,255,255,.12); }
.admin-segmented input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; }
.admin-segmented label:has(input:checked) { background: var(--brand-color-soft); color: #fff; }
.admin-featured-fields { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 14px; }
.admin-color-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.admin-color-dot--amber { background: #fbbf24; }
.admin-color-dot--blue  { background: #60a5fa; }

/* ─── pages/admin-prices.php ─── */
.admin-price-row {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding: 16px 0;
}
.admin-price-row + .admin-price-row {
    border-top: 1px solid rgba(255,255,255,.06);
}
/* Chaque ligne de prix est désormais enveloppée dans .admin-price-item (pour
   le récap de confirmation en JS, cf. pages/admin-prices.php), ce qui casse
   la relation de sibling direct entre deux lignes de prix différentes : on
   reproduit donc le même séparateur au niveau du wrapper. */
.admin-price-item + .admin-price-item {
    border-top: 1px solid rgba(255,255,255,.06);
}
.admin-price-row-label {
    flex: 0 0 220px;
    font-weight: 600;
    color: #fff;
    font-size: .92rem;
}

/* Même langage visuel que .form-group select/input (fond sombre, bordure
   discrète, chevron custom, glow au focus) mais en gabarit compact pour
   tenir sur une ligne au lieu d'un formulaire vertical classique. */
.admin-price-mode {
    flex: 0 0 210px;
    box-sizing: border-box;
    padding: 10px 36px 10px 14px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.10);
    background-color: rgba(0,0,0,.28);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff99' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 14px;
    appearance: none;
    -webkit-appearance: none;
    color: #fff;
    font-size: .86rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.admin-price-mode:hover { border-color: rgba(255,255,255,.22); }
.admin-price-mode:focus {
    outline: none;
    border-color: rgba(var(--header-accent),.55);
    background-color: rgba(var(--header-accent),.06);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.12);
}
.admin-price-mode option { background: #10141f; color: #fff; }

.admin-price-fields {
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 200px;
}
.admin-price-field {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-muted);
    font-size: .88rem;
    font-weight: 600;
}
.admin-price-field input[type="number"] {
    width: 96px;
    box-sizing: border-box;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.28);
    color: #fff;
    font-size: .92rem;
    font-weight: 700;
    text-align: center;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.admin-price-field input[type="number"]:hover { border-color: rgba(255,255,255,.22); }
.admin-price-field input[type="number"]:focus {
    outline: none;
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.06);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.12);
}
.admin-price-field em {
    font-style: normal;
    color: rgba(255,255,255,.4);
    font-weight: 400;
    font-size: .82rem;
}

/* Nav répétée avant chaque section (+ en première section) : liens d'ancrage
   vers les 3 catégories + un bouton "Enregistrer les prix" à chaque fois
   (même <form> unique pour toute la page, donc n'importe lequel des boutons
   soumet TOUS les champs, pas seulement la section courante). */
.admin-prices-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    padding: 14px 18px;
    margin: 0 0 18px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 12px;
    position: sticky;
    top: 12px;
    z-index: 5;
    backdrop-filter: blur(8px);
}
.admin-prices-nav-links {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.admin-prices-nav-link {
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.24);
    color: var(--text-muted);
    font-size: .84rem;
    font-weight: 600;
    text-decoration: none;
    transition: border-color .15s ease, background .15s ease, color .15s ease;
    white-space: nowrap;
}
.admin-prices-nav-link:hover {
    border-color: rgba(255,255,255,.22);
    color: #fff;
}
.admin-prices-nav-link.is-current {
    background: rgba(var(--header-accent),.14);
    border-color: rgba(var(--header-accent),.5);
    color: #fff;
}
/* Répété 3 fois (nav sticky avant chaque section) : le dégradé plein
   .btn-account--cta d'origine (bleu marque saturé + glow) devenait trop
   présent à l'écran en permanence pendant le scroll. Fond assourdi (bleu
   mélangé au fond sombre plutôt que saturé) + halo au repos supprimé ; le
   glow ne revient qu'au hover, pour garder un vrai CTA sans qu'il crie. */
.admin-prices-nav-save {
    flex: 0 0 auto;
    padding: 10px 22px;
    font-size: .88rem;
    white-space: nowrap;
    background: linear-gradient(135deg, color-mix(in srgb, var(--brand-color) 55%, #12151f), color-mix(in srgb, var(--brand-color) 30%, #05070c));
    border: 1px solid color-mix(in srgb, var(--brand-color) 45%, transparent);
    box-shadow: none;
}
.admin-prices-nav-save:hover {
    box-shadow: 0 4px 16px color-mix(in srgb, var(--brand-color) 25%, transparent);
}

/* ─── "Interface CMS" (pages/admin-cms.php + les 4 pages CMS) : conteneur
   de page DÉDIÉ, volontairement séparé de la grille .account-page (demande
   explicite : "une nouvelle interface externe à la dashboard admin... avoir
   tout l'espace de disponible pour le CMS" — .account-page réserve 310px +
   260px aux 2 colonnes de menu latéral admin, que ces 5 pages n'affichent
   plus). Bloc simple (pas de grid), plus large que .account-page
   (1650px) puisqu'il n'a plus de colonnes latérales à loger. Les classes
   généralistes déjà posées sur .account-page (--text-muted plus lisible,
   liens "bruts" en bleu clair) sont reprises telles quelles ici pour rester
   cohérent avec le reste de l'espace admin. ─── */
.cms-shell {
    max-width: 1900px;
    margin: 0 auto;
    padding: 32px 24px var(--footer-clearance);
    --text-muted: rgba(255,255,255,.85);
}
.cms-shell a:not([class]) {
    color: #7cb8ff;
    font-weight: 600;
    text-decoration: underline;
    text-decoration-color: rgba(124,184,255,.45);
    text-underline-offset: 2px;
    transition: color .15s ease;
}
.cms-shell a:not([class]):hover { color: #fff; text-decoration-color: currentColor; }

/* ─── Barre d'onglets sticky commune aux 5 pages de l'Interface CMS (hub +
   Modules/Prix Site/Tableau comparatif/FAQ) — même langage visuel que
   .admin-prices-nav-link ci-dessus (pills sticky), sous des noms de classe
   génériques puisque partagée par tout le CMS et non plus propre aux prix.
   .admin-back-link (déjà existant, cf. pages/admin-modules.php) est
   réutilisé tel quel pour le lien "← Retour au dashboard". ─── */
.cms-subnav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    padding: 14px 18px;
    margin: 0 0 18px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 12px;
    position: sticky;
    top: 12px;
    z-index: 5;
    backdrop-filter: blur(8px);
}
.cms-subnav-links {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.cms-subnav-link {
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.24);
    color: var(--text-muted);
    font-size: .84rem;
    font-weight: 600;
    text-decoration: none;
    transition: border-color .15s ease, background .15s ease, color .15s ease;
    white-space: nowrap;
}
.cms-subnav-link:hover {
    border-color: rgba(255,255,255,.22);
    color: #fff;
}
.cms-subnav-link.is-current {
    background: rgba(var(--header-accent),.14);
    border-color: rgba(var(--header-accent),.5);
    color: #fff;
}

/* Descriptif de l'offre (partagé accueil/offres-site/services). */
.admin-price-row--offer-desc {
    padding: 0 14px 12px;
    margin-top: -8px;
    background: rgba(255,255,255,.02);
    border-radius: 0 0 10px 10px;
    border-top: none !important;
}
.admin-offer-desc {
    width: 100%;
    box-sizing: border-box;
    padding: 10px 14px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.28);
    color: #fff;
    font-size: .88rem;
    line-height: 1.5;
    font-family: inherit;
    resize: vertical;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.admin-offer-desc:hover { border-color: rgba(255,255,255,.22); }
.admin-offer-desc:focus {
    outline: none;
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.06);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.12);
}

/* Éléments inclus (Hébergement & Maintenance), édition ligne par ligne. */
.admin-price-row--features {
    align-items: flex-start;
}
.admin-price-row--feature-actions {
    padding-top: 0;
    border-top: none !important;
}
.admin-feature-list {
    flex: 1;
    min-width: 240px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.admin-feature-row {
    display: flex;
    align-items: center;
    gap: 8px;
}
.admin-feature-input {
    flex: 1;
    box-sizing: border-box;
    padding: 9px 12px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.28);
    color: #fff;
    font-size: .86rem;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.admin-feature-input:hover { border-color: rgba(255,255,255,.22); }
.admin-feature-input:focus {
    outline: none;
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.06);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.12);
}
.admin-feature-remove {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(255,255,255,.03);
    color: rgba(255,255,255,.5);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.admin-feature-remove:hover {
    border-color: rgba(248,113,113,.5);
    background: rgba(248,113,113,.12);
    color: #fca5a5;
}
.admin-feature-add {
    margin-top: 10px;
    padding: 8px 16px;
    border-radius: 999px;
    border: 1px dashed rgba(255,255,255,.22);
    background: transparent;
    color: var(--text-muted);
    font-size: .82rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.admin-feature-add:hover {
    border-color: rgba(var(--header-accent),.5);
    background: rgba(var(--header-accent),.06);
    color: #fff;
}

/* Mini-FAQ éditable des 3 offres de création de site (question + réponse par
   ligne), même langage visuel que .admin-price-row--features ci-dessus. */
.admin-price-row--faq {
    align-items: flex-start;
    flex-direction: column;
    padding: 12px 14px 14px;
    margin-top: -4px;
    background: rgba(255,255,255,.02);
    border-radius: 10px;
    border-top: none !important;
}
/* .admin-price-row-label hérite de "flex: 0 0 220px" (pensé pour l'axe
   horizontal des autres lignes) — mais ici le conteneur est en
   flex-direction: column, donc ce flex-basis s'applique à la HAUTEUR au lieu
   de la largeur : le libellé "FAQ de l'offre" se retrouvait forcé dans une
   boîte de 220px de haut, créant un grand vide avant la liste de questions.
   On repasse sur la taille naturelle du texte. */
.admin-price-row--faq .admin-price-row-label {
    flex: 0 0 auto;
}
.admin-faq-mini-list {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 8px;
}
.admin-faq-mini-item {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.admin-faq-mini-q,
.admin-faq-mini-a {
    width: 100%;
    box-sizing: border-box;
    padding: 9px 12px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.28);
    color: #fff;
    font-size: .86rem;
    font-family: inherit;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.admin-faq-mini-q { font-weight: 600; }
.admin-faq-mini-a { resize: vertical; line-height: 1.5; }
.admin-faq-mini-q:hover, .admin-faq-mini-a:hover { border-color: rgba(255,255,255,.22); }
.admin-faq-mini-q:focus, .admin-faq-mini-a:focus {
    outline: none;
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.06);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.12);
}

/* Nom + badge de l'offre (sous-ligne dédiée, en retrait, avec un fond léger
   pour bien la distinguer de la ligne de prix juste au-dessus). */
.admin-price-row--offer-meta {
    padding: 12px 14px;
    margin: -4px 0 0;
    background: rgba(255,255,255,.02);
    border-radius: 10px;
    border-top: none !important;
}
.admin-offer-name {
    flex: 1;
    min-width: 160px;
    box-sizing: border-box;
    padding: 10px 14px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.28);
    color: #fff;
    font-size: .9rem;
    font-weight: 600;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.admin-offer-name:hover { border-color: rgba(255,255,255,.22); }
.admin-offer-name:focus {
    outline: none;
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.06);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.12);
}
.admin-offer-badge {
    flex: 0 0 260px;
    box-sizing: border-box;
    padding: 10px 36px 10px 14px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.10);
    background-color: rgba(0,0,0,.28);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff99' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 14px;
    appearance: none;
    -webkit-appearance: none;
    color: #fff;
    font-size: .86rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.admin-offer-badge:hover { border-color: rgba(255,255,255,.22); }
.admin-offer-badge:focus {
    outline: none;
    border-color: rgba(var(--header-accent),.55);
    background-color: rgba(var(--header-accent),.06);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.12);
}
.admin-offer-badge option { background: #10141f; color: #fff; }
.admin-offer-meta-hint {
    margin: 4px 0 0 !important;
    font-size: .76rem !important;
}

/* Boîte de confirmation avant enregistrement (récap des changements). */
.admin-confirm-overlay {
    position: fixed;
    inset: 0;
    background: rgba(5,8,15,.72);
    backdrop-filter: blur(4px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 200;
    padding: 24px;
}
.admin-confirm-overlay[hidden] { display: none; }
.admin-confirm-modal {
    width: 100%;
    max-width: 520px;
    max-height: 82vh;
    display: flex;
    flex-direction: column;
    background: #12151f;
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 16px;
    padding: 24px;
    box-shadow: 0 24px 60px rgba(0,0,0,.5);
}
.admin-confirm-modal h3 {
    margin: 0 0 14px;
    font-size: 1.15rem;
    color: #fff;
}
.admin-confirm-body {
    overflow-y: auto;
    flex: 1;
    margin-bottom: 18px;
}
.admin-confirm-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.admin-confirm-list > li {
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
}
.admin-confirm-list > li > strong {
    display: block;
    color: #fff;
    font-size: .92rem;
    margin-bottom: 6px;
}
.admin-confirm-list ul {
    list-style: disc;
    margin: 0;
    padding-left: 18px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.admin-confirm-list ul li {
    color: var(--text-muted);
    font-size: .84rem;
    line-height: 1.4;
}
.admin-confirm-empty {
    color: var(--text-muted);
    font-size: .9rem;
    margin: 0;
}
.admin-confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
}
.admin-confirm-cancel {
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.12);
}

/* ─── compte-sites.php : suivi de projet (maquettes / phases) ───
   Ces classes (mockup-*) existaient déjà dans le HTML mais n'avaient
   jamais reçu de style : les icônes du bloc Support s'affichaient donc
   à leur taille native (énorme, "cassé") et la barre de phases du suivi
   de projet n'avait aucune mise en forme. Ajouté ci-dessous. */
.status-badge--waiting     { background: rgba(255,255,255,.08); color: var(--text-muted); }
.status-badge--in-progress { background: rgba(var(--header-accent),.14); color: #60a5fa; }
.status-badge--done        { background: rgba(16,185,129,.14); color: #34d399; }

.account-notice {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 20px;
    border-radius: 12px;
    font-size: .88rem;
    margin-bottom: 22px;
}
.account-notice--success { background: rgba(16,185,129,.10); border: 1px solid rgba(16,185,129,.3); color: #34d399; }
.account-notice--error   { background: rgba(239,68,68,.10);  border: 1px solid rgba(239,68,68,.3);  color: #f87171; }
/* Facture payée, propriété du domaine pas encore transférée au client (cf.
   pages/admin-custom-quotes.php, suivi de réservation de domaine) — même
   teinte ambre que les autres avertissements du site (badges "en attente",
   échéance à 30j sur admin-sites.php...), pas de nouvelle couleur. */
.account-notice--warning { background: rgba(251,191,36,.10); border: 1px solid rgba(251,191,36,.3); color: #fbbf24; }
/* Bandeau "nouveaux messages" en tête d'admin-maquettes.php (demande
   explicite, cf. $newMessageProjects côté PHP) — bleu neutre plutôt
   qu'ambre/rouge, ce n'est pas une alerte mais une information. */
.account-notice--info { background: rgba(96,165,250,.10); border: 1px solid rgba(96,165,250,.3); color: #60a5fa; }

.mockup-item + .mockup-item {
    margin-top: 24px;
    padding-top: 24px;
    border-top: 1px solid rgba(255,255,255,.08);
}
.mockup-item__header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.mockup-item__title { font-weight: 600; color: #fff; font-size: .98rem; }
.mockup-item__body { margin-top: 22px; }
.mockup-item__desc { color: var(--text-muted); font-size: .88rem; line-height: 1.5; margin-bottom: 4px; }
.mockup-cta { margin-top: 16px; }
/* "Voir la maquette" grisé tant qu'aucune URL n'est renseignée par l'admin
   (demande explicite : "doit être visible mais grisé à toutes les phases...
   il devient visible [actif] dès que l'admin a ajouté une URL") — un <span>
   plutôt qu'un <a> désactivé : jamais de lien mort, rien à cliquer (pas de
   href/onclick). pointer-events reste actif exprès (contrairement à un
   pattern "disabled" classique) pour que le survol continue de déclencher le
   tooltip .btn-tooltip expliquant pourquoi le bouton est grisé. */
.mockup-cta--disabled {
    opacity: .45;
    cursor: not-allowed;
    filter: grayscale(.4);
}
/* Actions de validation client par étape (demande explicite, spec de
   finalisation "Mes projets" : valider le cahier des charges/la maquette,
   validation combinée + "demander un changement", "passer à la mise en
   ligne") — mêmes boutons .btn-account que le reste du compte, simplement
   espacés de la notification d'étape juste au-dessus (cf.
   render_project_validation_action() dans pages/compte-projets.php). */
/* Encart "Signatures officielles" côté admin (pages/admin-maquettes.php —
   demande explicite : "cette validation doit faire office de signature
   officielle") — trace horodatée + IP de chaque validation client, purement
   informatif (aucune action possible dessus). */
.mockup-signatures {
    margin: 10px 0 4px;
    padding: 10px 14px;
    background: rgba(52,211,153,.06);
    border: 1px solid rgba(52,211,153,.22);
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.mockup-signatures-title { font-size: .78rem; font-weight: 600; color: #34d399; }
.mockup-signature-row { font-size: .78rem; color: var(--text-muted); }
.mockup-validate-form { margin-top: 16px; }
.mockup-validate-actions {
    margin-top: 16px;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.mockup-validate-actions .mockup-validate-form { margin-top: 0; }
.mockup-chat-closed-notice { margin-top: 14px; margin-bottom: 0; }
.mockup-item__notes {
    margin-top: 16px;
    padding: 12px 16px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 10px;
    font-size: .85rem;
    color: var(--text-muted);
    line-height: 1.5;
}
/* Boutons "Télécharger le cahier des charges" / "Voir le devis" (demande
   explicite) — cf. pages/compte-projets.php et pages/admin-maquettes.php. */
.mockup-item__extras { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.mockup-item__extras .btn-account svg { width: 15px; height: 15px; margin-right: 5px; vertical-align: -3px; }
/* pages/compte-devis.php : mis en évidence temporaire du devis visé par le
   bouton "Voir le devis" d'un projet (ancre #devis-{id}, cf.
   .mockup-item__extras ci-dessus) — purement visuel, disparaît si l'ancre
   change ou après navigation. */
.devis-card-target:target { border-color: var(--brand-color); box-shadow: 0 0 0 2px rgba(var(--header-accent),.3); animation: devisTargetFlash 1.6s ease; }
@keyframes devisTargetFlash {
    0%   { background: rgba(var(--header-accent),.14); }
    100% { background: rgba(255,255,255,.02); }
}
/* pages/compte-factures.php : même principe que .devis-card-target ci-dessus,
   pour le lien "Voir mes factures" depuis "Mes projets" (phase 4 — demande
   explicite : "un lien vers la page Mes factures pour consulter la facture
   émise par l'admin et la régler"), ancre #facture-{id}. */
.facture-card-target:target { border-color: var(--brand-color); box-shadow: 0 0 0 2px rgba(var(--header-accent),.3); animation: devisTargetFlash 1.6s ease; }

/* Titre au-dessus de la frise d'avancement (demande explicite : "un titre
   avant la barre d'avancement") — repris tel quel par pages/admin-
   maquettes.php dans son aperçu client (cf. renderClientPreview()). */
.mockup-phases-title {
    margin: 26px 0 16px;
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-muted);
}

/* Frise d'avancement (demande explicite : "donner plus d'importance visuel à
   cette ligne d'avancement" + "que tout les items soient bien alignés sur
   leur ligne et colonne respective") — passage de flex à grid : 6 colonnes
   strictement égales garantissent l'alignement des puces ET des libellés
   quelle que soit la longueur de chacun, contrairement à `flex: 1` qui
   laissait chaque étape dériver selon son contenu. Le trait de connexion
   (::before = piste neutre, ::after = remplissage coloré) ajoute le poids
   visuel d'une vraie barre de progression derrière les puces ; sa largeur
   suit --phase-fill (0 à 100, posée en style inline par compte-projets.php
   et par l'aperçu JS de admin-maquettes.php à partir de la phase courante). */
.mockup-phases {
    position: relative;
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    column-gap: 4px;
    margin: 10px 0 4px;
}
.mockup-phases::before,
.mockup-phases::after {
    content: "";
    position: absolute;
    top: 22px;
    height: 3px;
    border-radius: 3px;
}
.mockup-phases::before {
    left: calc(100% / 12);
    right: calc(100% / 12);
    background: rgba(255,255,255,.10);
    z-index: 0;
}
.mockup-phases::after {
    left: calc(100% / 12);
    width: calc((100% - (100% / 6)) * var(--phase-fill, 0) / 100);
    background: linear-gradient(90deg, var(--brand-color), rgba(var(--header-accent),.9));
    z-index: 1;
    transition: width .5s ease;
}
.mockup-phases--empty { opacity: .55; }
.mockup-phase-step {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    min-width: 0;
    gap: 10px;
}
.mockup-phase-num {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    font-size: .92rem;
    font-weight: 700;
    background: rgba(255,255,255,.08);
    border: 2px solid rgba(255,255,255,.14);
    color: var(--text-muted);
    flex-shrink: 0;
    transition: background .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.mockup-phase-name {
    font-size: .74rem;
    color: var(--text-muted);
    line-height: 1.3;
    padding: 0 2px;
}
/* Fond OPAQUE (pas juste "peu transparent") — bug réel signalé : "la barre
   bleue est visible dans les cercles verts". La ligne de progression
   (.mockup-phases::after, bleue, z-index:1) passe pile derrière chaque
   puce ; l'ancien fond translucide (rgba(...,.18)) laissait cette ligne
   transparaître à travers les puces "done" (vert). La puce "active" juste
   à côté n'a jamais ce problème car son fond (var(--brand-color)) est déjà
   100% opaque — même recette reprise ici plutôt qu'inventée : plus de
   canal alpha sur le fond/la bordure, texte repassé en blanc (le vert clair
   #34d399 d'origine n'était lisible que sur un fond quasi transparent —
   illisible sur un vrai fond vert plein). */
.mockup-phase-step--done .mockup-phase-num {
    background: rgb(16,185,129);
    border-color: rgb(16,185,129);
    color: #fff;
}
.mockup-phase-step--done .mockup-phase-name { color: rgba(255,255,255,.55); }
.mockup-phase-step--active .mockup-phase-num {
    background: var(--brand-color);
    border-color: var(--brand-color);
    color: var(--brand-color-contrast, #fff);
    box-shadow: 0 0 0 5px rgba(var(--header-accent),.20);
}
.mockup-phase-step--active .mockup-phase-name { color: #fff; font-weight: 700; }
.mockup-phase-step--pending .mockup-phase-num { color: rgba(255,255,255,.35); }

/* Indication détaillée de l'étape en cours (demande explicite : "visible et
   mise en avant juste en dessous de l'étape en cours") — mise en avant sous
   la frise .mockup-phases, distincte du simple libellé court de l'étape. */
.mockup-phase-current-desc {
    margin-top: 14px;
    padding: 12px 16px;
    background: rgba(var(--header-accent),.10);
    border: 1px solid rgba(var(--header-accent),.35);
    border-left: 3px solid var(--brand-color);
    border-radius: 10px;
}
.mockup-phase-current-desc-badge {
    display: inline-block;
    font-size: .7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--brand-color);
    margin-bottom: 4px;
}
.mockup-phase-current-desc p {
    margin: 0;
    font-size: .85rem;
    color: rgba(255,255,255,.85);
    line-height: 1.5;
}

/* Descriptif de l'étape au survol de l'étape EN COURS (demande explicite),
   sur l'icône de la frise elle-même — même mécanique [data-tooltip]::after
   que .method-step-badge, avec retour à la ligne autorisé (les descriptifs
   sont des phrases complètes, contrairement aux tooltips courts de
   .btn-tooltip qui restent sur une seule ligne). */
.mockup-phase-step-tooltip { position: relative; cursor: help; }
.mockup-phase-step-tooltip[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    width: max-content;
    max-width: 220px;
    background: rgba(10,14,30,.97);
    border: 1px solid rgba(255,255,255,.10);
    color: #fff;
    border-radius: 8px;
    font-size: .72rem;
    font-weight: 500;
    line-height: 1.4;
    text-align: left;
    white-space: normal;
    padding: 8px 12px;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .2s ease, visibility .2s ease, transform .2s ease;
    z-index: 30;
}
.mockup-phase-step-tooltip[data-tooltip]:hover::after,
.mockup-phase-step-tooltip[data-tooltip]:focus-visible::after {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
}

/* Aperçu côté client (pages/admin-maquettes.php, demande explicite) : encart
   au bord pointillé pour bien le distinguer visuellement du formulaire
   d'édition qui l'entoure — le contenu à l'intérieur (.mockup-phases /
   .mockup-phase-current-desc) reprend tel quel le rendu de
   pages/compte-projets.php. */
.mockup-client-preview-wrap {
    margin-top: 12px;
    padding: 18px 20px;
    border: 1px dashed rgba(255,255,255,.18);
    border-radius: 12px;
    background: rgba(255,255,255,.015);
}
.mockup-client-preview .mockup-phases-title { margin-top: 0; }
.mockup-client-preview .mockup-phases { margin: 10px 0 0; }

/* Couleur de la notification d'étape selon sa catégorie (demande explicite :
   "3 notifications différentes... avec chacune une couleur différente") —
   mêmes teintes que les status-badge existants (orange ~ .status-badge
   --pending, bleu ~ .status-badge--in-progress, vert ~ .status-badge--done)
   pour rester cohérent avec la palette déjà utilisée ailleurs sur le site.
   Sans catégorie (texte personnalisé ou valeur par défaut de l'étape),
   .mockup-phase-current-desc garde son style neutre habituel (cf. plus haut). */
.mockup-phase-current-desc--waiting {
    background: rgba(251,191,36,.10);
    border-color: rgba(251,191,36,.35);
    border-left-color: #fbbf24;
}
.mockup-phase-current-desc--waiting .mockup-phase-current-desc-badge { color: #fbbf24; }
.mockup-phase-current-desc--in-progress {
    background: rgba(96,165,250,.10);
    border-color: rgba(96,165,250,.35);
    border-left-color: #60a5fa;
}
.mockup-phase-current-desc--in-progress .mockup-phase-current-desc-badge { color: #60a5fa; }
.mockup-phase-current-desc--finalization {
    background: rgba(52,211,153,.10);
    border-color: rgba(52,211,153,.35);
    border-left-color: #34d399;
}
.mockup-phase-current-desc--finalization .mockup-phase-current-desc-badge { color: #34d399; }

/* Sélecteur de couleur de bannière pour un message personnalisé
   (pages/admin-maquettes.php, demande explicite) — mêmes 3 teintes que les
   catégories suggérées (orange/bleu/vert) + une option "Neutre", sous forme
   de petits ronds de couleur cliquables plutôt qu'un select classique. */
.mockup-notice-color-picker {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 10px;
    flex-wrap: wrap;
}
/* Le sélecteur de couleur de bannière ne doit être visible que si
   "Personnalisée" est choisie en notification d'étape (demande explicite) —
   sans cette règle, "display: flex" ci-dessus écrasait l'attribut [hidden]
   posé par PHP/JS (cf. pages/admin-maquettes.php), rendant le sélecteur
   visible en permanence quelle que soit la sélection. */
.mockup-notice-color-picker[hidden] {
    display: none;
}
.mockup-notice-color-picker-label {
    font-size: .78rem;
    color: var(--text-muted);
}
.mockup-color-swatch-label {
    display: inline-flex;
    cursor: pointer;
}
.mockup-color-swatch-label input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}
.mockup-color-swatch {
    display: inline-block;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid rgba(255,255,255,.18);
    transition: transform .15s ease, border-color .15s ease;
}
.mockup-color-swatch--neutral      { background: rgba(255,255,255,.18); }
.mockup-color-swatch--waiting      { background: #fbbf24; }
.mockup-color-swatch--in-progress  { background: #60a5fa; }
.mockup-color-swatch--finalization { background: #34d399; }
.mockup-color-swatch-label input[type="radio"]:checked + .mockup-color-swatch {
    border-color: #fff;
    transform: scale(1.15);
}
.mockup-color-swatch-label input[type="radio"]:focus-visible + .mockup-color-swatch {
    outline: 2px solid var(--brand-color);
    outline-offset: 2px;
}

/* ─── compte-dashboard.php : bloc Support ─── */
.support-actions { display: flex; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; }
.support-action-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 20px;
    border-radius: 11px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(255,255,255,.03);
    color: #fff;
    font-size: .85rem;
    font-weight: 600;
    text-decoration: none;
    transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.support-action-btn svg { width: 18px; height: 18px; flex-shrink: 0; }
.support-action-btn:hover { border-color: rgba(var(--header-accent),.4); background: var(--brand-color-soft); transform: translateY(-1px); }
.support-action-btn--tel svg { color: #34d399; }
.support-action-btn--faq svg { color: #60a5fa; }

/* Bouton support "Appeler" (mobile, tel:) / "Nous contacter" (desktop, vers
   contact.php) : un seul des deux est affiché selon la largeur d'écran. */
.support-action-btn--desktop-only { display: none; }
@media (min-width: 769px) {
    .support-action-btn--mobile-only { display: none; }
    .support-action-btn--desktop-only { display: flex; }
}

/* ─── partials/account-widgets.php : encart "Mes projets" + pastille de notification ─── */
.account-widgets-row {
    display: flex;
    margin-bottom: 24px;
}
.account-widget-card {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    max-width: 420px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 18px 20px;
    text-decoration: none;
    transition: border-color .2s ease, background .2s ease, transform .15s ease;
}
.account-widget-card:hover {
    border-color: rgba(var(--header-accent),.35);
    background: var(--brand-color-soft);
    transform: translateY(-1px);
}
.account-widget-icon {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 10px;
    background: rgba(255,255,255,.06);
    flex-shrink: 0;
}
.account-widget-icon svg { width: 20px; height: 20px; color: var(--brand-color); }
.account-widget-dot {
    position: absolute;
    top: -3px;
    right: -3px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #ef4444;
    border: 2px solid #14161e;
    box-shadow: 0 0 0 2px rgba(239,68,68,.25);
}
.account-widget-body { flex: 1; min-width: 0; }
.account-widget-value { font-size: .95rem; font-weight: 700; color: #fff; }
.account-widget-label { font-size: .78rem; color: var(--text-muted); margin-top: 2px; }
.account-widget-arrow { width: 16px; height: 16px; color: var(--text-muted); flex-shrink: 0; }

/* ─── partials/account-nav.php : colonne de gauche complète (bandeau stat +
     menu). Élément unique de la grille .account-layout côté colonne 220px,
     pour que le bandeau reste bien rattaché au menu sans déborder sur le
     contenu à droite. ─── */
.account-sidenav-col { display: flex; flex-direction: column; min-width: 0; }

/* Bandeau stat publique CroisierWeb : rattaché au menu (juste au-dessus),
   mais volontairement hors de sa "box" (pas de fond ni de bordure encadrée)
   pour rester discret — simple ligne fine avec un léger séparateur. */
/* margin-bottom augmenté (7px -> 14px, demande explicite "crée de l'espace
   entre eux", sans changer sa taille propre — gap/padding-bottom/
   border-bottom/font-size inchangés) : plus de séparation avant le menu qui
   suit juste en dessous. */
.account-stat-banner {
    display: flex;
    align-items: center;
    gap: 7px;
    /* margin-bottom réaugmenté 14px -> 17px (même demande que top ci-dessus :
       "petit écart" avant la nav, actuellement quasi invisible). */
    margin-bottom: 17px;
    padding-bottom: 7px;
    border-bottom: 1px solid rgba(255,255,255,.08);
    text-decoration: none;
    font-size: .7rem;
    color: var(--text-muted);
    transition: color .2s ease;
}
.account-stat-banner:hover { color: #fff; }
/* Variante "cale" invisible, colonne de droite (cf. partials/account-nav.php)
   — mêmes dimensions que le bandeau réel de la colonne de gauche (garantit
   l'alignement des 2 <nav> côte à côte, demande explicite), simplement
   invisible et non interactive. */
.account-stat-banner--ghost { visibility: hidden; pointer-events: none; }
.account-stat-banner svg { width: 13px; height: 13px; flex-shrink: 0; color: var(--brand-color); }
.account-stat-banner strong { color: #fff; font-weight: 700; }
.account-stat-banner-lines { display: flex; flex-direction: column; gap: 1px; }

/* ─── partials/account-nav.php : pastille stats CroisierWeb (colonne de gauche) ─── */
.account-sidenav-stat {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px;
    margin-bottom: 8px;
    border-radius: 9px;
    background: rgba(var(--header-accent),.08);
    border: 1px solid rgba(var(--header-accent),.2);
    text-decoration: none;
    color: #fff;
    font-size: .8rem;
    transition: border-color .2s ease, background .2s ease;
}
.account-sidenav-stat:hover { border-color: rgba(var(--header-accent),.4); background: rgba(var(--header-accent),.14); }
.account-sidenav-stat svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--brand-color); }
.account-sidenav-stat strong { color: #fff; }
.account-sidenav-stat em { display: block; font-style: normal; font-size: .7rem; color: var(--text-muted); }

/* ─── partials/account-nav.php : stats personnelles du client (projets en
     cours / accomplis) — reprend exactement le style de .account-sidenav-stat
     (même teinte bleue, même discrétion), en désactivant juste le hover
     puisque ce n'est pas un lien cliquable. ─── */
.account-sidenav-stat--static { cursor: default; }
.account-sidenav-stat--static:hover { border-color: rgba(var(--header-accent),.2); background: rgba(var(--header-accent),.08); }

/* ─── stats client : taille très réduite (nettement plus petites que la
     pastille CroisierWeb) pour rester discrètes dans le menu latéral. ─── */
.account-sidenav-stat--compact {
    padding: 4px 7px;
    gap: 5px;
    margin-bottom: 4px;
    font-size: .66rem;
    border-radius: 6px;
}
.account-sidenav-stat--compact svg { width: 11px; height: 11px; }

/* ─── pastille "projet(s) accompli(s)" : toujours en vert (demande explicite),
     même teinte que .status-badge--done. ─── */
.account-sidenav-stat--done { background: rgba(16,185,129,.10); border-color: rgba(16,185,129,.28); }
.account-sidenav-stat--done:hover { background: rgba(16,185,129,.16); border-color: rgba(16,185,129,.45); }
.account-sidenav-stat--done svg { color: #34d399; }

/* ─── partials/account-nav.php : "Créer site web" sorti de la nav "travail",
     mis en avant en grand juste en dessous (demande explicite) — fond teinté
     à la couleur d'accent choisie par le client (même variable que
     .account-sidenav-stat ci-dessus, rgba(var(--header-accent),...)), plus
     grand/gras que les liens de la nav pour bien se distinguer.
     Taille resserrée (demande explicite : "que la NAV travail ne soit pas
     trop grande") — ces 4 cartes empilées (Créer un site/Sur-mesure/
     Hébergement/Conseil) étaient le principal poste de hauteur de la colonne
     de gauche, désormais à hauteur d'écran limitée (position:fixed, cf.
     .account-sidenav-col). ─── */
.account-sidenav-cta {
    display: flex;
    align-items: center;
    gap: 10px;
    /* margin-top augmenté (8px -> 16px, demande explicite "crée de l'espace
       entre eux" sans agrandir les cartes elles-mêmes) : espace le bloc de 4
       CTA du menu au-dessus, et chaque CTA entre elles. */
    margin-top: 16px;
    padding: 11px 14px;
    border-radius: 12px;
    background: rgba(var(--header-accent),.14);
    border: 1px solid rgba(var(--header-accent),.35);
    color: #fff;
    font-size: .85rem;
    font-weight: 700;
    text-decoration: none;
    transition: border-color .2s ease, background .2s ease, box-shadow .2s ease;
}
.account-sidenav-cta:hover {
    background: rgba(var(--header-accent),.22);
    border-color: rgba(var(--header-accent),.55);
    box-shadow: 0 12px 30px -18px rgba(var(--header-accent),.6);
}
.account-sidenav-cta svg { width: 18px; height: 18px; flex-shrink: 0; }
/* Icône planète Terre (assets/image/planet-terre.png) à la place du
   pictogramme SVG générique (demande explicite) — même traitement circulaire
   que .offer-planet img sur offres-site.php. */
.account-sidenav-cta-icon { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.account-sidenav-cta--active {
    background: rgba(var(--header-accent),.26);
    border-color: rgba(var(--header-accent),.6);
}

/* Colonne "travail" trop grande sur Chrome, pas sur Edge (demande explicite,
   captures d'écran à l'appui) : la piste "police/rem" (cf. html{font-size}
   plus haut) n'a rien changé — confirme que la vraie cause est un budget de
   hauteur trop juste (.account-sidenav-col, position:fixed entre top:96px et
   bottom:130px) : quelques dizaines de px de barres de navigateur en plus ou
   en moins (barre de favoris affichée ou non, hauteur d'onglets légèrement
   différente selon le navigateur) suffisent à faire basculer d'"tout tient"
   à "défilement interne nécessaire", d'où la différence Chrome/Edge sur la
   même machine sans aucun réglage particulier. Resserre l'espacement UNIQUEMENT
   sous cette hauteur de fenêtre, pour dégager une vraie marge de sécurité,
   sans changer l'apparence sur un écran assez haut (comportement inchangé
   au-delà de 960px de hauteur). */
/* Resserrage revu à la baisse (demande explicite "un peu trop tassé à
   gauche") : la version précédente (8px/8px/10px) coupait trop large,
   au-delà du strict nécessaire pour éviter le débordement. Valeurs
   intermédiaires : gardent une vraie marge de sécurité sous 960px de hauteur
   tout en laissant plus d'air que la 1re tentative. */
@media (max-height: 960px) {
    .account-stat-banner { margin-bottom: 12px; padding-bottom: 6px; }
    .account-sidenav-col--left .account-sidenav-link { padding: 9px 14px; }
    .account-sidenav-cta { margin-top: 13px; padding: 10px 14px; }
}

/* ─── pastille "projet(s) en cours" : couleur dépendant du statut le plus
     urgent parmi les projets en cours du client (cf. partials/account-nav.php).
     "in-progress" (équipe en train d'y travailler) reprend le bleu de
     .status-badge--in-progress ; "waiting" (pas encore démarré) reste neutre,
     comme .status-badge--waiting. ─── */
.account-sidenav-stat--in-progress { background: rgba(var(--header-accent),.10); border-color: rgba(var(--header-accent),.28); }
.account-sidenav-stat--in-progress:hover { background: rgba(var(--header-accent),.16); border-color: rgba(var(--header-accent),.45); }
.account-sidenav-stat--in-progress svg { color: #60a5fa; }

.account-sidenav-stat--waiting { background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.14); }
.account-sidenav-stat--waiting:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.22); }
.account-sidenav-stat--waiting svg { color: var(--text-muted); }

/* ─── partials/account-nav.php : pastille de notification sur un lien (ex :
     Messages non lus) — poussée à droite par le gap du flex parent. ─── */
.account-sidenav-badge {
    margin-left: auto;
    min-width: 19px;
    height: 19px;
    padding: 0 6px;
    border-radius: 999px;
    background: linear-gradient(135deg, #f87171, #ef4444);
    color: #fff;
    font-size: .68rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    box-shadow: 0 0 0 3px rgba(239,68,68,.16), 0 1px 3px rgba(0,0,0,.4);
    animation: navBadgePulse 2.4s ease-in-out infinite;
}
@keyframes navBadgePulse {
    0%, 100% { box-shadow: 0 0 0 3px rgba(239,68,68,.16), 0 1px 3px rgba(0,0,0,.4); }
    50%      { box-shadow: 0 0 0 5px rgba(239,68,68,.26), 0 1px 3px rgba(0,0,0,.4); }
}
/* Variante posée sur l'étiquette de catégorie (partials/admin-nav.php
   _admin_nav_label, à l'intérieur de .account-sidenav-group-label-text) :
   plus petite, pas de margin-left:auto (déjà collée au texte via le gap du
   flex parent). */
.account-sidenav-badge--inline { margin-left: 0; min-width: 15px; height: 15px; font-size: .62rem; padding: 0 5px; }

/* ─── compte-projets.php / admin-chats.php : chat avec l'équipe CroisierWeb ─── */
.account-chat-header { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 18px; }
.account-chat-header-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--brand-color-soft);
    color: var(--brand-color);
    flex-shrink: 0;
}
.account-chat-header-icon svg { width: 20px; height: 20px; }
.account-chat-thread {
    max-height: 420px;
    overflow-y: auto;
    margin-bottom: 14px;
    padding-right: 4px;
    /* Barre de défilement fine et discrète plutôt que le rendu par défaut du
       navigateur (le défilement lui-même reste inchangé). */
    scrollbar-width: thin;
    scrollbar-color: rgba(255,255,255,.18) transparent;
}
.account-chat-thread::-webkit-scrollbar { width: 6px; }
.account-chat-thread::-webkit-scrollbar-track { background: transparent; }
.account-chat-thread::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,.18);
    border-radius: 999px;
}
.account-chat-thread::-webkit-scrollbar-thumb:hover { background: var(--brand-color); }

/* Piège à robots (antispam) : invisible et inatteignable pour un utilisateur
   réel (clavier ou souris), mais présent dans le HTML pour les scripts qui
   remplissent tous les champs d'un formulaire sans distinction. */
.account-chat-honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
}

/* Fils de discussion longs : messages précédents repliés par défaut */
.account-chat-older { margin-bottom: 10px; }
.account-chat-older summary {
    cursor: pointer;
    list-style: none;
    font-size: .78rem;
    font-weight: 600;
    color: var(--text-muted);
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px dashed rgba(255,255,255,.16);
    text-align: center;
    transition: border-color .2s ease, color .2s ease;
}
.account-chat-older summary::-webkit-details-marker { display: none; }
.account-chat-older summary:hover { border-color: var(--brand-color); color: #fff; }
.account-chat-older[open] summary { margin-bottom: 10px; }
.comment-item .comment-text {
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.06);
    border-radius: 10px;
    padding: 10px 12px;
    margin-top: 4px;
    display: inline-block;
}
.comment-item--self { flex-direction: row-reverse; }
.comment-item--self .comment-body { display: flex; flex-direction: column; align-items: flex-end; text-align: right; }
.comment-item--self .comment-header { flex-direction: row-reverse; }
.comment-item--self .comment-text {
    background: var(--brand-color-soft);
    border: 1px solid rgba(var(--header-accent),.25);
}
.account-chat-composer {
    display: flex;
    gap: 10px;
    align-items: flex-end;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.1);
    border-radius: 12px;
    padding: 10px;
}
.account-chat-composer textarea {
    flex: 1;
    resize: vertical;
    min-height: 42px;
    background: transparent;
    border: none;
    color: #fff;
}
.account-chat-composer textarea:focus { outline: none; }
/* Chat FAQ (pages/compte-faq.php) : ce textarea porte aussi .js-autogrow
   (agrandissement automatique selon le texte saisi, demande explicite) — la
   poignée de redimensionnement manuel (resize:vertical ci-dessus) n'a alors
   plus lieu d'être puisque la hauteur suit déjà le contenu ; règle plus
   spécifique que .js-autogrow seul (0,1,0) pour l'emporter ici. */
.account-chat-composer textarea.js-autogrow { resize: none; overflow-y: hidden; }
.account-chat-composer .btn-account { flex-shrink: 0; }
.account-chat-uploads { margin-top: 22px; padding-top: 18px; border-top: 1px solid rgba(255,255,255,.08); }
.account-chat-upload-form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.account-chat-dropzone {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border: 1px dashed rgba(var(--header-accent),.35);
    border-radius: 9px;
    color: var(--text-muted);
    font-size: .82rem;
    cursor: pointer;
    /* Même retour que .btn-account--primary ci-dessus ("boutons non
       stylisé" = trop plats au repos) : bordure teintée + halo léger en
       permanence plutôt qu'une bordure blanche neutre visible seulement au
       survol. */
    box-shadow: 0 0 10px rgba(var(--header-accent),.08);
    transition: border-color .2s ease, color .2s ease, box-shadow .2s ease;
}
.account-chat-dropzone:hover {
    border-color: var(--brand-color);
    color: #fff;
    box-shadow: 0 0 16px color-mix(in srgb, var(--brand-color) 25%, transparent);
}
.account-chat-dropzone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }

/* ─── admin-chats.php : liste des clients en accordéon ─── */
.account-chat-summary { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.account-chat-summary-name { font-weight: 700; color: #fff; }
.account-chat-summary-count { margin-left: auto; }

/* ─── compte-sites.php : en-tête de chaque carte de site ─── */
.account-site-card-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    padding-bottom: 16px;
    margin-bottom: 12px;
    border-bottom: 1px solid rgba(255,255,255,.08);
}
.account-site-card-heading {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}
.account-site-card-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--brand-color-soft);
    color: var(--brand-color);
    flex-shrink: 0;
}
.account-site-card-icon svg { width: 20px; height: 20px; }
.account-site-card-name {
    display: block;
    color: #fff;
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1.3;
}
.account-site-card-domain {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--text-muted);
    font-size: .82rem;
    text-decoration: none;
    transition: color .2s ease;
}
.account-site-card-domain:hover { color: var(--brand-color); }
.account-site-card-domain--empty { cursor: default; }
.account-site-card-domain--empty:hover { color: var(--text-muted); }
.account-site-card-meta {
    color: var(--text-muted);
    font-size: .78rem;
    margin: 0 0 14px;
}

/* ─── compte-sites.php : avertissement(s) ─── */
/* Couleur au choix de l'admin (demande explicite : "un choix de couleur de
   notification") — la couleur n'est plus figée en orange : la règle de base
   ne pose plus que la structure, les 4 modificateurs ci-dessous (mêmes
   teintes que .account-kpi-card--danger/--warning/--info/--success)
   déterminent fond/bordure/texte selon la couleur choisie pour CET
   avertissement précis (un site peut désormais en cumuler plusieurs, de
   couleurs différentes). */
.account-site-warning {
    display: flex;
    align-items: center;
    gap: 10px;
    border-radius: 9px;
    padding: 10px 14px;
    font-size: .82rem;
    margin: -4px 0 10px;
}
.account-site-warning svg { flex-shrink: 0; }
.account-site-warning--warning { background: rgba(245,158,11,.10); border: 1px solid rgba(245,158,11,.3); color: #fbbf24; }
.account-site-warning--danger  { background: rgba(239,68,68,.10);  border: 1px solid rgba(239,68,68,.3);  color: #f87171; }
.account-site-warning--success { background: rgba(16,185,129,.10); border: 1px solid rgba(16,185,129,.3); color: #34d399; }
.account-site-warning--info    { background: var(--brand-color-soft); border: 1px solid rgba(var(--header-accent),.3); color: #93c5fd; }

/* Badge palier d'hébergement (demande explicite), à la suite de "Ajouté le
   %s" dans .account-site-card-meta — même esprit que
   .dashboard-add-site-detail (pastille discrète, pas un gros badge coloré :
   l'info est utile mais secondaire sur cette carte). */
.account-site-plan-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 10px;
    border-radius: 999px;
    background: rgba(255,255,255,.07);
    color: rgba(255,255,255,.85);
    font-size: .74rem;
    font-weight: 600;
    vertical-align: middle;
}

/* ─── admin-sites.php : bandeau de filtre (demande explicite) ─── */
.admin-site-filters { padding: 18px 22px; }
.admin-site-filters-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 14px;
}
.admin-site-filters-row .form-group { flex: 1; min-width: 180px; margin-bottom: 0; }
/* Harmonisation demandée (demande explicite : "les box des filtres ne sont pas
   belles, il faut les harmoniser" puis, sur un 2e retour avec capture annotée,
   le label "Nom du site" restait affiché plus bas que les 2 labels de date) —
   cause : les 3 colonnes ont un label de même hauteur, mais le champ <input
   type="date"> (icône calendrier native redimensionnée, cf. plus bas) rendait
   sa colonne globalement plus haute que la colonne texte ; avec align-items:
   flex-end ci-dessus, la colonne texte (plus courte) était donc poussée vers
   le bas pour aligner les BAS de colonnes, décalant son label. Fixer une
   hauteur identique aux 3 champs neutralise l'écart, quel que soit
   align-items. */
.admin-site-filters-row .form-group input,
.admin-site-filters-row .form-group select {
    height: 44px;
    box-sizing: border-box;
}
.admin-site-filters-actions { display: flex; gap: 10px; flex-shrink: 0; }

/* ─── admin-sites.php : liste d'avertissements multiples + formulaire d'ajout
     (demande explicite, remplace l'ancien champ unique alert_message) ─── */
.admin-site-warnings-block { margin-bottom: 18px; }
.admin-site-warnings-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.admin-site-warning-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    border-radius: 8px;
    padding: 8px 12px;
    font-size: .84rem;
}
.admin-site-warning-row--warning { background: rgba(245,158,11,.10); border: 1px solid rgba(245,158,11,.3); color: #fbbf24; }
.admin-site-warning-row--danger  { background: rgba(239,68,68,.10);  border: 1px solid rgba(239,68,68,.3);  color: #f87171; }
.admin-site-warning-row--success { background: rgba(16,185,129,.10); border: 1px solid rgba(16,185,129,.3); color: #34d399; }
.admin-site-warning-row--info    { background: var(--brand-color-soft); border: 1px solid rgba(var(--header-accent),.3); color: #93c5fd; }
.admin-site-warning-text { flex: 1; }
/* Bouton "Ajouter" sous les champs, pas à côté (demande explicite) — les 2
   champs (texte + couleur) restent groupés côte à côte dans
   .admin-site-warning-add-fields, le formulaire devient une colonne pour que
   le bouton passe sur sa propre ligne, juste au-dessus de "Discussion". */
.admin-site-warning-add-form {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
}
.admin-site-warning-add-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    width: 100%;
}
.admin-site-warning-add-fields .form-group { margin-bottom: 0; }
.admin-site-warning-add-fields .form-group:first-child { flex: 1; min-width: 220px; }
.admin-site-warning-add-fields .form-group:last-of-type { flex: 0 0 220px; }

/* ─── compte-modules.php : description au clic ─── */
.account-module-info-btn {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,.16);
    background: rgba(255,255,255,.04);
    color: var(--text-muted);
    font-size: .75rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.account-module-info-btn:hover { border-color: var(--brand-color); color: #fff; background: var(--brand-color-soft); }
.account-module-desc {
    font-size: .8rem;
    color: rgba(255,255,255,.7);
    line-height: 1.5;
    background: rgba(0,0,0,.2);
    border-radius: 8px;
    padding: 10px 12px;
    margin: 4px 0 10px;
}

/* ─── partials/account-nav.php : séparateur avant Mon profil / Livre d'or ─── */
.account-sidenav-divider {
    height: 1px;
    background: rgba(255,255,255,.08);
    margin: 5px 6px;
}

/* ─── partials/admin-nav.php : étiquette de catégorie (Stats, CroisierWeb,
     Gestion projets, Outil, Modération) au-dessus de chaque sous-groupe de
     liens. Les 2 groupes "hors catégorie" (haut/bas) n'affichent pas d'étiquette.
     Simple libellé statique (non cliquable) : l'ancien bouton +/- repliable
     a été retiré (demande explicite : "tu peux enlever le déplie/replie des
     catégories, ils ne sont plus nécessaire vu la nouvelle organisation"). ─── */
.account-sidenav-group-label {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    font-size: .7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--text-muted);
    opacity: .7;
    padding: 9px 10px 3px;
}
/* Texte + pastille de notification de l'étiquette (cf. partials/admin-nav.php
   _admin_nav_label), regroupés dans un span dédié. */
.account-sidenav-group-label-text { display: flex; align-items: center; gap: 6px; min-width: 0; }

/* Enveloppe des liens d'une catégorie (cf. partials/admin-nav.php) : reprend
   le même flex-column + gap que .account-sidenav lui-même avait directement
   sur ses <a> enfants avant l'ajout de ce wrapper, pour ne rien changer à
   l'espacement visuel entre 2 liens d'une même catégorie. Toujours visible
   désormais (plus de pliage/dépliage, cf. commentaire ci-dessus).*/
.account-sidenav-group-links {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

/* ─── partials/account-nav.php : "Tableau de bord" affiché en plus grand,
     seul lien du groupe "hors catégorie" du haut (demande explicite : "en gros"),
     placé avant le bandeau stat CroisierWeb. Taille réduite (demande
     explicite : "que la NAV travail ne soit pas trop grande", cf.
     .account-sidenav-col--left .account-sidenav-link ci-dessus pour le même
     motif) — reste plus grand que les autres liens, juste moins qu'avant. ─── */
/* margin-top ajouté (demande explicite : trop d'espace DANS la nav travail,
   pas assez ENTRE les stats et elle) — recrée à part l'écart avant ce 1er
   élément du bloc "nav travail", maintenant que le gap général du
   conteneur (.account-sidenav-col--left .account-sidenav) a été resserré à
   4px pour l'intérieur de la liste (Tableau de bord/Mes projets/liens). */
.account-sidenav-link--big {
    font-size: 1.08rem;
    font-weight: 700;
    color: #fff;
    padding: 10px 14px;
    margin-top: 6px;
    margin-bottom: 6px;
}
.account-sidenav-link--big svg { width: 21px; height: 21px; }

/* ─── compte-projets.php : formulaires de demande (details/summary) ─── */
.account-request-details { margin-bottom: 12px; }
.account-request-details summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    border-radius: 9px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(255,255,255,.03);
    font-size: .88rem;
    font-weight: 600;
    color: #fff;
    transition: border-color .2s ease, background .2s ease;
}
.account-request-details summary::-webkit-details-marker { display: none; }
.account-request-details summary::before {
    content: '+';
    font-size: 1.1rem;
    color: var(--brand-color);
    transition: transform .2s ease;
}
.account-request-details[open] summary::before { content: '−'; }
.account-request-details summary:hover { border-color: rgba(var(--header-accent),.35); background: var(--brand-color-soft); }

/* ─── Repli complet par item (demande explicite : "gros travaux... fait la
   meme chose pour le cms du site... Utilise le dépli/repli pour une
   meilleure lisibilité") — pages/admin-modules.php (catégories),
   pages/admin-prices.php (lignes de prix), pages/admin-comparison-table.php
   (lignes du tableau) et pages/admin-faq.php (questions) : chaque item
   devient une seule ligne .account-request-details repliée par défaut
   (résumé + aperçu compact), à déplier pour voir/éditer le détail. Réutilise
   le même langage visuel que .account-request-details ci-dessus (déjà
   utilisé pour les modèles multilingues d'admin-messages.php) plutôt que
   d'inventer un 2e style d'accordéon.
   .admin-collapsible-topbar : les actions de réordonnancement (↑/↓, quand
   l'item est triable) restent volontairement HORS du <details> — repliées à
   l'intérieur, elles obligeraient à déplier l'item juste pour le déplacer. */
.admin-collapsible-topbar {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    margin-bottom: 8px;
}
.account-request-details-meta {
    margin-left: auto;
    font-size: .78rem;
    font-weight: 500;
    color: var(--text-muted);
    white-space: nowrap;
}
/* Le résumé passe en 2 lignes sur mobile plutôt que de faire déborder
   l'aperçu compact hors de la carte (summary est déjà en flex, cf. règle
   .account-request-details summary plus haut). */
.account-request-details summary:has(.account-request-details-meta) { flex-wrap: wrap; }

/* Séparateur discret entre 2 items repliés consécutifs (mêmes esprit que
   .admin-price-item + .admin-price-item plus bas) — utilisé quand plusieurs
   items repliés se suivent sans .account-card propre à chacun (ex. les
   questions d'une même catégorie sur admin-faq.php). */
.admin-collapsible-item + .admin-collapsible-item {
    margin-top: 4px;
    padding-top: 12px;
    border-top: 1px solid rgba(255,255,255,.06);
}

/* Espace entre 2 champs empilés dans les formulaires de demande (hébergement /
   développement sur mesure / conseil / module) — .form-group n'a par défaut
   aucune marge propre (cf. règle générique plus haut), ce qui collait des
   paires comme "Nom du projet" + "Avez-vous un nom de domaine ?" ou "Budget"
   + "Décrivez votre besoin" l'une contre l'autre (demande explicite). Scopé à
   .demande-form-card (une classe posée sur chacune des 4 cartes de demande de
   pages/compte-modules.php, une par type de demande depuis qu'elles ont été
   séparées en sections distinctes — demande explicite) pour ne pas affecter
   les autres usages de .form-group ailleurs sur le site (auth-card,
   admin-add-category, etc. gèrent déjà leur propre espacement). Le bouton
   d'envoi de chaque formulaire suit la même logique (sinon collé contre le
   dernier champ visible, ex : groupe de boutons Oui/Non/Plus tard). */
.demande-form-card .form-group + .form-group { margin-top: 18px; }
.demande-form-card form button[type="submit"] { margin-top: 16px; }

/* Teinte par carte de demande, sur pages/compte-creer-site.php (demande
   explicite : "en colonne dans cet ordre : Créer un site (bleu) / Sur-mesure
   (vert) / Hébergement-maintenance (blanc) / Conseil-accompagnement
   (violet)") — même logique que .account-card--danger ci-dessus (bordure/
   fond teintés d'une couleur FIXE, pas de la couleur d'accent active du
   client), pour que chaque carte reprenne visuellement la couleur de son CTA
   correspondant dans la nav (cf. .account-sidenav-cta.accent-* dans
   partials/account-nav.php). Le "Créer un site" (1re carte, non-accordéon)
   reste volontairement neutre : c'est déjà la carte la plus proéminente de la
   page, une 4e teinte ajouterait de la charge visuelle sans rien clarifier.
   Le marqueur +/- de l'accordéon (cf. .account-request-details summary::before
   plus haut) et le survol du résumé reprennent la même couleur.
   --header-accent redéfini localement sur chaque carte (bug remonté : "le
   champ de saisie est bleu dans tous les formulaires, il faut l'adapter au
   formulaire") — .form-group input/textarea/select:focus (cf. plus haut)
   colore sa bordure/glow avec rgba(var(--header-accent),...), qui sans ce
   correctif reste celle du thème actif du client (souvent bleu) au lieu de
   suivre la teinte propre de chaque carte de demande. Même mécanisme que les
   classes .accent-* posées sur les CTA de la nav (cf.
   partials/account-nav.php) : une redéfinition locale de la variable CSS
   n'affecte que le sous-arbre concerné. */
.demande-form-card--emerald { border-color: rgba(16,185,129,.28); background: linear-gradient(135deg, rgba(16,185,129,.06), rgba(255,255,255,.02)); --header-accent: 16,185,129; }
.demande-form-card--emerald summary::before { color: rgb(16,185,129); }
.demande-form-card--emerald summary:hover { border-color: rgba(16,185,129,.4); background: rgba(16,185,129,.08); }

.demande-form-card--cyan { border-color: rgba(232,237,245,.24); background: linear-gradient(135deg, rgba(232,237,245,.05), rgba(255,255,255,.02)); --header-accent: 232,237,245; }
.demande-form-card--cyan summary::before { color: rgb(232,237,245); }
.demande-form-card--cyan summary:hover { border-color: rgba(232,237,245,.4); background: rgba(232,237,245,.08); }

.demande-form-card--violet { border-color: rgba(139,92,246,.28); background: linear-gradient(135deg, rgba(139,92,246,.06), rgba(255,255,255,.02)); --header-accent: 139,92,246; }
.demande-form-card--violet summary::before { color: rgb(139,92,246); }
.demande-form-card--violet summary:hover { border-color: rgba(139,92,246,.4); background: rgba(139,92,246,.08); }

/* "Créer un site" (1re carte, non-accordéon) reste neutre visuellement (cf.
   plus haut) mais son CTA de nav est fixé au bleu (demande explicite passée :
   "créer un site... doit toujours être bleu") — les champs de son formulaire
   suivent la même logique fixe pour ne pas dépendre du thème actif. */
#creer-site-form { --header-accent: 59,130,246; }

/* ─── pages/compte-projets.php : renommer un projet ("Mes projets") — le
   champ de saisie utilisait le style par défaut du navigateur (demande
   explicite : "pas très sexy"), n'étant pas posé dans un .form-group. Reprend
   le même langage visuel que .form-group input (fond sombre, bordure et halo
   au focus à la couleur d'accent) dans une petite carte dédiée, plutôt qu'une
   simple ligne de champs collés au texte du projet. ─── */
.mockup-rename-toggle {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.mockup-rename-form {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
    margin: 10px 0 4px;
    padding: 12px 14px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 12px;
}
/* Bug réel constaté : "le champ pour renommer le titre du projet est
   toujours visible, il devrait se déployer que si l'utilisateur clique sur
   Renommer" — le <form> porte l'attribut HTML `hidden` (posé par défaut au
   chargement, basculé en JS par toggleRenameForm() ci-dessus dans
   pages/compte-projets.php), mais `display:flex` ci-dessus a la même
   spécificité (0,0,1,0) que la règle `[hidden] { display:none }` du
   navigateur — en cas d'égalité de spécificité, une règle d'origine
   "auteur" (ce fichier) l'emporte toujours sur celle d'origine
   "navigateur", donc le formulaire restait affiché en flex même avec
   `hidden` posé. `[hidden]` ajouté à ce sélecteur (spécificité 0,0,2,0,
   l'emporte cette fois) rétablit le masquage par défaut. */
.mockup-rename-form[hidden] {
    display: none;
}
.mockup-rename-input {
    flex: 1;
    min-width: 180px;
    box-sizing: border-box;
    padding: 10px 14px;
    border-radius: 9px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(0,0,0,.28);
    color: #fff;
    font-size: .92rem;
    font-family: inherit;
    outline: none;
    transition: border-color .25s ease, box-shadow .25s ease, background .25s ease;
}
.mockup-rename-input:focus {
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.05);
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.10), 0 0 20px rgba(var(--header-accent),.08);
}
.mockup-rename-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* Zones de texte en agrandissement automatique (cf. bloc ".js-autogrow" en
   fin de assets/js/main.js, appliqué à TOUTE page compte-*.php/admin-*.php,
   demande explicite) — la poignée de redimensionnement manuel et le scroll
   interne n'ont plus lieu d'être puisque la hauteur suit déjà le contenu. */
.js-autogrow {
    resize: none;
    overflow-y: hidden;
}
/* Un textarea générique dans .form-group (la quasi-totalité des formulaires
   admin/compte) hérite de ".form-group textarea { resize: vertical; }" plus
   haut — même spécificité (0,1,1) que ".account-chat-composer textarea"
   déjà traité plus haut, donc même règle : override explicite nécessaire
   pour que .js-autogrow gagne ici aussi, sinon la poignée de redimensionnement
   manuel resterait affichée malgré l'agrandissement automatique. */
.form-group textarea.js-autogrow { resize: none; overflow-y: hidden; }

/* Paragraphes d'aide à la rédaction de la zone "Parlez-moi de votre projet"
   (ex-"Décrivez votre besoin") — affichés EN DESSOUS de la zone de saisie
   (demande explicite, cf. pages/compte-modules.php#demande-site : la zone de
   texte doit venir en premier) — texte discret, ne rentre pas en compétition
   visuelle avec le label ni la zone de saisie. */
.field-guide {
    margin: 0;
    font-size: .82rem;
    line-height: 1.6;
    color: rgba(255,255,255,.55);
}

/* Variante "avertissement" de .field-guide (compte-creer-site.php, demande
   explicite : note "disponibilité limitée à la Romandie" affichée quand
   "Présentiel" est choisi pour une demande de conseil) — plus visible que le
   texte d'aide discret standard, sans être aussi alarmant qu'un message
   d'erreur (account-notice--error).
*/
.field-guide--warning {
    margin-top: 8px;
    color: #fbbf24;
    background: rgba(251,191,36,.1);
    border: 1px solid rgba(251,191,36,.3);
    border-radius: 8px;
    padding: 8px 12px;
}

/* Label "Parlez-moi de votre projet" (pages/compte-creer-site.php) : le label
   générique .form-group label ci-dessus (petit, majuscules, très discret)
   le rendait difficile à repérer au-dessus des paragraphes d'aide qui
   suivent — demande explicite : "améliorer la lisibilité de 'parlez moi de
   votre projet'". Casse normale, plus grand, gras, couleur pleine (au lieu du
   blanc à 45% d'opacité) pour bien marquer le début du bloc d'aide. */
.field-guide-heading {
    display: block;
    font-size: 1.05rem;
    font-weight: 700;
    text-transform: none;
    letter-spacing: normal;
    color: #fff;
    margin: 6px 0 10px;
}

/* ─── pages/compte-creer-site.php : le formulaire était trop "tassé" (demande
   explicite) — contrairement à #demandes (compte-modules.php), ce formulaire
   n'a pas d'id partagé et n'héritait donc d'aucun espacement entre champs
   (.form-group n'a par défaut aucune marge propre). Espacement plus généreux
   que #demandes (24px au lieu de 18px) puisque cette page est entièrement
   dédiée à ce formulaire, avec plus de place disponible. ─── */
#creer-site-form .form-group + .form-group { margin-top: 24px; }

/* Titres de champs pas assez visibles (demande explicite) — le label
   générique .form-group label reste volontairement discret ailleurs (petit,
   majuscules, blanc à 45% d'opacité, cf. règle plus haut), mais sur ce
   formulaire particulièrement dense (nombreuses questions Oui/Non/QCM), ce
   contraste trop faible rendait les titres difficiles à repérer d'un coup
   d'œil. Plus gras + couleur plus opaque, scoping limité à #creer-site-form
   (même principe que .mockup-admin-form/.register-form-col plus bas dans ce
   fichier) pour ne pas changer l'apparence des autres formulaires du site. */
/* :not(.field-guide-heading) exclu (demande explicite antérieure : "Parlez-moi
   de votre projet" doit rester blanc plein #fff, cf. règle .field-guide-heading
   plus bas) — sans cette exclusion, l'ID #creer-site-form ci-dessus
   l'emporterait sur la classe .field-guide-heading (spécificité CSS ID >
   classe) et repasserait son opacité à .75 au lieu du blanc plein voulu. */
#creer-site-form .form-group label:not(.field-guide-heading) {
    font-weight: 700;
    color: rgba(255,255,255,.75);
}

/* "Sites qui vous inspirent" : liste de liens à nombre variable (demande
   explicite) — une ligne = un champ URL + le bouton de suppression
   .comment-delete-btn (déjà stylé ailleurs, réutilisé tel quel). Le champ
   input hérite déjà du style générique .form-group input (largeur, fond,
   bordure) plus haut dans ce fichier : seule la mise en ligne (flex) est
   ajoutée ici. */
.inspiration-links-list { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.inspiration-link-row { display: flex; align-items: center; gap: 8px; }
.inspiration-link-row input { flex: 1 1 auto; }

/* Bouton "Envoyer la demande" : ne suit pas la règle ci-dessus (ce n'est pas
   un .form-group) et se retrouvait collé directement contre le dernier champ
   visible — en particulier contre le groupe de 3 boutons Oui/Non/Plus tard
   quand la zone "Fichiers joints" juste avant reste masquée (demande
   explicite : "y a pas d'espacement vertical" entre ces boutons et l'envoi). */
#creer-site-form button[type="submit"] { margin-top: 24px; }

/* Bloc "Parlez-moi de votre projet" mis en évidence : utilise l'espace
   libéré par le déplacement de "Pouvez-vous fournir le contenu ?" plus bas
   dans le formulaire pour donner à cette section — la plus importante — une
   place à part entière plutôt qu'un simple champ parmi d'autres (demande
   explicite : "avec l'espace récupéré, trouver une place plus stratégique").
   Légère mise en avant (fond teinté + liseré à la couleur d'accent) sans
   rivaliser avec les cartes .account-card elles-mêmes. */
.form-project-highlight {
    background: rgba(var(--header-accent),.05);
    border: 1px solid rgba(var(--header-accent),.16);
    border-left: 3px solid rgba(var(--header-accent),.5);
    border-radius: 12px;
    padding: 20px 22px;
}
.form-project-highlight .field-guide-heading { margin-top: 0; }

/* ─── compte-projets.php : choix Oui/Non en boutons ronds sur une ligne
   (ex : "Avez-vous un nom de domaine ?") — même langage visuel que
   .channel-radio-group/.channel-option (fond sombre, halo à la couleur
   d'accent quand coché) mais pleinement arrondi. ─── */
.yesno-radio-group {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 4px;
}
.yesno-option { cursor: pointer; width: fit-content; }
.yesno-option input[type="radio"] { display: none; }
/* Réutilisé pour la question à choix multiple "Quel est l'objectif de ce
   site ?" (pages/compte-creer-site.php, demande explicite) — mêmes pastilles
   que les groupes oui/non existants, juste avec des cases à cocher
   (plusieurs réponses possibles) au lieu de boutons radio. */
.yesno-option input[type="checkbox"] { display: none; }
.yesno-label {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 22px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(0,0,0,.28);
    color: rgba(255,255,255,.55);
    font-size: .86rem;
    font-weight: 500;
    font-family: inherit;
    transition: border-color .25s ease, background .25s ease, color .25s ease, box-shadow .25s ease;
}
.yesno-option input:checked + .yesno-label {
    border-color: rgba(var(--header-accent),.55);
    background: rgba(var(--header-accent),.14);
    color: #fff;
    box-shadow: 0 0 0 3px rgba(var(--header-accent),.10), 0 0 18px rgba(var(--header-accent),.08);
}
.yesno-option:hover .yesno-label { border-color: rgba(255,255,255,.16); color: rgba(255,255,255,.8); }

/* Note tarif "conseil", volontairement discrète, désormais juste sous le
   select "Formule souhaitée" (demande explicite : "il faut encore lui
   rajouter un gap vertical avec le titre Type de rendez-vous souhaité" —
   le bloc étant un <p> entre deux .form-group, la règle générale
   ".demande-form-card .form-group + .form-group { margin-top: 18px; }"
   ne s'appliquait pas ici, d'où le collage constaté). */
.account-card-hint--discreet {
    margin: 14px 0 18px;
    font-size: .76rem;
    font-style: italic;
    color: rgba(255,255,255,.40);
}
.account-card-hint--discreet a {
    color: rgba(var(--header-accent),.9);
    font-style: normal;
    text-decoration: underline;
}
.account-card-hint--discreet a:hover { color: #fff; }

/* ─── compte-profil.php : sous-titre "Style et couleur du header" ─── */
.account-subcard-title {
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 12px;
    padding-top: 16px;
    border-top: 1px solid rgba(255,255,255,.08);
}
.account-card > .account-subcard-title:first-of-type { padding-top: 0; border-top: none; }

/* ─── admin-maquettes.php ─── */
.mockup-admin-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 18px;
    padding-bottom: 14px;
    border-bottom: 1px solid rgba(255,255,255,.08);
}
/* ─── Carte projet repliable (demande explicite, tâche #34 : "section
     repliable") — le header (<summary>, toujours visible) devient cliquable,
     avec un chevron indiquant l'état ouvert/fermé ; fermée par défaut (cf.
     absence de l'attribut [open] côté PHP) pour que la liste des projets
     clients reste courte à parcourir, chaque carte se dépliant à la demande.
     Modificateur scopé (plutôt que sur .mockup-admin-header directement) car
     cette classe est réutilisée telle quelle, non repliable, sur
     admin-maquette-access.php (cf. .mockup-admin-header--maquette). ─── */
.mockup-admin-header--collapsible {
    position: relative;
    padding-right: 26px;
    cursor: pointer;
    list-style: none;
}
.mockup-admin-header--collapsible::-webkit-details-marker { display: none; }
.mockup-admin-header--collapsible::after {
    content: "";
    position: absolute;
    top: 4px;
    right: 2px;
    width: 9px;
    height: 9px;
    border-right: 2px solid rgba(255,255,255,.4);
    border-bottom: 2px solid rgba(255,255,255,.4);
    transform: rotate(45deg);
    transition: transform .15s ease;
}
.mockup-admin-header--collapsible:hover::after { border-color: #fff; }
.mockup-admin-collapse[open] > .mockup-admin-header--collapsible::after { transform: rotate(-135deg); }
.mockup-admin-collapse-body { padding-top: 2px; }
/* Carte projet ayant reçu un message client tout juste marqué lu à l'arrivée
   sur la page (demande explicite : "la notification se retire immédiatement
   sans m'indiquer dans quel chat il y a un nouveau message") — liseré bleu
   bien visible même carte encore repliée, en complément du badge dans le
   header et du bandeau récapitulatif en haut de page (cf.
   pages/admin-maquettes.php :: $justUnreadMockupIds). Ne dure qu'un
   chargement de page (même logique que .comment-item--new). */
.mockup-admin-card--has-new-message { border-color: rgba(96,165,250,.5); box-shadow: 0 0 0 1px rgba(96,165,250,.25); }
.mockup-new-msg-badge { background: rgba(96,165,250,.16); color: #60a5fa; }
/* Titre du projet visible même carte repliée (demande explicite : "il me faut
   le titre de visible pour les fiches projets") — devient la ligne la plus
   marquante du header, au-dessus des infos client (secondaires ici), pour
   distinguer d'un coup d'œil les projets d'un client ayant plusieurs fiches. */
.mockup-admin-project-title {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--brand-color);
    margin-bottom: 4px;
}
.mockup-admin-project-client { display: flex; align-items: center; flex-wrap: wrap; }
.mockup-admin-actions { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; align-items: center; }
/* "Supprimer" en bas à droite, à l'écart des actions positives (demande
   explicite) — poussé à l'extrémité du flex par margin-left:auto plutôt que
   placé au milieu entre "Mettre à jour" et "Voir la maquette". */
.mockup-admin-actions .mockup-delete-btn { margin-left: auto; }
.mockup-admin-submit { margin-top: 16px; }
/* Espacement entre champs de la fiche projet admin (demande explicite :
   "certains textes/champs de saisie sont collés, il faut que le visuel aide à
   la lecture") — .form-group n'a par défaut aucune marge propre (cf.
   commentaire plus haut sur .form-group), et ce formulaire n'avait, contrairement
   à .demande-form-card ou #creer-site-form, aucune règle scopée pour espacer
   ses groupes successifs : le label du champ suivant se retrouvait collé
   contre le texte d'aide (hint) du champ précédent.
   Combinateur ">" (enfants DIRECTS de .mockup-admin-form) : bug réel trouvé
   ici (demande explicite : "les sélecteurs/champs ne sont pas bien alignés")
   — sans lui, ".form-group + .form-group" matchait AUSSI les 2 .form-group
   placés CÔTE À CÔTE à l'intérieur d'un même .form-row (ils sont bien
   "frères" en CSS même si visuellement sur la même ligne d'une grille 2
   colonnes) : le margin-top s'appliquait alors À L'INTÉRIEUR de sa propre
   cellule de grille, poussant le 2e champ ("URL de la maquette", "Phase")
   visiblement plus bas que le 1er de la même ligne ("Nom du projet",
   "Statut") — reproduit et confirmé hors-ligne (rendu Chromium headless +
   mesure des rects avant/après ce correctif). Restreint désormais aux seuls
   .form-group enfants directs du formulaire (donc jamais ceux nichés dans un
   .form-row), qui restent les seuls concernés par cet espacement vertical. */
.mockup-admin-form > .form-row + .form-group,
.mockup-admin-form > .form-group + .form-row,
.mockup-admin-form > .form-group + .form-group {
    margin-top: 22px;
}
.project-comments + .mockup-admin-form {
    margin-top: 22px;
    padding-top: 20px;
    border-top: 1px solid rgba(255,255,255,.08);
}

/* Labels de la fiche projet admin plus visibles (demande explicite : "les
   titres soit en gras ou en tout cas plus visible" — Nom du projet, URL de la
   maquette, Lien vers devis, Statut, Phase, Notification d'étape) —
   .form-group label est par défaut très atténué (opacité .45, cf. règle de
   base plus haut) pour rester discret sur la quasi-totalité des formulaires
   du site ; ce formulaire dense (fiche projet admin, une dizaine de champs)
   gagne en lisibilité avec des labels plus contrastés. Scopé à
   .mockup-admin-form (couvre aussi bien la fiche "Nouveau projet" que celle
   de mise à jour d'un projet existant, qui partagent les mêmes libellés) :
   les autres formulaires du site gardent le style discret existant. */
.mockup-admin-form .form-group label {
    font-weight: 700;
    color: rgba(255,255,255,.82);
    /* Aligne le picto (cf. .mockup-field-icon ci-dessous) avec le texte du
       label, qui reste par ailleurs en display:flex (colonne) hérité de
       .form-group — le label lui-même passe donc en ligne (icône + texte). */
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Icône + couleur distincte par champ de la fiche projet admin (demande
   explicite : "il faut que chaqu un est un icon et une couleur diffirente")
   — cf. render_mockup_field_icon() dans pages/admin-maquettes.php, seul
   générateur du SVG associé à chaque clé ci-dessous. Icônes volontairement
   discrètes (14px, trait fin) pour ne pas rivaliser avec le texte du label,
   colorées pour aider à repérer un champ en un coup d'œil sur un formulaire
   dense plutôt que pour attirer l'attention en soi. */
.mockup-field-icon {
    display: inline-flex;
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
}
.mockup-field-icon svg { width: 100%; height: 100%; }
.mockup-field-icon--label    { color: #60a5fa; } /* Nom du projet — bleu */
.mockup-field-icon--url      { color: #22d3ee; } /* URL de la maquette — cyan */
.mockup-field-icon--quote    { color: #a78bfa; } /* Lien vers devis — violet */
.mockup-field-icon--status   { color: #fbbf24; } /* Statut — ambre */
.mockup-field-icon--phase    { color: #34d399; } /* Phase — vert émeraude */
.mockup-field-icon--notice   { color: #f472b6; } /* Notification d'étape — rose */
.mockup-field-icon--notes    { color: #2dd4bf; } /* Notes pour clients — turquoise */
.mockup-field-icon--internal { color: #818cf8; } /* Notes internes — indigo */

/* ─── Carte "danger" (outil de test admin-maquettes.php : vider tous les
     projets) — reflet rouge pour signaler une action destructive/irréversible,
     même logique de couleurs que .account-notice--error. ─── */
.account-card--danger {
    border-color: rgba(239,68,68,.35);
    background: linear-gradient(135deg, rgba(239,68,68,.08), rgba(255,255,255,.02));
    box-shadow: 0 16px 40px -30px rgba(239,68,68,.55);
}
.account-card--danger h2 { color: #f87171; }
.mockup-wipe-warning { font-size: .82rem; font-weight: 600; color: #f87171; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }

/* ─── admin-maquette-access.php : catalogue + "Modifier" (nom client / catégorie) ─── */
.mockup-admin-header--maquette { align-items: flex-start; }
.mockup-admin-row-main { display: flex; align-items: center; flex-wrap: wrap; gap: 2px; }
.mockup-admin-meta-form {
    flex-basis: 100%;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed rgba(255,255,255,.10);
}
.mockup-admin-meta-form .form-row { margin-bottom: 12px; }
.mockup-admin-cat-checks {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(255,255,255,.02);
}
.mockup-admin-cat-row { display: flex; flex-wrap: wrap; gap: 10px 14px; }

/* Cases à cocher "chip" : la case native est masquée, le libellé entier
   devient un badge cliquable qui se colore (couleur propre à chaque
   catégorie) quand il est coché — plus lisible qu'une case + texte plat. */
.mockup-admin-cat-check {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0;
    padding: 6px 12px 6px 8px;
    border-radius: 999px;
    border: 1.5px solid rgba(255,255,255,.14);
    background: rgba(255,255,255,.03);
    color: var(--text-muted);
    font-size: .78rem;
    font-weight: 600;
    white-space: nowrap;
}
.mockup-admin-cat-check:hover { border-color: rgba(255,255,255,.3); color: #fff; }
.mockup-admin-cat-check input[type="checkbox"] {
    position: absolute;
    width: 0; height: 0;
    opacity: 0;
    pointer-events: none;
}
.mockup-admin-cat-check::before {
    content: "";
    display: flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    border-radius: 5px;
    border: 1.5px solid rgba(255,255,255,.3);
    font-size: 10px;
    line-height: 1;
    color: #fff;
    transition: background .15s ease, border-color .15s ease;
}
.mockup-admin-cat-check:has(input:checked) {
    color: #fff;
    border-color: var(--chip-color, var(--brand-color));
    background: var(--chip-bg, var(--brand-color-soft));
}
.mockup-admin-cat-check:has(input:checked)::before {
    content: "✓";
    background: var(--chip-color, var(--brand-color));
    border-color: var(--chip-color, var(--brand-color));
}
.mockup-admin-cat-check--express     { --chip-color: #fbbf24; --chip-bg: rgba(251,191,36,.14); }
.mockup-admin-cat-check--business    { --chip-color: #60a5fa; --chip-bg: rgba(var(--header-accent),.14); }
.mockup-admin-cat-check--premium     { --chip-color: #c084fc; --chip-bg: rgba(168,85,247,.14); }
.mockup-admin-cat-check--ecommerce   { --chip-color: #34d399; --chip-bg: rgba(16,185,129,.14); }
.mockup-admin-cat-check--marketplace { --chip-color: #f472b6; --chip-bg: rgba(236,72,153,.14); }
.mockup-admin-cat-check--vitrine     { --chip-color: #22d3ee; --chip-bg: rgba(34,211,238,.14); }
.mockup-admin-cat-check--autre       { --chip-color: #9ca3af; --chip-bg: rgba(255,255,255,.08); }

.mockup-admin-cat-save { align-self: flex-end; margin-top: 2px; }

/* Badges catégorie (catalogue + accès accordés) : mêmes couleurs que les
   chips ci-dessus, pour que la couleur d'une catégorie reste identique
   partout où elle apparaît sur la page. */
.maquette-cat-badge {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 700;
}
.maquette-cat-badge--express     { background: rgba(251,191,36,.14); color: #fbbf24; }
.maquette-cat-badge--business    { background: rgba(var(--header-accent),.14); color: #60a5fa; }
.maquette-cat-badge--premium     { background: rgba(168,85,247,.14); color: #c084fc; }
.maquette-cat-badge--ecommerce   { background: rgba(16,185,129,.14); color: #34d399; }
.maquette-cat-badge--marketplace { background: rgba(236,72,153,.14); color: #f472b6; }
.maquette-cat-badge--vitrine     { background: rgba(34,211,238,.14); color: #22d3ee; }
.maquette-cat-badge--autre       { background: rgba(255,255,255,.08); color: var(--text-muted); }

/* ─── admin-newsletter.php : aperçu de l'email (demande explicite, tâche
     #38 : "améliorer la qualité des newsletters") — reproduit le visuel du
     template HTML réellement envoyé (cf. _newsletter_html_body() côté PHP :
     bandeau bleu + logo, corps blanc, pied de page discret) pour que l'admin
     voie un rendu fidèle avant l'envoi. ─── */
.newsletter-preview {
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid rgba(255,255,255,.08);
    background: #fff;
    max-width: 480px;
}
.newsletter-preview-band {
    background: var(--brand-color);
    padding: 16px 22px;
    text-align: center;
}
.newsletter-preview-band img { display: inline-block; height: 24px; }
.newsletter-preview-body {
    padding: 22px;
    color: #1a1a2e;
    font-size: .88rem;
    line-height: 1.6;
    white-space: pre-wrap;
    word-break: break-word;
}
.newsletter-preview-footer {
    padding: 14px 22px;
    border-top: 1px solid #eaeef5;
    color: #8a93a6;
    font-size: .72rem;
    line-height: 1.6;
}

/* ─── compte-projets.php : projets groupés par statut ─── */
.project-status-group + .project-status-group { margin-top: 32px; }
.project-status-group-title {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: .78rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 14px;
}
.project-status-group-title .status-badge { font-size: .68rem; }
.project-status-group-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background: rgba(255,255,255,.08);
    color: #fff;
    font-size: .70rem;
    font-weight: 700;
}

/* ─── Commentaires (échange client / codeur) ─── */
.project-comments { margin-top: 22px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,.08); }
.project-comments-title { font-size: .85rem; font-weight: 700; color: #fff; margin-bottom: 14px; }
/* Ligne titre + bouton "Supprimer les 10 plus anciens" (demande explicite) —
   remplace le simple <div class="project-comments-title"> seul quand ce
   bouton est présent (cf. pages/admin-maquettes.php / admin-sites.php). */
.project-comments-title-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.project-comments-title-row .project-comments-title { margin-bottom: 0; }
.comment-purge-form { flex-shrink: 0; }
.comment-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; max-height: 420px; overflow-y: auto; }
.comment-item {
    display: flex;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
}
.comment-item--admin { background: rgba(var(--header-accent),.07); border-color: rgba(var(--header-accent),.18); }
.comment-avatar {
    width: 30px; height: 30px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: .72rem; font-weight: 700; color: #fff;
    background: rgba(255,255,255,.10);
    flex-shrink: 0;
}
.comment-item--admin .comment-avatar { background: var(--brand-color); color: var(--brand-color-contrast, #fff); }
.comment-body { min-width: 0; flex: 1; }
.comment-header { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.comment-author { font-size: .82rem; font-weight: 700; color: #fff; }
.comment-date { font-size: .72rem; color: var(--text-muted); }
/* Message client tout juste marqué lu à l'arrivée sur admin-maquettes.php
   (demande explicite : "la notification se retire immédiatement sans
   m'indiquer dans quel chat il y a un nouveau message") — pastille "Nouveau"
   + léger surlignage bleu du message concerné, en plus du badge sur la carte
   et du bandeau récapitulatif en haut de page (cf. pages/admin-maquettes.php
   :: $justUnreadCommentIds). Ne dure qu'un chargement de page : le message
   est déjà marqué lu en base, un rechargement fera disparaître ces repères. */
.comment-item--new { background: rgba(96,165,250,.10); border-color: rgba(96,165,250,.35); }
.comment-new-tag {
    display: inline-flex; align-items: center;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: .66rem; font-weight: 700; text-transform: uppercase; letter-spacing: .02em;
    background: rgba(96,165,250,.18); color: #60a5fa;
}
/* Croix de suppression d'un message de "Commentaires" (admin-maquettes.php /
   admin-sites.php) — demande explicite : "la croix (x) de suppression de
   message doit être stylisée (tech/spatial)". Jusqu'ici un <button> sans
   AUCUN style (croix brute du navigateur, cf. .comment-delete-btn absent de
   ce fichier avant ce correctif) — contrairement à .message-delete-btn
   ci-dessous (compte-messages.php, déjà stylisé en icône poubelle ronde).
   Traitement délibérément différent de ce dernier (coins coupés façon HUD de
   vaisseau plutôt qu'un simple rond, typo monospace var(--font-title) déjà
   utilisée pour l'esthétique "tech" du site, cf. .btn-account--functional)
   pour rester dans le même langage visuel que le reste du site plutôt que de
   dupliquer telle quelle la poubelle ronde. Rouge (action destructive), mais
   discret par défaut — ne s'illumine qu'au survol/focus. */
.comment-delete-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
    background: rgba(239,68,68,.08);
    border: 1px solid rgba(239,68,68,.4);
    color: #f87171;
    font-family: var(--font-title);
    font-size: .8rem;
    line-height: 1;
    cursor: pointer;
    /* Coins opposés coupés (façon plaque HUD) plutôt qu'un rectangle/cercle
       classique — même esprit que .cockpit-corner sur accueil.php sans en
       reprendre le markup (ici un seul élément, clip-path suffit). */
    clip-path: polygon(0 0, calc(100% - 6px) 0, 100% 6px, 100% 100%, 6px 100%, 0 calc(100% - 6px));
    transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.comment-delete-btn:hover,
.comment-delete-btn:focus-visible {
    background: rgba(239,68,68,.22);
    border-color: rgba(239,68,68,.8);
    color: #fecaca;
    box-shadow: 0 0 10px rgba(239,68,68,.5);
    outline: none;
}
/* Bouton de suppression d'UN message (compte-messages.php, demande explicite :
   "remplacer la x pour supprimer un message par un icon poubelle bien plus
   visible") — icône poubelle SVG, fond rouge discret visible EN PERMANENCE
   (pas seulement au survol comme l'ancienne croix "&times;") pour bien
   ressortir. */
.message-delete-btn {
    display: flex; align-items: center; justify-content: center;
    width: 30px; height: 30px;
    border-radius: 50%;
    border: 1px solid rgba(239,68,68,.35);
    background: rgba(239,68,68,.12);
    color: #f87171;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.message-delete-btn:hover { background: rgba(239,68,68,.26); border-color: rgba(239,68,68,.6); transform: scale(1.06); }

/* Filtres de compte-messages.php (demande explicite : "un ou deux filtres") —
   même esprit visuel que les autres barres de filtres du site (form-row en
   ligne, boxes de taille uniforme). */
.messages-filter-bar {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    align-items: flex-end;
    margin: 4px 0 20px;
    padding-bottom: 18px;
    border-bottom: 1px solid rgba(255,255,255,.08);
}
.messages-filter-bar .form-group { min-width: 180px; margin: 0; }

/* Badge "Nouveau" sur un message non lu (compte-messages.php) — repère visuel
   rapide, complémentaire du filtre Statut. */
.message-unread-badge {
    display: inline-block;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(139,92,246,.18);
    color: #c4b5fd;
    border: 1px solid rgba(139,92,246,.35);
}
.comment-text { font-size: .87rem; color: rgba(255,255,255,.82); line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
.comment-empty { color: var(--text-muted); font-size: .85rem; margin-bottom: 16px; }
.comment-form { display: flex; gap: 10px; align-items: flex-start; }
.comment-form textarea { flex: 1; resize: vertical; min-height: 44px; }

/* ─── Fichiers envoyés (contenu du site : images / vidéos) ─── */
.project-uploads { margin-top: 22px; padding-top: 20px; border-top: 1px solid rgba(255,255,255,.08); }
.project-uploads-title { font-size: .85rem; font-weight: 700; color: #fff; margin-bottom: 6px; }
.project-uploads-hint { font-size: .78rem; color: var(--text-muted); margin-bottom: 14px; line-height: 1.5; }
.upload-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.upload-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    text-decoration: none;
    transition: background .15s ease, border-color .15s ease;
}
.upload-item:hover { background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.14); }
/* Regroupe la carte fichier et son bouton "Supprimer" sur une même ligne
   (demande explicite : "améliore le visuel des boutons") — auparavant deux
   formulaires empilés en colonne (cf. .upload-list flex-direction:column),
   le bouton Supprimer se retrouvait sur sa propre ligne pleine largeur en
   dessous du fichier plutôt qu'à côté de lui. */
.upload-item-row { display: flex; align-items: center; gap: 10px; }
.upload-item-row .upload-item { flex: 1; min-width: 0; }
.upload-item-icon {
    width: 34px; height: 34px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    background: rgba(var(--header-accent),.12); color: #60a5fa; flex-shrink: 0;
}
.upload-item-icon svg { width: 17px; height: 17px; }
.upload-item-info { min-width: 0; flex: 1; }
.upload-item-name { font-size: .85rem; color: #fff; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-item-meta { font-size: .74rem; color: var(--text-muted); margin-top: 2px; }
.upload-form-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.upload-form-row input[type="file"] {
    flex: 1;
    min-width: 200px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px dashed rgba(255,255,255,.18);
    background: rgba(0,0,0,.20);
    color: var(--text-muted);
    font-size: .82rem;
    transition: border-color .2s ease;
}
.upload-form-row input[type="file"]:hover,
.upload-form-row input[type="file"]:focus-visible {
    border-color: rgba(var(--header-accent),.6);
}
/* Bouton natif "Choisir un fichier" (demande explicite : "meme consigne pour
   les formulaires d'envoies de fichiers 'choose file'", même style spatial
   tech déjà appliqué aux checkboxes) — le conteneur ci-dessus était déjà
   habillé, mais le sous-élément natif du navigateur (bouton "Parcourir")
   restait blanc/système car non ciblé par du CSS classique : il faut passer
   par le pseudo-élément ::file-selector-button (::-webkit-file-upload-button
   pour les navigateurs Chromium/Safari plus anciens). Même langage visuel
   que .btn-account--functional (bouton d'action technique sobre, pas un CTA)
   pour rester cohérent avec le reste du site plutôt que d'inventer un
   nouveau style de bouton. */
.upload-form-row input[type="file"]::file-selector-button,
.upload-form-row input[type="file"]::-webkit-file-upload-button {
    margin-right: 12px;
    padding: 7px 16px;
    border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--brand-color) 40%, rgba(255,255,255,.16));
    background: rgba(255,255,255,.04);
    color: var(--brand-color);
    font-family: var(--font-title);
    font-weight: 600;
    font-size: .78rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.upload-form-row input[type="file"]::file-selector-button:hover,
.upload-form-row input[type="file"]::-webkit-file-upload-button:hover {
    background: color-mix(in srgb, var(--brand-color) 16%, transparent);
    border-color: var(--brand-color);
    color: #fff;
}

/* ─── compte-dashboard.php : carte "Ajouter un site" ─── */
.dashboard-add-site {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    background: linear-gradient(135deg, rgba(var(--header-accent),.10), rgba(var(--header-accent),.04));
    border: 1px solid rgba(var(--header-accent),.22);
    text-decoration: none;
    color: inherit;
    transition: transform .15s ease, box-shadow .15s ease;
}
.dashboard-add-site:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 26px -16px rgba(0,0,0,.6);
}
.dashboard-add-site-text h2 { margin-bottom: 6px; }
.dashboard-add-site-text p { color: var(--text-muted); font-size: .88rem; max-width: 480px; }
.dashboard-add-site-detail {
    display: inline-block;
    margin-top: 8px;
    padding: 4px 12px;
    border-radius: 999px;
    background: rgba(255,255,255,.07);
    color: rgba(255,255,255,.85);
    font-size: .78rem;
}

/* Grille 3 colonnes (demande explicite, cf. compte-dashboard.php) : les 3
   cartes de demande (sur-mesure/hébergement/conseil) forment un choix, pas
   une séquence à lire l'une après l'autre. */
.dashboard-add-site-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}
.dashboard-add-site-grid .dashboard-add-site {
    flex-direction: column;
    align-items: flex-start;
    margin-bottom: 0;
    height: 100%;
}
.dashboard-add-site-grid .dashboard-add-site-text h2 { font-size: .95rem; }

/* ─── compte-dashboard.php : carte "Réservez votre nom de domaine" (demande
     explicite, solution provisoire — cf. pages/domain-check.php) ─── */
/* Teinte accentuée (demande explicite : "je rajouterai juste au nom de
   domaine le fait que sa couleur dépende de la couleur active") — même
   mécanisme que .dashboard-add-site juste au-dessus (carte "Vos projets en
   cours"), posé sur rgba(var(--header-accent), ...) plutôt qu'une nouvelle
   variable : la carte suit donc automatiquement la couleur d'accent choisie
   par le client, sans logique supplémentaire ni nouvelle classe à poser côté
   PHP (.dashboard-domain-card existe déjà sur la carte). */
.dashboard-domain-card {
    background: linear-gradient(135deg, rgba(var(--header-accent),.10), rgba(var(--header-accent),.04));
    border: 1px solid rgba(var(--header-accent),.22);
}
.dashboard-domain-row {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 4px;
}
.dashboard-domain-row .form-group { flex: 1; min-width: 0; margin-bottom: 0; }
.dashboard-domain-row .btn-account { flex-shrink: 0; white-space: nowrap; }
.dashboard-domain-result {
    min-height: 1.2em;
    font-size: .85rem;
    font-weight: 600;
    margin: 6px 0 14px;
    transition: color .2s ease;
}
.dashboard-domain-result--checking { color: var(--text-muted); }
.dashboard-domain-result--available { color: #34d399; }
.dashboard-domain-result--taken { color: #f87171; }
.dashboard-domain-result--unknown,
.dashboard-domain-result--error { color: #fbbf24; }
.dashboard-domain-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}
@media (max-width: 560px) {
    .dashboard-domain-row { flex-direction: column; align-items: stretch; }
}

/* ─── compte-dashboard.php : fil d'activité récente ─── */
.dashboard-activity-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}
.dashboard-activity-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 2px;
    border-bottom: 1px solid rgba(255,255,255,.06);
}
.dashboard-activity-item:last-child { border-bottom: none; }
/* Bug signalé ("y en a plus que 4 et le voir plus n'a pas l'air fonctionnel") :
   display:flex ci-dessus l'emporte sur la règle par défaut du navigateur
   [hidden] { display: none } — un attribut hidden posé côté PHP (cf.
   pages/compte-dashboard.php) n'avait donc AUCUN effet visuel, tous les
   événements s'affichaient d'emblée. Règle explicite pour redonner la
   priorité à hidden sur cet élément précis. */
.dashboard-activity-item[hidden] { display: none; }
.dashboard-activity-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    padding: 7px;
    border-radius: 8px;
    background: rgba(var(--header-accent),.10);
    color: rgb(var(--header-accent));
    box-sizing: content-box;
}
.dashboard-activity-icon svg { width: 100%; height: 100%; display: block; }
.dashboard-activity-text { flex: 1; min-width: 0; font-size: .88rem; color: rgba(255,255,255,.85); }
.dashboard-activity-date { font-size: .75rem; color: var(--text-muted); white-space: nowrap; }

@media (max-width: 860px) {
    .account-layout { grid-template-columns: 1fr; }

    /* Sur mobile, le bandeau titre/description (.account-hero--banner) doit
       s'afficher APRÈS le menu de navigation du compte (et non avant, comme
       en desktop) — cf. demande explicite. Comme .account-hero et
       .account-layout sont deux éléments frères directs de <main
       class="account-page">, on ne peut pas se contenter d'un "order" sur
       .account-layout seul : ses propres enfants (nav + contenu) doivent
       devenir des enfants directs de .account-page (display: contents) pour
       participer au même flex et pouvoir être réordonnés individuellement
       via "order" aux côtés du bandeau. */
    /* align-items:stretch (root cause du bug de swipe, confirmé via
       getComputedStyle en direct sur le site déployé) : la règle desktop
       .account-page (display:grid, plus haut dans ce fichier) pose
       align-items:start pour sa grille 3 colonnes — sans le réinitialiser
       ici, cette valeur restait active même une fois repassé en display:flex
       sur mobile (même sélecteur, même spécificité, mais "align-items"
       n'était réécrit nulle part dans ce bloc mobile). Avec align-items:start,
       aucun enfant (dont .account-sidenav-col) ne s'étirait à la largeur de
       l'écran : ils gardaient tous la largeur naturelle de leur contenu,
       ce qui empêchait .account-sidenav-links de recevoir une largeur
       réellement contrainte et donc de devenir scrollable (scrollWidth
       restait égal à clientWidth) — d'où le swipe tactile sans aucun effet
       malgré un CSS par ailleurs correct sur l'élément scrollable lui-même. */
    .account-page { display: flex; flex-direction: column; align-items: stretch; }
    .account-layout { display: contents; }
    /* .account-layout passe en display:contents ci-dessus : ses enfants ne
       sont donc plus sélectionnés par ".account-page > *" (qui ne vise que
       les enfants DIRECTS dans l'arbre DOM) et perdraient le position:relative
       + z-index:1 qui les fait passer au-dessus du fond fixe .account-page::before
       — réappliqué explicitement plus bas (cf. règle .account-sidenav-col
       existante) et ici pour .account-content. */
    /* .account-topbar (Accueil/Mon profil) en tout premier, avant les 2 menus
       (gauche puis droite, départagés par leur ordre dans le DOM puisqu'ils
       partagent le même "order" ci-dessous) — même traitement de position
       que .account-sidenav-col ci-dessous : nécessaire pour rester au-dessus
       du fond fixe .account-page::before depuis le passage en display:contents. */
    /* display:flex explicite ici : la règle de base (desktop) pose
       display:contents sur .account-topbar pour que ses 2 boutons deviennent
       des enfants de grille indépendants de .account-page (placés de part et
       d'autre du titre) — en mobile on veut au contraire les regrouper en une
       seule rangée au-dessus du menu, d'où ce retour explicite à flex. */
    .account-topbar {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 4px;
        order: 0;
        position: relative;
        z-index: 1;
        flex-wrap: wrap;
        gap: 10px;
    }
    /* Repasse en flux normal (demande explicite de rendre la nav/les boutons
       fixes ne concerne que le desktop, cf. règles hors media query
       plus haut) : sur mobile, .account-topbar redevient un simple bloc
       flex (cf. règle ci-dessus) au fil de la page, comme avant l'ajout du
       position:fixed. left/right explicitement réinitialisés : sans ça, les
       valeurs var(--dash-edge) de .account-topbar-btn--home/--profile
       (même spécificité, définies plus haut dans ce fichier) resteraient
       appliquées malgré ce retour à un positionnement normal. */
    .account-topbar-btn, .account-topbar-switch {
        position: static;
        top: auto;
        left: auto;
        right: auto;
    }
    .account-topbar-btn--home, .account-topbar-btn--profile { left: auto; right: auto; }
    .account-topbar-btn { padding: 8px 14px; font-size: .78rem; }
    .account-topbar-btn svg { width: 16px; height: 16px; }
    .account-topbar-switch-opt { padding: 8px 12px; font-size: .78rem; gap: 5px; }
    .account-topbar-switch-opt svg { width: 13px; height: 13px; }
    .account-sidenav-col { order: 1; }
    /* margin-top : espace le bandeau titre du bloc stats+nav qui le précède
       désormais en mobile (sinon collés l'un à l'autre). */
    .account-hero.account-hero--banner { order: 2; margin-top: 24px; margin-bottom: 24px; }
    .account-content { order: 3; position: relative; z-index: 1; }

    /* Menu du compte en mobile : la stat "sites mis en ligne" reste en pleine
       largeur au-dessus, et tous les liens deviennent une bande défilable
       horizontalement (plutôt qu'un retour à la ligne anarchique où chaque
       item se retrouvait écrasé/tronqué sur une largeur imposée de 100px).
       Le collage au scroll (sticky) n'a de sens qu'en layout 2 colonnes :
       on le désactive ici sur le wrapper. */
    .account-sidenav-col {
        /* "relative" (et non "static") : le collage au scroll (sticky) reste
           désactivé de la même façon, mais "relative" permet à z-index de
           s'appliquer — nécessaire depuis le passage de .account-layout en
           display:contents plus haut (cf. commentaire associé), qui retire
           à cet élément l'élévation position:relative/z-index:1 qu'il
           recevait auparavant via son ancêtre direct .account-layout
           (règle ".account-page > *"), et sans laquelle il se retrouverait
           peint sous le fond fixe .account-page::before.
           "top: 0" est nécessaire ici : la règle de base (desktop, plus haut
           dans ce fichier) pose "top: 96px" pour le collage au scroll
           (sticky) — sans effet tant que position était "static" (top n'a
           aucun effet sur un élément static), mais qui reprenait effet dès
           le passage à "relative" ci-dessus, décalant tout le menu de 96px
           vers le bas et le faisant chevaucher le bandeau titre suivant. */
        position: relative;
        top: 0;
        /* Réinitialise le passage en position:fixed du desktop (cf. règles
           hors media query plus haut, .account-sidenav-col--left/--right) —
           sans ça, left/right/width/bottom resteraient appliqués malgré ce
           retour à un positionnement normal (même spécificité, cette règle
           gagne car plus bas dans le fichier). */
        left: auto;
        right: auto;
        width: auto;
        bottom: auto;
        z-index: 1;
        max-height: none;
        overflow: visible;
        /* Sépare les 2 bandes de menu (gauche puis droite) empilées l'une
           sous l'autre en mobile — sans quoi elles se touchent. */
        margin-bottom: 12px;
    }
    /* L'ancienne règle body.footer-revealed .account-sidenav-col (hors media
       query) a été supprimée : la nav reste désormais fixe en permanence sur
       desktop, peu importe le scroll (demande explicite), elle ne se
       détache donc plus jamais près du footer. Conservée ici pour le mobile
       uniquement : le sticky n'existe de toute façon plus à cette taille
       d'écran (position:relative ci-dessus), ce sélecteur ne fait donc que
       réaffirmer top:0 sans dépendre de l'état du footer. */
    body.footer-revealed .account-sidenav-col {
        position: relative;
        top: 0;
        z-index: 1;
    }
    .account-sidenav {
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
        padding: 12px;
        /* min-width:0 (root cause du bug de swipe, confirmé via getComputedStyle
           en direct sur le site déployé) : .account-sidenav est overflow-x:visible
           et, sans ce reset, garde min-width:auto (valeur flexbox par défaut) —
           il refuse alors de rétrécir en dessous de la largeur naturelle de son
           contenu (la bande de liens, ~900px), ce qui élargit toute la colonne
           parente avec lui. .account-sidenav-links (l'enfant scrollable) avait
           déjà min-width:0 posé dessus, mais ça ne suffit pas : le piège
           flexbox "automatic minimum size" s'applique à CHAQUE niveau
           overflow:visible de la chaîne, pas seulement à l'élément scrollable
           lui-même. Sans ce correctif, .account-sidenav-links ne recevait
           jamais une largeur réellement contrainte à l'écran (elle grandissait
           à la taille de son contenu comme le reste de la chaîne, scrollWidth
           == clientWidth) : il n'y avait donc rien à faire défiler en interne,
           d'où le swipe tactile totalement sans effet malgré un CSS par
           ailleurs correct sur l'élément scrollable. */
        min-width: 0;
    }
    .account-sidenav-stat { width: 100%; }
    .account-sidenav-divider { display: none; }
    /* Sur mobile, la nav devient une bande horizontale scrollable (cf.
       .account-sidenav-links ci-dessous) : les étiquettes de catégorie
       (Mes projets, nom client/entreprise, À propos…) n'ont pas leur place
       dans ce contexte et sont masquées (demande explicite). */
    .account-sidenav-group-label { display: none; }

    .account-sidenav-links {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        gap: 8px;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        /* touch-action: pan-x RETIRÉ (correctif du correctif) : posé dans un
           premier temps pour "aider" le geste tactile, mais sur Android
           Chrome (confirmé par le client) cette valeur restreinte peut au
           contraire faire échouer la reconnaissance du geste de scroll côté
           moteur de rendu au lieu de l'autoriser — contre-intuitif, mais le
           défilement tactile ne fonctionnait plus DU TOUT (pas même un
           rebond) une fois cette ligne posée. La valeur par défaut du
           navigateur ("auto") est le choix le plus sûr pour un simple
           conteneur overflow-x:auto : elle laisse le moteur décider librement
           quel axe traiter en natif au lieu de le contraindre nous-mêmes.
           min-width:0 : classique piège flexbox — un enfant flex garde par
           défaut min-width:auto (= la largeur de son contenu total), ce qui
           l'empêche de se faire réellement contraindre par la largeur du
           parent et donc de déclencher son propre overflow-x. Sans cette
           ligne, le conteneur peut s'étirer au-delà de l'écran au lieu de
           défiler en interne selon la largeur réelle du contenu/police du
           navigateur. */
        min-width: 0;
        padding-bottom: 6px;
        scrollbar-width: thin;
        scrollbar-color: rgba(255,255,255,.18) transparent;
    }
    .account-sidenav-links::-webkit-scrollbar { height: 5px; }
    .account-sidenav-links::-webkit-scrollbar-track { background: transparent; }
    .account-sidenav-links::-webkit-scrollbar-thumb { background: rgba(255,255,255,.18); border-radius: 999px; }

    .account-sidenav-link {
        flex: 0 0 auto;
        white-space: nowrap;
        padding: 9px 16px;
    }
    .account-sidenav-link--logout { border-top: none; margin-top: 0; padding-top: 9px; }
    .data-table { display: block; overflow-x: auto; white-space: nowrap; }
    /* Sous 860px : 6 colonnes deviennent trop étroites pour rester lisibles
       (libellés coupés) — grille 3 colonnes / 2 lignes, toujours strictement
       alignée sur ses lignes ET colonnes (demande explicite), contrairement
       à l'ancien flex-wrap qui laissait chaque étape dériver. Le trait de
       connexion ::before/::after n'a de sens visuel que sur une seule ligne
       (cf. version desktop ci-dessus) : masqué ici plutôt que de tenter de
       le faire suivre un tracé sur 2 lignes. */
    .mockup-phases { grid-template-columns: repeat(3, 1fr); row-gap: 20px; }
    .mockup-phases::before,
    .mockup-phases::after { display: none; }
    .support-actions { flex-direction: column; }
    .support-action-btn { justify-content: center; }
    .form-row { grid-template-columns: 1fr; }
}

/* ─── BACKGROUND FIXE : login.php / register.php / forgot-password.php / reset-password.php ─── */
.page-auth::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}
.page-auth > * {
    position: relative;
    z-index: 1;
}
/* Bug réel trouvé (demande explicite : "rien ne se passe ni au hover ni au
   clic" sur la nav Inscription/Connexion de login.php/register.php) :
   ".hmg-nav" a sa propre règle "position:absolute" (cf. plus haut dans ce
   fichier), mais ".page-auth > *" ci-dessus a la MÊME spécificité (1
   classe) et vient APRÈS dans la cascade — elle l'emportait donc et
   repassait .hmg-nav en position:relative. Résultat : .hmg-nav restait
   dans le flux normal du document, et .register-split/.login-split (même
   z-index:1, mais peints APRÈS lui car plus tard dans le DOM) se
   retrouvaient visuellement ET fonctionnellement AU-DESSUS de la nav —
   le texte de la nav restait lisible (juste à côté/au-dessus dans le
   flux) mais tout clic sur cette zone de l'écran atterrissait sur le
   conteneur transparent qui la recouvrait. Sélecteur à 2 classes
   ci-dessous = spécificité supérieure, l'emporte quel que soit l'ordre. */
.page-auth > .hmg-nav {
    position: absolute;
    z-index: 2;
}

/* Formulaires login/register */
/* padding-bottom généreux pour laisser la place au footer flottant, qui ne
   doit jamais recouvrir le bouton de soumission (visible surtout sur
   register.php, dont le formulaire est plus long que login.php). */
.auth-page {
    min-height: calc(100dvh - 200px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 120px 20px var(--footer-clearance);
}

/* login.php / register.php seulement (cf. classe ajoutée à côté de
   ".auth-page" dans ces 2 fichiers) : la barre ".hmg-nav" ajoutée en haut
   (Accueil / Inscription-Connexion) est en position absolute et pouvait se
   retrouver visuellement collée, voire superposée, à la carte du formulaire
   quand celle-ci se centre haut dans les viewports courts. Un padding-top
   plus généreux garantit un écart vertical, quelle que soit la hauteur de
   l'écran (le centrage flex ne peut jamais remonter la carte au-dessus de
   ce padding). */
.auth-page.auth-page--with-nav {
    padding-top: 190px;
}

/* Bulles de nav légèrement resserrées/décentrées par rapport à la barre
   large (680px) utilisée sur les pages marketing : alignées sur la largeur
   réelle de la carte (440px, cf. .auth-card) plutôt que de flotter, isolées,
   sur toute la largeur de l'écran. */
.auth-page--with-nav .hmg-nav {
    width: min(440px, calc(100% - 40px));
}

.auth-card {
    width: 100%;
    max-width: 440px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: var(--radius);
    padding: 40px 36px;
}

.auth-card h1 { font-family: var(--font-title); font-size: 1.4rem; color: #fff; margin-bottom: 8px; }
.auth-card > p { color: var(--text-muted); font-size: .88rem; margin-bottom: 24px; }
.auth-card .form-group { margin-bottom: 16px; }
.auth-footer { text-align: center; margin-top: 20px; font-size: .84rem; color: var(--text-muted); }
.auth-footer a { color: var(--brand-color); font-weight: 600; text-decoration: none; }
.auth-footer a:hover { text-decoration: underline; }
.auth-row-split { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* pages/oauth-link.php (demande explicite "styliser comme le reste du
   site") : email en blanc plein (au lieu du gris muted hérité de
   ".auth-card > p") pour bien ressortir dans la phrase, nom du provider
   dans l'accent du site (var(--brand-color), même variable que
   .auth-footer a juste au-dessus) pour l'ancrer visuellement comme un nom
   de marque plutôt qu'un mot ordinaire. */
.oauthlink-email { color: #fff; }
.oauthlink-provider { color: var(--brand-color); }

/* Connexion "Continuer avec Google" (login.php + register.php) — Facebook
   retiré (demande explicite), règle .btn-social.facebook supprimée avec. */
.auth-social { display: flex; flex-direction: column; gap: 10px; margin-bottom: 22px; }
.btn-social {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 11px 16px;
    border-radius: var(--radius);
    font-size: .92rem;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid rgba(255,255,255,.14);
    transition: filter .15s ease, transform .15s ease;
}
.btn-social:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn-social svg { flex-shrink: 0; }
.btn-social.google { background: #fff; color: #1f1f1f; border-color: rgba(0,0,0,.08); }

.auth-divider {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 4px 0 22px;
    color: var(--text-muted);
    font-size: .76rem;
    text-transform: uppercase;
    letter-spacing: .06em;
}
.auth-divider::before,
.auth-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: rgba(255,255,255,.12);
}

@media (max-width: 480px) {
    .auth-row-split { grid-template-columns: 1fr; }
    .auth-card { padding: 30px 22px; }
}

/* ─── register.php : layout 2 colonnes (demande explicite) ───
   Gauche = reprise du bloc "De l'idée à la mise en orbite" (accueil.php,
   #method-heading, cf. commentaire dans pages/register.php pour le détail).
   Droite = .auth-card (formulaire, inchangée). Remplace l'ancien wrapper
   ".auth-page/.auth-page--with-nav" — celui-ci reste utilisé tel quel par
   login.php/forgot-password.php/reset-password.php, non concernés par ce
   changement. */
/* .auth-nav-logo (logo flottant remplaçant temporairement la nav sur
   register.php/login.php) retiré (demande explicite) : navigation
   rétablie en boucle avec .hmg-nav/.hmg-offer-track, cf. pages/register.php
   et pages/login.php — règles génériques déjà définies plus haut dans ce
   fichier, aucune classe dédiée à réintroduire ici. */

.register-split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(32px, 5vw, 72px);
    /* Élargie (1200px -> 1560px, demande explicite) : nécessaire pour que
       les 6 étapes en 2 colonnes (cf. .register-method-grid plus bas)
       gardent une largeur de carte confortable, sans quoi elles seraient
       plus étroites que la version 2 colonnes d'origine sur accueil.php. */
    max-width: 1560px;
    margin: 0 auto;
    /* Ni "height" ni "min-height" fixé à 100dvh (valeurs essayées
       précédemment) : les deux forçaient la grille à occuper tout l'écran
       même quand le contenu réel (méthode + formulaire) est plus court,
       ce qui étirait .auth-card dans une cellule artificiellement trop
       grande et recréait le "gros espace vide" déjà corrigé une première
       fois. La hauteur se calcule maintenant uniquement à partir du
       contenu le plus haut des 2 colonnes (align-items:stretch par défaut
       sur une grille = les 2 colonnes restent alignées à la même hauteur
       l'une sur l'autre, mais celle-ci n'est plus jamais gonflée
       artificiellement au-delà du contenu réel). Le scroll de page reste
       possible normalement dès que ce contenu dépasse un écran, sans
       overflow:hidden ni max-height pour le bloquer. */
    /* Padding-haut augmenté (150px -> 190px, demande explicite : ".hmg-nav"
       Accueil/Connexion restait collé à la section méthode) : aligné sur la
       même valeur que ".auth-page--with-nav" (login.php...) qui gère déjà
       ce même écart nav/carte ailleurs sur le site.
       Padding-bas : remplacé la valeur fixe (56px) par var(--footer-clearance)
       — demande explicite "le footer chevauche le formulaire" : 56px ne
       réservait pas assez de place pour le footer flottant (position:fixed,
       cf. .site-footer) qui pouvait donc recouvrir le bas du formulaire.
       var(--footer-clearance) est le mécanisme standard déjà utilisé en fin
       de page partout ailleurs sur le site pour éviter ce recouvrement. */
    padding: 190px 20px var(--footer-clearance);
}

/* .register-method/.register-method-grid/les overrides .method-step* liés
   (grille 2 colonnes des 6 étapes, tooltips désactivés, paddings badge...)
   entièrement retirés : demande explicite "au lieu de mettre 'de l'idée à
   la mise en orbite' mets comme pour login.php une section livre d'or" —
   remplacés par .register-reviews ci-dessous.
   2e correction (bug réel constaté sur capture d'écran, persistant après un
   1er correctif partiel) : "il suffit de faire comme sur login.php" —
   .register-reviews reprend maintenant EXACTEMENT .login-reviews (min-width:0
   + text-align:center, rien d'autre). Le 1er essai avait ajouté
   display:flex/flex-direction:column pour centrer verticalement le contenu,
   ce qui transformait .reviews-slider-wrap en item flex (min-width:auto par
   défaut, se cale sur le min-content de .reviews-track malgré son
   overflow:hidden) — un simple min-width:0 supplémentaire sur cet item n'a
   pas suffi à éliminer le débordement. Reproduire .login-reviews au lieu de
   réinventer une variante règle le problème à la racine. */
.register-reviews {
    min-width: 0;
    text-align: center;
}

/* .register-trust-badges/.register-trust-badge* retirés (demande explicite :
   "les badges Données confidentielles et Connexion chiffrée à enlever
   également") — n'étaient utilisés que sur register.php, aucune autre page
   ne référence ces classes. */

/* Pas de "align-items" sur .register-split (stretch par défaut) : les 2
   colonnes s'étirent à la même hauteur (celle du conteneur, 100dvh moins
   padding) — .register-form-col centre alors la carte verticalement dans
   cet espace, et défile elle aussi de façon indépendante si le formulaire
   ne tient pas en entier (petits écrans courts). */
/* align-items: stretch (pas "center", demande explicite "les 2 sections
   doivent être alignées et de même taille verticale") : .auth-card s'étire
   désormais sur toute la hauteur de sa colonne — elle-même déjà étirée à la
   hauteur de .register-method via le "stretch" par défaut de .register-split
   (cf. plus haut) — au lieu de flotter, plus petite, centrée au milieu d'un
   espace plus grand qu'elle. Son propre contenu reste centré À L'INTÉRIEUR
   d'elle (cf. .auth-card ci-dessous, display:flex + justify-content:center),
   donc le rendu visuel ne change pas pour l'utilisateur, seul le contour de
   la carte s'aligne maintenant exactement sur celui de la colonne de
   gauche. */
.register-form-col {
    display: flex;
    /* stretch -> flex-start (demande explicite : "le formulaire est étiré",
       même bug déjà rencontré et corrigé sur .login-form-col) : stretch
       avait du sens quand la colonne voisine était la longue grille de 6
       étapes (.register-method, retirée) — désormais que c'est un bandeau
       d'avis court (.register-reviews), stretch étirait la carte sur toute
       la hauteur disponible, créant un grand vide interne malgré le
       centrage de secours posé sur .auth-card (cf. plus bas). flex-start :
       la carte garde sa hauteur naturelle, calée en haut de la colonne —
       exactement la même logique que .login-form-col. */
    align-items: flex-start;
    justify-content: center;
    overflow-y: auto;
}

/* Formulaire compacté (demande explicite) : scopé à ".register-form-col
   .auth-card" pour ne toucher QUE la carte de register.php — .auth-card
   reste inchangée sur login.php/forgot-password.php/reset-password.php,
   qui n'ont pas cette contrainte de hauteur (pas de layout 2 colonnes ni de
   100dvh). Les propriétés génériques (.form-group input/select, padding,
   font-size...) sont partagées avec tout le reste du site (contact.php...)
   donc jamais modifiées à la base, uniquement surchargées ici. */
.register-form-col .auth-card {
    padding: 26px 30px;
    max-width: 400px;
    /* Centre le contenu verticalement À L'INTÉRIEUR de la carte, maintenant
       que celle-ci s'étire (align-items:stretch ci-dessus) sur toute la
       hauteur de la colonne plutôt que d'épouser juste la hauteur de son
       contenu. */
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.register-form-col .auth-card h1 {
    font-size: 1.15rem;
    /* Léger espace avant le bouton Google (demande explicite) : 4px ->
       16px, la carte n'a plus de sous-titre entre le titre et le bouton
       depuis son retrait. */
    margin-bottom: 16px;
}
.register-form-col .auth-card .form-group {
    margin-bottom: 10px;
}
.register-form-col .auth-social {
    gap: 8px;
    margin-bottom: 14px;
}
.register-form-col .btn-social {
    padding: 8px 14px;
    font-size: .84rem;
}
.register-form-col .auth-divider {
    /* Très léger gap supplémentaire (demande explicite) entre le bouton
       "Créer mon compte" (submit, juste au-dessus) et ce séparateur "ou" :
       2px -> 10px, presque imperceptible mais les 2 ne se touchent plus. */
    margin: 10px 0 14px;
}
.register-form-col .auth-row-split {
    gap: 10px;
}
.register-form-col .form-group label {
    font-size: .68rem;
}
.register-form-col .form-group input,
.register-form-col .form-group select {
    padding: 9px 14px;
    font-size: .86rem;
}
.register-form-col .btn-contact {
    padding: 10px 32px;
    font-size: .92rem;
    /* Même logique de couleur que sur index.php (demande explicite) :
       .btn-contact utilise par défaut le dégradé --accent-harmony-1/-2
       (cf. règle de base plus haut dans ce fichier, pensée pour
       login.php/contact.php...). Ici, scopé à .register-form-col
       uniquement, on reprend plutôt le traitement de .btn-accueil sur
       index.php — teinte unique --accent-harmony-3, remplissage/contour/
       glow identiques — sans toucher au .btn-contact partagé par les
       autres pages (contact.php, login.php...). */
    background: rgba(var(--accent-harmony-3), .14);
    border-color: rgba(var(--accent-harmony-3), .32);
    box-shadow: 0 0 24px rgba(var(--accent-harmony-3), .08), inset 0 1px 0 rgba(255,255,255,.07);
    color: #ffffff;
}
.register-form-col .btn-contact:hover {
    background: rgba(var(--accent-harmony-3), .22);
    box-shadow: 0 12px 36px rgba(var(--accent-harmony-3), .28);
}
.register-form-col .auth-footer {
    margin-top: 12px;
    font-size: .78rem;
}

@media (max-width: 900px) {
    .register-split {
        grid-template-columns: 1fr;
        /* Empilé (demande explicite : contexte d'abord, formulaire ensuite,
           cf. ordre déjà posé dans le HTML) : chaque section reçoit une
           moitié fixe de l'écran plutôt qu'une hauteur "au contenu", sinon
           les 2 sections mises bout à bout dépasseraient largement 100dvh
           et on retomberait dans un scroll de page classique. */
        /* "1fr 1fr" (valeur précédente) forçait les 2 lignes à la MÊME
           hauteur — celle de la plus haute des deux (cf. répartition des
           fr sur un conteneur en auto-height) — ce qui étirait
           artificiellement .register-form-col (plus courte que
           .register-method et ses 6 étapes) et recréait le "gros espace
           vide" au-dessus du formulaire (demande explicite : "je crois
           qu'il y a un min-height... le formulaire est étiré"). C'était
           pensé à l'origine pour une page bloquée à 100dvh (chaque bloc =
           une moitié d'écran fixe) — ce plafond a été retiré depuis
           (cf. .register-split plus haut, la page défile désormais
           normalement), donc cette répartition figée n'a plus lieu d'être :
           "auto auto" laisse chaque section prendre sa propre hauteur de
           contenu, sans étirer la plus courte des deux. */
        grid-template-rows: auto auto;
        gap: 16px;
        /* Padding-haut augmenté (110px -> 170px, demande explicite : le nav
           Accueil/Connexion restait collé à la section méthode) — même
           raisonnement que la valeur desktop plus haut, ".hmg-nav" garde le
           même positionnement absolu (top ~70-90px + sa propre hauteur) quel
           que soit l'écran. Padding-bas : idem desktop, var(--footer-clearance)
           au lieu de 16px pour que le footer flottant ne recouvre plus le
           formulaire sur mobile. Padding-haut réajusté (170px -> 190px) en
           cohérence avec le logo redescendu juste en dessous. */
        padding: 190px 16px var(--footer-clearance);
    }
    /* Ordre inversé UNIQUEMENT sur mobile (demande explicite, revient sur le
       choix précédent "contexte d'abord") : le formulaire d'inscription
       passe avant la section méthode. Scopé à cette media query via
       "order" (pas un changement d'ordre dans le HTML) : le bureau garde
       l'ordre naturel du DOM (méthode = colonne de gauche, formulaire =
       colonne de droite, cf. .register-split display:grid plus haut),
       totalement indépendant de cette valeur "order" qui ne s'applique
       qu'ici. */
    .register-form-col {
        order: 1;
    }
    .register-reviews {
        order: 2;
    }
}


/* ========================= login.php ========================= */
/* Même logique que .register-split (cf. juste au-dessus dans ce fichier) :
   2 colonnes (avis livre d'or à gauche, formulaire à droite), pensée dès le
   départ sans "height"/"min-height" fixe (le bug d'étirement corrigé au fil
   des itérations sur register.php ne doit pas se reproduire ici) — la
   hauteur se cale uniquement sur le contenu réel des 2 colonnes. */
.login-split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(32px, 5vw, 72px);
    max-width: 1400px;
    margin: 0 auto;
    /* 190px : même clearance que .register-split pour ".hmg-nav" (nav en
       boucle Inscription/Connexion, cf. pages/login.php et pages/register.php). */
    padding: 190px 20px var(--footer-clearance);
}

/* min-width:0 (bug réel constaté, cf. capture d'écran) : .login-reviews est
   un item de grille (.login-split, display:grid) contenant .reviews-track
   (display:flex, width:max-content — TOUS les avis mis bout à bout, cf.
   .reviews-track dans ce fichier). Sans min-width:0, la largeur minimale
   automatique d'un item de grille se cale sur le min-content de son
   contenu — potentiellement énorme ici — ce qui étirait toute la 1ère
   colonne (et donc toute la grille) à la largeur cumulée des avis, au lieu
   de rester à 1fr : le formulaire se retrouvait poussé hors du viewport à
   droite, et les avis s'affichaient tous côte à côte sans effet de défilement
   (le même correctif existe déjà sur .reviews-inner pour accueil.php, cf.
   plus haut dans ce fichier — même bug, contexte grid au lieu de flex). */
.login-reviews {
    min-width: 0;
    text-align: center;
    /* order:2 (demande explicite : "inverse, livre d'or à droite et
       formulaire à gauche") : le HTML garde son ordre d'origine (avis
       d'abord, formulaire ensuite — important pour ne pas changer l'ordre
       de lecture clavier/lecteur d'écran), seul l'ordre VISUEL change via
       "order" sur la grille .login-split, même principe que le
       row-reverse de .problem-layout sur accueil.php. */
    order: 2;
}

/* PAS "align-items: stretch" ici (contrairement à .register-form-col) :
   demande explicite "de nouveau le formulaire s'étire". Sur register.php,
   étirer + centrer le contenu à l'intérieur avait du sens car les 2
   colonnes (méthode / formulaire) étaient de hauteurs assez proches. Ici,
   le bandeau d'avis est nettement plus court que sur register.php (LIMIT
   réduit à 10, une seule ligne de cartes) alors que .auth-card, une fois
   étirée à la hauteur de la colonne "avis" ET centrée dedans (l'ancien
   réglage), créait un grand espace vide visible au-dessus/en dessous.
   "flex-start" : la carte garde sa hauteur naturelle et se cale en haut de
   la colonne, alignée avec le haut du bandeau d'avis. */
.login-form-col {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    /* order:1, cf. .login-reviews juste au-dessus : place le formulaire
       dans la 1ère colonne (gauche) de la grille, demande explicite. */
    order: 1;
}

/* "Se connecter" (demande explicite) : même logique de couleur que sur
   index.php/register.php — teinte unique --accent-harmony-3 (cf.
   .btn-accueil et .register-form-col .btn-contact plus haut dans ce
   fichier) au lieu du dégradé --accent-harmony-1/-2 par défaut de
   .btn-contact. Le bouton "Livre d'or" (.reviews-all-btn) hérite déjà de
   --accent-harmony-3 via .btn-accueil de base, sans rien à ajouter ici. */
.login-form-col .btn-contact {
    background: rgba(var(--accent-harmony-3), .14);
    border-color: rgba(var(--accent-harmony-3), .32);
    box-shadow: 0 0 24px rgba(var(--accent-harmony-3), .08), inset 0 1px 0 rgba(255,255,255,.07);
    color: #ffffff;
}
.login-form-col .btn-contact:hover {
    background: rgba(var(--accent-harmony-3), .22);
    box-shadow: 0 12px 36px rgba(var(--accent-harmony-3), .28);
}

/* pages/oauth-link.php : bouton "Lier mon compte" — même logique de couleur
   que .register-form-col/.login-form-col .btn-contact ci-dessus (demande
   explicite) : teinte unique --accent-harmony-3 (cf. .btn-accueil sur
   index.php) au lieu du dégradé --accent-harmony-1/-2 par défaut de
   .btn-contact. Classe dédiée (pas de scope par conteneur de page ici) car
   .auth-page est partagé avec verify-2fa.php/reset-password.php/
   forgot-password.php/confirm-email.php, qui gardent le style par défaut. */
.oauthlink-submit-btn {
    background: rgba(var(--accent-harmony-3), .14);
    border-color: rgba(var(--accent-harmony-3), .32);
    box-shadow: 0 0 24px rgba(var(--accent-harmony-3), .08), inset 0 1px 0 rgba(255,255,255,.07);
    color: #ffffff;
}
.oauthlink-submit-btn:hover {
    background: rgba(var(--accent-harmony-3), .22);
    box-shadow: 0 12px 36px rgba(var(--accent-harmony-3), .28);
}

/* Pas de display:flex/justify-content:center ici : inutile désormais que
   .login-form-col ne l'étire plus (align-items:flex-start ci-dessus) —
   .auth-card garde simplement sa taille/mise en page naturelle (cf. règle
   de base .auth-card plus haut dans ce fichier). */

@media (max-width: 900px) {
    .login-split {
        grid-template-columns: 1fr;
        /* "auto auto" (pas "1fr 1fr") dès le départ : cf. commentaire sur
           .register-split plus haut, "1fr 1fr" sur un conteneur en
           auto-height étire la section la plus courte à la hauteur de
           l'autre — corrigé après coup sur register.php, appliqué ici
           directement pour ne pas reproduire le même bug. */
        grid-template-rows: auto auto;
        gap: 16px;
        padding: 170px 16px var(--footer-clearance);
    }
    /* Formulaire d'abord sur mobile (demande explicite, cohérent avec la
       décision finale sur register.php) : "order" plutôt qu'un changement
       d'ordre dans le HTML, pour ne pas toucher à l'ordre desktop (avis à
       gauche, formulaire à droite). */
    .login-form-col {
        order: 1;
    }
    .login-reviews {
        order: 2;
    }
}


/* ========================= cgv.php ========================= */

/* ─── BACKGROUND ─── */
.page-cgv::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}

.page-cgv > *:not(.back-to-top) {
    position: relative;
    z-index: 1;
}

.page-cgv > .back-to-top {
    position: fixed;
}

/* ─── PAS DE SCROLL REVEAL ───
   Page légale (CGV) : le texte doit être visible dès le chargement plutôt
   que d'attendre le défilement pour apparaître (auparavant opacity:0 par
   défaut, révélé seulement via JS/IntersectionObserver au scroll). */
.page-cgv .section-block {
    opacity: 1;
    transform: none;
}

/* ─── HERO ─── */
.cgv-hero {
    /* Padding-top relevé (140px → 200px, cf. .about-hero) : laisse la place
       à .hmg-nav (position absolute, top ~90-120px) sans chevaucher le h1,
       depuis l'ajout de la navigation inter-pages légales. */
    padding: 200px 20px 56px;
    text-align: center;
}

.cgv-hero h1 {
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 800;
    line-height: 1.15;
    margin-bottom: 14px;
    background: linear-gradient(110deg, #ffffff 30%, rgba(var(--header-accent),.90) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.cgv-updated {
    font-size: 0.8rem;
    color: rgba(255,255,255,.38);
    letter-spacing: .025em;
}

/* ─── BODY ───
   .cgv-back-link (le bouton retour à l'accueil) suit cette section et est
   désormais le vrai dernier bloc visible de la page : c'est donc lui qui
   réserve l'espace du footer flottant (cf. plus bas). Garder aussi
   var(--footer-clearance) ici en plus créait un double espacement énorme
   entre le dernier article et le bouton. */
.cgv-body {
    padding: 0 20px 40px;
}

.cgv-container {
    max-width: 860px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 18px;
}

/* ─── ARTICLE CARDS ─── */
.cgv-section {
    padding: 28px 32px;
    border-radius: 18px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.07);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    position: relative;
    overflow: hidden;
    transition: border-color .3s ease, box-shadow .3s ease;
}

.cgv-section::before {
    content: "";
    position: absolute;
    top: 0;
    left: 10%;
    right: 10%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(var(--header-accent),.40), transparent);
}

.cgv-section:hover {
    border-color: rgba(var(--header-accent),.16);
    box-shadow: 0 22px 55px rgba(0,0,0,.22), 0 0 30px rgba(var(--header-accent),.05);
}

/* ─── ARTICLE HEADINGS ─── */
.cgv-section h2 {
    display: flex;
    align-items: baseline;
    gap: 14px;
    margin-bottom: 16px;
    line-height: 1.2;
}

.cgv-article-num {
    font-size: 2rem;
    font-weight: 800;
    line-height: 1;
    flex-shrink: 0;
    color: rgba(var(--header-accent),.35);
    font-variant-numeric: tabular-nums;
    letter-spacing: -.02em;
}

.cgv-article-title {
    font-size: 1.05rem;
    font-weight: 700;
    color: rgba(255,255,255,.88);
    letter-spacing: .01em;
}

/* ─── PARAGRAPHS ─── */
.cgv-section p {
    font-size: 0.875rem;
    line-height: 1.8;
    color: rgba(255,255,255,.65);
    margin-bottom: 10px;
}

.cgv-section p:last-child { margin-bottom: 0; }

.cgv-section p strong {
    color: rgba(255,255,255,.88);
    font-weight: 600;
}

/* ─── LIENS INLINE (mailto, renvois vers d'autres pages légales) ───
   Auparavant sans style dédié : ils héritaient du style par défaut du
   navigateur (bleu/violet, peu lisible sur fond sombre). */
.cgv-section a {
    color: rgb(var(--header-accent));
    text-decoration: underline;
    text-decoration-color: rgba(var(--header-accent),.4);
    text-underline-offset: 3px;
    transition: color .2s ease, text-decoration-color .2s ease;
}

.cgv-section a:hover {
    color: #60a5fa;
    text-decoration-color: rgba(96,165,250,.7);
}

/* ─── LISTS ─── */
.cgv-section ul {
    list-style: none;
    padding: 0;
    margin: 14px 0 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.cgv-section ul li {
    font-size: 0.855rem;
    color: rgba(255,255,255,.68);
    line-height: 1.65;
    padding: 11px 16px 11px 42px;
    background: rgba(255,255,255,.03);
    border: 1px solid rgba(255,255,255,.055);
    border-radius: 10px;
    position: relative;
    transition: background .22s ease, border-color .22s ease, color .22s ease;
}

.cgv-section ul li::before {
    content: "▸";
    position: absolute;
    left: 16px;
    top: 12px;
    color: rgba(var(--header-accent),.65);
    font-size: .78rem;
    line-height: 1;
}

.cgv-section ul li:hover {
    background: rgba(var(--header-accent),.06);
    border-color: rgba(var(--header-accent),.16);
    color: rgba(255,255,255,.88);
}

.cgv-section ul li strong {
    color: rgba(255,255,255,.88);
    font-weight: 600;
}

/* ─── CTA FOOTER ─── */
/* Dernier bloc visible de la page (cgv.php, politique-cookies.php...) :
   réserve donc l'espace du footer flottant via la variable partagée
   plutôt qu'une valeur fixe, pour rester cohérent si sa hauteur change. */
.cgv-back-link {
    text-align: center;
    padding: 20px 0 var(--footer-clearance);
}

/* .btn-primary est trop sombre au repos par défaut (pensé pour être toujours
   surchargé par une couleur de page) : le bouton "Retour à l'accueil" de
   cgv.php n'avait pas cette surcharge et restait quasi noir avant le survol.
   On lui donne la même teinte bleue déjà utilisée partout ailleurs sur cette
   page (cgv-article-num, cgv-section::before, cgv-section:hover...). */
.page-cgv .btn-primary {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.45);
    box-shadow:
        0 4px 20px rgba(var(--header-accent),.18),
        inset 0 1px 0 rgba(255,255,255,.08);
}

.page-cgv .btn-primary:hover {
    background: rgba(var(--header-accent),.30);
    border-color: rgba(var(--header-accent),.65);
    box-shadow:
        0 12px 32px rgba(var(--header-accent),.32),
        inset 0 1px 0 rgba(255,255,255,.12);
}

/* .btn-primary est trop sombre au repos par défaut (pensé pour être toujours
   surchargé par une couleur de page, cf. .page-vitrine/.page-pro/etc.) :
   le bouton "Découvrir nos services" de livre-dor.php n'avait pas cette
   surcharge et restait quasi noir avant le survol. On lui donne la teinte
   bleue déjà utilisée sur cette page (review-toggle-btn, hmg-nav-link...). */
.page-livre-dor .btn-primary {
    background: rgba(var(--header-accent),.18);
    border-color: rgba(var(--header-accent),.45);
    box-shadow:
        0 4px 20px rgba(var(--header-accent),.18),
        inset 0 1px 0 rgba(255,255,255,.08);
}

.page-livre-dor .btn-primary:hover {
    background: rgba(var(--header-accent),.30);
    border-color: rgba(var(--header-accent),.65);
    box-shadow:
        0 12px 32px rgba(var(--header-accent),.32),
        inset 0 1px 0 rgba(255,255,255,.12);
}

/* ================================================================
   REFONTE DE SITE + PROGRAMMATION — nouvelles familles de services
   ================================================================ */

/* ─── services.php : bulles de titre + planètes (nouvelles teintes) ─── */
@keyframes galaxyPulseAmber {
    0%, 100% { box-shadow: 0 0 28px rgba(217,119,6,.18), 0 0 56px rgba(217,119,6,.07); }
    50%       { box-shadow: 0 0 44px rgba(217,119,6,.30), 0 0 88px rgba(217,119,6,.12); }
}
@keyframes galaxyPulseEmerald {
    0%, 100% { box-shadow: 0 0 28px rgba(5,150,105,.18), 0 0 56px rgba(5,150,105,.07); }
    50%       { box-shadow: 0 0 44px rgba(5,150,105,.30), 0 0 88px rgba(5,150,105,.12); }
}

/* ── programmation (section 5) : demande explicite, texture planet-vert
   en bg (au lieu de la galaxie teintée émeraude), bleu au survol. ── */
.section-title--programmation {
    background-image: url('../image/planet-vert.webp');
    background-size: cover;
    background-position: center;
    border: 1px solid rgba(5,150,105,.16);
    animation: galaxyPulseEmerald 9s ease-in-out infinite;
    transition: background-image 0.3s ease;
}
.section-title--programmation:hover {
    background-image: none;
    background-color: rgba(59,130,246,.92);
}

/* ── refonte (section 3) : demande explicite, texture planet-orange en bg
   (au lieu de la galaxie teintée ambre), bleu au survol. ── */
.section-title--refonte {
    background-image: url('../image/planet-orange.webp');
    background-size: cover;
    background-position: center;
    border: 1px solid rgba(217,119,6,.16);
    animation: galaxyPulseAmber 9s ease-in-out infinite;
    transition: background-image 0.3s ease;
}
.section-title--refonte:hover {
    background-image: none;
    background-color: rgba(59,130,246,.92);
}

/* ── emerald : monde brume-mousse teal/vert — Programmation — texture dédiée, plus de duplication avec « nebula » ── */
/* Corrigé (demande explicite : "toutes les planètes de #programmation
   doivent être planet-vert") : planet-blanc.webp était utilisée par erreur
   ici (copier-coller, cf. .planet--ice juste au-dessus qui l'utilise
   légitimement) au lieu de planet-vert.webp, la texture verte cohérente
   avec la couleur fixe de cette section. */
.planet--emerald .planet-sphere {
    background-image: url('../image/planet-vert.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 24px rgba(5,150,105,.22),
        0 0 48px rgba(5,150,105,.08),
        inset -30px -30px 60px rgba(0,10,4,.90);
}
.planet--emerald:hover .planet-sphere {
    box-shadow:
        0 0 46px rgba(5,150,105,.48),
        0 0 92px rgba(5,150,105,.18),
        inset -30px -30px 60px rgba(0,10,4,.90);
}
.planet--emerald .planet-sphere::before {
    background: repeating-linear-gradient(
        -16deg,
        transparent             0px,  transparent             28px,
        rgba(20,180,140,.07)   28px,  rgba(20,180,140,.07)   30px,
        transparent             30px,  transparent             56px,
        rgba(10,120,95,.05)    56px,  rgba(10,120,95,.05)    58px
    );
    animation-duration: 55s;
}
.planet--emerald .planet-sphere::after {
    box-shadow:
        inset 0 0 18px rgba(5,150,105,.16),
        inset 0 0 36px rgba(5,150,105,.08);
}

/* ── amber : monde rocheux au terminateur marqué — Refonte — texture dédiée, plus de duplication avec « gold » ── */
/* Texture "magma" (déplacée depuis Maintenance) — Refonte de site,
   teinte ambre inchangée. */
.planet--amber .planet-sphere {
    background-image: url('../image/planet-rouge.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 24px rgba(217,119,6,.22),
        0 0 48px rgba(217,119,6,.08),
        inset -30px -30px 60px rgba(20,8,0,.90);
}
.planet--amber:hover .planet-sphere {
    box-shadow:
        0 0 46px rgba(217,119,6,.48),
        0 0 92px rgba(217,119,6,.18),
        inset -30px -30px 60px rgba(20,8,0,.90);
}
.planet--amber .planet-sphere::before {
    background: repeating-linear-gradient(
        -22deg,
        rgba(217,119,6,.10)  0px,  rgba(217,119,6,.10) 20px,
        rgba(120,50,4,.08)  20px,  rgba(120,50,4,.08)  42px,
        rgba(160,80,10,.06) 42px,  rgba(160,80,10,.06) 64px
    );
    animation-duration: 50s;
}
.planet--amber .planet-sphere::after {
    box-shadow:
        inset 0 0 18px rgba(217,119,6,.16),
        inset 0 0 36px rgba(217,119,6,.08);
}

/* ── graphite : Audit de site — texture "business" (remplace la texture
   "custom" d'origine), teinte grise inchangée. ── */
.planet--graphite .planet-sphere {
    background-image: url('../image/planet-orange.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 24px rgba(148,163,184,.22),
        0 0 48px rgba(148,163,184,.08),
        inset -30px -30px 60px rgba(10,12,16,.90);
}
.planet--graphite:hover .planet-sphere {
    box-shadow:
        0 0 46px rgba(148,163,184,.48),
        0 0 92px rgba(148,163,184,.18),
        inset -30px -30px 60px rgba(10,12,16,.90);
}
.planet--graphite .planet-sphere::before {
    background: repeating-linear-gradient(
        -20deg,
        rgba(148,163,184,.08) 0px,  rgba(148,163,184,.08) 22px,
        rgba(71,85,105,.06)  22px,  rgba(71,85,105,.06)  46px,
        transparent            46px,  transparent            68px
    );
    animation-duration: 60s;
}
.planet--graphite .planet-sphere::after {
    box-shadow:
        inset 0 0 18px rgba(148,163,184,.16),
        inset 0 0 36px rgba(148,163,184,.08);
}

/* ── blurple : monde sombre aux fractures lumineuses — Bot Discord —
   texture "violette" (remplace l'ancienne texture "custom", partie
   déplacée vers Audit de site), teinte proche de la couleur de marque
   Discord inchangée ── */
.planet--blurple .planet-sphere {
    background-image: url('../image/planet-violet.webp');
    background-size: cover;
    background-position: center;
    box-shadow:
        0 0 24px rgba(88,101,242,.26),
        0 0 48px rgba(88,101,242,.10),
        inset -30px -30px 60px rgba(4,4,12,.90);
}
.planet--blurple:hover .planet-sphere {
    box-shadow:
        0 0 46px rgba(88,101,242,.52),
        0 0 92px rgba(88,101,242,.20),
        inset -30px -30px 60px rgba(4,4,12,.90);
}
.planet--blurple .planet-sphere::before {
    background: repeating-linear-gradient(
        -24deg,
        rgba(88,101,242,.10) 0px,  rgba(88,101,242,.10) 18px,
        rgba(30,20,70,.08)  18px,  rgba(30,20,70,.08)  40px,
        transparent            40px,  transparent            62px
    );
    animation-duration: 45s;
}
.planet--blurple .planet-sphere::after {
    box-shadow:
        inset 0 0 18px rgba(88,101,242,.18),
        inset 0 0 36px rgba(88,101,242,.09);
}

/* ─── BACKGROUND FIXE : programmation.php / refonte.php ─── */
.page-programmation::before,
.page-refonte::before {
    content: "";
    position: fixed;
    inset: 0;
    background:
        linear-gradient(rgba(0,0,0,.52), rgba(0,0,0,.52)),
        var(--space-bg) center / cover no-repeat;
    z-index: 0;
}
.page-programmation > *,
.page-refonte > * {
    position: relative;
    z-index: 1;
}

/* Planète (programmation.php ET bot-discord.php partagent désormais la même
   planet-vert, demande explicite — l'ancienne répartition différenciée,
   planet-blanc pour programmation.php / planet-violet en override pour
   bot-discord.php, est abandonnée : plus de règle .page-bot-discord::after
   séparée, la règle de base ci-dessous s'applique identiquement aux 2
   pages) sur son propre calque ::after, masquée en fondu radial + rétrécie/
   effacée au scroll — même mécanisme que .page-vitrine::after (cf. main.js,
   bloc "DÉCOR DE FOND"). */
.page-programmation::after {
    content: "";
    position: fixed;
    inset: 0;
    background: url("../image/planet-vert.webp") center / 62vmin no-repeat;
    -webkit-mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    mask-image: radial-gradient(circle 22vmin at center, #000 30%, transparent 92%);
    pointer-events: none;
    z-index: 0;
    transform: scale(var(--bg-scroll-scale, 1));
    opacity: var(--bg-scroll-opacity, 1);
    transform-origin: center center;
    transition: transform .08s linear, opacity .08s linear;
}
.page-programmation.bg-entrance::after {
    transition: transform 1s cubic-bezier(.16,1,.3,1), opacity 1s ease;
}
.page-programmation .section-block,
.page-refonte .section-block {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .7s ease, transform .7s ease;
}
.page-programmation .section-block.is-visible,
.page-refonte .section-block.is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* Couleurs figées par catégorie (ambre/émeraude) retirées ici (demande
   explicite "tu as oublié de faire les changements de couleurs pour les
   boutons de navigation interne à la catégorie") : ces overrides écrasaient
   var(--header-accent) déjà posé sur .hmg-nav-link/.hmg-track-dot--active de
   base avec l'ancienne teinte fixe — supprimés, la règle de base (déjà
   accent-aware) s'applique désormais identiquement à refonte.php/
   audit-site.php et programmation.php/bot-discord.php. */


/* ─── accueil.php : sections dédiées Refonte / Programmation ───
   Réutilisent le style natif de cette page (carte .why-box/.target-box,
   badges .wt-badge, listes .feature-list, bouton .btn-accueil) plutôt que
   le style de pages/services.php (planètes / bulles de titre). ─── */
.home-service-section {
    /* min-height:100dvh + flex column, même principe que .why-target /
       .modules : .container (flex:1, cf. plus bas) remplit l'espace
       disponible et le divider reste juste au-dessus de la barre de
       couleur (border-top) qui ouvre la section suivante — d'où le
       padding-bottom réduit par rapport au padding-top. */
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    padding: 70px clamp(1rem, 4vw, 3rem) clamp(28px, 4vh, 44px);
    position: relative;
    overflow: hidden;
}

/* Texture "scanline" désactivée (demande explicite : "que le bg de la page"
   pour #new-hebergement, seule section utilisant .home-service-section sur
   accueil.php — cf. .home-service-section--hebergement plus bas, qui n'a
   déjà plus de fond dédié depuis une demande précédente). content:none
   plutôt qu'une suppression complète de la règle : garde la trace du choix
   sans risquer d'affecter un futur usage de cette classe. */
.home-service-section::before {
    content: none;
}

.home-service-section > .container {
    position: relative;
    z-index: 1;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
}

.home-service-section .section-divider {
    flex-shrink: 0;
}

/* ─── Fond assorti au reste de la page (grille + halos radiaux) ─── */
.home-service-section--refonte {
    background:
        radial-gradient(ellipse at 50% 0%,   rgba(245,158,11,.11) 0%, transparent 52%),
        radial-gradient(ellipse at 50% 100%, rgba(var(--header-accent),.05) 0%, transparent 60%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.020) 0,
            rgba(255,255,255,.020) 1px,
            transparent 1px,
            transparent 54px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.014) 0,
            rgba(255,255,255,.014) 1px,
            transparent 1px,
            transparent 54px
        ),
        rgba(7,10,18,.94);
    border-top: 1px solid rgba(245,158,11,.12);
}

.home-service-section--programmation {
    background:
        radial-gradient(ellipse at 50% 0%,   rgba(16,185,129,.11) 0%, transparent 52%),
        radial-gradient(ellipse at 50% 100%, rgba(var(--header-accent),.05) 0%, transparent 60%),
        repeating-linear-gradient(
            0deg,
            rgba(255,255,255,.020) 0,
            rgba(255,255,255,.020) 1px,
            transparent 1px,
            transparent 54px
        ),
        repeating-linear-gradient(
            90deg,
            rgba(255,255,255,.014) 0,
            rgba(255,255,255,.014) 1px,
            transparent 1px,
            transparent 54px
        ),
        rgba(7,10,18,.94);
    border-top: 1px solid rgba(16,185,129,.12);
}

/* ─── Fond bgsiteindex.png + planète violette (hm.php + conseilaccompagnement.php
   — Hébergement & maintenance / Conseil & accompagnement) ───
   Ancien fond (radial-gradients cyan + grille + aplat sombre) entièrement
   retiré, remplacé par le même traitement "image + overlay" que #why-cta
   (.why-cta-section) : bgsiteindex.png en fond, planète violette en ::after
   (le ::before générique de .home-service-section garde son léger effet de
   trame/scanline, partagé avec refonte/programmation). */
.home-service-section--hebergement {
    /* Regroupe désormais Hébergement, Accompagnement, Refonte ET
       Programmation (anciennement 3 sections .home-service-section
       distinctes) : repasse à 100dvh comme les autres .home-service-section
       (hérité de .home-service-section, plus besoin de l'exception à
       80dvh qui ne se justifiait que pour l'ancien contenu plus compact
       — 2 cards). */
    /* Plus de fond dédié (demande explicite : inverser les fonds des 2
       sections suite à leur permutation — "continuer la visite" suit
       désormais la FAQ, qui récupère bgsiteindex.png) : le bgsite.png fixe
       posé sur .site-main::before suffit, comme sur les autres sections
       sans fond propre. */
    border-top: 1px solid rgba(59,130,246,.12);
}

/* En-tête de section (demande explicite : "je trouve la section un peu
   fade [...] rajouter un titre") — la section n'avait jusqu'ici aucun texte
   d'ensemble, seulement les 4 titres de colonne. Même structure/gabarit
   que .faq-preview-header (eyebrow + h2 + p, centré) pour rester cohérent
   avec le reste du site. */
.new-hebergement-header {
    text-align: center;
    max-width: 640px;
    margin: 0 auto 48px;
}

.new-hebergement-header h2 {
    font-family: var(--font-title);
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    color: #fff;
    margin-bottom: 10px;
}

.new-hebergement-header p:not(.reviews-eyebrow) {
    color: var(--text-muted);
}

/* accueil.php : "continuer la visite" n'est plus la dernière section de la
   page (la newsletter a désormais sa propre section juste après, demande
   explicite) — plus besoin de réserver l'espace du footer flottant ici,
   c'est .newsletter-home-section qui s'en charge. Padding-bottom réduit
   hérité de .home-service-section (base) suffit donc à nouveau. */

/* ─── Nouvelle structure : 4 colonnes (titre / planète-lien / bouton) ───
   Hébergement, Accompagnement, Refonte et Programmation réunis dans la même
   section/grille, sous exactement le même schéma. Les cards
   (.target-box/.why-box) sont supprimées : la planète devient l'élément
   central de chaque colonne, avec le descriptif affiché dedans. Chaque
   planète garde/reprend les mêmes animations (rotation continue sur
   ::before, stoppée au survol, zoom au clic/survol de l'élément <a>
   lui-même) — seul leur contexte de mise en page change (flux normal
   centré dans la colonne, au lieu d'un positionnement absolu). 4 colonnes
   sur la même ligne en desktop, empilées verticalement en mobile (cf.
   responsive.css). */
.home-service-planet-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: clamp(20px, 3vw, 40px);
    width: 100%;
    max-width: 1420px;
    margin: 0 auto;
}

.home-service-planet-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 20px;
}

/* Les 4 libellés de bouton n'ont pas la même longueur ("Découvrir les
   tarifs" vs "Demander une étude de faisabilité") : .btn-accueil est en
   inline-flex avec une largeur qui suit son texte, donc largeur ET hauteur
   différaient d'un bouton à l'autre. Fix : largeur calée pour que TOUS les
   libellés tiennent sur exactement 2 lignes (y compris le plus long,
   "Demander une étude de faisabilité"), + min-height commun pour 2 lignes
   — les 4 boutons ont désormais toujours la même largeur ET la même
   hauteur. */
.home-service-planet-col .btn-accueil {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    width: 100%;
    max-width: 240px;
    min-height: 66px;
    padding: 12px 16px;
    /* Registre "tech"/"spatial" (demande explicite), même police que les
       boutons fonctionnels et les titres à effet terminal du site
       (var(--font-title) = JetBrains Mono). */
    font-family: var(--font-title);
    font-size: .82rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: normal;
    line-height: 1.35;
}

/* "Découvrir les tarifs" (et ses équivalents EN/DE, plus courts que les 3
   autres libellés) tenait sur 1 seule ligne malgré le max-width commun de
   240px, cassant l'ALIGNEMENT DE HAUTEUR avec les 3 autres boutons.
   Rétrécir le bouton lui-même (comme tenté précédemment) le rendait plus
   PETIT que les 3 autres — pas ce qui est voulu : le bouton doit garder
   exactement la même largeur (240px, cf. règle du dessus) que les 3
   autres, seul le TEXTE À L'INTÉRIEUR doit être forcé sur 2 lignes.
   Solution : un span interne étroit (max-width réduit) contraint le texte
   à se replier, pendant que le bouton lui-même reste à sa pleine largeur
   commune — sans <br> codé en dur, donc valable dans les 3 langues. */
.hebergement-cta-label {
    display: inline-block;
    max-width: 120px;
}

/* Hauteur réservée fixe (≈ 2 lignes, quel que soit le nombre de mots du
   titre) + centrage vertical du texte dedans : les 4 titres n'ont pas
   forcément le même nombre de lignes, mais réservent tous le même espace,
   ce qui garde les planètes (et donc les boutons) parfaitement alignés
   d'une colonne à l'autre. */
.home-service-planet-col h2 {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 2.6em;
    font-size: clamp(1.1rem, 1.6vw, 1.4rem);
    font-weight: 700;
    line-height: 1.3;
    margin: 0;
}

/* Les 4 titres doivent être IDENTIQUES (demande explicite) : texte blanc
   uni, sur le fond bleu doux + glow hérité de la règle générale "h2{}" tout
   en haut de ce fichier (var(--title-accent-soft)). Avant cette règle,
   Accompagnement/Refonte/Programmation avaient un dégradé de couleur
   "background-clip:text" qui masquait ce fond (background-clip:text
   redéfinit "background" pour l'appliquer au texte, faisant disparaître le
   rectangle bleu) — seul Hébergement le conservait, d'où l'incohérence. */
.home-service-planet-col--hebergement h2,
.home-service-planet-col--accompagnement h2,
.home-service-planet-col--refonte h2,
.home-service-planet-col--programmation h2 {
    color: #ffffff;
}

/* Planète cliquable : taille fixe (clamp px, pas vmin — plus prévisible en
   flux normal qu'en positionnement absolu), zoom au survol/focus porté par
   l'élément <a> lui-même (transform: scale). Agrandie à nouveau : la
   section occupe désormais 100dvh, il y a la place pour des planètes plus
   imposantes. */
.home-service-planet {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: clamp(230px, 21vw, 320px);
    height: clamp(230px, 21vw, 320px);
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    text-decoration: none;
    transform: scale(1);
    transition: transform .35s ease;
}

.home-service-planet:hover,
.home-service-planet:focus-visible,
.home-service-planet.is-touch-revealed {
    transform: scale(1.08);
}

/* Rotation lente et continue au repos, sur ::before (pleine taille, rond) —
   vitesse/sens propres à chaque planète, stoppée net au survol via
   animation-play-state (sans à-coup, contrairement à une pause de
   transition). La rotation est sur ::before (pas sur le <a> lui-même) pour
   ne pas entrer en conflit avec le scale du survol : les deux animent
   "transform" mais sur 2 éléments différents. */
.home-service-planet::before {
    content: "";
    position: absolute;
    inset: -10%;
    border-radius: 50%;
    background-size: cover;
    background-position: center;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    z-index: 0;
}

.hebergement-ice-planet::before {
    background-image: url("../image/planet-blanc.webp");
    animation-name: planetSpinClockwise;
    animation-duration: 40s;
}

.accompagnement-violet-planet::before {
    background-image: url("../image/planet-violet.webp");
    animation-name: planetSpinCounterClockwise;
    animation-duration: 65s;
}

.refonte-magma-planet::before {
    background-image: url("../image/planet-rouge.webp");
    animation-name: planetSpinClockwise;
    animation-duration: 50s;
}

.programmation-green-planet::before {
    /* planet-vert.webp : même fichier que celui utilisé par programmation.php
       et bot-discord.php ailleurs sur le site (cf. ligne ~29252). L'ancien
       commentaire ici affirmait à tort que planet-blanc.webp était "la verte" —
       corrigé pour utiliser la véritable planète verte. */
    background-image: url("../image/planet-vert.webp");
    animation-name: planetSpinCounterClockwise;
    animation-duration: 75s;
}

.home-service-planet:hover::before,
.home-service-planet:focus-visible::before,
.home-service-planet.is-touch-revealed::before {
    animation-play-state: paused;
}

/* Le flou (backdrop-filter du voile ::after, cf. plus bas) devient trop
   visible/agressif une fois la planète zoomée au survol (scale 1.08) —
   désactivé pendant le hover/focus, actif seulement au repos. Idem pour
   is-touch-revealed (équivalent tactile du hover, cf. plus bas). */
.home-service-planet:hover::after,
.home-service-planet:focus-visible::after,
.home-service-planet.is-touch-revealed::after {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

/* Voile sombre + texte descriptif, posés par-dessus la planète qui tourne.
   Corrigé : le texte est centré dans le cercle, or le dégradé précédent
   était plus clair au centre et plus sombre sur les bords — exactement
   l'inverse de ce qu'il fallait pour la lisibilité. Inversé (centre sombre,
   bords plus clairs) + backdrop-filter pour un effet "verre dépoli" qui
   détache mieux le texte de la texture de la planète en dessous. */
.home-service-planet::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(0,0,0,.80) 0%, rgba(0,0,0,.40) 100%);
    backdrop-filter: blur(1.5px);
    -webkit-backdrop-filter: blur(1.5px);
    z-index: 1;
    pointer-events: none;
}

/* Texte agrandi/plus lisible + tronqué proprement (ellipsis) au-delà de 5
   lignes plutôt que de déborder ou d'être écrasé : les descriptifs
   (hm_hero_subtitle, rf_hero_sub, pg_hero_sub...) sont plus longs que ce
   qu'un cercle de cette taille peut afficher en entier confortablement.
   letter-spacing légèrement resserré + poids 600 pour un rendu plus net
   sur fond texturé. */
.home-service-planet-text {
    position: relative;
    z-index: 2;
    /* isolation + couche de composition dédiée : évite que ce flou
       "bave" de façon incontrôlée sur le reste de la carte (bug de rendu
       classique avec backdrop-filter + overflow:hidden + border-radius
       sur l'ancêtre) — le flou ci-dessous est désormais volontaire et
       entièrement piloté par ce filter, pas un effet de bord. */
    isolation: isolate;
    transform: translateZ(0);
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 5;
    overflow: hidden;
    padding: 0 26px;
    font-family: var(--font-title);
    font-size: clamp(.78rem, 1.3vw, .9rem);
    font-weight: 600;
    letter-spacing: .02em;
    line-height: 1.5;
    color: #ffffff;
    text-shadow: 0 1px 4px rgba(0,0,0,.75), 0 0 20px rgba(0,0,0,.6);
    /* Texte quasi illisible au repos (demande explicite) : ne se révèle
       nettement qu'au survol/focus de la planète, cf. règle plus bas. */
    filter: blur(5px);
    transition: filter .4s ease;
}

.home-service-planet:hover .home-service-planet-text,
.home-service-planet:focus-visible .home-service-planet-text,
.home-service-planet.is-touch-revealed .home-service-planet-text {
    filter: blur(0);
}

/* is-touch-revealed : équivalent du hover pour les écrans tactiles (pas de
   vrai survol) — posé par JS (main.js, "PLANÈTES CONTINUER LA VISITE").
   Demande explicite : sur mobile, le 1er tap doit juste dévoiler le texte
   (comme le hover desktop), le 2e tap confirme et suit le lien, plutôt que
   de naviguer directement sans jamais montrer le texte flouté. */

@keyframes planetSpinClockwise {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@keyframes planetSpinCounterClockwise {
    from { transform: rotate(360deg); }
    to   { transform: rotate(0deg); }
}

/* ─── Accent BLANC (Hébergement & maintenance) ───
   Remplace l'accent cyan d'origine sur cette carte précise (le reste des
   usages de .target-box / .wt-badge--cyan / .btn-accueil--cyan, ailleurs
   sur le site, n'est pas concerné). */
.wt-badge--white {
    color: #ffffff;
    background: rgba(255,255,255,.09);
    border: 1px solid rgba(255,255,255,.30);
    box-shadow: 0 0 12px rgba(255,255,255,.14);
}

.hebergement-box::before {
    background: linear-gradient(to right, transparent, rgba(255,255,255,.55), transparent);
}

.hebergement-box h2 {
    background: none;
    -webkit-background-clip: initial;
    background-clip: initial;
    -webkit-text-fill-color: initial;
    color: #ffffff;
}

.btn-accueil--white {
    background: rgba(255,255,255,.10);
    border: 1px solid rgba(255,255,255,.35);
    box-shadow: 0 0 24px rgba(255,255,255,.08), inset 0 1px 0 rgba(255,255,255,.07);
}
.btn-accueil--white:hover {
    background: rgba(255,255,255,.22);
    box-shadow: 0 12px 36px rgba(255,255,255,.22);
}

.home-service-box {
    max-width: 720px;
    margin: 0 auto;
}

.home-service-lead {
    margin: 0;
    color: rgba(255,255,255,.62);
    font-size: .98rem;
    line-height: 1.6;
}

.home-service-box .btn-accueil {
    margin-bottom: 0;
    margin-top: 4px;
    align-self: flex-start;
}

/* ─── 2 cards côte à côte (section Hébergement & maintenance / Accompagnement) ───
   Réutilise .why-target-grid (2 colonnes) mais neutralise le centrage en
   colonne unique de .home-service-box (max-width:720px + margin:auto)
   hérité des sections mono-carte Refonte/Programmation : ici chaque carte
   doit remplir sa colonne de grille, pas se centrer sur toute la largeur.
   align-items:stretch (au lieu du align-items:start hérité de .why-target-grid)
   pour que les 2 cards fassent la même hauteur — sinon les CTA "Découvrir..."
   ne s'alignent pas si un texte est plus long que l'autre. */
.home-service-dual-grid {
    width: 100%;
    max-width: 940px;
    margin: 0 auto;
    align-items: stretch;
}

.home-service-dual-grid .home-service-box--dual {
    max-width: none;
    margin: 0;
    height: 100%;
}

.home-service-dual-grid .home-service-box--dual .btn-accueil {
    margin-top: auto;
}

/* ─── Accent AMBRE (Refonte) ─── */
.wt-badge--amber {
    color: #f59e0b;
    background: rgba(245,158,11,.10);
    border: 1px solid rgba(245,158,11,.28);
    box-shadow: 0 0 12px rgba(245,158,11,.15);
}
.refonte-box::before {
    background: linear-gradient(to right, transparent, rgba(245,158,11,.55), transparent);
}
.refonte-box h2 {
    background: linear-gradient(100deg, #ffffff 40%, rgba(245,158,11,.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    box-shadow: 0 0 14px rgba(245,158,11,.15);
}
.refonte-box h2::before {
    color: #f59e0b;
    -webkit-text-fill-color: #f59e0b;
}
.feature-list--refonte li::before {
    content: "✓";
    color: #f59e0b;
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}
.feature-list--refonte li:hover {
    background: rgba(245,158,11,.07);
    border-color: rgba(245,158,11,.18);
    color: rgba(255,255,255,.82);
    transform: translateX(4px);
}
.btn-accueil--amber {
    background: rgba(245,158,11,.14);
    border: 1px solid rgba(245,158,11,.35);
    box-shadow: 0 0 24px rgba(245,158,11,.08), inset 0 1px 0 rgba(255,255,255,.07);
}
.btn-accueil--amber:hover {
    background: rgba(245,158,11,.24);
    box-shadow: 0 12px 36px rgba(245,158,11,.28);
}

/* ─── Accent ÉMERAUDE (Programmation) ─── */
.wt-badge--emerald {
    color: #10b981;
    background: rgba(16,185,129,.10);
    border: 1px solid rgba(16,185,129,.28);
    box-shadow: 0 0 12px rgba(16,185,129,.15);
}
.programmation-box::before {
    background: linear-gradient(to right, transparent, rgba(16,185,129,.55), transparent);
}
.programmation-box h2 {
    background: linear-gradient(100deg, #ffffff 40%, rgba(16,185,129,.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    box-shadow: 0 0 14px rgba(16,185,129,.15);
}
.programmation-box h2::before {
    color: #10b981;
    -webkit-text-fill-color: #10b981;
}
.feature-list--programmation li::before {
    content: "✓";
    color: #10b981;
    font-weight: 700;
    flex-shrink: 0;
    margin-top: 1px;
}
.feature-list--programmation li:hover {
    background: rgba(16,185,129,.07);
    border-color: rgba(16,185,129,.18);
    color: rgba(255,255,255,.82);
    transform: translateX(4px);
}
.btn-accueil--emerald {
    background: rgba(16,185,129,.14);
    border: 1px solid rgba(16,185,129,.35);
    box-shadow: 0 0 24px rgba(16,185,129,.08), inset 0 1px 0 rgba(255,255,255,.07);
}
.btn-accueil--emerald:hover {
    background: rgba(16,185,129,.24);
    box-shadow: 0 12px 36px rgba(16,185,129,.28);
}

/* ─── Accent CYAN (Hébergement & maintenance) ─── */
.btn-accueil--cyan {
    background: rgba(59,130,246,.14);
    border: 1px solid rgba(59,130,246,.35);
    box-shadow: 0 0 24px rgba(59,130,246,.08), inset 0 1px 0 rgba(255,255,255,.07);
}
.btn-accueil--cyan:hover {
    background: rgba(59,130,246,.24);
    box-shadow: 0 12px 36px rgba(59,130,246,.28);
}

/* ─── Accent VIOLET (Accompagnement) ─── */
.accompagnement-box::before {
    background: linear-gradient(to right, transparent, rgba(139,92,246,.55), transparent);
}
.accompagnement-box h2 {
    background: linear-gradient(100deg, #ffffff 40%, rgba(139,92,246,.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    box-shadow: 0 0 14px rgba(139,92,246,.15);
}
.btn-accueil--violet {
    background: rgba(139,92,246,.14);
    border: 1px solid rgba(139,92,246,.35);
    box-shadow: 0 0 24px rgba(139,92,246,.08), inset 0 1px 0 rgba(255,255,255,.07);
}
.btn-accueil--violet:hover {
    background: rgba(139,92,246,.24);
    box-shadow: 0 12px 36px rgba(139,92,246,.28);
}

/* ─── pages/refonte.php + programmation.php (réutilisent les classes .cw-*) ───
   Couleur d'accent unifiée : suit rgb(var(--header-accent)) (amber pour
   refonte.php/audit-site.php, émeraude pour programmation.php/bot-discord.php,
   cf. $_header_accent_map dans partials/header.php) au lieu d'une couleur
   écrite en dur — suit désormais aussi le choix explicite d'un client
   connecté, comme le reste du site. */
/* Dégradé toujours mélangé vers le noir (jamais la couleur d'accent pure) —
   demande explicite : "les boutons (couleur blanc) ne sont pas assez
   lisibles", le texte du bouton restant blanc quel que soit l'accent
   (notamment "Blanc"/cyan, quasi-blanc, qui rendait le texte illisible). */
.page-refonte .btn-primary,
.page-programmation .btn-primary {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 42%, #000), color-mix(in srgb, rgb(var(--header-accent)) 38%, #000));
    box-shadow: 0 4px 20px rgba(var(--header-accent),.35);
}
.page-refonte .btn-primary:hover,
.page-programmation .btn-primary:hover {
    background: linear-gradient(135deg, color-mix(in srgb, rgb(var(--accent-harmony-1)) 58%, #000), color-mix(in srgb, rgb(var(--accent-harmony-3)) 52%, #000));
    box-shadow: 0 6px 28px rgba(var(--header-accent),.50);
}
.page-refonte .cw-page-label,
.page-programmation .cw-page-label {
    color: rgba(var(--header-accent),.95);
    border-color: rgba(var(--header-accent),.38);
    background: rgba(var(--header-accent),.10);
}
.page-refonte .cw-hero h1,
.page-programmation .cw-hero h1 {
    background: linear-gradient(120deg, #fff 50%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.page-refonte .cw-section-header h2,
.page-refonte .cw-approach-inner h2,
.page-refonte .cw-when-inner h2,
.page-refonte .cw-benefits-inner h2,
.page-refonte .cw-expertise-card h2,
.page-programmation .cw-section-header h2,
.page-programmation .cw-approach-inner h2,
.page-programmation .cw-when-inner h2,
.page-programmation .cw-benefits-inner h2,
.page-programmation .cw-expertise-card h2 {
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.page-refonte .cw-impact-list li, .page-programmation .cw-impact-list li { background: rgba(var(--header-accent),.14); border-color: rgba(var(--header-accent),.32); }
.page-refonte .cw-benefits-list li, .page-programmation .cw-benefits-list li { background: rgba(var(--header-accent),.09); border-color: rgba(var(--header-accent),.16); }
.page-refonte .cw-benefits-list li::before, .page-programmation .cw-benefits-list li::before { color: rgba(var(--header-accent),.95); }
.page-refonte .cw-approach-steps li, .page-programmation .cw-approach-steps li { border-color: rgba(var(--header-accent),.18); }
.page-refonte .cw-approach-steps li:hover, .page-programmation .cw-approach-steps li:hover { border-color: rgba(var(--header-accent),.34); background: rgba(var(--header-accent),.08); }
.page-refonte .cw-step-num, .page-programmation .cw-step-num { color: rgba(var(--header-accent),.95); background: rgba(var(--header-accent),.16); border-color: rgba(var(--header-accent),.30); }
.page-refonte .cw-domain:hover, .page-programmation .cw-domain:hover { border-color: rgba(var(--header-accent),.24); box-shadow: 0 6px 20px rgba(var(--header-accent),.09); }
.page-refonte .cw-domain-body li::before, .page-programmation .cw-domain-body li::before { color: rgba(var(--header-accent),.70); }
.page-refonte .cw-when-list li, .page-programmation .cw-when-list li { background: rgba(var(--header-accent),.07); border-color: rgba(var(--header-accent),.14); }
.page-refonte .cw-when-list li:hover, .page-programmation .cw-when-list li:hover { background: rgba(var(--header-accent),.13); border-color: rgba(var(--header-accent),.24); }
.page-refonte .cw-when-list li::before, .page-programmation .cw-when-list li::before { color: rgba(var(--header-accent),.80); }
.page-refonte .cw-when-tagline, .page-programmation .cw-when-tagline { color: rgba(var(--header-accent),.88); }
.page-refonte .cw-offer-card, .page-programmation .cw-offer-card { border-color: rgba(var(--header-accent),.32); box-shadow: 0 0 40px rgba(var(--header-accent),.10); }
.page-refonte .cw-offer-left, .page-programmation .cw-offer-left { background: rgba(var(--header-accent),.10); border-right-color: rgba(var(--header-accent),.22); }
.page-refonte .cw-offer-tier, .page-programmation .cw-offer-tier { color: rgba(var(--header-accent),.95); background: rgba(var(--header-accent),.16); border-color: rgba(var(--header-accent),.34); }
.page-refonte .cw-offer-section-label, .page-programmation .cw-offer-section-label { color: rgba(var(--header-accent),.78); }
.page-refonte .cw-offer-list--ideal li, .page-programmation .cw-offer-list--ideal li { background: rgba(var(--header-accent),.09); border-color: rgba(var(--header-accent),.20); }
.page-refonte .cw-benefits-pills li, .page-programmation .cw-benefits-pills li { background: rgba(var(--header-accent),.11); border-color: rgba(var(--header-accent),.28); }
.page-refonte .cw-benefits-tagline, .page-programmation .cw-benefits-tagline { color: rgba(var(--header-accent),.88); }
.page-refonte .cw-vs-card--conseil, .page-programmation .cw-vs-card--conseil { border-color: rgba(var(--header-accent),.27); }
.page-refonte .cw-vs-card--conseil li, .page-programmation .cw-vs-card--conseil li { background: rgba(var(--header-accent),.08); border-color: rgba(var(--header-accent),.14); }
.page-refonte .cw-vs-tagline, .page-programmation .cw-vs-tagline { color: rgba(var(--header-accent),.85) !important; }
.page-refonte .cw-exp-list li, .page-programmation .cw-exp-list li { background: rgba(var(--header-accent),.10); border-color: rgba(var(--header-accent),.24); }
.page-refonte .cw-exp-tagline, .page-programmation .cw-exp-tagline { color: rgba(var(--header-accent),.88); }
.page-refonte .cw-bonus-card, .page-programmation .cw-bonus-card { background: linear-gradient(135deg, rgba(var(--header-accent),.13), rgba(var(--accent-harmony-3),.09)); border-color: rgba(var(--header-accent),.32); }
.page-refonte .cw-bonus-badge, .page-programmation .cw-bonus-badge { color: rgba(var(--header-accent),.95); background: rgba(var(--header-accent),.16); border-color: rgba(var(--header-accent),.38); }
.page-refonte .cw-bonus-list li, .page-programmation .cw-bonus-list li { background: rgba(var(--header-accent),.11); border-color: rgba(var(--header-accent),.28); }
.page-refonte .cw-bonus-tagline, .page-programmation .cw-bonus-tagline { color: rgba(var(--header-accent),.90); }
.page-programmation .cw-hosting-card h2 {
    background: linear-gradient(100deg, #fff 40%, rgba(var(--header-accent),.90) 100%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
.page-programmation .cw-hosting-list li { background: rgba(var(--header-accent),.10); border-color: rgba(var(--header-accent),.24); }
.page-programmation .cw-hosting-tagline { color: rgba(var(--header-accent),.88); }
.page-programmation .cw-hosting-link {
    background: linear-gradient(135deg, rgba(var(--accent-harmony-1),.85) 0%, rgba(var(--accent-harmony-3),.75) 100%);
    border-color: rgba(var(--accent-harmony-1),.55);
    box-shadow:
        0 0 24px rgba(var(--header-accent),.30),
        0 8px 20px rgba(var(--header-accent),.18),
        inset 0 1px 0 rgba(255,255,255,.12);
}
.page-programmation .cw-hosting-link:hover {
    background: linear-gradient(135deg, rgba(var(--accent-harmony-1),.95) 0%, rgba(var(--header-accent),.85) 100%);
    box-shadow:
        0 0 32px rgba(var(--header-accent),.45),
        0 12px 28px rgba(var(--header-accent),.28),
        inset 0 1px 0 rgba(255,255,255,.16);
}

/* ─── accueil.php : section teaser homepage (grille de 2 cartes) ─── */
.home-newservices {
    padding: 90px 24px;
    max-width: 1100px;
    margin: 0 auto;
}
.home-newservices-header {
    text-align: center;
    margin-bottom: 44px;
}
.home-newservices-header h2 {
    font-size: clamp(1.4rem, 2.5vw, 1.9rem);
    font-weight: 700;
    color: #fff;
    margin: 0 0 10px;
}
.home-newservices-header p {
    color: rgba(255,255,255,.55);
    font-size: .95rem;
    max-width: 560px;
    margin: 0 auto;
}
.home-newservices-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 24px;
}
.home-newservice-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 32px 28px;
    border-radius: 18px;
    background: rgba(255,255,255,.03);
    border: 1px solid var(--hns-border, rgba(255,255,255,.10));
    text-decoration: none;
    transition: transform .3s ease, box-shadow .3s ease, border-color .3s ease;
}
.home-newservice-card:hover {
    transform: translateY(-4px);
    border-color: var(--hns-border-hover, rgba(255,255,255,.24));
    box-shadow: 0 16px 40px rgba(0,0,0,.28), 0 0 32px var(--hns-glow, rgba(255,255,255,.08));
}
.home-newservice-card--refonte { --hns-border: rgba(245,158,11,.24); --hns-border-hover: rgba(245,158,11,.55); --hns-glow: rgba(245,158,11,.20); }
.home-newservice-card--programmation { --hns-border: rgba(16,185,129,.24); --hns-border-hover: rgba(16,185,129,.55); --hns-glow: rgba(16,185,129,.20); }
.home-newservice-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border-radius: 12px;
    background: var(--hns-glow, rgba(255,255,255,.08));
    color: var(--hns-icon-color, #fff);
    flex-shrink: 0;
}
.home-newservice-card--refonte .home-newservice-icon { --hns-icon-color: #f59e0b; }
.home-newservice-card--programmation .home-newservice-icon { --hns-icon-color: #10b981; }
.home-newservice-card h3 {
    font-size: 1.1rem;
    font-weight: 700;
    color: #fff;
    margin: 0;
}
.home-newservice-card p {
    color: rgba(255,255,255,.55);
    font-size: .88rem;
    line-height: 1.6;
    margin: 0;
}
.home-newservice-cta {
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .03em;
    color: var(--hns-icon-color, #fff);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: auto;
}
.home-newservice-card:hover .home-newservice-cta { gap: 10px; }


/* ================================================================
   BANNIÈRE DE CONSENTEMENT AUX COOKIES
   ================================================================ */
.cookie-banner {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 500;
    padding: 16px 20px;
    background: rgba(10, 14, 24, .97);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    /* demande explicite : "la bannière cookies n'est pas adaptée aux choix
       de couleur du sélecteur" — reprend la même recette que sa voisine
       .translation-banner (color-mix sur var(--brand-color)) au lieu d'un
       liseré blanc fixe. */
    border-top: 1px solid color-mix(in srgb, var(--brand-color) 55%, transparent);
    box-shadow: 0 -8px 30px rgba(0,0,0,.35);
    animation: cookieBannerIn .5s ease both;
    animation-delay: .3s;
    opacity: 0;
    transform: translateY(20px);
}
@keyframes cookieBannerIn {
    to { opacity: 1; transform: translateY(0); }
}
.cookie-banner--hidden {
    transition: opacity .35s ease, transform .35s ease;
    opacity: 0 !important;
    transform: translateY(20px) !important;
}
.cookie-banner-inner {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
}
.cookie-banner-text {
    margin: 0;
    color: rgba(255,255,255,.75);
    font-size: .88rem;
    line-height: 1.6;
    max-width: 720px;
}
.cookie-banner-text a {
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.cookie-banner-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    flex-shrink: 0;
}
@media (max-width: 640px) {
    .cookie-banner-inner { flex-direction: column; align-items: stretch; }
    .cookie-banner-actions { justify-content: stretch; }
    .cookie-banner-actions .btn-account { flex: 1; justify-content: center; }
}


/* ================================================================
   BANNIÈRE D'INFORMATION — TRADUCTIONS EN COURS DE VÉRIFICATION
   (visiteurs EN/DE uniquement, cf. partials/translation_banner.php)
   Volontairement plus "douce" que la bannière cookies (fond moins
   opaque, pas de blur, liseré fin à la teinte de marque en haut plutôt
   qu'une bordure pleine) : simple information, pas une demande de
   consentement. z-index légèrement inférieur à .cookie-banner pour
   qu'elle s'efface derrière elle si jamais les deux se chevauchaient
   avant que le calage JS (syncBannerStack, cf. main.js) ne s'applique.
   ================================================================ */
.translation-banner {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 490;
    padding: 14px 20px;
    background: rgba(10, 14, 24, .90);
    border-top: 2px solid color-mix(in srgb, var(--brand-color) 55%, transparent);
    box-shadow: 0 -6px 22px rgba(0,0,0,.28);
    animation: cookieBannerIn .5s ease both;
    opacity: 0;
    transform: translateY(20px);
    transition: bottom .35s ease;
}
.translation-banner--hidden {
    transition: opacity .35s ease, transform .35s ease;
    opacity: 0 !important;
    transform: translateY(20px) !important;
}
.translation-banner-inner {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
}
.translation-banner-text {
    margin: 0;
    color: rgba(255,255,255,.7);
    font-size: .86rem;
    line-height: 1.6;
    max-width: 720px;
}
.translation-banner-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-shrink: 0;
}
.translation-banner-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    background: transparent;
    border: 1px solid rgba(255,255,255,.16);
    border-radius: 50%;
    color: rgba(255,255,255,.55);
    cursor: pointer;
    transition: background .2s ease, border-color .2s ease, color .2s ease;
}
.translation-banner-close svg { width: 14px; height: 14px; }
.translation-banner-close:hover,
.translation-banner-close:focus-visible {
    background: rgba(255,255,255,.06);
    border-color: rgba(255,255,255,.32);
    color: #fff;
}
@media (max-width: 640px) {
    .translation-banner-inner { flex-direction: column; align-items: stretch; }
    .translation-banner-actions { justify-content: space-between; }
}

