/* ==========================================================================
   Landing « Formation IA & Automatisation » — Inperfect
   --------------------------------------------------------------------------
   Calquée sur inperfect.webflow.io : contenu centré, fonds travaillés
   (filets verticaux, arcs de cercle, nappes mauves diffuses),
   cartes à grand rayon, un seul bloc sombre, boutons pilule en dégradé
   mauve vers indigo avec flèche.

   ⚠ Écart assumé à la charte PDF : le dégradé des boutons va du mauve vers
   un indigo, comme le bouton « Planifier un appel » du site de l'agence.
   Le PDF Style Guide V01 n'autorise que noir, blanc et mauve. L'arbitrage
   vient du client, sur capture du site officiel. Les deux extrémités du
   dégradé passent le contraste AA avec le libellé blanc (5,2:1 et 8,9:1).

   Le pattern hybride Gilroy Medium + Apple Garamond Italic s'applique au H1
   et à tous les titres de section (.hybride).
   ========================================================================== */

:root {
  /* ⚠ Les couleurs, l'accent et le dégradé du CTA sont désormais définis
     dans tokens.css, sur la charte officielle (InperfectEms/inperfect-dev) :
     noir #171717, Opera Mauve #AA78A6. Ne rien redéfinir ici, ce bloc
     écraserait la charte. */
  --gradient-accent: linear-gradient(100deg,
    var(--mauve-80) 0%, var(--accent-b) 50%, var(--mauve-80) 100%);

  --arrow-color: var(--noir);

  --radius-card-lg: 24px;
  --radius-panel:   32px;
  --radius-media:   20px;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  line-height: var(--leading-relaxed);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.nav-open { overflow: hidden; }

/* ---- Défilement fluide (Lenis) ------------------------------------------
   Ces règles sont le contrat de la bibliothèque : elles ne s'appliquent
   qu'une fois les classes posées par Lenis lui-même. Sans script, ou en
   mouvement réduit, rien ne change et le défilement reste natif.
   `scroll-behavior: auto` est indispensable : le lissage natif et celui de
   Lenis se combattent, et l'ancre finit par osciller. */
html.lenis,
html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
/* Zones qui gardent leur défilement propre (à baliser avec
   `data-lenis-prevent`) : le geste ne doit pas fuir vers la page. */
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

img, picture { max-width: 100%; display: block; }
img { height: auto; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-snug);
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }
ul, ol, dl, dd { margin: 0; padding: 0; }
li { list-style: none; }
a { color: inherit; }

:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-xs);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: var(--space-2);
  z-index: 40;
  background: var(--blanc);
  color: var(--text-primary);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-control);
  font-weight: var(--weight-medium);
}
.skip-link:focus { left: var(--space-4); }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
/* La marque officielle est au trait, donc optiquement plus légère que le
   glyphe plein qu'elle remplace : 20px au lieu de 18 pour qu'elle tienne
   son poids à côté du libellé. */
.wa { width: 20px; height: 20px; flex: none; fill: currentColor; }

/* ---- Conteneur centré --------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: 1120px;
  margin-inline: auto;
  padding-inline: var(--space-5);
  position: relative;
  z-index: 1;
}

@media (min-width: 769px) {
  .wrap { padding-inline: var(--space-10); }
}

/* ==========================================================================
   MOTIFS DE FOND
   Chaque motif est un <span class="dec"> posé sous le contenu. Aucun n'est
   décoratif au hasard : filets verticaux sur les sections de texte, arcs de
   cercle sur les panneaux, anneaux mauves dans le bloc sombre. Les trames
   horizontales ont été retirées : elles n'apportaient rien et se battaient
   avec les filets des séparateurs.
   ========================================================================== */
.dec {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  border-radius: inherit;
}

/* Trame verticale */
.dec--vlines {
  background-image: repeating-linear-gradient(
    90deg, var(--hairline-soft) 0 1px, transparent 1px 12.5%);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent);
          mask-image: linear-gradient(180deg, transparent, #000 14%, #000 86%, transparent);
}

/* Arcs de cercle en filet, comme sur le panneau « Pourquoi nous ? ».
   Les deux arcs partagent le même centre : ils sont réellement
   concentriques, et c'est le débord hors du cadre qui les découpe. */
.dec--arcs::before,
.dec--arcs::after {
  content: "";
  position: absolute;
  border: 1px solid var(--hairline);
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

/* Centre sous le coin bas droit */
.dec--arcs-br::before,
.dec--arcs-br::after { left: 86%; top: 116%; }
.dec--arcs-br::before { width: 720px; height: 720px; }
.dec--arcs-br::after  { width: 940px; height: 940px; }

/* Centre au-dessus du coin haut gauche */
.dec--arcs-bl::before,
.dec--arcs-bl::after { left: 12%; top: -14%; }
.dec--arcs-bl::before { width: 620px; height: 620px; }
.dec--arcs-bl::after  { width: 830px; height: 830px; }

/* Centre sur le bord bas du panneau : on ne voit que la calotte
   supérieure, exactement comme sur la carte « Pourquoi nous ? ». */
.dec--arcs-panel::before,
.dec--arcs-panel::after { left: 72%; top: 100%; }
.dec--arcs-panel::before { width: 520px; height: 520px; }
.dec--arcs-panel::after  { width: 660px; height: 660px; }

/* Anneaux mauves du bloc sombre */
.dec--rings::before,
.dec--rings::after {
  content: "";
  position: absolute;
  border: 1px solid rgba(179, 135, 175, 0.18);
  border-radius: 50%;
}
.dec--rings::before { width: 900px;  height: 900px;  left: -300px; top: -300px; }
.dec--rings::after  { width: 1180px; height: 1180px; right: -420px; bottom: -520px; }

/* Sur fond sombre les filets s'inversent. */
.section--dark .dec--arcs::before,
.section--dark .dec--arcs::after,
.closing .dec--arcs::before,
.closing .dec--arcs::after { border-color: var(--hairline-light); }

@media (max-width: 640px) {
  .dec--arcs::after { display: none; }   /* un seul arc suffit sur mobile */
}

/* ---- Sections & nappes -------------------------------------------------- */
.section {
  position: relative;
  isolation: isolate;
  padding-block: var(--space-16);
  /* La barre collante compte désormais le bandeau haut : les ancres
     doivent s'arrêter en dessous, pas derrière. */
  /* Hauteur de la barre + son décalage haut, depuis qu'elle flotte. */
  scroll-margin-top: 116px;
}

@media (min-width: 1025px) {
  .section { padding-block: var(--space-24); scroll-margin-top: 132px; }
}

/* Le hero se termine sur le bandeau clients, qui porte déjà son propre air.
   Son padding bas s'ajoutait à celui de la section suivante ET au séparateur :
   près de 250px de vide entre les logos et le titre. On coupe ici. */
.section--hero { padding-top: var(--space-12); padding-bottom: var(--space-8); }

/* ---- Ligne de flottaison mobile ----------------------------------------
   Sur un écran de 640px de haut, le bouton d'appel se retrouvait coupé :
   personne ne le voyait sans faire défiler. On resserre les espaces du hero
   pour le faire remonter au-dessus de la ligne. Rien n'est supprimé, tout
   respire simplement un cran plus serré. */
@media (max-width: 768px) {
  .section--hero { padding-top: var(--space-6); padding-bottom: var(--space-6); }
  .section--hero .voyant { margin-bottom: var(--space-3); }
  .section--hero .eyebrow { margin-bottom: var(--space-3); }
  .section--hero .lead { margin-top: var(--space-3); }
  .section--hero .head__cta { margin-top: var(--space-5); }
  .section--hero .micro { margin-top: var(--space-3); }
}

@media (min-width: 1025px) {
  .section--hero { padding-bottom: var(--space-10); }
}

/* La section qui suit immédiatement le hero ouvre sur un séparateur décoratif,
   pas sur du contenu : les 96px du rythme normal s'y ajoutent pour rien.
   Les sections suivantes, elles, gardent la trame commune. */
.section--hero + .section { padding-top: var(--space-10); }
@media (min-width: 1025px) {
  .section--hero + .section { padding-top: var(--space-12); }
}

.bloom::before {
  content: "";
  position: absolute;
  inset: -10% -5%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(48% 42% at 8% 4%,   rgba(179,135,175,.40), transparent 72%),
    radial-gradient(42% 38% at 96% 10%, rgba(179,135,175,.32), transparent 72%),
    radial-gradient(46% 40% at 88% 96%, rgba(179,135,175,.24), transparent 72%);
  filter: blur(10px);
}
.bloom--soft::before {
  background:
    radial-gradient(46% 40% at 96% 12%, rgba(179,135,175,.24), transparent 74%),
    radial-gradient(42% 36% at 4% 92%,  rgba(179,135,175,.18), transparent 74%);
}

.section--dark {
  background: var(--surface-inverse);
  color: var(--text-inverse);
  overflow: hidden;
  --arrow-color: var(--mauve);
}
.section--dark::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(38% 26% at 0% 6%,    rgba(179,135,175,.32), transparent 70%),
    radial-gradient(34% 24% at 100% 52%, rgba(179,135,175,.22), transparent 70%),
    radial-gradient(40% 26% at 12% 98%,  rgba(179,135,175,.18), transparent 70%);
}

/* ==========================================================================
   SÉPARATEUR DE SECTION
   UN seul filet horizontal, qui s'estompe vers l'extérieur, et l'icône de
   la section qui s'ouvre posée dessus. Pas de médaillon, pas de cadre, pas
   d'anneau. Les fichiers sont détourés en alpha : l'icône se pose
   directement sur n'importe quel fond, y compris sur les nappes mauves,
   sans carré blanc ni liseré et sans dépendre d'un mode de fusion.
   ========================================================================== */
.divider {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  max-width: 44rem;
  margin: calc(-1 * var(--space-6)) auto var(--space-12);
}

.divider__line {
  flex: 1;
  height: 1px;
  background-image: linear-gradient(90deg, transparent, var(--hairline));
}
.divider__line:last-child {
  background-image: linear-gradient(270deg, transparent, var(--hairline));
}

.divider__badge { flex: none; display: block; }
.divider__badge img {
  width: 52px;
  height: 52px;
}

@media (min-width: 769px) {
  /* 64px sous le séparateur s'ajoutaient aux 96px de la section : le badge
     flottait au milieu d'un vide. 48px suffisent à le détacher du titre. */
  .divider { margin-bottom: var(--space-12); gap: var(--space-8); }
  .divider__badge img { width: 64px; height: 64px; }
}

/* ---- Têtes de section (centrées) ---------------------------------------- */
.head {
  max-width: 44rem;
  margin-inline: auto;
  margin-bottom: var(--space-12);
  text-align: center;
}
.head--spaced { margin-top: var(--space-20); }

/* ---- Voyant d'état ------------------------------------------------------
   Pastille blanche, point qui clignote, libellé en gras. Le point reprend
   le mauve de la marque plutôt qu'un vert de notification : la charte tient
   à trois couleurs, et le halo suffit à dire « c'est en cours ».
   ------------------------------------------------------------------------ */
.voyant {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
  padding: var(--space-2) var(--space-5) var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
}
.voyant__dot {
  position: relative;
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent-a);
  animation: voyant-blink 2s var(--ease-standard) infinite;
}
/* Halo qui s'ouvre et s'efface : le clignotement se voit sans agresser. */
.voyant__dot::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1px solid var(--accent-a);
  animation: voyant-halo 2s var(--ease-standard) infinite;
}

@keyframes voyant-blink {
  0%, 55%, 100% { opacity: 1; }
  75%           { opacity: 0.35; }
}
@keyframes voyant-halo {
  0%   { transform: scale(0.55); opacity: 0.85; }
  70%  { transform: scale(1.5);  opacity: 0; }
  100% { transform: scale(1.5);  opacity: 0; }
}

/* Le clignotement est une animation d'ambiance : on la coupe, on ne la
   raccourcit pas, sinon le point se fige à une opacité arbitraire. */
@media (prefers-reduced-motion: reduce) {
  .voyant__dot,
  .voyant__dot::after { animation: none !important; }
  .voyant__dot::after { opacity: 0.4; transform: scale(1); }
}

.eyebrow {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-5);
}
.head--inverse .eyebrow { color: var(--text-inverse-muted); }

.head h1, .head h2, .panel__title, .closing__title { font-size: var(--h2-size); }
.section--hero .head h1 {
  font-size: clamp(2.5rem, 1.7rem + 3.3vw, 3.5rem);
  letter-spacing: -0.015em;
}

/* Écrans courts (700px de haut et moins) : le bouton d'appel passait sous la
   ligne de flottaison, donc personne ne le voyait sans faire défiler. On
   réduit le titre et le texte d'accroche pour le faire remonter.
   Ce bloc doit rester APRÈS la règle ci-dessus : à spécificité égale, c'est
   l'ordre du fichier qui tranche. */
@media (max-width: 768px) and (max-height: 700px) {
  .section--hero .head h1 { font-size: 2rem; }
  .section--hero .head .lead { font-size: var(--text-base); }
  .section--hero .voyant { margin-bottom: var(--space-2); }
  .section--hero .eyebrow { margin-bottom: var(--space-2); }
}

.lead {
  margin-top: var(--space-5);
  font-size: var(--text-lg);
  color: var(--text-secondary);
  max-width: 40rem;
  margin-inline: auto;
}
/* La phrase qui doit convertir passe en couleur pleine : elle se lit avant
   le reste du paragraphe, sans changer de taille. */
.lead strong { color: var(--text-primary); font-weight: var(--weight-medium); }
.head--inverse .lead { color: var(--text-inverse-muted); }
.head--inverse .lead strong { color: var(--text-inverse); }

.head__cta { margin-top: var(--space-8); }
.micro { margin-top: var(--space-4); font-size: var(--text-sm); color: var(--text-muted); }

/* ---- Pattern signature — charte officielle ------------------------------
   Le rapport est INVERSÉ par rapport à l'ancienne charte : Apple Garamond
   porte désormais tous les titres, donc l'accent ne peut plus être du
   Garamond italique (il disparaîtrait sur lui-même). C'est le mot-clé qui
   bascule en Gilroy : le contraste serif → sans-serif tient toujours, dans
   l'autre sens. */
.hybride em {
  font-family: var(--font-sans);
  font-style: normal;
  font-weight: var(--fw-medium);
  font-size: 0.88em;   /* le Gilroy a un œil plus grand que le Garamond */
  letter-spacing: -0.01em;
}

/* ==========================================================================
   BOUTONS
   Pilule, dégradé mauve → indigo qui voyage au survol, flèche pleine qui
   glisse, élévation qui monte. Rien ne clignote, rien ne rebondit.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: var(--control-md);
  padding: var(--space-3) var(--space-6);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-position var(--duration-slow) var(--ease-standard),
              background-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard),
              color var(--duration-base) var(--ease-standard);
}
.btn:active { transform: translateY(0) scale(0.98); }

.btn--lg { min-height: var(--control-lg); padding-inline: var(--space-8); font-size: var(--text-base); }
.btn--sm { min-height: var(--control-md); padding-inline: var(--space-5); }

/* CTA principal : le noir de marque monte vers le mauve, verticalement.
   Le mauve porte l'identite sans jamais toucher le texte : le blanc repose sur
   la zone sombre du bas. Contraste de 8.1 au point le plus clair a 20.0 en bas,
   la ou un aplat mauve avec du texte blanc tomberait a 3.0.
   Ni indigo ni bleu : l'ancien bouton du site Webflow est hors charte. */
.btn--accent {
  background-color: var(--btn-accent-bottom);   /* repli si pas de dégradé */
  background-image: linear-gradient(180deg,
    var(--btn-accent-top) 0%,
    var(--btn-accent-mid) 46%,
    var(--btn-accent-bottom) 100%);
  color: var(--blanc);
  box-shadow: 0 6px 20px rgba(23, 23, 23, 0.26);
}
.btn--accent:hover {
  background-image: linear-gradient(180deg,
    var(--btn-accent-top-h) 0%,
    var(--btn-accent-mid-h) 46%,
    var(--btn-accent-bottom-h) 100%);
  transform: translateY(-2px);
  box-shadow: 0 12px 30px rgba(23, 23, 23, 0.32);
}

/* Sur fond noir, le dégradé sombre n'a plus rien contre quoi se détacher :
   le bouton se fond dans la section. On inverse, blanc plein et texte noir,
   qui redevient le point le plus contrasté de l'écran (20:1). L'ombre portée
   ne sert plus à rien sur du noir : c'est un halo mauve qui décolle le bouton. */
.section--dark .btn--accent,
.closing .btn--accent,
.footer .btn--accent {
  background-color: var(--blanc);
  background-image: none;
  color: var(--noir);
  box-shadow: 0 6px 24px rgba(179, 135, 175, 0.20);
}
.section--dark .btn--accent:hover,
.closing .btn--accent:hover,
.footer .btn--accent:hover {
  background-color: var(--mauve-20);
  background-image: none;
  box-shadow: 0 12px 32px rgba(179, 135, 175, 0.32);
}
/* L'anneau de focus mauve disparaîtrait sur un bouton blanc : on le double
   d'un liseré noir pour qu'il reste visible au clavier. */
.section--dark .btn--accent:focus-visible,
.closing .btn--accent:focus-visible,
.footer .btn--accent:focus-visible {
  box-shadow: 0 0 0 2px var(--noir), 0 0 0 5px rgba(179, 135, 175, 0.75);
}

.btn--primary { background-color: var(--noir); color: var(--text-inverse); }
.btn--primary:hover {
  background-color: var(--noir-80);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

/* Flèche pleine : hampe + pointe, en CSS. Elle glisse au survol. */
.btn__arrow {
  position: relative;
  width: 16px;
  height: 10px;
  flex: none;
  margin-left: var(--space-1);
  transition: transform var(--duration-base) var(--ease-standard);
}
.btn__arrow::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 100%; height: 1.5px;
  background: currentColor;
  transform: translateY(-50%);
}
.btn__arrow::after {
  content: "";
  position: absolute;
  right: 1px; top: 50%;
  width: 6px; height: 6px;
  border-top: 1.5px solid currentColor;
  border-right: 1.5px solid currentColor;
  transform: translateY(-50%) rotate(45deg);
}
.btn:hover .btn__arrow { transform: translateX(4px); }

.cta-center { margin-top: var(--space-12); text-align: center; }

/* CTA Livrables : libellé long — rester dans la largeur utile mobile */
[data-od-id="cta-livrables-wa"] {
  max-width: 100%;
  box-sizing: border-box;
  white-space: normal;
  padding-inline: var(--space-5);
  gap: var(--space-2);
  text-align: center;
}

/* ==========================================================================
   BARRE DE TÊTE + NAVIGATION
   ========================================================================== */
/* La barre flotte : elle se détache des bords gauche et droit et porte un
   arrondi sur les quatre coins. Un arrondi collé au bord de l'écran donne
   l'impression d'une barre trop étroite, mal calée. Le retrait latéral rend
   la forme lisible, et la bordure devient un contour complet plutôt qu'un
   simple filet sous la barre. */
.topbar {
  position: sticky;
  top: var(--space-2);
  z-index: 30;
  margin-inline: var(--space-3);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
          backdrop-filter: blur(14px) saturate(1.1);
  border: 1px solid var(--border-subtle);
  transition: box-shadow var(--duration-base) var(--ease-standard);
}
.topbar.is-stuck { box-shadow: 0 6px 24px rgba(23, 23, 23, 0.07); }

@media (min-width: 1025px) {
  .topbar { margin-inline: var(--space-5); top: var(--space-3); }
}

/* Bandeau haut : fond noir, un point mauve qui respire, et la pastille
   du compte à rebours. C'est la seule information qui suit le lecteur
   sur toute la page. */
/* Le bandeau suit les coins hauts de la barre. On n'utilise pas
   `overflow: hidden` sur la barre elle-même : cela rognerait le menu
   déroulant mobile, qui se déploie en dessous. */
.topline {
  background: var(--noir);
  color: var(--text-inverse);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide);
  border-radius: calc(var(--radius-lg) - 1px) calc(var(--radius-lg) - 1px) 0 0;
}
.topline__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  padding-block: var(--space-2);
}
.topline p { display: flex; align-items: center; gap: var(--space-3); }
.topline__strong {
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-widest);
}
.topline__session { color: var(--text-inverse-muted); }
.topline__sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.45;
}
.topline__places { color: var(--text-inverse-muted); }

/* Le point qui respire : deux secondes, sans à-coup, jamais plus. */
.topline__pulse {
  position: relative;
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--mauve);
}
.topline__pulse::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1px solid var(--mauve);
  animation: pulse 2.4s var(--ease-standard) infinite;
}
@keyframes pulse {
  0%   { transform: scale(0.6); opacity: 0.9; }
  70%  { transform: scale(1.35); opacity: 0; }
  100% { transform: scale(1.35); opacity: 0; }
}

/* Pastille du décompte.
   Le dégradé mauve-indigo des boutons était illisible ici : il est sombre,
   et le bandeau l'est aussi. Sur fond noir la pastille prend donc le mauve
   clair de la charte avec du texte noir, ce qui la fait ressortir et donne
   8,7:1 de contraste à l'intérieur. */
.jminus {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 3px var(--space-4) 4px;
  border-radius: var(--radius-pill);
  background: var(--mauve);
  color: var(--text-on-accent);
}
.jminus__value,
.jminus__unit { display: none; }
.jminus.is-live .jminus__value,
.jminus.is-live .jminus__unit { display: inline; }
.jminus.is-live .jminus__fallback { display: none; }

.jminus__value {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 15px;
  line-height: 1;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
/* Noir plein, pas noir 80 % : à 11px le noir 80 % sur mauve tombe à
   3,84:1. La hiérarchie se fait par la graisse, pas par la couleur. */
.jminus__unit,
.jminus__fallback {
  font-size: var(--text-2xs);
  font-weight: var(--weight-regular);
  color: var(--text-on-accent);
}
.jminus__fallback { letter-spacing: var(--tracking-wide); }

/* Sur petit écran le bandeau se réduit à une seule ligne courte : le point
   qui respire, la pastille et le nombre de places. La date n'est pas perdue,
   c'est la pastille qui la porte quand le décompte n'est pas encore calculé.

   ⚠ `.topline p.topline__session` et non `.topline__session` : la règle
   `.topline p { display: flex }` est plus spécifique, et une media query
   n'ajoute aucune spécificité. Sans ce renfort la ligne longue restait
   affichée et le bandeau montait à trois lignes. */
@media (max-width: 640px) {
  .topline p.topline__session { display: none; }
  .topline__inner {
    flex-wrap: nowrap;
    justify-content: center;
    gap: var(--space-3);
    padding-block: 5px;
  }
  .topline p.topline__meta { gap: var(--space-2); }
  .jminus { padding: 2px var(--space-3) 3px; gap: 4px; }
  .jminus__value { font-size: 13px; }
}

.topbar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
}

/* Progression de lecture, collée sous la barre. */
/* Rentrée dans la barre plutôt que débordante : posée à -1px, elle sortait
   des coins arrondis. Le retrait latéral la garde à l'intérieur de la forme. */
.topbar__progress {
  position: absolute;
  left: var(--space-4);
  right: var(--space-4);
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  overflow: hidden;
  background: transparent;
}
.topbar__progress span {
  display: block;
  height: 100%;
  width: 0;
  background-image: linear-gradient(90deg, var(--accent-a), var(--accent-b));
  transition: width 90ms linear;
}
/* `flex: none` sur les deux : sans lui, le conteneur flex de la barre écrase
   le logo quand la place manque. Le wordmark passait de 141px en français à
   98px en anglais, simplement parce que les libellés anglais sont plus longs.
   Un logo ne se comprime jamais : c'est la nav qui cède. */
.topbar__brand { display: inline-flex; flex: none; }
.topbar__brand img { height: 22px; width: auto; flex: none; }
.topbar__actions { display: flex; align-items: center; gap: var(--space-4); }

/* ---- Bascule de langue --------------------------------------------------
   Discrète : c'est une commodité, pas une action. Elle ne doit jamais
   concurrencer le CTA WhatsApp posé juste à côté. */
.lang {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--control-md);
  padding-inline: var(--space-3);
  background: transparent;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  color: var(--text-secondary);
  cursor: pointer;
  transition: border-color var(--duration-base) var(--ease-standard),
              color var(--duration-base) var(--ease-standard);
}
.lang:hover { border-color: var(--accent-a); color: var(--accent-a); }

/* Le drapeau porte un filet plutôt qu'une ombre : le blanc du drapeau
   français se perdrait sinon sur le fond clair de la barre. */
.lang__flag {
  width: 21px;
  height: 14px;
  flex: none;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(23, 23, 23, 0.16);
}

@media (max-width: 420px) {
  /* Très petit écran : le drapeau seul suffit, le code prendrait la place
     du bouton WhatsApp. */
  .lang__code { display: none; }
  .lang { padding-inline: var(--space-2); }
}

/* ---- Navigation ---------------------------------------------------------
   État par défaut, sans JavaScript : la navigation est dépliée sur une
   ligne qui passe à la ligne, et le bouton sandwich n'existe pas. Les liens
   restent donc toujours atteignables, même si main.js ne charge pas.

   Avec JavaScript (classe .js posée dans le <head>), elle se replie derrière
   le bouton sous 1025px. L'ouverture joue sur opacity / visibility, pas sur
   display : la transition existe et l'état est plus fiable.
   ------------------------------------------------------------------------ */
.nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  order: 3;
  width: 100%;
  padding-bottom: var(--space-2);
}
.burger { display: none; }

.js .nav {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: var(--space-5);
  right: var(--space-5);
  z-index: 5;
  order: 0;
  width: auto;
  flex-direction: column;
  flex-wrap: nowrap;
  gap: var(--space-1);
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card-lg);
  padding: var(--space-4) var(--space-5) var(--space-5);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  pointer-events: none;
  transition: opacity var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard),
              visibility 0s linear var(--duration-base);
}
/* Trois chemins d'ouverture, dont deux sans JavaScript :
   1. la classe posée par main.js ;
   2. le simple fait que le bouton ait le focus, ce qu'un clic provoque
      toujours, même si l'écouteur d'événement est intercepté ;
   3. le focus à l'intérieur du menu, pour la navigation au clavier.
   Le menu s'ouvre donc même si le script ne reçoit jamais le clic. */
.js .topbar.nav-open .nav,
.js .topbar:not(.js-nav):has(.burger:focus) .nav,
.js .topbar:has(.nav:focus-within) .nav {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition-delay: 0s;
}
.js .burger { display: grid; }

/* Voile derrière le menu ouvert : un tap n'importe où le referme. */
.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 25;
  background: rgba(23, 23, 23, 0.32);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--duration-base) var(--ease-standard),
              visibility 0s linear var(--duration-base);
}
body.nav-open .nav-scrim {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

/* ---- Rubriques ----------------------------------------------------------
   Des libellés, rien d'autre. Au survol le texte passe en gras et prend la
   couleur d'accent, avec un trait en dégradé qui pousse depuis la gauche.

   Le passage en gras ne décale rien : `::before` place une copie du libellé
   en gras, masquée et de hauteur nulle, dans la même cellule de grille. La
   largeur du lien est donc toujours celle du texte gras.
   ------------------------------------------------------------------------ */
.nav a {
  position: relative;
  display: inline-grid;
  padding: var(--space-3);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
  transition: color var(--duration-base) var(--ease-standard),
              background-color var(--duration-base) var(--ease-standard);
}
.nav a::before {
  content: attr(data-label);
  grid-area: 1 / 1;
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: var(--weight-bold);
  pointer-events: none;
}
.nav a > span { grid-area: 1 / 1; }

.nav a:hover,
.nav a[aria-current] { color: var(--accent-a); }
.nav a:hover > span,
.nav a[aria-current] > span { font-weight: var(--weight-bold); }
.nav a:hover { background-color: var(--mauve-20); }


.burger {
  /* `display` est piloté plus haut : `none` par défaut, `grid` avec .js,
     `none` à nouveau au-delà de 1025px. Ne pas le redéclarer ici. */
  width: var(--control-md);
  height: var(--control-md);
  place-items: center;
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: border-color var(--duration-base) var(--ease-standard);
}
.burger:hover { border-color: var(--accent-a); }
.burger span, .burger span::before, .burger span::after {
  display: block;
  width: 17px;
  height: 1.5px;
  background: var(--noir);
  border-radius: 2px;
  transition: transform var(--duration-base) var(--ease-standard),
              opacity var(--duration-fast) var(--ease-standard);
}
.burger span { position: relative; }
.burger span::before, .burger span::after { content: ""; position: absolute; left: 0; }
.burger span::before { top: -6px; }
.burger span::after  { top: 6px; }
.burger[aria-expanded="true"] span { background: transparent; }
.burger[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.burger[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 560px) {
  /* Le CTA reste visible mais se réduit à la marque WhatsApp. */
  .topbar__actions .btn span,
  .topbar__actions .btn .btn__arrow { display: none; }
  .topbar__actions .btn { padding-inline: var(--space-4); }
}

@media (min-width: 1025px) {
  .topbar__inner { padding-block: var(--space-4); flex-wrap: nowrap; }
  .topbar__brand img { height: 34px; }

  /* La barre doit garder EXACTEMENT la même hauteur en français et en
     anglais : les libellés changent de longueur, rien ne doit passer à la
     ligne, et rien ne doit se chevaucher.

     `flex: 0 1 auto` sans `min-width: 0` : la nav peut céder de la place
     jusqu'à la largeur de son contenu, mais pas en dessous. Avec
     `min-width: 0` elle se laissait écraser sous sa taille réelle et les
     actions venaient se poser par-dessus le dernier lien. */
  .nav { flex: 0 1 auto; }
  .nav a { white-space: nowrap; }
  .topbar__actions { flex: none; }
  .topbar__actions .btn { white-space: nowrap; flex: none; }
  .lang { flex: none; white-space: nowrap; }

  /* Les trois groupes (logo, navigation, actions) respiraient moins que les
     liens entre eux : l'ensemble paraissait tassé. */
  .topbar__inner { gap: var(--space-10); }
  .nav, .js .nav { gap: var(--space-6); }
  .nav, .js .nav {
    position: static;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--space-8);
    order: 0;
    width: auto;
    background: none;
    border: 0;
    padding: 0;
    box-shadow: none;
    border-radius: 0;
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
  }
  .nav-scrim { display: none; }
  /* En ligne, sans fond au survol : seuls le gras et le trait parlent. */
  .nav a { padding: var(--space-2) 0; border-radius: 0; }
  .nav a:hover { background-color: transparent; }
  .nav a::after {
    content: "";
    position: absolute;
    left: 0; bottom: 0;
    width: 100%; height: 1.5px;
    background-image: linear-gradient(90deg, var(--accent-a), var(--accent-b));
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--duration-base) var(--ease-standard);
  }
  .nav a:hover::after,
  .nav a[aria-current]::after { transform: scaleX(1); }
  /* `.js .burger` est plus spécifique que `.burger` : une media query
     n'ajoute pas de spécificité, il faut donc neutraliser les deux. */
  .burger, .js .burger { display: none; }
}

/* ---- Hero : pastilles d'informations ------------------------------------ */
.pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-12);
}
.pills li {
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-5);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  box-shadow: var(--shadow-xs);
  transition: transform var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
}
.pills li:hover {
  transform: translateY(-2px);
  border-color: var(--mauve);
  box-shadow: var(--shadow-sm);
}

/* ---- Nos clients -------------------------------------------------------- */
.clients { margin-top: var(--space-12); text-align: center; }
.clients__label {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-6);
}
/* Bande de logos : défilement lent et continu vers la gauche.
   Le rail contient deux copies de la liste et glisse de -50 % : il revient
   donc exactement sur lui-même, sans saut visible. L'espacement est porté
   par une marge sur chaque logo et non par `gap`, sinon il manquerait un
   intervalle à la jointure entre les deux copies.
   Nuance de gris atténuée au repos, couleur d'origine au survol. Les logos
   ont des rapports très différents : c'est la HAUTEUR qui les harmonise. */
.clients__marquee {
  position: relative;
  overflow: hidden;
  padding-block: var(--space-2);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.clients__track {
  display: flex;
  align-items: center;
  width: max-content;
  animation: clients-scroll 48s linear infinite;
}
.clients__track li {
  display: flex;
  flex: none;
  margin-right: var(--space-10);
}

@keyframes clients-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Le survol suspend le défilement : sans cela on ne peut pas viser un logo. */
.clients__marquee:hover .clients__track,
.clients__marquee:focus-within .clients__track { animation-play-state: paused; }

.clients__track img {
  height: 26px;
  width: auto;
  max-width: 132px;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.55;
  transition: filter var(--duration-base) var(--ease-standard),
              opacity var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard);
}
.clients__track img:hover {
  filter: none;
  opacity: 1;
  transform: scale(1.06);
}

@media (min-width: 641px) {
  .clients__track img { height: 30px; max-width: 152px; }
  .clients__track li { margin-right: var(--space-12); }
}
@media (min-width: 1025px) {
  .clients__track img { height: 34px; max-width: 168px; }
  .clients__track li { margin-right: var(--space-16); }
}

/* Mouvement réduit : plus de défilement du tout. La copie disparaît et la
   bande redevient une simple ligne qui passe à la ligne.
   `!important` est nécessaire pour passer devant la règle globale de fin de
   feuille, qui se contente de raccourcir les animations à 1ms : ici cela
   figerait le rail sur la fin de course, donc au mauvais endroit. */
@media (prefers-reduced-motion: reduce) {
  .clients__track {
    animation: none !important;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--space-6) 0;
  }
  .clients__track li.is-clone { display: none; }
  .clients__marquee { -webkit-mask-image: none; mask-image: none; }
}

/* ---- Cartes ------------------------------------------------------------- */
.cards { display: grid; gap: var(--space-5); }

.card {
  position: relative;
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card-lg);
  padding: var(--space-8);
  box-shadow: var(--shadow-sm);
  color: var(--text-primary);
  transition: transform var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard);
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: var(--mauve-60);
}
.card .ic {
  width: 56px;
  height: 56px;
  margin-bottom: var(--space-5);
  transition: transform var(--duration-slow) var(--ease-standard);
}
.card:hover .ic { transform: scale(1.06) rotate(-2deg); }
.card h3 { font-size: var(--text-lg); margin-bottom: var(--space-3); }
.card p { color: var(--text-secondary); font-size: var(--text-sm); }
.card__num {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  color: var(--text-muted);
  margin-bottom: var(--space-2);
}

@media (min-width: 641px) {
  .cards--3, .cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
}
@media (min-width: 1025px) {
  .cards--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cards--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---- Panneau blanc sur fond sombre -------------------------------------- */
.panel {
  position: relative;
  isolation: isolate;
  background: var(--blanc);
  color: var(--text-primary);
  border-radius: var(--radius-panel);
  padding: var(--space-8);
  display: grid;
  gap: var(--space-8);
  margin-bottom: var(--space-20);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.panel > *:not(.dec) { position: relative; z-index: 1; }
.panel__title { margin-bottom: var(--space-6); }

@media (min-width: 769px) {
  .panel {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    padding: var(--space-12);
  }
}

/* ---- Listes à flèches (hampe + pointe, comme sur le site) --------------- */
.arrows { display: grid; gap: var(--space-4); }
.arrows li {
  position: relative;
  padding-left: 34px;
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  transition: transform var(--duration-base) var(--ease-standard);
}
.arrows li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 18px;
  height: 1.5px;
  background: var(--arrow-color);
}
.arrows li::after {
  content: "";
  position: absolute;
  left: 12px;
  top: 0.68em;
  width: 6px;
  height: 6px;
  border-top: 1.5px solid var(--arrow-color);
  border-right: 1.5px solid var(--arrow-color);
  transform: translateY(-2.7px) rotate(45deg);
}
.arrows li:hover { transform: translateX(3px); }

.panel { --arrow-color: var(--noir); }
.closing { --arrow-color: var(--mauve); }
.arrows--dark li { color: var(--text-secondary); }

/* ---- La journée en images ----------------------------------------------- */
.showcase { display: grid; gap: var(--space-12); }

.shot { display: grid; gap: var(--space-6); align-items: center; }
.shot__media {
  margin: 0;
  border-radius: var(--radius-media);
  overflow: hidden;
  background: var(--noir-80);
}
.shot__media img {
  width: 100%;
  transition: transform var(--duration-slow) var(--ease-standard);
}
.shot:hover .shot__media img { transform: scale(1.04); }
.shot__text h3 { font-size: var(--text-xl); margin-bottom: var(--space-2); }
.shot__tag {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--mauve);
  margin-bottom: var(--space-4);
}
.shot__text p:last-child { color: var(--text-inverse-muted); font-size: var(--text-sm); max-width: 34ch; }

@media (min-width: 769px) {
  .shot { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: var(--space-10); }
  .shot--reverse .shot__media { order: 2; }
  .shot--reverse .shot__text { order: 1; }
}

/* ==========================================================================
   PROGRAMME — chronologie de la journée
   Une colonne vertébrale, des jalons numérotés, une fiche par module. La
   journée se lit comme une journée, pas comme une liste. Les deux bornes
   horaires sont les seules du brief : accueil 8h30, fin 17h00. Aucun horaire
   par module n'est inventé.
   Tout est en CSS : la section reste correcte si le script ne tourne pas.
   ========================================================================== */
.timeline {
  position: relative;
  max-width: 46rem;
  margin-inline: auto;
  display: grid;
  gap: var(--space-5);
}

/* La colonne vertébrale, alignée sur le centre des jalons. Elle s'éteint
   vers le bas : la journée se termine, le trait aussi. */
.timeline::before {
  content: "";
  position: absolute;
  left: 21px;
  top: 10px;
  bottom: 10px;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(180deg,
    var(--mauve-60) 0%,
    var(--accent-a) 18%,
    var(--accent-a) 76%,
    var(--mauve-40) 100%);
}

.tl {
  position: relative;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
}

/* ---- Jalon numéroté ----------------------------------------------------- */
.tl__node {
  position: relative;
  z-index: 1;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-sm);
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--accent-a);
  font-variant-numeric: tabular-nums;
  transition: background-color var(--duration-base) var(--ease-standard),
              background-image var(--duration-base) var(--ease-standard),
              color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
}
/* Le dernier jalon est déjà rempli : c'est l'aboutissement de la journée.
   Chiffre en noir de marque : sur le mauve, le blanc ne contraste pas assez. */
.tl--end .tl__node {
  background-image: var(--gradient-accent);
  background-size: 200% 100%;
  border-color: transparent;
  color: var(--text-on-accent);
}
.tl:hover .tl__node {
  background-image: var(--gradient-accent);
  background-size: 200% 100%;
  border-color: transparent;
  color: var(--text-on-accent);
  box-shadow: 0 0 0 5px var(--mauve-20), var(--shadow-sm);
}

/* ---- Bornes horaires ---------------------------------------------------- */
.tl--cap { align-items: center; }
.tl__dot {
  justify-self: center;
  width: 11px;
  height: 11px;
  position: relative;
  z-index: 1;
  border-radius: 50%;
  background: var(--blanc);
  border: 2px solid var(--accent-a);
}
.tl__cap {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-muted);
}
.tl__hour {
  display: inline-block;
  margin-right: var(--space-3);
  color: var(--accent-a);
}

/* ---- Fiche du module ---------------------------------------------------- */
.tl__card {
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-sm);
  transition: transform var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard);
}
.tl:hover .tl__card {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--mauve-60);
}
.tl__tag {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}
.tl__title { font-size: var(--text-xl); margin-bottom: var(--space-5); }
.tl__card .arrows { margin-bottom: var(--space-6); }

/* La ligne de gain : c'est la raison d'être du module, elle se voit. */
.tl__out {
  background: var(--surface-accent-soft);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-sm);
  color: var(--text-on-accent);
}
.tl__out span {
  display: block;
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--accent-a);
  margin-bottom: var(--space-2);
}

@media (min-width: 769px) {
  .timeline { gap: var(--space-6); }
  .timeline::before { left: 25px; }
  .tl { grid-template-columns: 52px minmax(0, 1fr); gap: var(--space-8); }
  .tl__node { width: 52px; height: 52px; font-size: var(--text-sm); }
  .tl__card { padding: var(--space-8); }
  .tl__title { max-width: 24ch; }
}

/* ---- Défilement parallaxe collant — MOBILE UNIQUEMENT -------------------
   Sur un écran étroit, la chronologie est plus haute que la fenêtre : on ne
   voit jamais un module et son numéro en même temps. Le jalon se décroche
   donc et reste épinglé sous la barre pendant que sa fiche défile dessous.
   Deux choses varient pendant qu'il tient : l'anneau qui se remplit autour
   du chiffre (avancée DANS le module) et le trait accent qui descend la
   colonne vertébrale (avancée dans la JOURNÉE). Le décalage entre le jalon
   immobile et la fiche qui monte est la parallaxe : rien n'est simulé.

   `--tl-p`, `--tl-lift` et `--tl-scan` sont écrits par le script. Sans lui,
   le jalon reste simplement collant : la section n'est jamais cassée.
   Au-delà de 768px et en mouvement réduit, aucune de ces règles ne
   s'applique — la chronologie retrouve son comportement d'origine.
   ------------------------------------------------------------------------ */
@media (min-width: 0px) {
  /* Repli si le script ne tourne pas : la barre haute mesure environ 100px
     bandeau compris, le jalon se pose juste en dessous. */
  .timeline { --tl-stick: 124px; }

  /* Le jalon tient sous la barre, jusqu'au bas de sa propre fiche. */
  .tl:not(.tl--cap) .tl__node {
    position: sticky;
    top: var(--tl-stick);
    z-index: 3;
    transform: scale(calc(1 + var(--tl-lift, 0) * 0.08));
  }

  /* Le module en cours de lecture se remplit : le chiffre devient le repère
     actif, pas une simple puce numérotée. */
  .tl.is-live .tl__node {
    background-image: var(--gradient-accent);
    background-size: 200% 100%;
    border-color: transparent;
    color: var(--text-on-accent);
    box-shadow: 0 6px 18px rgba(23, 23, 23, 0.20);
  }

  /* Anneau de progression : un arc, masqué pour ne laisser que son bord. */
  .tl:not(.tl--cap) .tl__node::before {
    content: "";
    position: absolute;
    inset: -6px;
    border-radius: 50%;
    pointer-events: none;
    opacity: var(--tl-ring, 0);
    background: conic-gradient(from -90deg,
      var(--accent-b) 0deg,
      var(--accent-a) calc(var(--tl-p, 0) * 360deg),
      transparent calc(var(--tl-p, 0) * 360deg));
    -webkit-mask: radial-gradient(closest-side,
      transparent calc(100% - 2.5px), #000 calc(100% - 2.5px));
            mask: radial-gradient(closest-side,
      transparent calc(100% - 2.5px), #000 calc(100% - 2.5px));
    transition: opacity var(--duration-base) var(--ease-standard);
  }

  /* La fiche monte un peu plus vite que le jalon : c'est la parallaxe.
     Le survol est neutralisé ici, sinon il écraserait le décalage. */
  .tl:not(.tl--cap) .tl__card,
  .tl:not(.tl--cap):hover .tl__card {
    transform: translate3d(0, calc(var(--tl-lift, 0) * -14px), 0);
    will-change: transform;
  }

  /* Le trait parcouru double la colonne vertébrale, sans la remplacer. */
  .timeline::after {
    content: "";
    position: absolute;
    left: 21px;
    top: 10px;
    width: 2px;
    height: calc(var(--tl-scan, 0) * (100% - 20px));
    border-radius: 2px;
    background: linear-gradient(180deg, var(--accent-b), var(--accent-a));
  }
}

/* Au-delà de 768px le jalon passe de 44 à 52px et la colonne se décale :
   l'anneau et le trait parcouru suivent, sinon ils tombent à côté. */
@media (min-width: 769px) {
  .timeline::after { left: 25px; }
  .tl:not(.tl--cap) .tl__node::before { inset: -7px; }
  /* La fiche est plus large sur grand écran : le décalage peut respirer
     un peu plus sans que le mouvement devienne voyant. */
  .tl:not(.tl--cap) .tl__card,
  .tl:not(.tl--cap):hover .tl__card {
    transform: translate3d(0, calc(var(--tl-lift, 0) * -18px), 0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .tl:hover .tl__card { transform: none; }
  /* Mouvement réduit : plus de décrochage, plus de décalage. La chronologie
     redevient une liste qui défile d'un bloc. */
  .tl:not(.tl--cap) .tl__node { position: relative; top: auto; transform: none; }
  .tl:not(.tl--cap) .tl__node::before { display: none; }
  .tl:not(.tl--cap) .tl__card,
  .tl:not(.tl--cap):hover .tl__card { transform: none; will-change: auto; }
  .timeline::after { display: none; }
  .confetti { display: none; }
}

/* ---- Éclats de fin de programme -----------------------------------------
   Ils partent du dernier jalon quand son anneau se referme. Purement
   décoratifs : `pointer-events: none` et `aria-hidden` côté script, ils
   n'existent ni pour la souris ni pour un lecteur d'écran. Le conteneur est
   positionné au pixel du jalon par le script, les fragments partent de là. */
.confetti {
  position: fixed;
  z-index: 60;
  width: 0;
  height: 0;
  pointer-events: none;
}
.confetti i {
  position: absolute;
  left: 0;
  top: 0;
  width: 7px;
  height: 7px;
  border-radius: 1px;
  opacity: 0;
  animation: confetti-fly 1100ms var(--ease-out) forwards;
  animation-delay: var(--delay, 0ms);
}
@keyframes confetti-fly {
  0%   { opacity: 1; transform: translate3d(-50%, -50%, 0) scale(0.4) rotate(0deg); }
  22%  { opacity: 1; }
  /* La gerbe s'ouvre, puis les fragments retombent un peu : la gravité
     évite l'explosion figée qui trahit l'animation générée. */
  100% {
    opacity: 0;
    transform: translate3d(calc(-50% + var(--dx)), calc(-50% + var(--dy) + 30px), 0)
               scale(0.85) rotate(var(--rot));
  }
}

/* ---- Infos pratiques ---------------------------------------------------- */
.infos-layout { display: grid; gap: var(--space-8); align-items: start; }

.card--flat { padding: var(--space-6) var(--space-8); }
.card--flat:hover { transform: none; box-shadow: var(--shadow-sm); border-color: var(--border-subtle); }

.infos__row {
  display: grid;
  gap: var(--space-1);
  padding-block: var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}
.infos__row:last-child { border-bottom: 0; }
.infos dt {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-muted);
}
.infos dd {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-base);
}
.infos__note {
  display: block;
  margin-top: var(--space-2);
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

.infos__media { margin: 0; }
.infos__media picture {
  display: block;
  border-radius: var(--radius-media);
  overflow: hidden;
}
.infos__media img {
  width: 100%;
  transition: transform var(--duration-slow) var(--ease-standard);
}
.infos__media:hover img { transform: scale(1.03); }
.infos__media figcaption {
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

@media (min-width: 641px) {
  .infos__row { grid-template-columns: 9rem 1fr; gap: var(--space-6); align-items: baseline; }
  .infos dt { padding-top: 0.3em; }
}
@media (min-width: 1025px) {
  .infos-layout { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--space-12); }

  /* La colonne de droite tient sous la barre pendant que le tableau défile.
     `align-self: start` est indispensable : sans lui la grille étire la
     colonne sur toute la hauteur et `sticky` n'a plus de course. */
  .infos__aside {
    position: sticky;
    /* Sous la barre flottante : ~112px de haut, plus son décalage de 12px. */
    top: 148px;
    align-self: start;
    display: grid;
    gap: var(--space-6);
  }
}

/* Repli mobile : rien ne colle, la colonne redevient un bloc qui suit. */
.infos__aside { display: grid; gap: var(--space-6); }
.infos__cta { display: flex; }
.infos__cta .btn { width: 100%; justify-content: center; }

@media (min-width: 1025px) {
  /* Sur grand écran l'appel à l'action reprend sa largeur naturelle : étiré
     sur toute la colonne, il aurait l'air d'une barre, pas d'un bouton. */
  .infos__cta { justify-content: flex-start; }
  .infos__cta .btn { width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .infos__aside { position: static; }
}

/* ---- FAQ ---------------------------------------------------------------- */
.faq {
  max-width: 46rem;
  margin-inline: auto;
  background: var(--blanc);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card-lg);
  padding-inline: var(--space-6);
  box-shadow: var(--shadow-sm);
}

.faq__item + .faq__item { border-top: 1px solid var(--border-subtle); }

.faq__item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  min-height: var(--control-md);
  padding-block: var(--space-5);
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-base);
  line-height: var(--leading-snug);
  cursor: pointer;
  list-style: none;
  transition: color var(--duration-base) var(--ease-standard);
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary:hover { color: var(--accent-a); }

.faq__item summary::after {
  content: "";
  flex: none;
  width: 9px;
  height: 9px;
  margin-block: 0 4px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--duration-base) var(--ease-standard);
}
.faq__item[open] summary::after { transform: rotate(225deg); margin-block: 4px 0; }
.faq__item[open] summary { color: var(--accent-a); }

.faq__body { padding-bottom: var(--space-6); }
.faq__body p { color: var(--text-secondary); font-size: var(--text-sm); }
.faq__body a { text-decoration: underline; text-underline-offset: 3px; }

/* ---- Bloc de clôture ---------------------------------------------------- */
.closing {
  position: relative;
  isolation: isolate;
  background: var(--surface-inverse);
  color: var(--text-inverse);
  border-radius: var(--radius-panel);
  padding: var(--space-8);
  display: grid;
  gap: var(--space-8);
  overflow: hidden;
  box-shadow: var(--shadow-xl);
}
.closing::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(40% 60% at 100% 0%, rgba(179,135,175,.34), transparent 70%),
    radial-gradient(40% 60% at 0% 100%, rgba(179,135,175,.20), transparent 70%);
}
.closing > *:not(.dec) { position: relative; z-index: 1; }
.closing__title { margin-bottom: var(--space-6); }

/* ---- Compte à rebours ---------------------------------------------------
   Quatre cadrans sur une réglure fine. Les chiffres sont en chasse fixe
   pour que rien ne saute d'une seconde à l'autre.
   ------------------------------------------------------------------------ */
.countdown { margin-bottom: var(--space-8); }
.countdown__label {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-inverse-muted);
  margin-bottom: var(--space-4);
}
.countdown__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
  max-width: 26rem;
}
.countdown__grid li {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-2);
  border: 1px solid var(--border-inverse);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.04);
  text-align: center;
}
.countdown__num {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
}
.countdown__unit {
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide);
  color: var(--text-inverse-muted);
}
.countdown__note {
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-inverse-muted);
}
/* Session commencée ou passée : les cadrans disparaissent, la note reste. */
.countdown.is-over .countdown__grid,
.countdown.is-over .countdown__label { display: none; }
.closing__note {
  margin-top: var(--space-6);
  font-size: var(--text-sm);
  color: var(--text-inverse-muted);
  max-width: 46ch;
}
.closing__note a { white-space: nowrap; text-decoration: underline; text-underline-offset: 3px; }

@media (min-width: 769px) {
  .closing {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    padding: var(--space-16);
  }
}

/* ---- Formulaire (CTA secondaire, section séparée) ----------------------- */
/* Le formulaire suit le rythme commun : il cassait la trame en restant à 64px
   quand toutes les autres sections passent à 96px sur grand écran. */
.section--form { padding-block: var(--space-16); }
@media (min-width: 1025px) {
  .section--form { padding-block: var(--space-24); }
}
/* Sélecteur porté à `.head .form__title` : sans cela `.head h2` l'emportait
   et le formulaire, qui reste un CTA secondaire, s'affichait à la taille
   d'un titre de section. */
.head .form__title { font-size: var(--h3-size); }

.card--form { max-width: 34rem; margin-inline: auto; }
.card--form:hover { transform: none; box-shadow: var(--shadow-sm); border-color: var(--border-subtle); }

.form { display: grid; gap: var(--space-6); }

.field { display: grid; gap: var(--space-2); }
.field label { font-size: var(--text-sm); font-weight: var(--weight-medium); }
.field .req, .field .opt {
  font-weight: var(--weight-regular);
  font-size: var(--text-xs);
  color: var(--text-muted);
  letter-spacing: var(--tracking-wide);
}

input, textarea {
  width: 100%;
  min-height: var(--control-md);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--blanc);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  transition: border-color var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
}
input:hover, textarea:hover { border-color: var(--noir-60); }
textarea { resize: vertical; min-height: 96px; }
input::placeholder, textarea::placeholder { color: var(--text-muted); opacity: 1; }
input:focus-visible, textarea:focus-visible { border-color: var(--mauve); box-shadow: var(--shadow-focus); }

.hint { font-size: var(--text-sm); color: var(--text-muted); }

/* Erreurs : jamais de rouge. Contour noir fort et copie explicite. */
.error { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-primary); }
.field[data-invalid] input,
.field[data-invalid] textarea { border: 1.5px solid var(--border-strong); }

.form button[type="submit"] { justify-self: start; }
.form__note { font-size: var(--text-sm); color: var(--text-muted); }

.form__success h3 { font-size: var(--h3-size); margin-bottom: var(--space-3); }
.form__success p { color: var(--text-secondary); }
.form__success-alt { margin-top: var(--space-4); }
.form__success-alt a { text-decoration: underline; text-underline-offset: 3px; }

/* ---- Footer ------------------------------------------------------------- */
.footer {
  background: var(--surface-inverse);
  color: var(--text-inverse);
  padding-top: var(--space-16);
  padding-bottom: var(--space-10);
}
.footer__inner { display: grid; gap: var(--space-10); }
.footer__brand img { height: 34px; width: auto; }
.footer__tagline {
  margin-top: var(--space-4);
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--text-lg);
  color: var(--text-inverse-muted);
}
.footer__label {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--text-inverse-muted);
  margin-bottom: var(--space-4);
}
.footer__col p { font-size: var(--text-sm); line-height: var(--leading-relaxed); }
.footer__col a { text-decoration: underline; text-underline-offset: 3px; }
.footer__muted { margin-top: var(--space-4); color: var(--text-inverse-muted); max-width: 34ch; }
.footer__col a.footer__cta { margin-top: var(--space-6); text-decoration: none; }

.footer__legal {
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-inverse);
}
.footer__legal p { font-size: var(--text-xs); color: var(--text-inverse-muted); }

@media (min-width: 769px) {
  .footer__inner { grid-template-columns: 1.2fr 1fr 1fr; gap: var(--space-10); }
}

/* ---- Bouton collant mobile ----------------------------------------------
   Consigne de mise en page : barre en bas d'écran sous 1025px, après la
   section « à qui s'adresse », absente dès que l'inscription est visible.
   Réutilise .btn--accent : aucune nouvelle apparence de bouton.
   ------------------------------------------------------------------------ */
.sticky-cta {
  display: none;
}

@media (max-width: 1024px) {
  .sticky-cta {
    --sticky-cta-pad: max(var(--space-3), env(safe-area-inset-bottom, 0px));
    display: block;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 45;
    padding: var(--space-3) var(--space-4) var(--sticky-cta-pad);
    background: linear-gradient(180deg,
      transparent 0%,
      color-mix(in srgb, var(--blanc) 88%, transparent) 28%,
      var(--blanc) 100%);
    transform: translateY(110%);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform var(--duration-base) var(--ease-standard),
                opacity var(--duration-base) var(--ease-standard),
                visibility var(--duration-base) var(--ease-standard);
  }

  .sticky-cta.is-visible {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  .sticky-cta__btn {
    width: 100%;
    justify-content: center;
    min-height: var(--control-lg);
  }

  .sticky-cta__price {
    font-weight: var(--weight-regular);
    opacity: 0.85;
    margin-left: var(--space-2);
  }

  /* Sur très petit écran, le libellé court suffit : le prix tombe. */
  @media (max-width: 380px) {
    .sticky-cta__price { display: none; }
  }

  /* Réserve la hauteur de la barre pour ne pas recouvrir pied de page
     ni dernier paragraphe quand elle est visible. */
  body.has-sticky-cta {
    padding-bottom: calc(var(--control-lg) + var(--space-3) + var(--space-3)
      + max(var(--space-3), env(safe-area-inset-bottom, 0px)));
  }
}

@media (max-width: 1024px) and (prefers-reduced-motion: reduce) {
  .sticky-cta {
    transition: none;
  }
}

/* ---- Mouvement réduit --------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
  }
  .card:hover, .btn:hover, .pills li:hover { transform: none; }
  .shot:hover .shot__media img, .infos__media:hover img, .card:hover .ic { transform: none; }
}
