/* =========================================================================
   3Event — page d'accueil
   Valeurs calées sur la maquette Figma « LP 3Event / VALIDÉE — PAGE ACCUEIL »
   (fichier iysRiEh29eak8SR2njxmkB, frame 347:370, cadre 1440 → contenu 1280).
   ========================================================================= */

:root {
	--tev-blue:      #3B55C7;
	--tev-orange:    #FF5527;
	--tev-cream:     #FBFBFB;
	--tev-white:     #FFFFFF;
	--tev-grey:      #61646E;
	--tev-tint:      rgba(59, 85, 199, .08);   /* fonds « bleu clair » de la maquette */
	--tev-tint-line: rgba(255, 85, 39, .32);

	--tev-container: 1280px;
	--tev-gutter:    80px;
	--tev-slant:     36px;                     /* dénivelé des bandes obliques */
	--tev-radius:    30px;
	--tev-radius-img:20px;

	--tev-font-title: 'Archivo Black', 'Archivo', system-ui, sans-serif;
	--tev-font-body:  'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
	--tev-font-form:  'Archivo', system-ui, sans-serif;

	--tev-ease: cubic-bezier(.22, .61, .36, 1);
}

/* --- reset minimal ------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html {
	-webkit-text-size-adjust: 100%;
	/* Pas de `scroll-behavior: smooth` : un saut d'ancre traverse ici jusqu'à
	   9 600 px de sections animées au défilement et de blocs épinglés, ce qui
	   donne un défilement interminable et illisible. Le saut est immédiat, la
	   réserve sous l'en-tête fixé est donnée par scroll-padding-top. */
	/* La barre est fixée : les ancres doivent s'arrêter sous elle. */
	scroll-padding-top: 110px;
}
body {
	margin: 0;
	background: var(--tev-white);
	color: var(--tev-blue);
	font-family: var(--tev-font-body);
	font-size: 16px;
	line-height: 1.4;
	overflow-x: clip;
}
img, svg, video { max-width: 100%; display: block; }
img, video { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, p, blockquote, figure { margin: 0; }
:focus-visible { outline: 3px solid var(--tev-orange); outline-offset: 3px; }

/* Petit titre SEO posé au-dessus d'une accroche (tev_petit_titre()). Même
   vocabulaire que le sur-titre des pages de référencement : petit, capitales,
   orange. Il ne remplace jamais l'accroche, il la précède. */
.tev-petit-titre {
	display: block; margin: 0 0 14px;
	font-family: var(--tev-font-form);
	font-size: 13px; line-height: 18px; font-weight: 700;
	letter-spacing: .12em; text-transform: uppercase;
	color: var(--tev-orange);
}
/* Le petit titre suit l'alignement de l'accroche qu'il précède. */
.tev-offres__petit-titre, .tev-reas__petit-titre, .tev-equipe__petit-titre { text-align: center; }

/* Accroches passées de <h2> en <div> le 30/09/2026 : leur classe ne fixait pas la
   graisse, elles tenaient leur gras de la balise. On le rend explicite, sans quoi
   elles s'affichent plus maigres (mesuré : 700 → 400). */
.tev-stats__title, .tev-equipe__title { font-weight: 700; }

.screen-reader-text {
	position: absolute !important; width: 1px; height: 1px; overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px); clip-path: inset(50%); white-space: nowrap;
}
.tev-skip {
	position: absolute; left: -9999px; top: 0; z-index: 200;
	background: var(--tev-orange); color: #fff; padding: 12px 20px; border-radius: 0 0 12px 0;
}
.tev-skip:focus { left: 0; }

.container {
	width: 100%;
	max-width: calc(var(--tev-container) + var(--tev-gutter) * 2);
	margin-inline: auto;
	padding-inline: var(--tev-gutter);
}

/* --- grain des aplats de couleur ---------------------------------------- */
/* ⚠️ Dans la maquette, AUCUN aplat de couleur n'est une couleur plate : les
   neuf grands aplats bleus et la bande orange portent tous l'effet `NOISE` de
   Figma. C'est ce que Lisa appelle « un pattern en fond » (16/09/2026).
   Deux erreurs corrigées ici :
   – le grain n'était posé que sur une partie des surfaces ;
   – il était RECONSTITUÉ (bruit gris en `mix-blend-mode: overlay`) au lieu
     d'être repris de la maquette. Un voile gris fait varier les trois canaux
     à parts égales ; le grain de Figma n'ÉCLAIRCIT que — mesuré sur un aplat
     exporté, l'écart-type vaut 2,25 dans le rouge pour 0,58 dans le bleu.
   `img/grain-maquette.png` est le VRAI pattern, extrait pixel par pixel d'un
   aplat #3B55C7 exporté de Figma (nœud 347:1027) : la tuile porte du blanc
   dont l'alpha est exactement l'écart mesuré entre chaque pixel bruité et la
   couleur de fond — 11,9 % des pixels touchés, alpha maximal 7,7 %. Aucune
   valeur n'est inventée, et l'opacité vaut donc 1 : l'intensité est déjà
   celle de la maquette. Recomposée sur le bleu, la tuile rend un écart-type
   de 2,38 / 2,06 / 0,68 contre 2,25 / 1,95 / 0,58 sur la maquette.
   Le grain est discret par construction : il se voit sur un aplat, pas sur une
   capture compressée. Ne pas « le monter un peu » — ce serait le réinventer.
   Une seule règle pour toutes les surfaces : avant, six copies de ce bloc
   traînaient dans le fichier avec trois opacités différentes.
   🛑 **La liste ci-dessous est celle de la maquette, PAS une extrapolation.**
   Figma pose l'effet `NOISE` sur neuf calques et neuf seulement : les grandes
   bandes pleine largeur (bannière, animations, réalisations, étapes, avis,
   contact, pied de page) et la carte d'offre bleue. Rien d'autre.
   - L'EN-TÊTE n'en fait pas partie : en maquette il est transparent au-dessus
     de la bannière, et c'est le grain de la bannière qu'on voit à travers. Le
     fond bleu qu'il prend au défilement n'existe pas en maquette. Y ajouter le
     grain « par cohérence » l'a visiblement changé (Lisa, 16/09/2026) — et le
     posait par-dessus le logo et la navigation. Retiré.
   - Les CARTES DE RÉALISATIONS non plus : elles se posent sur une bande qui,
     elle, porte le grain. Retirées pour la même raison.
   ⚠️ Les sections « bleu clair » (offres, réalisations, galerie, avis, soit
   `--tev-tint`) n'en reçoivent pas davantage : en maquette ce sont les mêmes
   aplats bleus bruités, mais portés à 8 % d'opacité — le grain y est douze fois
   plus faible, invisible. Le poser à pleine force les rendrait plus granuleuses
   que la maquette.
   Bref : si une surface n'est pas dans la liste des neuf, elle n'a pas de
   grain. Ne pas en rajouter « pour faire pareil ». */
.tev-grain::after,
.tev-hero__bg::after,
.tev-hero__band::after,
.tev-offre--blue::after,
.tev-anims::after,
.tev-etapes::before,
.tev-contact::after,
.tev-footer::after {
	content: ""; position: absolute; inset: 0; pointer-events: none;
	background-image: url(../img/grain-maquette.png);
	background-size: 400px 400px;
	border-radius: inherit;
}

/* --- typographie -------------------------------------------------------- */
.tev-h1, .tev-hero__title {
	font-family: var(--tev-font-title);
	font-size: 36px; line-height: 39px; text-transform: uppercase; font-weight: 400;
}
.tev-h2,
.tev-offres__title, .tev-anims__title, .tev-reas__title, .tev-avis__title, .tev-contact__title {
	font-family: var(--tev-font-title);
	font-size: 26px; line-height: 34px; text-transform: uppercase; font-weight: 400;
}

/* --- boutons ------------------------------------------------------------ */
.tev-btn {
	display: inline-flex; align-items: center; gap: 16px;
	padding: 13.5px 20px; border-radius: var(--tev-radius);
	font-family: var(--tev-font-body); font-weight: 700; font-size: 14px; line-height: 17px;
	text-transform: uppercase; letter-spacing: .01em;
	/* ⚠️ Le contour n'est PAS uniforme : la maquette épaissit le bord du BAS.
	   Relevé sur le composant `button-primary-fond-bleu` du design system —
	   `individualStrokeWeights` : haut 1,5 / droite 1 / bas 4 / gauche 1. C'est
	   ce léger relief qui manquait (retour de Lisa, 17/09/2026). Vaut pour TOUS
	   les boutons de la page, pas seulement celui sous la bannière : les neuf
	   instances de la maquette portent la même valeur. */
	border-style: solid; border-color: transparent;
	border-width: 1.5px 1px 4px;
	transition: background-color .3s var(--tev-ease), color .3s var(--tev-ease),
	            border-color .3s var(--tev-ease), transform .3s var(--tev-ease);
	will-change: transform;
}
.tev-btn:hover { transform: translateY(-2px); }
.tev-btn__icon { width: 16px; height: 14px; flex: 0 0 auto; transition: transform .3s var(--tev-ease); }
.tev-btn__icon--arrow-down { transform: rotate(90deg); }
.tev-btn:hover .tev-btn__icon--arrow-right { transform: translateX(4px); }
.tev-btn:hover .tev-btn__icon--arrow-down { transform: rotate(90deg) translateX(4px); }

.tev-btn--light  { background: var(--tev-cream); color: var(--tev-blue); border-color: var(--tev-blue); }
.tev-btn--light:hover { background: var(--tev-blue); color: var(--tev-cream); }
.tev-btn--blue   { background: var(--tev-blue); color: var(--tev-cream); border-color: var(--tev-cream); }
.tev-btn--blue:hover { background: var(--tev-cream); color: var(--tev-blue); border-color: var(--tev-blue); }
.tev-btn--orange { background: var(--tev-orange); color: var(--tev-cream); border-color: var(--tev-cream); }
.tev-btn--orange:hover { background: var(--tev-cream); color: var(--tev-orange); border-color: var(--tev-orange); }
.tev-btn--wide   { width: 100%; justify-content: center; }

/* Dans les colonnes de texte, seuls les boutons, pastilles et pictogrammes
   gardent leur largeur propre. */
.tev-offre__text > .tev-btn,
.tev-anim__body > .tev-btn,
.tev-rea__text > .tev-btn,
.tev-anim__picto,
.tev-rea__quote,
.tev-offre__text > .tev-pills,
.tev-anim__body > .tev-pills,
.tev-rea__text > .tev-pills { align-self: flex-start; }

/* pastilles de qualification */
.tev-pills { display: flex; flex-wrap: wrap; gap: 9px; }
.tev-pill {
	display: inline-flex; align-items: center; gap: 4px;
	padding: 6px 10px; border-radius: var(--tev-radius);
	background: var(--tev-blue); border: 1px solid rgba(251, 251, 251, .8);
	color: var(--tev-cream); font-size: 13px; line-height: 16px; font-weight: 600;
}
.tev-pills--ghost .tev-pill { background: transparent; }
.tev-pill--outline { background: transparent; border-color: rgba(251, 251, 251, .8); }

/* flèches de carrousel */
.tev-arrow {
	flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%;
	display: inline-flex; align-items: center; justify-content: center;
	transition: background-color .3s var(--tev-ease), color .3s var(--tev-ease), transform .3s var(--tev-ease);
}
.tev-arrow svg { width: 16px; height: 14px; }
.tev-arrow--light { background: var(--tev-cream); border: 1px solid var(--tev-orange); color: var(--tev-orange); }
.tev-arrow--solid { background: var(--tev-orange); color: var(--tev-cream); }
.tev-arrow--light svg { transform: rotate(180deg); }
.tev-arrow:hover { transform: scale(1.08); }
.tev-arrow--light:hover { background: var(--tev-orange); color: var(--tev-cream); }
.tev-arrow--solid:hover { background: var(--tev-blue); }
.tev-arrow[disabled] { opacity: .4; cursor: not-allowed; transform: none; }

/* =========================================================================
   En-tête
   ========================================================================= */
.tev-header {
	/* --tev-bar-offset : hauteur d'un bandeau fixé posé au-dessus du site
	   (bandeau de préproduction). Vaut 0 en production. */
	position: fixed; inset: var(--tev-bar-offset, 0px) 0 auto; z-index: 60;
	padding-block: 23px;
	color: var(--tev-cream);
	transition: background-color .3s var(--tev-ease), padding-block .3s var(--tev-ease),
	            box-shadow .3s var(--tev-ease);
}
/* Au repos la barre est transparente sur la bannière ; dès qu'on défile elle
   prend le fond bleu, sans quoi le texte crème disparaît sur les sections
   claires (offres, avis). */
.tev-header.is-stuck {
	background: var(--tev-blue);
	padding-block: 12px;
	box-shadow: 0 10px 30px rgba(15, 20, 60, .18);
}
/* Menu mobile ouvert : la barre prend le même bleu que le panneau, sinon la
   bannière transparaît derrière le logo et coupe le panneau en deux. */
.tev-header.is-open { background: var(--tev-blue); }
.tev-header__inner {
	width: 100%; max-width: calc(var(--tev-container) + var(--tev-gutter) * 2);
	margin-inline: auto; padding-inline: var(--tev-gutter);
	/* ⚠️ Alignement par le CENTRE, pas par le bas. Relevé sur la maquette
	   validée (frame 347:370) : logo 33→82 (centre 57,5), bouton 36→80
	   (centre 58), navigation 50→67 (centre 58,5), téléphone 50→66 (centre 58).
	   Tout est donc centré sur la même ligne à un pixel près.
	   L'alignement par le bas venait d'une version où le CTA n'était qu'un
	   libellé : le bloc de droite faisait alors 17 px de haut, et coller les
	   bas revenait au même. Depuis que ce CTA est un bouton de 44 px, coller
	   les bas faisait descendre la navigation de ~14 px sous le téléphone
	   (signalé par Lisa, 16/09/2026). */
	display: flex; align-items: center;
}
.tev-logo { position: relative; display: block; width: 121px; height: 49px; flex: 0 0 auto; }
/* L'opacité de 25 % est déjà portée par le tracé exporté de Figma : la
   reposer ici la mettrait au carré et effacerait la montagne. */
.tev-logo__mount { position: absolute; top: 0; left: 5px; width: 116px; height: auto; color: #fff; }
.tev-logo__word  { position: absolute; bottom: 0; left: 0; width: 120px; height: auto; color: #fff; }

.tev-nav { margin-left: auto; }
.tev-nav__list { display: flex; align-items: center; gap: 24px; }
.tev-nav__list a {
	font-size: 14px; line-height: 17px; font-weight: 700; color: var(--tev-cream);
	position: relative; padding-block: 4px;
}
.tev-nav__list a::after {
	content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 0;
	background: var(--tev-orange); transition: width .3s var(--tev-ease);
}
.tev-nav__list a:hover::after { width: 100%; }

.tev-header__right { display: flex; align-items: center; gap: 32px; margin-left: 72px; }
.tev-header__tel { display: inline-flex; align-items: center; gap: 6px; }
.tev-header__tel span { font-family: var(--tev-font-title); font-size: 15px; line-height: 16px; }
.tev-header__tel-icon { width: 16px; height: 16px; color: var(--tev-orange); }
/* (Les règles `.tev-header__cta*` ont été retirées le 16/09/2026 : le CTA de
   l'en-tête est désormais le bouton du thème `.tev-btn--orange`, conforme au
   composant du design system utilisé par la maquette validée. Voir header.php.) */

.tev-burger { display: none; width: 44px; height: 44px; flex-direction: column; justify-content: center; gap: 5px; }
.tev-burger span { display: block; height: 2px; background: currentColor; transition: transform .3s var(--tev-ease), opacity .2s; }
.tev-mobile-nav { display: none; }

/* =========================================================================
   Hero
   La scène est épinglée au défilement : la page ne bouge plus et c'est la
   silhouette de montagne (masque) qui s'ouvre sur la vidéo, jusqu'au plein
   écran. Tailles et positions du masque pilotées en JS (assets/js/app.js).
   ========================================================================= */
.tev-hero { position: relative; isolation: isolate; background: var(--tev-orange); }

.tev-hero__stage {
	position: relative; z-index: 3; overflow: hidden;
	height: 100vh; min-height: 640px; max-height: 1040px;
	clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--tev-slant)), 0 100%);
}
.tev-hero__stage::before {
	content: ""; position: absolute; inset: 0; z-index: 0;
	background: var(--tev-blue);
}
.tev-hero__bg { position: absolute; inset: 0; z-index: 1; overflow: hidden; pointer-events: none; }
.tev-hero__deco { position: absolute; color: var(--tev-cream); opacity: .04; }
.tev-hero__deco--right { top: 19%; right: 0; width: 356px; height: auto; }
.tev-hero__deco--left  { top: 50%; left: -133px; width: 280px; height: auto; }

/* halos bleu ciel « légèrement animés » (Clémence : sur l'ensemble du site) */
.tev-hero__halo {
	position: absolute; border-radius: 50%; filter: blur(90px);
	background: rgba(255, 255, 255, .07); animation: tev-halo 14s ease-in-out infinite;
}
.tev-hero__halo--1 { width: 420px; height: 420px; top: -160px; left: 14%; }
.tev-hero__halo--2 { width: 340px; height: 340px; top: 38%; right: 8%; animation-delay: -6s; }
@keyframes tev-halo {
	0%, 100% { transform: translate3d(0, 0, 0) scale(1); opacity: .8; }
	50%      { transform: translate3d(40px, -30px, 0) scale(1.14); opacity: 1; }
}

/* La vidéo occupe toute la scène ; seule la fenêtre découpée par le masque la
   laisse voir. Deux couches de masque, réunies (comportement par défaut) :
   la silhouette de montagne, qui grandit ; puis un halo doux qui prend le
   relais pour finir d'ouvrir sur le plein écran. Les crêtes de la montagne
   laissent trop de vide entre elles pour remplir l'écran à elles seules.
   Tailles pilotées en JS (assets/js/app.js). */
.tev-hero__media {
	position: absolute; inset: 0; z-index: 2;
	/* Masque vectoriel inline : sa géométrie est pilotée en direct (agrandissement
	   au défilement, éclatement de la matière sous la souris). Repli en image
	   fixe si le navigateur ne sait pas référencer un masque SVG. */
	/* Le tracé donne des bords parfaitement lisses. La seconde couche, soustraite,
	   creuse la zone touchée par la souris : la matière qui en part est redessinée
	   en particules sur le canvas. Au repos, sa taille est nulle. */
	-webkit-mask-image: url(../svg/hero-mask-0.svg), radial-gradient(closest-side, #000 52%, rgba(0, 0, 0, 0) 100%);
	        mask-image: url(../svg/hero-mask-0.svg), radial-gradient(closest-side, #000 52%, rgba(0, 0, 0, 0) 100%);
	-webkit-mask-repeat: no-repeat, no-repeat; mask-repeat: no-repeat, no-repeat;
	-webkit-mask-position: center 60%, -999px -999px; mask-position: center 60%, -999px -999px;
	-webkit-mask-size: 1071px 507px, 0 0; mask-size: 1071px 507px, 0 0;
	-webkit-mask-composite: source-out; mask-composite: subtract;
}
/* Les particules se superposent au média : elles ne dessinent que la matière
   arrachée par la souris, le reste de la montagne garde ses bords nets. */
.tev-hero__canvas {
	position: absolute; inset: 0; z-index: 3; width: 100%; height: 100%;
	pointer-events: none; display: none;
}
.tev-hero--particules .tev-hero__canvas { display: block; }
.tev-hero__media img, .tev-hero__media video { width: 100%; height: 100%; object-fit: cover; }
/* Lecteur YouTube recadré comme un `object-fit: cover` : au moins aussi large ET
   aussi haut que le cadre, au format 16:9, centré. Aucun clic ne lui parvient. */
.tev-hero__media { overflow: hidden; }
.tev-hero__poster { position: absolute; inset: 0; }
.tev-hero__yt {
	position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: auto; height: auto; min-width: 100%; min-height: 100%; aspect-ratio: 16 / 9;
	border: 0; pointer-events: none;
	/* Invisible tant que YouTube ne dit pas que la vidéo JOUE (app.js) : sinon le
	   lecteur noir recouvre l'image d'attente, et la montagne est noire. */
	opacity: 0; transition: opacity .6s var(--tev-ease);
}
.tev-hero__yt.is-playing { opacity: 1; }


/* L'érosion est portée par la seconde couche de masque : rien à dessiner. */

.tev-hero__content { position: relative; z-index: 4; padding-top: 18.5vh; }
.tev-hero__title { width: 648px; max-width: 100%; color: var(--tev-cream); }

/* pastille tournante (« pastille cliquable qui tourne ») */
.tev-badge {
	position: relative; display: grid; place-items: center; margin-top: 44px;
	width: 99px; height: 99px; color: var(--tev-cream);
}
.tev-badge::before {
	content: ""; position: absolute; inset: 0; border-radius: 50%;
	background: var(--tev-orange); border: 2px solid var(--tev-cream);
	transition: transform .4s var(--tev-ease);
}
.tev-badge__ring {
	position: absolute; inset: 6px; border-radius: 50%;
	border: .6px solid rgba(251, 251, 251, .6); opacity: .6;
}
.tev-badge__text {
	position: absolute; width: 76px; height: 76px;
	animation: tev-spin 18s linear infinite;
}
.tev-badge__arrow { position: relative; width: 22px; height: 23px; }
.tev-badge:hover::before { transform: scale(1.06); }
@keyframes tev-spin { to { transform: rotate(360deg); } }

.tev-hero__pause {
	position: absolute; bottom: 15%; right: var(--tev-gutter); z-index: 5;
	width: 40px; height: 40px; border-radius: 50%;
	background: var(--tev-orange); border: 2px solid var(--tev-cream);
	display: grid; place-items: center;
}
/* Dimensions relevées sur le tracé Figma : deux barres de 1,8 px, hautes de
   12,6 px, séparées de 5,4 px. */
.tev-hero__pause-icon { color: var(--tev-cream); }
.tev-hero__pause-icon--pause { width: 9px; height: 12.6px; }
.tev-hero__pause-icon--play { width: 9px; height: 11px; margin-left: 2px; display: none; }
.tev-hero__pause.is-paused .tev-hero__pause-icon--pause { display: none; }
.tev-hero__pause.is-paused .tev-hero__pause-icon--play { display: block; }

/* bande orange */
.tev-hero__band {
	position: relative; z-index: 2; margin-top: -38px; padding-block: 180px 190px;
	background: var(--tev-orange); color: var(--tev-cream);
	clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--tev-slant)), 0 100%);
}
.tev-hero__band-inner { display: flex; align-items: flex-start; gap: 143px; position: relative; z-index: 1; }
.tev-hero__lead {
	width: 100%; max-width: 760px; font-family: var(--tev-font-title);
	font-size: 22px; line-height: 29px; text-transform: uppercase;
	color: rgba(251, 251, 251, .38);
}
.tev-hero__lead .tev-word { transition: color .3s linear; }
/* Trait clair en travers de la bande orange — retiré du gabarit le 22/09/2026
   (Thomas : « encore une barre blanche qui n'a rien à faire là »). Règle
   conservée pour pouvoir le remettre.
.tev-hero__band-line {
	position: absolute; left: 0; right: 0; bottom: 66px; height: 1px;
	background: rgba(251, 251, 251, .36); transform: rotate(-1.4deg); transform-origin: left center;
} */

/* révélation progressive des textes (« texte qui s'affiche progressivement ») */
[data-tev-reveal] .tev-word { display: inline-block; }

/* Titres de bannière : apparition jouée par le CSS (01/10/2026). Opacité et
   déplacement seuls, donc animés par le compositeur : l'animation reste fluide
   pendant que GTM, Google Ads, Clarity et Axeptio occupent le navigateur, ce
   qui n'était pas le cas de la version GSAP (texte figé puis affiché d'un coup).
   Les mots sont découpés au serveur (tev_mots()), `--i` donne le rang.
   Mouvement réduit : la règle globale ramène la durée à presque rien, `both`
   laisse le texte visible. */
[data-tev-reveal="css-mots"] .tev-word {
	animation: tev-mot .6s cubic-bezier(.22, .61, .36, 1) both;
	animation-delay: calc(.15s + var(--i, 0) * 45ms);
}
/* Sous un sur-titre, l'accroche part juste après lui au lieu de démarrer en même temps. */
.tev-anim-hero__title--sur .tev-anim-hero__catch .tev-word { animation-delay: calc(.4s + var(--i, 0) * 45ms); }
[data-tev-reveal="css-fade"] { animation: tev-mot .6s cubic-bezier(.22, .61, .36, 1) .05s both; }
.tev-anim-hero__ctas[data-tev-reveal="css-fade"],
.tev-agence-hero__ctas[data-tev-reveal="css-fade"] { animation-delay: .55s; }
@keyframes tev-mot {
	from { opacity: 0; transform: translate3d(0, .4em, 0); }
	to   { opacity: 1; transform: none; }
}

/* =========================================================================
   Chiffres clés
   ========================================================================= */
.tev-stats {
	position: relative; background: var(--tev-cream);
	margin-top: -42px; padding-block: 144px 100px;
	clip-path: polygon(0 0, 100% 0, 100% calc(100% - 42px), 0 100%);
}
.tev-stats__inner { display: flex; justify-content: space-between; gap: 80px; align-items: flex-start; }
.tev-stats__left { width: 550px; max-width: 100%; }
.tev-stats__title {
	font-family: var(--tev-font-title); font-size: 36px; line-height: 43px;
	text-transform: uppercase; color: var(--tev-orange);
}
.tev-stats__nowrap { white-space: nowrap; }
.tev-stats__picto {
	display: inline-grid; place-items: center; width: 63px; height: 60px;
	border: 1px solid var(--tev-orange); border-radius: var(--tev-radius);
	background: var(--tev-white); vertical-align: middle; margin-inline: 2px;
	transform: translateY(-4px);
}
.tev-stats__picto svg { width: 41px; height: 25px; color: var(--tev-orange); transform: rotate(-15deg); }

.tev-marquee { position: relative; margin-top: 60px; overflow: hidden; width: 589px; max-width: 100%; }
.tev-marquee::before, .tev-marquee::after {
	content: ""; position: absolute; top: 0; bottom: 0; width: 96px; z-index: 2; pointer-events: none;
}
.tev-marquee::before { left: 0;  background: linear-gradient(90deg, var(--tev-cream), rgba(251,251,251,0)); }
.tev-marquee::after  { right: 0; background: linear-gradient(270deg, var(--tev-cream), rgba(251,251,251,0)); }
.tev-marquee__track { display: flex; align-items: center; gap: 48px; width: max-content; animation: tev-marquee 26s linear infinite; }
.tev-marquee:hover .tev-marquee__track { animation-play-state: paused; }
.tev-marquee__item { flex: 0 0 auto; display: grid; place-items: center; height: 60px; }
.tev-marquee__item img { max-height: 40px; max-width: 100px; width: auto; object-fit: contain; opacity: .68; filter: grayscale(1); }
@keyframes tev-marquee { to { transform: translate3d(-50%, 0, 0); } }

.tev-stats__list { width: 546px; max-width: 100%; display: flex; flex-direction: column; }
.tev-stats__item { display: flex; flex-direction: column; align-items: flex-end; text-align: right; padding-block: 24px; }
.tev-stats__item + .tev-stats__item { border-top: 1px solid var(--tev-tint-line); }
.tev-stats__value { font-family: var(--tev-font-title); font-size: 50px; line-height: 54px; color: var(--tev-orange); }
.tev-stats__label { font-family: var(--tev-font-title); font-size: 20px; line-height: 22px; text-transform: uppercase; color: var(--tev-blue); }

/* =========================================================================
   Offres — cartes qui se superposent au défilement
   ========================================================================= */
.tev-offres { position: relative; background: var(--tev-tint); padding-block: 154px 140px; }
.tev-offres__scene { position: relative; }
/* Le titre défile normalement, rien de collé ni d'épinglé : c'est la PILE qui
   fige la page (voir `offresPile` dans app.js), le titre passe avant et sort
   de l'écran comme n'importe quel titre (retour de Lisa, 15/09/2026). */
.tev-offres__title { text-align: center; margin-bottom: 106px; }
.tev-offres__stack { position: relative; }
/* Mesures de la maquette (frame 347:370). ⚠️ La carte bleue y est PIVOTÉE de
   6,8° : sa boîte englobante donnée par l'API (1027 × 558) est celle du
   rectangle tourné, pas celle de la carte. Redressée : 981 × 445. La carte
   orange, elle, n'a aucune rotation — sa boîte est directement la bonne
   (1198 × 587). Recopier la boîte englobante d'un calque pivoté donne une
   carte trop large et trop basse (ce qu'on avait, 16/09/2026). */
.tev-offre--blue   { width: 981px;  max-width: 100%; margin-inline: auto; }
.tev-offre--orange { width: 1198px; max-width: 100%; margin-inline: auto; }
/* Repli sans JS (ou mouvement réduit, ou petit écran) : les cartes s'empilent
   simplement les unes sous les autres, dans le flux. C'est `offresPile` qui
   les superpose et fige la page quand GSAP est là. */
.tev-offre {
	position: relative; z-index: calc(var(--i, 1) + 1); transform-origin: 50% 120%;
	border-radius: var(--tev-radius); overflow: hidden;
	padding: 32px 32px 32px 72px; color: var(--tev-cream);
	margin-bottom: 40px;
}
.tev-offre:last-of-type { margin-bottom: 0; }
/* 🛑 Piste ABANDONNÉE : `position: sticky` sur chaque carte. Deux cartes
   collantes sœurs dont les plages de collage se chevauchent — la 2ᵉ doit
   coller alors que la 1ʳᵉ l'est ENCORE — et la seconde ne colle JAMAIS dans
   ce cas (testé de 0 à 100vh de marge, en padding, avec un conteneur par
   carte : identique à chaque fois). Un pin GSAP sur la dernière carte cassait
   en prime le collage natif de la première. Remplacé par un épinglage de la
   scène entière + une timeline : la page se fige, les cartes montent l'une
   après l'autre, chacune recouvrant la précédente (15/09/2026). */

/* Mode pile, posé par `offresPile` : toutes les cartes au même endroit, la
   hauteur du conteneur est figée en JS sur la plus haute. */
.tev-offres__stack.is-pile .tev-offre {
	position: absolute; top: 0; left: 0; right: 0; margin-bottom: 0;
}
/* Chaque carte arrive droite ; c'est le défilement qui bascule la précédente
   quand la suivante monte (voir assets/js/app.js). */
.tev-offre--blue   { background: var(--tev-blue); box-shadow: 0 4px 36px rgba(59, 85, 199, .24); }
.tev-offre--orange { background: var(--tev-orange); box-shadow: 0 4px 36px rgba(255, 85, 39, .24); }
/* Le fond bleu de cette carte n'est pas un aplat : la maquette lui pose le même
   grain que les autres surfaces de couleur (voir `.tev-grain` en tête de
   fichier, qui porte la règle unique). La carte ORANGE n'en a pas en maquette :
   elle a une ombre portée à la place — d'où l'absence de `--orange` ici. */
/* Le motif de montagne est présent sur les DEUX cartes, à des échelles et des
   places différentes (mesuré sur la maquette, frame 347:370) :
   – bleue  : 733 px de large, à 182 px du bord gauche, 6 % d'opacité ;
   – orange : 1015 px de large, à 41 px du bord gauche, 10 % d'opacité.
   Il déborde en haut dans les deux cas, la carte le recoupe (`overflow`). */
.tev-offre__wave {
	position: absolute; width: 733px; height: auto;
	color: var(--tev-cream); opacity: .06;
	transform: rotate(-29.6deg); pointer-events: none;
}
.tev-offre--blue   .tev-offre__wave { top: -110px; left: 180px; width: 733px;  opacity: .06; }
.tev-offre--orange .tev-offre__wave { top: -150px; left: 175px; width: 1015px; opacity: .10; }
/* L'image est TOUJOURS à droite, sur les deux cartes (maquette : texte à
   gauche, visuel à droite, quelle que soit la couleur). Le `row-reverse` qui
   renvoyait le visuel de la carte orange à gauche était un écart (16/09/2026). */
.tev-offre__body { position: relative; z-index: 1; display: flex; align-items: center; gap: 48px; }
/* La colonne de texte fait 426 px sur les DEUX cartes en maquette (981−72−32−48−403
   pour la bleue, 1198−72−32−48−620 pour l'orange) : c'est ce qui donne un titre
   sur deux lignes. Laissée élastique, elle prenait toute la place restante et le
   titre passait sur trois lignes. Écart title/texte 40, texte/bouton 64. */
/* Les deux colonnes sont ÉLASTIQUES, avec les mesures de la maquette en base :
   à 1440 la somme (104 de marges + 426 + 48 + 403 ou 620) vaut exactement la
   largeur de la carte, donc rien ne bouge et le rendu est celui du pixel près ;
   en dessous, les deux colonnes rétrécissent dans la même proportion. Fixées en
   dur, elles débordaient de 194 px sur un portable de 1100 et la photo était
   coupée par l'`overflow` de la carte. */
.tev-offre__text { flex: 1 1 426px; min-width: 0; max-width: 100%; display: flex; flex-direction: column; gap: 40px; }
.tev-offre__text > .tev-btn { margin-top: 24px; }
/* ⚠️ Le titre fait 26 px, pas 36. Le `style` du calque Figma annonce 36/39,
   mais c'est la valeur PAR DÉFAUT du bloc de texte : tous ses caractères
   portent une surcharge (`styleOverrideTable`) à 26 px / 33,8 px, et le numéro
   à 16 px. Codé à 36 px, le titre passait sur trois lignes au lieu de deux
   (16/09/2026). Toujours lire les surcharges d'un calque de texte, la taille
   annoncée au niveau du nœud peut n'être portée par aucun caractère. */
.tev-offre__heading {
	font-family: var(--tev-font-title); font-size: 26px; line-height: 34px; text-transform: uppercase; font-weight: 400;
}
.tev-offre__num { font-size: 16px; line-height: 34px; margin-right: 8px; vertical-align: top; }
.tev-offre__desc { font-size: 18px; line-height: 22px; font-weight: 600; }
/* Le visuel a une taille POSÉE, pas déduite du ratio de la photo : la maquette
   donne 403 × 381 sur la bleue et 620 × 523 sur l'orange (le `cover` recadre).
   Sans hauteur posée, la carte prenait la hauteur du ratio de l'image — 150 px
   de moins que la maquette sur chaque carte. */
/* L'arrondi est posé sur le CADRE (avec `overflow: hidden`) en plus de l'image :
   un `border-radius` porté par le seul `<img>` peut ne pas rogner le rendu selon
   la façon dont la photo est peinte, et Lisa voyait des coins droits alors que
   le calculé annonçait 20 px. Le cadre, lui, rogne toujours. */
/* Le visuel garde les PROPORTIONS de la maquette (403 × 381 sur la bleue,
   620 × 523 sur l'orange) plutôt qu'une hauteur en pixels : ainsi il rétrécit
   avec la carte sans jamais se déformer. Une hauteur figée donnait, sur un
   écran étroit, une photo en portrait recadrée n'importe comment. */
.tev-offre__media {
	flex: 0 1 403px; min-width: 0; max-width: 100%;
	aspect-ratio: 403 / 381;
	border-radius: var(--tev-radius-img); overflow: hidden;
}
.tev-offre--orange .tev-offre__media { flex-basis: 620px; aspect-ratio: 620 / 523; }
.tev-offre__media img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: var(--tev-radius-img); }
.tev-offres__cta { display: flex; justify-content: center; margin-top: 86px; }

/* (Règle retirée le 16/09/2026 : elle décalait le `top` des cartes collantes
   sur les écrans courts. Les cartes ne sont plus collantes depuis le passage à
   la scène épinglée — elles sont superposées en absolu — ce `top` ne servait
   donc plus rien.) */

/* =========================================================================
   Animations — carrousel en fondu
   ========================================================================= */
.tev-anims { position: relative; background: var(--tev-blue); color: var(--tev-cream); padding-block: 110px 130px; overflow: hidden; }
.tev-anims__bg { position: absolute; inset: 0; pointer-events: none; }
.tev-anims__deco { position: absolute; right: 0; bottom: 180px; width: 361px; height: auto; color: var(--tev-cream); opacity: .10; }
/* Trait clair en travers de la section — retiré du gabarit le 22/09/2026
   (Thomas : « barre blanche visible en fond, elle ne devrait pas être
   visible »). Règle conservée pour pouvoir le remettre.
.tev-anims__line { position: absolute; left: 0; right: 0; top: 577px; height: 1px; background: rgba(251,251,251,.10); transform: rotate(-1.4deg); } */
.tev-anims__inner { position: relative; z-index: 1; }
.tev-anims__head { display: flex; align-items: center; justify-content: space-between; gap: 40px; margin-bottom: 46px; }
/* ⚠️ Pas de `text-transform: none` ici : la maquette écrit ce titre en
   CAPITALES comme les autres titres de section (« DÉCOUVREZ UNE SÉLECTION
   D'ANIMATIONS : », 26 px). La règle qui l'annulait était un écart (retour de
   Lisa, 17/09/2026). Seule la couleur change, la section étant sur fond bleu. */
.tev-anims__title { color: var(--tev-cream); }

.tev-anims__carousel { position: relative; }
.tev-anims__viewport { position: relative; overflow: hidden; height: 720px; }
.tev-anims__viewport::before, .tev-anims__viewport::after {
	content: ""; position: absolute; left: 0; right: 0; height: 110px; z-index: 2; pointer-events: none;
}
.tev-anims__viewport::before { top: 0; height: 90px; background: linear-gradient(var(--tev-blue), rgba(59, 85, 199, 0)); }
.tev-anims__viewport::after { bottom: 0; height: 90px; background: linear-gradient(rgba(59, 85, 199, 0), var(--tev-blue)); }
.tev-anims__list {
	display: flex; flex-direction: column; gap: 20px; align-items: center;
	transition: transform .75s var(--tev-ease); will-change: transform;
}
.tev-anims__nav { display: flex; justify-content: center; gap: 14px; margin-top: 40px; }
.tev-anims__nav .tev-arrow svg { transform: rotate(90deg); }
.tev-anims__nav .tev-arrow--light svg { transform: rotate(-90deg); }
.tev-anim {
	display: flex; align-items: center; gap: 88px; width: 100%; max-width: 1061px;
	opacity: .6; transform: scale(.8); filter: blur(1px);
	transition: opacity .6s var(--tev-ease), transform .6s var(--tev-ease), filter .6s var(--tev-ease);
}
.tev-anim.is-active { opacity: 1; transform: scale(1); filter: none; }
.tev-anim__media { flex: 0 0 432px; max-width: 45%; }
.tev-anim__media img {
	width: 100%; aspect-ratio: 432 / 286; object-fit: cover;
	border-radius: var(--tev-radius); border: 2px solid var(--tev-orange);
	box-shadow: 0 4px 42px rgba(255, 78, 79, .24);
}
.tev-anim__body { flex: 1 1 541px; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.tev-anim__picto {
	display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%;
	background: var(--tev-white); border: 1px solid var(--tev-orange);
}
.tev-anim__picto svg { width: 27px; height: 16px; color: var(--tev-orange); transform: rotate(-15deg); }
.tev-anim__title { font-family: var(--tev-font-title); font-size: 22px; line-height: 24px; font-weight: 400; }
.tev-anim__desc { font-size: 16px; line-height: 21px; font-weight: 600; }
.tev-anim .tev-pills { margin-top: 18px; }

/* =========================================================================
   Réalisations
   ========================================================================= */
.tev-reas { position: relative; background: var(--tev-tint); padding-block: 217px 190px; }
.tev-reas__title { text-align: center; margin-bottom: 129px; }
/* Chapô facultatif sous le titre (page Événements) : c'est lui qui porte alors
   la grande réserve avant le carrousel, sinon l'ensemble ferait deux fois
   129 px d'air. */
.tev-reas__title--chapo { margin-bottom: 28px; }
.tev-reas__chapo {
	display: flex; flex-direction: column; gap: 16px;
	max-width: 860px; margin: 0 auto 96px; text-align: center;
}
.tev-reas__chapo p { font-size: 16px; line-height: 26px; color: var(--tev-blue); }
.tev-reas__carousel { display: flex; align-items: center; gap: 24px; }
/* 🛑 Les cartes sont INCLINÉES de 1° : leur emprise est plus grande que leur
   boîte de mise en page — environ 4,5 px de chaque côté et 10 px en haut comme
   en bas (mesuré à 1144 x 519). Sans réserve, le cadre coupait le bas des
   cartes, et la carte voisine, posée à exactement 100 %, laissait dépasser sa
   tranche orange dans le cadre (retour de Thomas, 22/09/2026).
   La réserve verticale est reprise en marge négative : la mise en page ne
   bouge pas. L'écart horizontal, lui, est un vrai `gap` entre diapositives —
   c'est lui que le pas du carrousel doit franchir (voir reasCarousel dans
   app.js, qui lit ce gap plutôt que de le redéclarer). */
.tev-reas__viewport {
	flex: 1 1 auto; overflow: hidden;
	padding-block: 14px; margin-block: -14px;
	/* La réserve latérale est reprise en marge négative : le cadre gagne 16 px,
	   donc la carte garde EXACTEMENT sa largeur (mesuré : 1144 px avant comme
	   après). Sans elle, les coins arrondis de la carte active étaient rognés
	   de 4,4 px à gauche et à droite. */
	padding-inline: 8px; margin-inline: -8px;
}
.tev-reas__list { display: flex; gap: 48px; }
.tev-rea {
	position: relative; /* ancre le grain (.tev-rea--blue/--orange::after) */
	flex: 0 0 100%; display: flex; align-items: center; gap: 40px;
	border-radius: var(--tev-radius); padding: 24px 24px 24px 48px; color: var(--tev-cream);
	transform: rotate(-1deg);
}
/* Le sens de l'inclinaison ALTERNE d'une carte à l'autre (retour du
   23/09/2026) : −1° pour les impaires, +1° pour les paires. */
.tev-rea:nth-child(even) { transform: rotate(1deg); }
.tev-rea--orange { background: var(--tev-orange); }
.tev-rea--blue   { background: var(--tev-blue); }
.tev-rea__text { flex: 1 1 490px; min-width: 0; display: flex; flex-direction: column; gap: 24px; }
.tev-rea__quote { width: 77px; height: 53px; color: var(--tev-cream); opacity: .6; }
.tev-rea__title { font-family: var(--tev-font-title); font-size: 26px; line-height: 28px; font-weight: 400; }
.tev-rea__desc { font-size: 16px; line-height: 24px; font-weight: 600; font-style: italic; }
.tev-rea__media { position: relative; flex: 0 0 478px; max-width: 45%; aspect-ratio: 478 / 471; }
.tev-rea__media img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--tev-radius-img); border: 3px solid var(--tev-cream); }
.tev-play {
	position: absolute; inset: 0; margin: auto; width: 61px; height: 61px; border-radius: 50%;
	background: var(--tev-orange); border: 2px solid var(--tev-cream);
	display: grid; place-items: center; transition: transform .3s var(--tev-ease);
}
.tev-play svg { width: 22px; height: 24px; color: var(--tev-cream); margin-left: 3px; }
.tev-play:hover { transform: scale(1.08); }
/* 37 % de la photo, la proportion de la maquette (177 px sur 478) : en largeur fixe,
   la montagne couvrait 60 % de la photo sur téléphone (retour d'Émilie, 13/10/2026). */
.tev-rea__wave { position: absolute; right: -16px; bottom: 24px; width: min(177px, 37%); height: auto; color: var(--tev-cream); }
.tev-rea__logo {
	position: absolute; left: 22px; bottom: 26px; width: 111px; height: 83px; border-radius: 16px;
	background: var(--tev-cream); display: grid; place-items: center; padding: 12px;
}
/* Borné dans les DEUX sens : borné en hauteur seulement, un logo large
   (France Marquage 1,76:1, Batec 3,1:1) débordait de la pastille crème et
   ses bords passaient sur la photo (« écorché », retour client 29/09/2026). */
/* 01/10/2026 (retour client, 2ᵉ fois) : dans une GRILLE, max-height: 100% ne borne
   pas l'image (la piste s'agrandit à son contenu) : un logo carré sortait à 89 px de
   haut dans 61 px utiles. Boîte imposée + contain. Et `multiply` fond le fond blanc
   des logos fournis en JPEG/PNG opaque dans le crème : plus de carré blanc visible. */
.tev-rea__logo img { display: block; width: 100%; height: 100%; object-fit: contain; mix-blend-mode: multiply; }

.tev-reas__dots { display: flex; justify-content: center; align-items: center; gap: 16px; margin-top: 88px; }
.tev-dash { width: 48px; height: 1px; background: var(--tev-orange); opacity: .4; transition: all .3s var(--tev-ease); }
.tev-dash.is-active { width: 75px; height: 2px; opacity: 1; }
.tev-reas__cta { display: flex; justify-content: center; gap: 20px; margin-top: 112px; flex-wrap: wrap; }

/* =========================================================================
   Galerie — photos superposées
   ========================================================================= */
.tev-galerie { position: relative; background: var(--tev-tint); padding-bottom: 144px; }
/* ⚠️ 86 % et non 100 % : les photos sont inclinées (±4,5°), ce qui élargit
   leur emprise d'environ 8 % de chaque côté. À pleine largeur, la photo du bas
   sortait de l'écran de 12 à 40 px entre 600 et 1100 px de large (mesuré). La
   réserve suit la largeur, donc l'inclinaison reste visible partout. */
.tev-galerie__stack { position: relative; width: min(984px, 86%); margin-inline: auto; aspect-ratio: 984 / 610; }
.tev-galerie__item { position: absolute; inset: 0; margin: 0; transform-origin: 50% 60%; }
.tev-galerie__item img {
	width: 100%; height: 100%; object-fit: cover;
	border-radius: var(--tev-radius); border: 3px solid var(--tev-orange);
	box-shadow: 0 4px 36px rgba(251, 251, 251, .14);
}

/* =========================================================================
   Manifeste de l'agence — « Une équipe qui pense l'expérience »
   ⚠️ Section ABSENTE de la maquette (ajoutée le 16/09/2026 à la demande de
   Lisa). Rien n'est inventé côté style : on réemploie le vocabulaire déjà posé
   par la maquette ailleurs — titre Archivo Black, corps Inter 600, accroches
   en orange, motif de montagne en filigrane. Fond crème et non bleu : la scène
   des étapes qui suit est bleue, deux bandes bleues collées se confondraient.
   Pas de grain non plus, pour la même raison qu'ailleurs : il n'appartient
   qu'aux neuf aplats que la maquette désigne.
   ========================================================================= */
.tev-equipe {
	position: relative; overflow: hidden;
	background: var(--tev-white); color: var(--tev-blue);
	padding-block: 150px 140px;
}
.tev-equipe__mont {
	position: absolute; top: -80px; right: -160px; width: 780px; height: auto;
	color: var(--tev-blue); opacity: .05; pointer-events: none;
	transform: rotate(8deg);
}
.tev-equipe__inner { position: relative; z-index: 1; }
.tev-equipe__title {
	font-family: var(--tev-font-title); font-size: 36px; line-height: 43px;
	text-transform: uppercase; max-width: 900px; margin-bottom: 96px;
}
.tev-equipe__list { display: flex; flex-direction: column; gap: 64px; max-width: 980px; }
/* Le numéro vit dans la marge de gauche : la colonne de texte garde une
   longueur de ligne lisible (~75 signes) au lieu de courir sur 980 px. */
.tev-equipe__bloc {
	display: grid; grid-template-columns: 96px minmax(0, 1fr);
	column-gap: 32px; row-gap: 20px; align-items: start;
	padding-top: 40px; border-top: 1px solid var(--tev-tint-line);
}
.tev-equipe__bloc:first-child { padding-top: 0; border-top: 0; }
.tev-equipe__num {
	font-family: var(--tev-font-title); font-size: 40px; line-height: 40px;
	color: var(--tev-orange); grid-row: span 2;
}
.tev-equipe__texte { font-size: 17px; line-height: 27px; font-weight: 600; }
.tev-equipe__accroche {
	font-family: var(--tev-font-title); font-size: 22px; line-height: 30px;
	color: var(--tev-orange); grid-column: 2;
}

/* =========================================================================
   Étapes — défilement au scroll, cercles qui respirent
   ========================================================================= */
.tev-etapes { position: relative; background: var(--tev-blue); color: var(--tev-cream); }
/* Le grain de cette section doit passer AU-DESSUS des cercles décoratifs. */
.tev-etapes::before { z-index: 1; }
/* La scène est épinglée : elle doit occuper l'ÉCRAN, pas les 695 px de la
   maquette, sinon le bloc se colle en haut et laisse un vide sous lui. */
.tev-etapes__pin { position: relative; min-height: 100vh; display: grid; place-items: center; overflow: hidden; }

/* Deux cercles, mesurés sur la maquette : 697 et 536 px, trait de 1 px, le
   petit à 44 % d'opacité. Ils sont centrés sur l'ÉTAPE ACTIVE (d'où leur place
   dans la scène), pas sur la section : centrés sur la section, ils partaient
   plus bas que le bloc et traversaient l'écran en grands arcs. */
.tev-etapes__scene { position: relative; width: 100%; display: grid; place-items: center; }
.tev-etapes__rings { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
/* Le tracé respire par endroits (le filtre SVG `tev-ring-wobble`, animation SMIL
   dans le gabarit) plutôt que le cercle entier qui grossit et rétrécit — c'était
   trop uniforme au goût de Lisa (15/09/2026). */
.tev-etapes__rings span {
	position: absolute; border-radius: 50%; border: 1px solid var(--tev-cream);
	filter: url(#tev-ring-wobble);
}
.tev-etapes__rings span:nth-child(1) { width: 697px; height: 697px; opacity: 1; }
.tev-etapes__rings span:nth-child(2) { width: 536px; height: 536px; opacity: .44; }
/* Écarts repris de la maquette : 76 px sous la pastille, 89 px avant le bouton. */
.tev-etapes__inner { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 76px; padding-block: 80px; }
.tev-etapes__eyebrow { align-self: center; }

.tev-etapes__list { position: relative; width: 100%; height: 200px; }
.tev-etape {
	position: absolute; top: 0; left: 50%; width: 581px; max-width: 100%;
	display: flex; flex-direction: column; align-items: center; gap: 32px; text-align: center;
	transform: translateX(-50%); opacity: 0; pointer-events: none;
	transition: opacity .5s var(--tev-ease), transform .5s var(--tev-ease);
}
.tev-etape__num { font-family: var(--tev-font-title); font-size: 46px; line-height: 60px; }
.tev-etape__label { font-size: 20px; line-height: 26px; font-weight: 700; }
.tev-etape.is-prev, .tev-etape.is-next { opacity: .6; }
/* ⚠️ L'écart des étapes voisines doit être au moins la LARGEUR d'une étape,
   sinon elles se superposent à l'étape active. L'étape fait `min(581px, 100vw)` :
   605 px conviennent tant que l'écran est large, mais sur un téléphone de 390 il
   faut au moins 390 px — les 48vw posés pour le responsive (187 px) faisaient
   donc lire « 021. » par-dessus « 01. » (constaté le 18/09/2026). `min()` garde
   la valeur de la maquette sur grand écran et la borne sur petit. */
.tev-etape.is-prev { transform: translateX(calc(-50% - min(605px, 102vw))); }
.tev-etape.is-next { transform: translateX(calc(-50% + min(605px, 102vw))); }
.tev-etape.is-active { opacity: 1; pointer-events: auto; }
.tev-etape.is-active .tev-etape__num { font-size: 90px; line-height: 117px; }
.tev-etape.is-active .tev-etape__label { font-size: 32px; line-height: 42px; }
.tev-etapes__cta { align-self: flex-end; margin-top: 13px; } /* 89 px sous l'étape, gap compris */

/* =========================================================================
   Avis
   ========================================================================= */
.tev-avis { position: relative; background: var(--tev-tint); padding-block: 183px 190px; overflow: hidden; }
.tev-avis__title { text-align: center; margin-bottom: 98px; }
.tev-avis__carousel { position: relative; }
/* La carte active reste TOUJOURS au centre : ce n'est pas la ligne qui
   défile, c'est chaque carte qui se repositionne selon `--d`, son écart
   circulaire à l'avis actif (posé en JS, cf. `avisCarousel`) — boucle
   infinie garantie, y compris à l'avis n°1 ou au dernier (retour de Lisa,
   15/09/2026 : la carte agrandie sortait du cadre à droite en fin de
   liste, car la ligne ne recentrait rien). */
/* z-index explicite : la carte active peut dépasser les 460px de réserve
   quand son texte est long (l'avis 5 étoiles, plus long que les autres,
   est l'avis actif par défaut) — sans ça elle passe visuellement AU-DESSUS
   de la frise et des flèches en dessous et intercepte leurs clics : les
   boutons semblent morts (retour de Lisa, 15/09/2026). */
/* 🛑 TOUTES les cartes ont EXACTEMENT la même mise en page — même largeur de
   boîte, même padding, mêmes corps de texte, même épaisseur de bordure. Seule
   change l'ÉCHELLE (`--s`), plus les couleurs. Raison : une transition qui fait
   varier la largeur, le padding, la taille de police ou l'épaisseur d'une
   bordure REDÉCOUPE le texte à chaque image — la citation se recompose ligne à
   ligne pendant les 0,55 s et le glissement paraît saccadé (retour de Thomas,
   22/09/2026 : « le texte se réajuste à chaque positionnement de la card »).
   ⚠️ Une transformation, elle, ne déclenche AUCUN recalcul de mise en page :
   c'est la seule façon d'avoir une carte qui grandit sans que son contenu ne
   bouge. Corollaire à respecter si on retouche ce bloc : aucune propriété qui
   influence le flux (width, padding, gap, font-size, border-width, min-height)
   ne doit différer entre `.tev-avi` et `.tev-avi.is-active`. */
.tev-avis__list {
	position: relative; z-index: 1; min-height: 460px;
	--tev-avi-step: 360px;   /* écart entre deux centres de carte */
	--tev-avi-w: 461px;      /* largeur de MISE EN PAGE, la même pour toutes */
	--tev-avi-s: .475;       /* échelle des cartes voisines (219 / 461) */
}
.tev-avi {
	position: absolute; top: 50%; left: 50%; width: var(--tev-avi-w);
	transform: translate(-50%, -50%) translateX(calc(var(--d, 0) * var(--tev-avi-step)))
		rotate(var(--r, 0deg)) scale(var(--tev-avi-s));
	transition: transform .55s var(--tev-ease);
}
.tev-avi.is-active { --tev-avi-s: 1; z-index: 1; }
.tev-avi__card {
	position: relative; overflow: hidden;
	background: var(--tev-white); border: 3px solid var(--tev-orange); border-radius: var(--tev-radius);
	padding: 48px 61px; display: flex; flex-direction: column; gap: 32px; min-height: 428px;
	transition: background-color .55s var(--tev-ease), border-color .55s var(--tev-ease),
		box-shadow .55s var(--tev-ease), transform .55s var(--tev-ease);
}
.tev-avi__deco { position: absolute; right: -10px; bottom: -12px; width: 148px; height: auto; color: var(--tev-orange); opacity: .32; transform: rotate(-138deg); }
.tev-avi__note { display: flex; align-items: center; gap: 2px; font-family: var(--tev-font-title); font-size: 26px; line-height: 34px; color: var(--tev-orange); transition: color .55s var(--tev-ease); }
.tev-avi__star { width: 28px; height: 28px; color: var(--tev-orange); transition: color .55s var(--tev-ease); }
.tev-avi__quote { font-size: 16px; line-height: 19px; font-weight: 600; color: var(--tev-grey); transition: color .55s var(--tev-ease); }
/* L'avatar est posé en absolu dans le coin bas droit : sans cette réserve, le
   nom passe dessous dès que la carte se resserre (constaté à 1100 px). */
.tev-avi__author { display: flex; flex-direction: column; gap: 2px; margin-top: auto; padding-right: 96px; }
.tev-avi__name,
.tev-avi__role { font-size: 16px; line-height: 24px; font-weight: 700; color: var(--tev-orange); transition: color .55s var(--tev-ease); }
.tev-avi__avatar { position: absolute; right: 40px; bottom: 40px; width: 81px; height: 81px; border-radius: 50%; overflow: hidden; border: 2px solid var(--tev-cream); }
.tev-avi__avatar img { width: 100%; height: 100%; object-fit: cover; }

.tev-avi.is-active .tev-avi__card {
	transform: rotate(-1deg); background: var(--tev-orange); border-color: var(--tev-cream);
	box-shadow: 0 4px 36px rgba(255, 85, 39, .24);
}
.tev-avi.is-active .tev-avi__note,
.tev-avi.is-active .tev-avi__star,
.tev-avi.is-active .tev-avi__quote,
.tev-avi.is-active .tev-avi__name,
.tev-avi.is-active .tev-avi__role { color: var(--tev-cream); }

/* Positions FIXES, comme la maquette : ce sont les cartes qui recentrent,
   pas la frise (retour de Lisa, 15/09/2026 — revenu en arrière après un
   premier essai qui la faisait bouger elle aussi). Seul le « hotspot » —
   l'aura autour de la pastille active — vit, par une pulsation continue. */
.tev-avis__timeline { position: relative; z-index: 2; display: flex; align-items: center; justify-content: space-between; margin-top: 60px; }
.tev-avis__rail { position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: rgba(255, 85, 39, .10); }
.tev-hotspot {
	position: relative; width: 14px; height: 14px; border-radius: 50%;
	background: #FF4E4F; border: 1px solid var(--tev-orange); opacity: .6;
	transition: all .35s var(--tev-ease);
}
.tev-hotspot::after {
	content: ""; position: absolute; inset: -15px; border-radius: 50%;
	background: #FF4E4F; border: 1px solid var(--tev-orange); opacity: 0;
	transition: opacity .35s var(--tev-ease);
}
.tev-hotspot.is-active { width: 24px; height: 24px; opacity: 1; }
.tev-hotspot.is-active::after { opacity: .2; animation: tev-hotspot-aura 1.8s ease-in-out infinite; }
@keyframes tev-hotspot-aura {
	0%, 100% { transform: scale(1); opacity: .2; }
	50%      { transform: scale(1.35); opacity: .08; }
}
.tev-avis__nav { position: relative; z-index: 2; display: flex; justify-content: center; gap: 14px; margin-top: 60px; }

/* =========================================================================
   Contact
   ========================================================================= */
.tev-contact {
	position: relative; background: var(--tev-orange); color: var(--tev-cream);
	margin-top: -34px; padding-block: 208px 160px;
	clip-path: polygon(0 var(--tev-slant), 100% 0, 100% 100%, 0 100%);
}
.tev-contact__bg { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.tev-contact__deco { position: absolute; left: -44px; bottom: 40px; width: 474px; height: auto; color: var(--tev-cream); opacity: .05; }
.tev-contact__inner { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 64px; }
.tev-contact__title { display: flex; align-items: center; gap: 20px; color: var(--tev-cream); }
.tev-contact__picto {
	display: grid; place-items: center; width: 60px; height: 60px; border-radius: 50%;
	background: var(--tev-white); flex: 0 0 auto;
}
.tev-contact__picto svg { width: 41px; height: 25px; color: var(--tev-orange); transform: rotate(-15deg); }

.tev-form { width: 633px; max-width: 100%; display: flex; flex-direction: column; gap: 20px; }
.tev-form__row { display: flex; gap: 8px; }
.tev-form__row > * { flex: 1 1 0; min-width: 0; }
.tev-form__row--half > * { flex: 0 1 312px; }
.tev-field { position: relative; margin: 0; }
.tev-field input, .tev-field textarea, .tev-field select {
	width: 100%; background: transparent; color: var(--tev-cream);
	border: 1px solid var(--tev-cream); border-radius: var(--tev-radius);
	padding: 12.5px 16px; font-family: var(--tev-font-form); font-size: 14px; line-height: 15px;
	appearance: none;
}
.tev-field textarea { border-radius: var(--tev-radius-img); resize: vertical; min-height: 72px; padding-bottom: 44px; }
.tev-field input::placeholder, .tev-field textarea::placeholder { color: var(--tev-cream); font-style: italic; opacity: 1; }
.tev-field select { font-style: italic; }
.tev-field select option { color: var(--tev-blue); }
.tev-field__chevron, .tev-field__calendar {
	position: absolute; right: 16px; top: 50%; transform: translateY(-50%);
	color: var(--tev-cream); pointer-events: none;
}
.tev-field__chevron { width: 16px; height: 10px; }
.tev-field__calendar { width: 19px; height: 19px; }
.tev-form__hp { position: absolute !important; left: -9999px; }
.tev-form__altcha { margin-top: 4px; }
.tev-altcha {
	--altcha-color-base: transparent;
	--altcha-border-color: rgba(251, 251, 251, .8);
	--altcha-color-base-content: #FBFBFB;
	--altcha-color-success: #FBFBFB;
	--altcha-color-success-content: #FF5527;
	/* Le cadre « Je ne suis pas un robot » prend le rayon du champ de message,
	   pas celui des champs d'une ligne : c'est un bloc, comme le textarea
	   (retour de Lisa, 17/09/2026 — vaut pour le formulaire de tout le site). */
	--altcha-border-width: 1px; --altcha-border-radius: 20px;
	max-width: 320px;
}
.tev-altcha .altcha-checkbox-wrap label { font-size: 14px; }
.tev-form__submit { margin: 0; }
.tev-form__notice {
	width: 633px; max-width: 100%; padding: 14px 20px; border-radius: var(--tev-radius);
	background: var(--tev-cream); color: var(--tev-blue); font-weight: 600; font-size: 14px;
}
.tev-form__notice--err { color: #B3200A; }
.tev-form__rgpd { font-size: 12px; line-height: 16px; opacity: .85; }

/* Case de consentement RGPD, juste au-dessus du bouton d'envoi.
   La case reste NATIVE, simplement teintée : dessiner une coche à la main
   demanderait une icône que la maquette ne fournit pas, et le natif garde
   le comportement d'accessibilité du navigateur. */
.tev-form__consent { margin: 0; }
.tev-consent {
	display: flex; align-items: flex-start; gap: 12px; cursor: pointer;
	font-size: 12px; line-height: 17px; color: inherit; opacity: .92;
}
/* ⚠️ Le socle du formulaire pose `appearance: none`, un rayon de 30 px et un
   padding sur TOUS ses champs : sans cette reprise, la case sortait en pastille
   de 34 x 27 px, sans coche. On rend l'apparence native (la coche est alors
   dessinée par le navigateur, aucune icône à inventer) et on la teinte en crème
   pour qu'elle se voie sur l'orange de la section. Sélecteur porté par le
   conteneur (0-3-1), jamais un `!important` — piège consigné dans la skill
   formulaires-standard. */
.tev-form .tev-consent input[type="checkbox"] {
	flex: 0 0 auto;
	appearance: auto; -webkit-appearance: auto;
	width: 17px; height: 17px; min-height: 0; margin: 0 0 0 0; padding: 0;
	border: 0; border-radius: 3px; background: none;
	accent-color: var(--tev-cream); cursor: pointer;
}
.tev-consent__texte a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.tev-consent__texte a:hover { color: var(--tev-orange); }
.tev-consent input:focus-visible { outline: 3px solid var(--tev-orange); outline-offset: 2px; }

/* =========================================================================
   Pied de page
   ========================================================================= */
.tev-footer {
	position: relative; background: var(--tev-blue); color: var(--tev-cream);
	padding-block: 80px 60px; overflow: hidden;
}
.tev-footer__inner { position: relative; z-index: 1; }
.tev-footer__top { display: flex; align-items: flex-end; justify-content: space-between; gap: 40px; }
.tev-footer__baseline { font-family: var(--tev-font-title); font-size: 26px; line-height: 33px; }
.tev-footer__brand { position: relative; width: 305px; height: 123px; flex: 0 0 auto; }
.tev-footer__mount { position: absolute; top: 0; right: 0; width: 293px; height: auto; color: #fff; opacity: .25; }
.tev-footer__word  { position: absolute; bottom: 0; left: 0; width: 302px; height: auto; color: #fff; }
.tev-footer__mid { display: flex; align-items: flex-start; justify-content: space-between; gap: 40px; margin-top: 60px; }
.tev-footer__contact { display: flex; flex-direction: column; gap: 24px; }
.tev-footer__tel { display: inline-flex; align-items: center; gap: 6px; font-family: var(--tev-font-title); font-size: 20px; line-height: 22px; }
.tev-footer__tel-icon { width: 16px; height: 16px; color: var(--tev-orange); }
.tev-footer__addr { font-family: var(--tev-font-title); font-size: 16px; line-height: 17px; text-transform: uppercase; }
.tev-footer__list { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.tev-footer__list li { display: flex; align-items: center; gap: 20px; font-size: 16px; line-height: 19px; font-weight: 700; }
.tev-footer__list li + li::before { content: ""; width: 12px; height: 12px; border-radius: 50%; background: var(--tev-orange); opacity: .8; }
.tev-footer__list a:hover, .tev-footer__legal-list a:hover { text-decoration: underline; }
/* La ligne du bas n'occupe pas toute la largeur : la maquette la cale à droite,
   la mention « Réalisé par Commpagnie » commençant vers le milieu (x=553) pour
   ne pas se retrouver sous l'adresse postale, et les liens légaux la suivant
   (x=932). D'où l'alignement à droite plutôt qu'un `space-between`. */
.tev-footer__bottom { display: flex; align-items: center; justify-content: flex-end; gap: 56px; margin-top: 66px; flex-wrap: wrap; }
.tev-footer__copy { font-family: 'Outfit', var(--tev-font-body); font-weight: 600; font-size: 14px; line-height: 18px; }
.tev-footer__signature { text-decoration: underline; text-underline-offset: 3px; }
.tev-footer__signature:hover { color: var(--tev-orange); }
.tev-footer__legal-list { display: flex; gap: 40px; flex-wrap: wrap; font-size: 13px; line-height: 16px; font-weight: 600; }

/* =========================================================================
   Responsive
   ========================================================================= */
@media (max-width: 1439px) {
	:root { --tev-gutter: 48px; }
	.tev-hero__media { left: 8%; width: 84%; }
	.tev-offre { padding-left: 48px; }
	.tev-avis__list { --tev-avi-step: 330px; --tev-avi-w: 400px; --tev-avi-s: .548; }
}

/* Portables de 1280 et moins : le carrousel d'avis doit garder ses cinq cartes
   lisibles, et les étapes voisines doivent rester des amorces en bord d'écran
   plutôt que des mots coupés en deux. */
/* ⚠️ Sur les avis, c'est l'ÉCART entre les cartes qui se resserre, pas la carte
   active : la rétrécir sous ~380 px rend sa colonne de texte si étroite que la
   citation déborde sous la carte (essayé à 320 px). Les deux cartes des
   extrémités restent coupées par le bord — c'est déjà le cas en maquette. */
@media (max-width: 1280px) {
	.tev-avis__list { --tev-avi-step: 300px; --tev-avi-s: .5; }
	.tev-avi__card { padding: 40px 44px; }
}

@media (max-width: 1200px) {
	.tev-header__right { margin-left: 32px; gap: 20px; }
	.tev-nav__list { gap: 18px; }
}

/* Petits portables : sous 1120 px la carte orange (1198 en maquette) tient
   encore grâce à l'élasticité des colonnes, mais le titre a besoin d'un cran
   de moins pour rester sur deux lignes. */
@media (min-width: 1025px) and (max-width: 1120px) {
	.tev-offre { padding: 28px 28px 28px 40px; }
	.tev-offre__heading { font-size: 24px; line-height: 31px; }
	.tev-offre__text { gap: 28px; }
	.tev-offre__text > .tev-btn { margin-top: 12px; }
	.tev-avis__list { --tev-avi-step: 265px; --tev-avi-w: 380px; --tev-avi-s: .474; }
	.tev-avi__card { padding: 36px 36px; min-height: 0; }
	.tev-avi__note { font-size: 22px; line-height: 30px; }
}

@media (max-width: 1024px) {
	:root { --tev-gutter: 32px; --tev-slant: 24px; }

	.tev-nav, .tev-header__right { display: none; }
	.tev-burger { display: flex; margin-left: auto; color: var(--tev-cream); }
	.tev-header.is-open .tev-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
	.tev-header.is-open .tev-burger span:nth-child(2) { opacity: 0; }
	.tev-header.is-open .tev-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
	.tev-mobile-nav {
		display: block; position: absolute; inset: 100% 0 auto; background: var(--tev-blue);
		padding: 24px var(--tev-gutter) 32px; box-shadow: 0 18px 40px rgba(15, 20, 60, .28);
	}
	.tev-mobile-nav[hidden] { display: none; }
	/* Déroulé du haut vers le bas (01/10/2026). La découpe s'ouvre de haut en bas ;
	   la marge négative de l'état ouvert laisse passer l'ombre portée. Les liens
	   suivent avec un léger décalage. `hidden` n'est posé qu'en fin de fermeture
	   (app.js), sinon il n'y aurait rien à animer. */
	.tev-mobile-nav {
		clip-path: inset(0 0 100% 0);
		transition: clip-path .45s cubic-bezier(.22, .61, .36, 1);
	}
	.tev-header.is-open .tev-mobile-nav { clip-path: inset(0 -60px -60px -60px); }
	.tev-mobile-nav__list > li, .tev-mobile-nav__tel {
		opacity: 0; transform: translateY(-10px);
		transition: opacity .3s ease, transform .3s ease;
	}
	.tev-header.is-open .tev-mobile-nav__list > li,
	.tev-header.is-open .tev-mobile-nav__tel { opacity: 1; transform: none; }
	.tev-header.is-open .tev-mobile-nav__list > li:nth-child(1) { transition-delay: .08s; }
	.tev-header.is-open .tev-mobile-nav__list > li:nth-child(2) { transition-delay: .13s; }
	.tev-header.is-open .tev-mobile-nav__list > li:nth-child(3) { transition-delay: .18s; }
	.tev-header.is-open .tev-mobile-nav__list > li:nth-child(4) { transition-delay: .23s; }
	.tev-header.is-open .tev-mobile-nav__list > li:nth-child(5) { transition-delay: .28s; }
	.tev-header.is-open .tev-mobile-nav__list > li:nth-child(n+6),
	.tev-header.is-open .tev-mobile-nav__tel { transition-delay: .33s; }
	.tev-mobile-nav__list { display: flex; flex-direction: column; gap: 18px; margin-bottom: 24px; }
	.tev-mobile-nav__list a { font-size: 18px; font-weight: 700; color: var(--tev-cream); }
	.tev-mobile-nav__tel { display: block; font-family: var(--tev-font-title); font-size: 20px; color: var(--tev-cream); margin-bottom: 20px; }

	/* En colonne, le visuel repasse sous le titre (l'ordre du DOM le place avant
	   pour que le masque le recouvre sur grand écran). */
	/* Réserve sous la vidéo (01/10/2026) : avec 24 px, la coupe en biais du bas de
	   la scène (`--tev-slant`) mordait le pied de la montagne et la moitié du
	   bouton pause, placé par rapport à la scène et non à la vidéo. */
	.tev-hero__stage {
		height: auto; min-height: 0; max-height: none; padding-bottom: calc(var(--tev-slant) + 64px);
		display: flex; flex-direction: column;
	}
	.tev-hero__content { order: 1; }
	.tev-hero__media { order: 2; }
	.tev-hero__content { padding-top: 150px; }
	.tev-hero__title { width: 100%; font-size: 30px; line-height: 34px; }
	.tev-badge { margin-top: 28px; }
	.tev-hero__media {
		position: relative; inset: auto; width: 100%; height: auto;
		aspect-ratio: 1071 / 507; margin-top: 24px;
		-webkit-mask-position: center, -999px -999px; mask-position: center, -999px -999px;
		-webkit-mask-size: 100% 100%, 0 0; mask-size: 100% 100%, 0 0;
	}
	.tev-hero__pause { bottom: calc(var(--tev-slant) + 14px); right: var(--tev-gutter); }
	/* Découpe vectorielle posée par app.js (01/10/2026) : le masque d'image est
	   alors retiré, c'est le `clip-path` qui dessine la montagne. */
	.tev-hero__media.tev-hero__media--decoupe { -webkit-mask-image: none; mask-image: none; overflow: visible; }
	/* La vidéo couvre la scène entière (hauteur et décalage posés par app.js) : la
	   montagne n'est plus tranchée par le cadre du média quand elle grandit. */
	.tev-hero__media--decoupe > video, .tev-hero__media--decoupe > img {
		position: absolute; left: 0; width: 100%;
	}
	/* Halos sans filtre (01/10/2026) : un flou de 90 px sur un calque animé en
	   continu se recalcule à chaque image, ce que l'iPhone paie pendant le
	   défilement. Même lumière en dégradé radial, agrandi de la portée du flou. */
	.tev-hero__halo { filter: none; background: radial-gradient(closest-side, rgba(255, 255, 255, .066) 0%, rgba(255, 255, 255, .058) 35%, rgba(255, 255, 255, .03) 62%, rgba(255, 255, 255, 0) 100%); }
	.tev-hero__halo--1 { width: 780px; height: 780px; top: -340px; left: calc(14% - 180px); }
	.tev-hero__halo--2 { width: 640px; height: 640px; top: calc(38% - 150px); right: calc(8% - 150px); }
	.tev-hero__band { margin-top: 24px; padding-block: 64px 72px; }
	.tev-hero__band-inner { flex-direction: column; gap: 32px; }
	.tev-hero__lead { font-size: 18px; line-height: 24px; }
	.tev-hero__band-line { display: none; }

	.tev-stats { margin-top: -24px; padding-block: 80px 72px; clip-path: polygon(0 0, 100% 0, 100% calc(100% - 24px), 0 100%); }
	.tev-stats__inner { flex-direction: column; gap: 56px; }
	.tev-stats__title { font-size: 28px; line-height: 34px; }
	.tev-stats__list, .tev-stats__left, .tev-marquee { width: 100%; }

	.tev-offres { padding-block: 88px 80px; }
	.tev-offres__title { margin-bottom: 48px; }
	.tev-offres__title { position: static; }
	.tev-offres__queue { display: none; }
	.tev-offre { position: relative; top: auto; transform: none; padding: 24px; margin-bottom: 24px; }
	.tev-offre--blue, .tev-offre--orange { width: 100%; }
	.tev-offre__body { flex-direction: column-reverse; gap: 28px; }
	/* 🛑 En colonne, une `flex-basis` ne règle plus la LARGEUR mais la HAUTEUR :
	   le `flex: 1 1 426px` du bloc de texte lui imposait 426 px de haut quel que
	   soit son contenu, d'où la grande zone vide sous le bouton en tablette
	   (16/09/2026). Même piège sur les cartes de réalisations et d'animations.
	   À vérifier systématiquement quand une rangée passe en colonne. */
	.tev-offre__text { flex: 0 1 auto; width: 100%; gap: 20px; }
	.tev-offre__text > .tev-btn { margin-top: 8px; }
	.tev-offre__media, .tev-offre--orange .tev-offre__media {
		flex: 0 0 auto; width: 100%; aspect-ratio: 16 / 10;
	}
	.tev-offre__heading { font-size: 26px; line-height: 30px; }
	.tev-offre__desc { font-size: 16px; }
	.tev-offres__cta { margin-top: 48px; }

	.tev-anims { padding-block: 72px 80px; }
	.tev-anims__head { flex-direction: column; align-items: flex-start; gap: 20px; }
	.tev-anims__viewport { height: auto; overflow: visible; }
	.tev-anims__viewport::before, .tev-anims__viewport::after { display: none; }
	.tev-anims__list { transform: none !important; }
	.tev-anims__nav { display: none; }
	.tev-anim, .tev-anim:nth-child(even) { flex-direction: column; gap: 20px; opacity: 1; transform: none; filter: none; }
	.tev-anim__media { flex: 0 0 auto; max-width: 100%; width: 100%; }
	.tev-anim__body { flex: 0 1 auto; width: 100%; }   /* cf. piège de la flex-basis en colonne */

	.tev-reas { padding-block: 96px 88px; }
	.tev-reas__title { margin-bottom: 48px; }
	.tev-reas__title--chapo { margin-bottom: 20px; }
	.tev-reas__chapo { margin-bottom: 48px; gap: 12px; }
	.tev-reas__chapo p { font-size: 15px; line-height: 24px; }
	.tev-reas__carousel { gap: 8px; }
	.tev-rea { flex-direction: column; gap: 24px; padding: 20px; transform: none; }
	.tev-rea:nth-child(even) { transform: none; }
	.tev-rea__text { flex: 0 1 auto; width: 100%; }   /* cf. piège de la flex-basis en colonne */
	.tev-rea__media { flex: 0 0 auto; width: 100%; max-width: 100%; }
	.tev-reas__dots { margin-top: 40px; }
	.tev-reas__cta { margin-top: 56px; }

	.tev-galerie { padding-bottom: 80px; }

	.tev-equipe { padding-block: 88px 80px; }
	.tev-equipe__title { font-size: 26px; line-height: 32px; margin-bottom: 48px; }
	.tev-equipe__list { gap: 40px; }
	/* Le numéro repasse au-dessus du texte : une colonne de 96 px à gauche
	   ne laisserait plus qu'un filet de texte. */
	.tev-equipe__bloc { grid-template-columns: minmax(0, 1fr); row-gap: 14px; padding-top: 28px; }
	.tev-equipe__num { grid-row: auto; font-size: 32px; line-height: 32px; }
	.tev-equipe__accroche { grid-column: 1; font-size: 19px; line-height: 26px; }
	.tev-equipe__mont { top: -40px; right: -180px; width: 520px; }
	/* Les étapes s'empilent en colonne sur petit écran : des cercles
	   concentriques n'ont plus de centre à souligner, et ceux de la maquette
	   (697 et 536 px) déborderaient d'un écran de 390. Cette règle visait les
	   3e et 4e cercles, qui n'existent plus depuis le 10/09/2026. */

	.tev-avis { padding-block: 88px 80px; }
	.tev-avis__title { margin-bottom: 48px; }
	.tev-avis__list { min-height: 0; }
	.tev-avis__list > .tev-avi { display: none; }
	/* Une seule carte visible : plus besoin du positionnement absolu qui sert
	   au recentrage circulaire du bureau, sinon la carte se centre sur toute
	   la hauteur de la section au lieu de suivre le flux normal. */
	.tev-avis__list > .tev-avi.is-active { display: block; position: static; width: 100%; transform: none; }
	/* ⚠️ Spécificité : `.tev-avi.is-active .tev-avi__card` (0-2-0) pose le
	   rotate(-1deg) plus haut dans le fichier — un `.tev-avi__card` (0-1-0) ne
	   l'écraserait pas, media query ou pas. */
	.tev-avi__card { padding: 32px 28px; min-height: 0; }
	.tev-avi.is-active .tev-avi__card { transform: none; }
	/* L'avatar est posé en absolu dans le coin : sur une carte étroite, le nom
	   passait dessous. On lui réserve sa place. */
	.tev-avi__avatar { width: 64px; height: 64px; right: 24px; bottom: 24px; }
	.tev-avi__author { padding-right: 84px; }

	.tev-contact { margin-top: -24px; padding-block: 88px 88px; clip-path: polygon(0 24px, 100% 0, 100% 100%, 0 100%); }
	.tev-contact__inner { gap: 40px; }
	.tev-contact__title { font-size: 22px; line-height: 28px; }

	.tev-footer__top { flex-direction: column; align-items: flex-start; gap: 32px; }
	.tev-footer__brand { width: 220px; height: 90px; }
	.tev-footer__mount { width: 210px; }
	.tev-footer__word { width: 218px; }
	.tev-footer__mid { flex-direction: column; gap: 32px; margin-top: 40px; }
	.tev-footer__bottom { flex-direction: column; align-items: flex-start; gap: 20px; margin-top: 40px; }
}

@media (max-width: 640px) {
	:root { --tev-gutter: 20px; }
	/* Titres remontés d'un cran : à 20 px un titre de section en Archivo Black
	   tout en capitales se lit mal sur un téléphone, il se confond avec le
	   corps de texte en gras. */
	.tev-hero__title { font-size: 28px; line-height: 33px; }
	.tev-hero__lead { font-size: 16px; line-height: 22px; }
	/* `text-wrap: balance` évite les fins de titre orphelines sur deux mots —
	   « Nos offres sur-mesures » laissait le « : » seul sur sa ligne. Ignoré par
	   les navigateurs qui ne le connaissent pas, sans repli à prévoir. */
	.tev-h2, .tev-offres__title, .tev-anims__title, .tev-reas__title, .tev-avis__title, .tev-contact__title {
		font-size: 22px; line-height: 28px; text-wrap: balance;
	}
	.tev-stats__title { font-size: 24px; line-height: 32px; }
	/* Le pictogramme est INLINE dans le titre : gardé à 63 px, il dépasse de
	   deux fois la hauteur de ligne et disloque le mot qui l'entoure. */
	.tev-stats__picto { width: 42px; height: 40px; border-radius: 14px; transform: translateY(-2px); }
	.tev-stats__picto svg { width: 27px; height: 17px; }
	.tev-stats__value { font-size: 40px; line-height: 44px; }
	.tev-stats__label { font-size: 16px; line-height: 20px; }
	/* Les chiffres sont alignés à droite en maquette parce qu'ils occupent la
	   colonne de droite. Empilés sous un titre aligné à gauche, ils flottaient
	   seuls contre le bord opposé. */
	.tev-stats__item { align-items: flex-start; text-align: left; }
	.tev-form__row { flex-direction: column; }
	.tev-form__row--half > * { flex: 1 1 auto; }
	.tev-reas__cta { flex-direction: column; align-items: stretch; }
	.tev-reas__cta .tev-btn { justify-content: center; }
	.tev-badge { width: 88px; height: 88px; }
	.tev-badge__text { width: 68px; height: 68px; }

	/* Carrousel des réalisations : les flèches passent SOUS la carte. Placées
	   de part et d'autre, elles ne laissaient que 250 px de large à la carte sur
	   un écran de 390 et se superposaient à son texte. Même correction que celle
	   déjà faite sur la landing du site de production. */
	.tev-reas__carousel { flex-wrap: wrap; justify-content: center; gap: 20px; }
	.tev-reas__viewport { order: 1; flex: 0 0 100%; }
	.tev-reas__carousel > .tev-arrow { order: 2; }

	/* Galerie : sur un téléphone, une pile au format paysage de la maquette ne
	   remplissait qu'un cinquième de l'écran pendant que la page restait figée —
	   beaucoup de vide pour trois photos. Format carré et pile plus large (à
	   cette taille l'inclinaison n'est plus que de ±1,7°, elle n'a plus besoin
	   des 14 % de réserve des écrans intermédiaires). */
	.tev-galerie__stack { width: min(984px, 92%); aspect-ratio: 1 / 1; }
}

/* --- mouvement réduit --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after {
		animation-duration: .001ms !important; animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
	}
	.tev-marquee__track { animation: none; }

	/* Sans animation, les étapes ne peuvent plus défiler au même endroit :
	   elles s'affichent les unes sous les autres. */
	.tev-etapes__list { height: auto; display: flex; flex-direction: column; gap: 32px; }
	.tev-etape { position: relative; left: auto; margin-inline: auto; transform: none; opacity: 1; pointer-events: auto; }
	.tev-etape .tev-etape__num { font-size: 46px; line-height: 60px; }
	.tev-etape.is-active .tev-etape__num { font-size: 64px; line-height: 76px; }
	.tev-etape.is-active .tev-etape__label { font-size: 24px; line-height: 32px; }
}

/* =========================================================================
   Pages de contenu (mentions légales, confidentialité, remerciement)
   La maquette ne les dessine pas : elles reprennent la charte de la page
   d'accueil dans une largeur de lecture, sans rien inventer de plus.
   ========================================================================= */
.tev-page {
	background: var(--tev-cream);
	/* l'en-tête est fixé : sans cette réserve, le titre passe dessous */
	padding: calc(150px + var(--tev-bar-offset, 0px)) 0 120px;
}
.tev-page__inner { max-width: 800px; }
.tev-page__title {
	font-family: var(--tev-font-title);
	font-size: 40px;
	line-height: 46px;
	color: var(--tev-blue);
	margin: 0 0 40px;
}
.tev-page__body { color: var(--tev-grey); font-size: 16px; line-height: 28px; }
.tev-page__body h2 {
	font-family: var(--tev-font-title);
	font-size: 22px;
	line-height: 30px;
	color: var(--tev-blue);
	margin: 44px 0 14px;
}
.tev-page__body h3 { font-family: var(--tev-font-form); font-weight: 700; font-size: 17px; color: var(--tev-blue); margin: 30px 0 10px; }
.tev-page__body p, .tev-page__body ul, .tev-page__body ol { margin: 0 0 18px; }
.tev-page__body ul, .tev-page__body ol { padding-left: 22px; }
.tev-page__body li { margin-bottom: 8px; }
.tev-page__body a { color: var(--tev-orange); text-decoration: underline; }
.tev-page__body strong { color: var(--tev-blue); }
.tev-page__retour { display: inline-flex; margin-top: 40px; }

@media (max-width: 1024px) {
	.tev-page { padding: calc(110px + var(--tev-bar-offset, 0px)) 0 80px; }
	.tev-page__title { font-size: 30px; line-height: 36px; }
}

/* =========================================================================
   Curseur personnalisé
   Demande de Clémence (frame 271:44) : « En remplacement de la flèche
   standard noire du curseur », précisée par « S'applique partout sur le
   site, je vous l'ai juste matérialisé ici ». Les trois matérialisations de
   la maquette sont identiques : un seul état, pas de variante de survol.
   La classe qui masque le curseur du système est posée par app.js, jamais
   ici : si le script ne tourne pas, on garde le curseur du système plutôt
   que de n'en avoir aucun.
   ========================================================================= */
.tev-cursor { display: none; }

@media (pointer: fine) {
	html.tev-has-cursor,
	html.tev-has-cursor * { cursor: none; }

	/* Les champs de saisie gardent le curseur du système : sans le I-beam,
	   on ne voit plus où l'on écrit. Idem pour les listes déroulantes, dont
	   le menu est dessiné par le système par-dessus la page. */
	html.tev-has-cursor input:not([type="submit"]):not([type="button"]):not([type="checkbox"]):not([type="radio"]),
	html.tev-has-cursor textarea,
	html.tev-has-cursor select,
	html.tev-has-cursor [contenteditable="true"] { cursor: auto; }
	/* L'icône du menu (fenêtre étroite avec souris) : la pastille blanche la masquait
	   entièrement, retour du client du 30/09/2026. Main du système à la place. */
	html.tev-has-cursor .tev-burger, html.tev-has-cursor .tev-burger * { cursor: pointer; }

	.tev-cursor {
		display: block;
		position: fixed;
		top: 0;
		left: 0;
		width: 60px;
		height: 60px;
		margin: -30px 0 0 -30px; /* le point actif est le centre du disque */
		z-index: 2147483000;
		pointer-events: none;    /* ne rien intercepter : le hero écoute la souris */
		opacity: 0;
		transition: opacity .25s var(--tev-ease);
		will-change: transform;
	}
	.tev-cursor.is-on     { opacity: 1; }
	.tev-cursor.is-native { opacity: 0; }

	.tev-cursor__svg {
		display: block;
		width: 100%;
		height: 100%;
		transform-origin: 50% 50%;
		transition: transform .22s var(--tev-ease);
	}
	.tev-cursor.is-over .tev-cursor__svg { transform: scale(1.25); }
	.tev-cursor.is-down .tev-cursor__svg { transform: scale(.88); }
}

@media (prefers-reduced-motion: reduce) {
	.tev-cursor,
	.tev-cursor__svg { transition: none; }
}

/* --- étapes : la scène animée tient jusqu'à 768 px --------------------------
   Elle était aplatie en liste dès 1024 px, en CSS comme en JS (isDesktop()).
   Résultat : sur une fenêtre de portable un peu réduite, l'animation
   disparaissait alors qu'on est bien sur un poste avec souris — ce que Lisa
   ne veut pas (16/09/2026). Le repli ne vaut donc plus que sous 768 px, et
   le seuil du JS a suivi (assets/js/app.js, bloc `etapes`). */
/* ⚠️ Sous 768 px, la scène des étapes garde le MÊME mécanisme qu'au bureau —
   épinglée, une étape à la fois qui glisse (demande de Lisa, 18/09/2026 : « met
   l'animation desktop »). Elle était auparavant aplatie en simple pile. Seules
   les tailles changent, plus deux réglages propres au petit écran :
   – les cercles sont exprimés en `vw` et non en pixels (697 px sur un écran de
     390 traversaient l'écran en grands arcs — défaut relevé le 10/09/2026, qui
     avait conduit à les masquer purement et simplement) ;
   – les étapes voisines sont poussées bien plus loin (70vw au lieu de 48), sans
     quoi elles chevauchent l'étape active sur un écran étroit. */
@media (max-width: 767px) {
	.tev-etapes__inner { padding-block: 64px; gap: 48px; }
	.tev-etape__num { font-size: 40px; line-height: 48px; }
	.tev-etape.is-active .tev-etape__num { font-size: 56px; line-height: 64px; }
	.tev-etape.is-active .tev-etape__label { font-size: 22px; line-height: 30px; }
	.tev-etapes__cta { align-self: center; }
	.tev-etapes__rings span:nth-child(1) { width: 92vw; height: 92vw; }
	.tev-etapes__rings span:nth-child(2) { width: 68vw; height: 68vw; }
}
/* Entre 768 et 1024, la scène reste animée : les étapes voisines s'écartent
   en pourcentage de la fenêtre, donc elles restent hors champ. */

/* --- Fil d'Ariane --------------------------------------------------------
   🛑 Ce socle vivait dans `seo.css`, la feuille des seules pages de
   référencement. Or `tev_fil_ariane()` est un composant GÉNÉRIQUE, que
   n'importe quel gabarit peut rendre : la page Contact, créée le 22/09/2026,
   l'a affiché en LISTE À PUCES EMPILÉE, sans séparateur, parce qu'elle ne
   charge pas cette feuille. Le style d'un composant partagé appartient à la
   feuille globale ; seules ses déclinaisons contextuelles (couleurs claires
   sur la bannière bleue) restent dans `animations.css`. */

.tev-ariane__list {
	display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
	list-style: none; margin: 0; padding: 0;
	font-family: var(--tev-font-body);
	font-size: 13px; line-height: 20px; color: var(--tev-grey);
	margin-bottom: 0;
}

.tev-ariane__item + .tev-ariane__item::before {
	content: "\203A";
	margin-right: 10px;
	color: var(--tev-tint-line);
}

.tev-ariane__item a { color: inherit; text-decoration: none; }
.tev-ariane__item a:hover { color: var(--tev-orange); text-decoration: underline; }
.tev-ariane__item [aria-current] { color: var(--tev-blue); font-weight: 600; }

/* Bloc de maillage vers les pages de référencement (parts/seo-maillage.php).
   Composant générique depuis le 30/09/2026 : accueil, Animations, Événements, pages SEO. */
/* --- maillage ------------------------------------------------------------ */

.tev-seo-maillage {
	background: var(--tev-tint);
	padding: 72px 0;
}

.tev-seo-maillage__titre { color: var(--tev-blue); margin: 0 0 16px; }

.tev-seo-maillage__chapo {
	font-family: var(--tev-font-body);
	font-size: 16px; line-height: 28px; color: var(--tev-grey);
	margin: 0 0 28px; max-width: 68ch;
}

.tev-seo-maillage__list {
	list-style: none; margin: 0; padding: 0;
	display: grid; gap: 12px;
	grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}

.tev-seo-maillage__lien {
	display: flex; align-items: center; justify-content: space-between; gap: 16px;
	padding: 16px 20px;
	background: var(--tev-white);
	border: 1px solid transparent;
	border-radius: var(--tev-radius-img);
	font-family: var(--tev-font-form);
	font-size: 15px; line-height: 22px; font-weight: 600;
	color: var(--tev-blue);
	text-decoration: none;
	transition: border-color .2s var(--tev-ease), transform .2s var(--tev-ease);
}
.tev-seo-maillage__lien:hover {
	border-color: var(--tev-orange);
	transform: translateY(-2px);
}
.tev-seo-maillage__fleche { width: 16px; height: 14px; color: var(--tev-orange); flex: 0 0 auto; }
@media (max-width: 767px) { .tev-seo-maillage { padding: 48px 0; } }
