/* =============================================================================
   Qui Veut Rafraîchir Sa Ville : moteur de récit cartographique (scrollytelling)
   Feuille commune à la page d'accueil et aux études de cas.

   Principe de mise en page : une scène collante (position: sticky) dans un
   conteneur très haut. La carte reste à l'écran pendant que la page défile,
   sans jamais recourir à position: fixed, qui se bat avec la barre d'outils
   mobile de Safari et déborde des sections voisines.

   Les couleurs viennent de css/style.css (jetons de marque). Cette feuille
   n'invente aucune couleur : elle réutilise --bleu, --vert, --bleu-profond.

   Sommaire
     01. Scène collante et carte
     02. Habillage cinéma (vignette, grain)
     03. Légende (badge, titre, texte)
     04. Grand chiffre
     05. Jauge de progression et actes
     06. Thermomètre
     07. Compteurs vivants
     08. Cartes latérales : photo, plan
     09. Invite à défiler
     10. Repli sans animation (prefers-reduced-motion) et sans JavaScript
     11. Responsive
   ========================================================================== */

/* == 01. SCÈNE ============================================================= */

.qs-story {
	position: relative;
	/* la hauteur réelle est posée en ligne par le moteur (nb d'étapes) */
	background: var(--bleu-nuit, #0A1830);
}

.qs-stage {
	position: sticky;
	top: 0;
	height: 100vh;
	height: 100svh;
	overflow: hidden;
	background: var(--bleu-nuit, #0A1830);
	isolation: isolate;
}

/* Sélecteur volontairement plus précis que `.qs-map` seul, et dimensions
   écrites en toutes lettres.

   Raison : la feuille de Mapbox est injectée dans <head> au moment où le récit
   démarre, donc APRÈS celle-ci. Sa règle `.mapboxgl-map { position: relative }`
   a la même précision que `.qs-map` et gagne donc par ordre d'apparition. Le
   conteneur repassait en flux normal, `inset: 0` ne s'appliquait plus, et la
   carte se retrouvait haute de zéro pixel : plus rien à l'écran, sans la
   moindre erreur en console. */
.qs-stage .qs-map {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	opacity: 0;
	transition: opacity 900ms ease;
}
.qs-stage .qs-map.est-prete { opacity: 1; }

/* Mapbox pose ses propres commandes : le récit n'en veut aucune. */
.qs-stage .mapboxgl-ctrl-bottom-left,
.qs-stage .mapboxgl-ctrl-bottom-right,
.qs-stage .mapboxgl-ctrl-top-left,
.qs-stage .mapboxgl-ctrl-top-right { display: none !important; }
.qs-stage .mapboxgl-canvas { outline: none; }

/* Image de repli : affichée tant que la carte n'a pas chargé, et à sa place
   quand l'utilisateur a demandé moins d'animations. */
.qs-poster {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* L'image de repli n'est qu'un fond d'attente : très assombrie et
	   désaturée, elle ne se lit pas comme une photo du site, et la carte qui
	   arrive par-dessus ne crée pas de rupture visuelle. */
	filter: saturate(0.35) brightness(0.42) blur(2px);
	transform: scale(1.04);
}

.qs-fx {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
	opacity: 0;
	transition: opacity 600ms ease;
	z-index: 2;
}
.qs-fx.est-actif { opacity: 1; }

/* == 02. HABILLAGE CINÉMA ================================================== */

.qs-vignette {
	position: absolute;
	inset: 0;
	pointer-events: none;
	z-index: 3;
	box-shadow: inset 0 0 140px 36px rgba(4, 14, 30, 0.42);
	background:
		linear-gradient(to top, rgba(6, 18, 38, 0.78) 0%,
		                        rgba(6, 18, 38, 0.42) 24%,
		                        rgba(6, 18, 38, 0.06) 48%,
		                        transparent 62%),
		linear-gradient(to bottom, rgba(6, 18, 38, 0.44) 0%,
		                           transparent 22%);
}

/* == 03. LÉGENDE =========================================================== */

.qs-legende {
	position: absolute;
	inset: auto 0 0 0;
	z-index: 6;
	padding: 0 clamp(1.25rem, 5vw, 4.5rem) clamp(2.5rem, 8vh, 6rem);
	pointer-events: none;
	opacity: 0;
	transition: opacity 420ms ease;
}
.qs-legende.est-actif { opacity: 1; }

.qs-legende-boite { max-width: 46rem; }

.qs-badge {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.6875rem;
	font-weight: 800;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: #fff;
	background: rgba(255, 255, 255, 0.13);
	border: 1px solid rgba(255, 255, 255, 0.26);
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
	padding: 0.4rem 0.9rem;
	border-radius: 999px;
	margin-bottom: 0.85rem;
	transform: translateY(12px);
	opacity: 0;
	transition: transform 520ms cubic-bezier(0.22, 1, 0.36, 1),
	            opacity 400ms ease;
}
.qs-badge::before {
	content: '';
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--vert, #62D652);
	box-shadow: 0 0 10px var(--vert, #62D652);
	flex: none;
}

.qs-titre {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: clamp(1.6rem, 4.6vw, 3.35rem);
	font-weight: 800;
	line-height: 1.08;
	letter-spacing: -0.025em;
	color: #fff;
	margin: 0;
	text-wrap: balance;
	text-shadow: 0 2px 34px rgba(4, 14, 30, 0.6), 0 1px 3px rgba(4, 14, 30, 0.5);
	transform: translateY(20px);
	opacity: 0;
	transition: transform 620ms cubic-bezier(0.22, 1, 0.36, 1) 60ms,
	            opacity 480ms ease 60ms;
}
.qs-titre em {
	font-style: normal;
	color: var(--vert, #62D652);
}

.qs-texte {
	font-size: clamp(0.9375rem, 1.5vw, 1.125rem);
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.87);
	max-width: 34rem;
	margin: 0.7rem 0 0;
	text-wrap: pretty;
	text-shadow: 0 1px 12px rgba(4, 14, 30, 0.55);
	transform: translateY(16px);
	opacity: 0;
	transition: transform 620ms cubic-bezier(0.22, 1, 0.36, 1) 140ms,
	            opacity 480ms ease 140ms;
}

.qs-legende.est-actif .qs-badge,
.qs-legende.est-actif .qs-titre,
.qs-legende.est-actif .qs-texte {
	transform: translateY(0);
	opacity: 1;
}

/* Source affichée sous le texte : rien n'est avancé sans dire d'où ça vient. */
.qs-source {
	display: block;
	margin-top: 0.55rem;
	font-size: 0.75rem;
	line-height: 1.45;
	color: rgba(255, 255, 255, 0.6);
	max-width: 34rem;
	text-shadow: 0 1px 8px rgba(4, 14, 30, 0.5);
}

/* == 04. GRAND CHIFFRE ===================================================== */

.qs-chiffre {
	position: absolute;
	top: 34%;
	left: 50%;
	z-index: 5;
	transform: translate(-50%, -50%) scale(0.72);
	text-align: center;
	pointer-events: none;
	opacity: 0;
	transition: opacity 460ms ease,
	            transform 720ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.qs-chiffre.est-actif { opacity: 1; transform: translate(-50%, -50%) scale(1); }

.qs-chiffre-v {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: clamp(3.2rem, 13vw, 8.5rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.04em;
	color: #fff;
	text-shadow: 0 6px 70px rgba(4, 14, 30, 0.55);
	font-variant-numeric: tabular-nums;
}
.qs-chiffre-l {
	display: block;
	margin-top: 0.5rem;
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: clamp(0.6875rem, 1.5vw, 0.875rem);
	font-weight: 700;
	letter-spacing: 0.11em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.68);
	text-shadow: 0 1px 10px rgba(4, 14, 30, 0.5);
}

/* == 05. PROGRESSION ======================================================= */

.qs-progression {
	position: absolute;
	top: clamp(0.85rem, 2.5vh, 1.6rem);
	left: 50%;
	transform: translateX(-50%);
	z-index: 7;
	display: flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.4rem 0.9rem;
	border-radius: 999px;
	background: rgba(10, 24, 48, 0.55);
	border: 1px solid rgba(255, 255, 255, 0.16);
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
	pointer-events: none;
	opacity: 0;
	transition: opacity 460ms ease;
	white-space: nowrap;
}
.qs-progression.est-actif { opacity: 1; }

.qs-progression-n {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.75rem;
	font-weight: 800;
	color: #fff;
	font-variant-numeric: tabular-nums;
}
.qs-progression-n small { opacity: 0.5; font-weight: 600; }

.qs-rail {
	position: relative;
	width: clamp(72px, 22vw, 148px);
	height: 4px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.2);
	overflow: hidden;
}
.qs-rail-jauge {
	position: absolute;
	inset: 0 auto 0 0;
	width: 0;
	border-radius: 999px;
	background: linear-gradient(90deg,
		var(--orange, #E95722) 0%,
		var(--bleu, #377EED) 45%,
		var(--vert, #62D652) 100%);
	transition: width 140ms linear;
}

.qs-acte {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.625rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.66);
}

/* == 06. THERMOMÈTRE ======================================================= */

.qs-temp {
	position: absolute;
	top: 50%;
	right: clamp(0.6rem, 2vw, 1.6rem);
	z-index: 6;
	transform: translateY(-50%) translateX(14px);
	min-width: 6rem;
	padding: 0.65rem 0.8rem;
	border-radius: 14px;
	text-align: center;
	background: rgba(10, 24, 48, 0.55);
	border: 1px solid rgba(255, 255, 255, 0.16);
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
	pointer-events: none;
	opacity: 0;
	transition: opacity 460ms ease,
	            transform 560ms cubic-bezier(0.22, 1, 0.36, 1);
}
.qs-temp.est-actif { opacity: 1; transform: translateY(-50%) translateX(0); }

.qs-temp-l {
	font-size: 0.5rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.6);
	margin-bottom: 0.2rem;
}
.qs-temp-v {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 1.75rem;
	font-weight: 800;
	line-height: 1;
	color: #fff;
	font-variant-numeric: tabular-nums;
	transition: color 400ms ease;
}
.qs-temp-v small { font-size: 0.5em; font-weight: 700; opacity: 0.75; }
.qs-temp-rail {
	height: 4px;
	border-radius: 999px;
	margin: 0.4rem 0 0.3rem;
	background: rgba(255, 255, 255, 0.2);
	overflow: hidden;
}
.qs-temp-jauge {
	height: 100%;
	border-radius: 999px;
	background: linear-gradient(90deg, var(--vert, #62D652), #E9A722, var(--orange, #E95722));
	transition: width 220ms ease;
}
.qs-temp-d {
	font-size: 0.5625rem;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.62);
}

/* == 07. COMPTEURS ========================================================= */

.qs-compteurs {
	position: absolute;
	right: clamp(0.6rem, 2vw, 1.6rem);
	bottom: clamp(7rem, 16vh, 9rem);
	z-index: 6;
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
	pointer-events: none;
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 560ms ease, transform 560ms cubic-bezier(0.22, 1, 0.36, 1);
}
.qs-compteurs.est-actif { opacity: 1; transform: translateY(0); }

.qs-compteur {
	min-width: 10.5rem;
	padding: 0.45rem 0.75rem;
	border-radius: 12px;
	background: rgba(10, 24, 48, 0.55);
	border: 1px solid rgba(255, 255, 255, 0.16);
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
}
.qs-compteur-v {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 1.0625rem;
	font-weight: 800;
	line-height: 1.05;
	color: #fff;
	font-variant-numeric: tabular-nums;
}
.qs-compteur-v small { font-size: 0.58em; font-weight: 700; opacity: 0.8; margin-left: 0.15em; }
.qs-compteur-l {
	font-size: 0.5rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.62);
	margin-top: 0.1rem;
}

/* == 08. CARTES LATÉRALES ================================================== */

.qs-photo {
	position: absolute;
	top: 50%;
	right: clamp(0.6rem, 2.5vw, 2rem);
	z-index: 7;
	width: clamp(9rem, 20vw, 16rem);
	transform: translateY(-50%) translateX(28px) scale(0.94);
	pointer-events: none;
	opacity: 0;
	transition: opacity 520ms ease,
	            transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
.qs-photo.est-actif { opacity: 1; transform: translateY(-50%) translateX(0) scale(1); }

.qs-carte {
	border-radius: 16px;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.96);
	box-shadow: 0 18px 56px rgba(4, 14, 30, 0.34);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
}
.qs-carte-media { position: relative; }
.qs-carte-media img { width: 100%; display: block; }
.qs-carte-etiquette {
	position: absolute;
	top: 0.5rem;
	left: 0.5rem;
	z-index: 2;
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.5rem;
	font-weight: 800;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: #fff;
	background: var(--bleu-profond, #0F56A5);
	padding: 0.22rem 0.6rem;
	border-radius: 999px;
}
.qs-carte-corps { padding: 0.55rem 0.75rem 0.65rem; }
.qs-carte-sur {
	font-size: 0.5rem;
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--bleu-lien, #0B4C93);
}
.qs-carte-t {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.8125rem;
	font-weight: 700;
	line-height: 1.28;
	color: var(--encre, #0E1B2E);
	margin-top: 0.1rem;
}
.qs-carte-s {
	font-size: 0.625rem;
	line-height: 1.4;
	color: var(--encre-douce, #4A5B70);
	margin-top: 0.15rem;
}
.qs-carte-stats {
	display: flex;
	border-top: 1px solid var(--trait, #DFE7F0);
}
.qs-carte-stats div { flex: 1; text-align: center; padding: 0.3rem 0.2rem; }
.qs-carte-stats .v {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.8125rem;
	font-weight: 800;
	color: var(--bleu-lien, #0B4C93);
}
.qs-carte-stats .l {
	font-size: 0.4375rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--encre-tres-douce, #7C8BA0);
}

/* Plan d'implantation, en vis-à-vis de la photo */
.qs-plan {
	position: absolute;
	top: clamp(3.5rem, 9vh, 5.5rem);
	left: clamp(0.6rem, 2.5vw, 2rem);
	z-index: 7;
	width: clamp(8.5rem, 22vw, 19rem);
	pointer-events: none;
	opacity: 0;
	transform: translateX(-22px) scale(0.95);
	transition: opacity 520ms ease,
	            transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}
.qs-plan.est-actif { opacity: 1; transform: translateX(0) scale(1); }

/* == 09. INVITE À DÉFILER ================================================== */

.qs-invite {
	position: absolute;
	left: 50%;
	bottom: clamp(1rem, 4vh, 2.2rem);
	z-index: 6;
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.3rem;
	pointer-events: none;
	opacity: 0;
	transition: opacity 620ms ease;
}
.qs-invite.est-actif { opacity: 0.82; }
.qs-invite span {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.5625rem;
	font-weight: 700;
	letter-spacing: 0.17em;
	text-transform: uppercase;
	color: #fff;
	text-shadow: 0 1px 8px rgba(4, 14, 30, 0.55);
}
.qs-invite svg {
	filter: drop-shadow(0 2px 8px rgba(4, 14, 30, 0.45));
	animation: qs-plonge 1.9s ease-in-out infinite;
}
@keyframes qs-plonge {
	0%, 100% { transform: translateY(0); }
	50%      { transform: translateY(7px); }
}

/* == 10. REPLIS ============================================================ */

/* Le moteur masque l'en-tête et le rappel d'action collant pendant le récit :
   rien ne doit passer devant la carte. */
body.qvrsv-in-story .entete,
body.qvrsv-in-story .qvrsv-header,
body.qvrsv-in-story .rappel-collant,
body.qvrsv-in-story .qvrsv-sticky-cta {
	opacity: 0;
	transform: translateY(-100%);
	pointer-events: none;
}
body.qvrsv-in-story .rappel-collant,
body.qvrsv-in-story .qvrsv-sticky-cta {
	transform: translateY(100%);
}
.entete, .qvrsv-header { transition: opacity 480ms ease, transform 480ms ease; }

/* Sans JavaScript, le récit se lit comme une suite de sections classiques :
   le contenu reste intégralement accessible et indexable. */
.qs-repli { display: block; }
.qs-story .qs-repli-etape {
	max-width: 44rem;
	margin: 0 auto;
	padding: clamp(2.5rem, 7vw, 4.5rem) clamp(1.25rem, 5vw, 2rem);
	color: #fff;
	border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.qs-repli-etape:last-child { border-bottom: 0; }
.qs-repli-etape h3 {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: clamp(1.25rem, 3.2vw, 1.9rem);
	font-weight: 800;
	line-height: 1.15;
	color: #fff;
	margin: 0.4rem 0 0.5rem;
}
.qs-repli-etape p { color: rgba(255, 255, 255, 0.85); margin: 0; }
.qs-repli-etape img {
	width: 100%;
	height: auto;
	border-radius: 14px;
	margin-top: 1.1rem;
}
.qs-repli-num {
	font-family: var(--titre, 'Montserrat', sans-serif);
	font-size: 0.6875rem;
	font-weight: 800;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--vert, #62D652);
}

/* Quand le moteur prend la main, le repli disparaît. */
.qs-story.est-anime .qs-repli { display: none; }

/* Moins d'animations demandées : on garde le récit lisible, sans carte animée,
   sans effets de particules, sans caméra qui bouge. */
@media (prefers-reduced-motion: reduce) {
	.qs-story.est-anime .qs-repli { display: block; }
	.qs-story .qs-stage { display: none; }
	.qs-story { height: auto !important; }
	* { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
	.qs-badge, .qs-titre, .qs-texte, .qs-chiffre, .qs-temp, .qs-compteurs,
	.qs-photo, .qs-plan { transition: none; transform: none; opacity: 1; }
}

/* == 11. RESPONSIVE ======================================================== */

/* Sur un téléphone, l'écran se lit en trois bandes horizontales et non en
   coins : un bandeau d'indicateurs en haut, la carte au milieu, la légende en
   bas. Les compteurs empilés en bas à droite du bureau venaient sinon se poser
   exactement sur le titre et le texte de l'étape. */
@media (max-width: 900px) {
	/* --- bande haute : progression, compteurs, thermomètre --- */
	.qs-compteurs {
		flex-direction: row;
		top: 3.1rem;
		bottom: auto;
		left: 0.6rem;
		right: 0.6rem;
		gap: 0.3rem;
		transform: translateY(-12px);
	}
	.qs-compteurs.est-actif { transform: translateY(0); }
	.qs-compteur {
		flex: 1 1 0;
		min-width: 0;
		text-align: center;
		padding: 0.3rem 0.25rem;
		border-radius: 10px;
	}
	.qs-compteur-v { font-size: 0.9375rem; }
	.qs-compteur-v small { font-size: 0.55em; margin-left: 0.1em; }
	.qs-compteur-l {
		font-size: 0.4375rem;
		letter-spacing: 0.04em;
		line-height: 1.25;
		margin-top: 0.05rem;
	}

	.qs-temp {
		top: 7.2rem;
		right: 0.6rem;
		min-width: 4.5rem;
		padding: 0.45rem 0.5rem;
		transform: translateY(0) translateX(14px);
	}
	.qs-temp.est-actif { transform: translateY(0) translateX(0); }
	.qs-temp-v { font-size: 1.3125rem; }
	.qs-temp-d { display: none; }

	/* --- bande médiane : le grand chiffre, la photo, le plan --- */
	.qs-chiffre { top: 31%; }
	.qs-chiffre-l { max-width: 15rem; margin-inline: auto; }

	.qs-photo {
		top: 45%;
		bottom: auto;
		right: 0.6rem;
		width: clamp(7rem, 32vw, 9.5rem);
		transform: translateY(0) translateX(24px) scale(0.94);
		transform-origin: top right;
	}
	.qs-photo.est-actif { transform: translateY(0) translateX(0) scale(1); }
	.qs-plan {
		top: 45%;
		bottom: auto;
		left: 0.6rem;
		width: clamp(6.5rem, 30vw, 9rem);
	}
	.qs-carte-s, .qs-carte-stats { display: none; }

	/* --- bande basse : la légende, seule --- */
	.qs-legende { padding-bottom: clamp(3rem, 11vh, 5rem); }
	.qs-source { font-size: 0.6875rem; }
}

/* Très petits écrans : le plan et la photo mangeraient la carte, on les retire
   et on garde le récit (carte, chiffre, légende). */
@media (max-width: 380px) {
	.qs-photo, .qs-plan { display: none; }
}

/* Écrans très courts (téléphone en paysage) : on allège pour ne pas empiler. */
@media (max-height: 520px) {
	.qs-chiffre, .qs-photo, .qs-plan, .qs-compteurs { display: none; }
	.qs-legende { padding-bottom: 1.5rem; }
}
