/* ============================================================
   Au Cocon Du Bonheur — fondation
   Conforme à design-loop/design-system.md.
   Couleurs VERROUILLÉES. Poids ≤ 500. Aucune ombre. Zéro JS.
   ============================================================ */

:root {
  /* --- Couleurs : verrouillées, ne jamais modifier --- */
  --c-cream:        #FDF6E6;
  --c-cream-deep:   #FBF2D8;
  --c-white:        #FFFFFF;
  --c-purple:       #873897;
  --c-purple-deep:  #5A2166;
  --c-yellow:       #FFD400;   /* RÉSERVÉ à l'appel téléphonique */
  --c-yellow-pale:  #F8E6A5;
  --c-heading:      #5E4966;
  --c-text:         #331F3A;

  /* Filet : jamais une ombre (M2) */
  --hairline: 1px solid rgb(94 73 102 / .15);

  /* --- Typographie : l'échelle porte la hiérarchie, pas la graisse (M1) --- */
  /* Plafond baisse de 6,5rem a 5,6rem : « Un cocon pour bien grandir. » passait
     sur DEUX lignes des 1440px avec l'ancien 104px, ce que le titre court ne
     faisait pas. Mesure : la ligne fait 1104px de large disponible, elle tient
     jusqu'a ~92px de corps. 89,6px laisse une marge. */
  --fs-hero:    clamp(3.4rem, 7.2vw, 5.6rem);   /* 54 → 89,6px */
  --fs-section: clamp(1.9rem, 3.4vw, 2.5rem);   /* 30 → 40px  */
  --fs-card:    clamp(1.25rem, 1.9vw, 1.5rem);  /* 20 → 24px  */
  --fs-body:    clamp(1.0625rem, 1.5vw, 1.25rem); /* 17 → 20px */
  --fs-note:    clamp(1rem, 1.3vw, 1.125rem);   /* 16 → 18px  */
  --fs-fine:    0.875rem;                        /* 14px       */

  /* Police d'affichage : reservee aux h1/h2. Poppins garde tout le reste.
     Cout mesure : +15,6 Ko (sous-ensemble latin, woff2). */
  --font-display: "Baloo 2", Poppins, system-ui, sans-serif;
  --font-body:    Poppins, system-ui, sans-serif;

  --w-regular: 400;
  --w-medium:  500;   /* PLAFOND ABSOLU — aucun 600, aucun 700 */

  --lh-hero: 1.05;
  --lh-title: 1.2;
  --lh-card: 1.3;
  --lh-body: 1.5;

  /* --- Formes : 8 / 12 / 16 / 20 uniquement, + pilule pour les boutons --- */
  --r-8: 8px;  --r-12: 12px;  --r-16: 16px;  --r-20: 20px;
  --r-pill: 9999px;

  /* --- Rythme --- */
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --content-max: 1200px;
  --section-y: clamp(4rem, 9vw, 8rem);

  /* --- Mouvement : trois vitesses, aucune autre valeur (M4) --- */
  --m-micro: 150ms;
  --m-state: 300ms;
  --m-enter: 1000ms;
  /* Ouverture de page : le rideau tient 1,9s puis se retire en 600ms.
     Total 2,5s, dans la fourchette 2-3s demandee par la cliente. */
  --m-veil: 2500ms;
  --m-veil-out: 1900ms;   /* instant ou le rideau commence a se retirer */
  --m-boot: 900ms;        /* duree d'entree d'un element du heros */
  /* Revelation au defilement : une DUREE, pas une distance de scroll. C'est
     tout l'objet du passage au JS — voir app.js. 1100ms se lit comme un
     glissement ; en dessous de ~700ms ca redevient un « pop ». */
  --m-reveal: 1100ms;
  /* Expo-out : demarre franc, se pose tres longuement. C'est cette longue fin
     de course qui donne la sensation « premium », pas la duree seule. */
  --ease-out: cubic-bezier(.16, 1, .3, 1);

  /* --- En-tete : deux echelles, pleine en haut de page puis compacte --- */
  --header-logo:     clamp(180px, 18vw, 262px);
  --header-pad:      14px;
  --header-cta-fs:   clamp(1.05rem, 1.5vw, 1.375rem);
  --header-cta-pad:  16px 30px;
  --header-cta-icon: 24px;
  --ease-ui: cubic-bezier(.4, 0, .2, 1);
  /* Ressort : dépasse la cible d'environ 11% avant de se poser */
  --ease-spring: linear(
    0, .008 1.1%, .031 2.2%, .129 4.8%, .257 7.2%, .671 14.2%, .789 16.5%,
    .881 18.6%, .957 20.7%, 1.019 22.9%, 1.063 25.1%, 1.094 27.4%,
    1.114 30.7%, 1.112 34.5%, 1.018 49.9%, .99 59.1%, 1 100%
  );
}

/* ============================================================
   Réinitialisation
   ============================================================ */

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

/* Un [hidden] doit gagner contre tout display: flex/grid posé ailleurs.
   Sans ça le masquage échoue en silence. */
[hidden] { display: none !important; }

/* Defilement fluide sur les liens du menu. `scroll-padding-top` est
   indispensable : sans lui l'ancre se cale en haut de fenetre, donc DERRIERE
   l'en-tete collant, et le titre vise est invisible. La valeur suit la hauteur
   reelle de l'en-tete (~122px desktop, ~150px en deux rangees sous 900px). */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 138px;
}
@media (max-width: 899px) { html { scroll-padding-top: 162px; } }
/* Sous 420px le bouton d'appel descend sur sa propre rangee : l'en-tete monte
   a ~187px et l'ancre repassait dessous. Mesure, pas estimation. */
@media (max-width: 420px) { html { scroll-padding-top: 196px; } }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--c-cream);
  color: var(--c-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: var(--w-regular);
  line-height: var(--lh-body);
  letter-spacing: normal;          /* normal partout, aucune exception */
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
img, svg { display: block; max-width: 100%; }
img { height: auto; }              /* sinon width/height du HTML écrasent aspect-ratio */
a { color: inherit; }

h1, h2, h3, h4 {
  font-weight: var(--w-medium);    /* plafond : 500 */
  color: var(--c-heading);
  text-wrap: balance;
}
/* Regle simple : tout ce qui est titre prend la police d'affichage, tout le
   reste prend Poppins. Melanger les deux a l'interieur des titres se lisait
   comme une incoherence. */
h1, h2, h3, h4 { font-family: var(--font-display); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ============================================================
   Anneau de focus — contraste avec le FOND, pas avec l'élément
   ============================================================ */

:root { --focus-ring: var(--c-purple-deep); }

:where(a, button, [tabindex]):focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: var(--r-8);
}
/* Sur fond violet un anneau violet est invisible */
.on-purple { --focus-ring: var(--c-yellow); }
/* Sur un aplat jaune, l'anneau doit virer au violet foncé */
.on-yellow { --focus-ring: var(--c-purple-deep); }

/* ============================================================
   Mise en page
   ============================================================ */

.wrap {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { position: relative; padding-block: var(--section-y); overflow-x: clip; }
.section--cream      { background: var(--c-cream); }
.section--cream-deep { background: var(--c-cream-deep); }
.section--white      { background: var(--c-white); }

/* Un plan de composition dedie pour l'en-tete collant : sans lui, chaque
   defilement repeignait la bande. Mesure : pire frame 47,5ms -> voir plus bas. */
.site-header { will-change: transform; }

/* En haut de page l'en-tete est plein : le logo fait 125px de haut, l'en-tete
   153px. Colle tel quel pendant toute la lecture, il mangerait 17% d'un ecran
   de 900px. Des 60px de defilement il se compacte a ~93px — le logo reste le
   premier point d'accroche a l'arrivee, sans peser ensuite.
   Pilote par app.js (classe `is-compact`) ; sans JS l'en-tete reste plein,
   ce qui est le cas correct par defaut. */
.site-header.is-compact {
  --header-logo:     clamp(120px, 11vw, 158px);
  --header-pad:      9px;
  --header-cta-fs:   var(--fs-note);
  --header-cta-pad:  11px 20px;
  --header-cta-icon: 19px;
}
.site-header__inner { transition: padding-block var(--m-state) var(--ease-ui); }

/* ============================================================
   Marques du Cocon — pose (M5)
   Rotation 3–12°, hors grille, décoratives donc aria-hidden.
   ============================================================ */

.mark {
  position: absolute;
  pointer-events: none;
  color: var(--c-purple);          /* le tracé hérite via currentColor */
  z-index: 1;
}
.mark--pale  { color: var(--c-yellow-pale); }
.mark--deep  { color: var(--c-purple-deep); }
.mark--muted { color: var(--c-heading); }
/* Aucune variante jaune vif : #FFD400 n'habille que l'appel (M3). */

/* Marque decorative qui deborde (M7). Sous 900px le contenu remplit la
   fenetre : il ne reste aucune marge, et ces marques tombent forcement sur du
   texte. Elles disparaissent alors. Les marques ANCREES a un mot ou pointant
   une cible, elles, restent a toutes les largeurs. */
@media (max-width: 899px) {
  .mark--bleed { display: none; }
}

.mark--r3  { rotate:   3deg; }
.mark--r6  { rotate:   6deg; }
.mark--r9  { rotate:   9deg; }
.mark--r12 { rotate:  12deg; }
.mark--l5  { rotate:  -5deg; }
.mark--l8  { rotate:  -8deg; }
.mark--l11 { rotate: -11deg; }

/* ============================================================
   Entrées au scroll — CSS pur, zéro JS (M4)
   Sans animation-timeline, le contenu s'affiche : jamais masqué.
   ============================================================ */

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* Promeut les elements animes sur leur propre plan de composition.
       Mesure honnete sur passes isolees : gain modeste, ~10% sur la pire
       frame — pas la division par trois qu'une premiere mesure bruitee avait
       laisse croire. Conserve parce que c'est gratuit et que ca ne coute une
       couche que sur les elements qui s'animent reellement. */
    .enter, .enter--pop, .enter--draw { will-change: transform, opacity; }

    .enter {
      animation: enter-rise var(--m-enter) var(--ease-spring) both;
      animation-timeline: view();
      animation-range: entry 0% cover 92%;
    }
    .enter--draw {
      animation: enter-draw var(--m-enter) var(--ease-ui) both;
      animation-timeline: view();
      animation-range: entry 0% cover 95%;
    }
    .enter--pop {
      animation: enter-pop var(--m-enter) var(--ease-spring) both;
      animation-timeline: view();
      animation-range: entry 0% cover 94%;
    }
    .enter--d1 { animation-delay: 0s; animation-range: entry 0%  cover 92%; }
    .enter--d2 { animation-delay: 0s; animation-range: entry 6%  cover 98%; }
    .enter--d3 { animation-delay: 0s; animation-range: entry 12% cover 100%; }
  }
}

/* 28px -> 44px : sur une course courte le bloc « apparait » d'un coup au lieu
   de glisser. C'est la difference que la cliente decrivait comme « trop rapide ». */
@keyframes enter-rise {
  from { opacity: 0; transform: translateY(44px); }
  to   { opacity: 1; transform: none; }
}
@keyframes enter-pop {
  from { opacity: 0; transform: scale(.86) rotate(-4deg); }
  to   { opacity: 1; transform: none; }
}
/* Le tracé se dessine : la marque a l'air écrite à la main, en direct */
@keyframes enter-draw {
  from { opacity: 0; stroke-dashoffset: var(--dash, 400); }
  to   { opacity: 1; stroke-dashoffset: 0; }
}

/* ============================================================
   Rideau d'ouverture — CSS pur, zero JS
   Le rideau tient 1,9s, puis se retire en 600ms. Il finit sur
   `visibility: hidden` : passe ce point il n'intercepte plus rien.
   Aucun script ne l'enleve — s'il en fallait un, une erreur JS laisserait
   la page murée derriere un ecran creme. Ici le pire cas est une animation
   qui ne part pas, et la page est deja lisible dessous.
   ============================================================ */

.boot-veil {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center;
  background: var(--c-cream);
  animation: veil-lift var(--m-veil) var(--ease-ui) forwards;
}
.boot-veil__inner { display: grid; justify-items: center; }

.boot-veil__logo {
  width: clamp(170px, 30vw, 230px); height: auto;
  animation: veil-logo 1100ms var(--ease-spring) both;
}

/* Une barre qui se remplit, pas un sablier qui tourne : elle dit combien de
   temps il reste. Le violet de marque, jamais le jaune — celui-ci n'habille
   que l'appel telephonique (M3). */
.boot-veil__rail {
  width: clamp(130px, 22vw, 180px); height: 3px;
  margin-top: clamp(22px, 3vw, 30px);
  background: rgb(94 73 102 / .14);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.boot-veil__fill {
  display: block; height: 100%; width: 100%;
  background: var(--c-purple);
  border-radius: var(--r-pill);
  transform-origin: left center;
  animation: veil-fill var(--m-veil-out) var(--ease-ui) both;
}

@keyframes veil-lift {
  0%, 76%  { opacity: 1; visibility: visible; }
  100%     { opacity: 0; visibility: hidden; }
}
@keyframes veil-logo {
  from { opacity: 0; transform: translateY(16px) scale(.93); }
  to   { opacity: 1; transform: none; }
}
@keyframes veil-fill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ------------------------------------------------------------
   Entree du heros, pilotee par le TEMPS et non par le scroll
   Les entrees `.enter` sont pilotees par `view()` : en haut de page le heros
   est deja entierement visible, donc elles sont figees sur leur etat final et
   ne jouent jamais. Il faut une animation temporelle pour que le premier ecran
   se compose apres le rideau.
   Le depart est cale 250ms AVANT la fin du rideau : le contenu glisse deja
   quand le voile s'efface, au lieu de demarrer sur une page morte.
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
  .boot {
    animation: enter-rise var(--m-boot) var(--ease-spring) both;
    animation-delay: calc(var(--m-veil-out) - 250ms + var(--i, 0) * 120ms);
  }
  .boot--pop {
    animation-name: enter-pop;
  }
  /* Le decalage passe par une classe, jamais par un style en ligne. */
  .boot--i1 { --i: 1; }
  .boot--i2 { --i: 2; }
  .boot--i3 { --i: 3; }
  .boot--i4 { --i: 4; }
}

/* ------------------------------------------------------------
   Photo qui se pose au defilement (M4)
   Elle arrive legerement agrandie et revient a l'echelle 1. Sur `transform`
   uniquement : aucun recalcul de mise en page, donc aucune frame perdue.
   La figure decoupe, sinon le debordement creerait un scroll horizontal.
   ------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .glide {
      animation: glide-settle linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 55%;
      will-change: transform;
    }
  }
}
@keyframes glide-settle {
  from { transform: scale(1.07); }
  to   { transform: scale(1); }
}

/* ============================================================
   Revelations au defilement — version JS (app.js)
   Sans JS : les regles `animation-timeline: view()` plus haut s'appliquent,
   le contenu reste visible en toutes circonstances.
   Avec JS : la classe `js` est posee sur <html> et les entrees basculent sur
   une TRANSITION. La difference est le point que la cliente ne cessait de
   signaler : une animation liee a `view()` avance a la vitesse du doigt, donc
   un defilement rapide la traverse en deux frames et le mouvement n'existe
   plus. Une transition dure --m-reveal quoi qu'il arrive.
   ============================================================ */

html.js .enter,
html.js .enter--pop,
html.js .enter--draw {
  animation: none;
  animation-timeline: auto;
  opacity: 0;
  transform: translateY(52px);
  transition: opacity   var(--m-reveal) var(--ease-out) var(--d, 0ms),
              transform var(--m-reveal) var(--ease-out) var(--d, 0ms);
  will-change: transform, opacity;
}
html.js .enter--pop  { transform: scale(.9) rotate(-3deg); }
html.js .enter--draw { transform: translateY(24px); }

html.js .enter.is-in,
html.js .enter--pop.is-in,
html.js .enter--draw.is-in {
  opacity: 1;
  transform: none;
}

/* Le JS pilote lui-meme le defilement vers les ancres : il connait la hauteur
   REELLE de l'en-tete a l'instant du clic, ce qu'un `scroll-padding` fige ne
   peut pas faire (l'en-tete se compacte pendant le trajet). */
html.js { scroll-behavior: auto; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0ms !important;
  }
}


/* ═══ 01-hero — Héros + en-tête ═══ */

/* ── 01-hero — en-tête + héros ────────────────────────────────
   Tokens : ../../build/tokens.css. Aucune couleur en dur.
   ───────────────────────────────────────────────────────────── */

/* ---------- En-tête ---------- */

.site-header {
  position: sticky; top: 0; z-index: 20;
  background: var(--c-cream);
  border-bottom: var(--hairline);
}
.site-header__inner {
  display: flex; align-items: center; gap: clamp(14px, 1.9vw, 28px);
  padding-block: var(--header-pad);
}
.site-header__brand {
  flex: none; display: flex; align-items: center;
  min-height: 44px;              /* cible tactile : le logo seul tombait a 40,06px */
  border-radius: var(--r-8);
}
/* Le logo est le premier point d'accroche : il remplit la hauteur de l'en-tete
   sans en toucher les bords (14px d'air en haut et en bas). 262px affiches,
   soit 125px de haut — et 524w en source pour un ecran 2x, exactement la plus
   grande variante disponible : aucun agrandissement, aucun flou.
   La transition sert a l'en-tete compact (voir plus bas). */
.site-header__logo {
  width: var(--header-logo); height: auto;
  transition: width var(--m-state) var(--ease-ui);
}

.site-nav { display: flex; gap: clamp(8px, 1.4vw, 20px); margin-inline: auto; }
.site-nav__link {
  text-decoration: none;
  color: var(--c-heading);
  font-size: var(--fs-note);
  /* Le logo et le bouton d'appel ayant grossi, la navigation est le seul
     element compressible de la rangee : ses liens se coupaient en deux lignes
     (« La vie de / l'ecole »). Un lien de menu ne se coupe jamais. */
  white-space: nowrap;
  padding: 8px 9px; border-radius: var(--r-8);
  transition: background-color var(--m-micro) var(--ease-ui);
}
.site-nav__link:hover { background: var(--c-cream-deep); color: var(--c-heading); }

/* Le bouton d'appel de l'en-tete suit le logo : demande cliente, « de meme
   pour le numero a droite en jaune ». Il se compacte avec lui au defilement. */
.site-header .btn-call {
  font-size: var(--header-cta-fs);
  padding: var(--header-cta-pad);
  transition: background-color var(--m-micro) var(--ease-ui),
              transform var(--m-micro) var(--ease-ui),
              font-size var(--m-state) var(--ease-ui),
              padding var(--m-state) var(--ease-ui);
}
.site-header .btn-call__icon {
  width: var(--header-cta-icon); height: var(--header-cta-icon);
  transition: width var(--m-state) var(--ease-ui), height var(--m-state) var(--ease-ui);
}

/* ---------- Le bouton d'appel — seul objet #FFD400 (M3) ---------- */

.btn-call {
  flex: none;
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--c-yellow);
  color: var(--c-purple-deep);
  text-decoration: none;
  font-weight: var(--w-medium);
  font-size: var(--fs-note);
  padding: 12px 22px;
  border-radius: var(--r-pill);
  white-space: nowrap;          /* le numero ne se coupe jamais */
  line-height: var(--lh-title);
  --focus-ring: var(--c-purple-deep);
  transition: background-color var(--m-micro) var(--ease-ui),
              transform var(--m-micro) var(--ease-ui);
}
.btn-call:hover { background: var(--c-yellow-pale); transform: translateY(-1px); }
.btn-call:active { transform: translateY(0); }
.btn-call__icon { width: 20px; height: 20px; flex: none; }

.btn-call--lg {
  font-size: clamp(1.05rem, 1.7vw, 1.375rem);
  padding: 18px 34px;
  gap: 12px;
}
.btn-call--lg .btn-call__icon { width: 24px; height: 24px; }

/* ---------- Héros ---------- */

.hero {
  position: relative;
  padding-top: clamp(40px, 7vw, 84px);
  overflow-x: clip;           /* laisse déborder sans créer de scroll (M7) */
}

/* Pas de bride sur le bloc : a 21ch le bouton d'appel etait ramene a 224px
   et coupait le numero en deux lignes — sur l'unique action de la page. */
.hero__copy { max-width: none; }

/* Le bandeau ne porte plus l'autorisation — elle est deja au pied de page —
   mais l'ADRESSE, avec une epingle a la place de la marque « cocon ».
   Le cadrage (fond creme profond, filet, pilule) est celui dessine pour
   l'autorisation : on garde la forme, on change le contenu. */
.hero__badge {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: var(--fs-note);
  color: var(--c-heading);
  background: var(--c-cream-deep);
  border: var(--hairline);
  border-radius: var(--r-pill);
  padding: 9px 20px 9px 16px;
  margin-bottom: clamp(20px, 3vw, 30px);
}
.hero__badge-icon {
  width: 19px; height: 19px; flex: none;
  color: var(--c-purple);
}
.mark--inline { width: 16px; height: 16px; flex: none; color: var(--c-purple); }

.hero__title {
  font-size: var(--fs-hero);
  line-height: var(--lh-hero);
  color: var(--c-heading);
  margin: 0;
  text-wrap: balance;
}
/* Le mot souligné : le trait se pose SOUS le mot, pas à côté */
.hero__title-mark { position: relative; display: inline-block; }
.hero__trait {
  position: absolute;
  left: 0; bottom: -.2em;
  width: 106%; height: .2em;
  color: var(--c-purple);
}

.hero__subtitle {
  margin-top: clamp(18px, 2.4vw, 26px);
  max-width: 52ch;
  color: var(--c-text);
  font-size: var(--fs-body);
}

/* Le decalage porte sur le conteneur, pas sur le bouton : c'est lui qui sert
   desormais de repere a la fleche. */
.hero__cta {
  position: relative; display: inline-block;
  margin-top: clamp(26px, 3.4vw, 38px);
}

/* ---------- Marques (M5) ---------- */

/* Le fil désigne le gros bouton d'appel SANS le traverser : miroir horizontal
   (scaleX) pour que la pointe revienne vers la gauche, posé à droite du bouton. */
/* ANCREE AU BOUTON, plus au fond de section. Les anciennes coordonnees
   (`left`/`top` en clamp sur la largeur de fenetre) etaient calees sur une
   hauteur de heros donnee : des qu'une ligne s'ajoutait — ici l'adresse — la
   fleche retombait sur le sous-titre a 1280px et sur le titre a 1024px.
   Accrochee au bouton, elle le suit a toutes les largeurs. Meme principe que
   l'eclat, accroche au dernier mot du titre. */
.hero__mark-fil {
  width: clamp(90px, 9.5vw, 136px); height: auto; aspect-ratio: 100/60;
  left: calc(100% + clamp(14px, 2vw, 34px));
  top: 50%;
  translate: 0 -50%;            /* propriete separee : ne heurte pas `transform` */
  transform: scaleX(-1);
  color: var(--c-purple);
  display: none;
}
/* Sous 1000px la fleche frole le sous-titre : il n'y a plus la place. */
@media (min-width: 1000px) { .hero__mark-fil { display: block; } }

/* Accroche au dernier mot du titre, pas au fond de section : la marque suit
   le texte quand il se recompose, au lieu de flotter sur des coordonnees
   figees. Ecartee de la lettre : posee dessus elle se lisait comme un accent. */
.hero__title-end { position: relative; display: inline-block; }
.hero__mark-eclat {
  width: clamp(20px, 2.2vw, 32px); height: auto; aspect-ratio: 1;
  right: -.42em; top: -.16em;
  color: var(--c-purple);
}

/* Le soleil déborde par la droite (M7) */
.hero__mark-soleil {
  width: clamp(150px, 20vw, 290px); height: auto; aspect-ratio: 1;
  /* Le titre a gagne un mot (« bien ») et s'etend plus a droite : il venait
     recouvrir le soleil. Celui-ci remonte de ~26px et sort un peu plus par la
     droite. Il reste sous l'en-tete en z-index, donc il ne mord pas dessus. */
  right: clamp(-110px, -7.4vw, -48px);
  top: clamp(2px, 0.5vw, 8px);
  color: var(--c-yellow-pale);
  z-index: 0;
}

/* Sous 900px le soleil restait masque : la seule chose qui franchissait un bord
   etait alors la photo de facade, et elle s'arrete PILE au bord au lieu de le
   depasser. Le soleil revient, petit, a droite du bouton d'appel — la seule
   zone libre du premier ecran (mesure : 150px a 390px de large). */
@media (max-width: 899px) {
  /* `bottom: 96px` le posait DERRIERE la photo de facade : present dans le DOM,
     compte comme visible par un detecteur, invisible a l'oeil. Il remonte a
     droite du titre, la seule zone reellement libre du premier ecran — le
     badge s'arrete a 225px et la 1re ligne du titre a 250px de large. */
  .hero__mark-soleil {
    display: block;
    width: 110px;
    /* -40px laissait 7px d'encre sur « Un cocon » : on sort davantage. */
    right: -56px;
    top: 20px;
    bottom: auto;
  }
}

/* Sous ~460px, la premiere ligne du titre s'etend jusqu'a x=362 (mesure a
   390px) et passait DANS le soleil, qui commencait a x=329. Le soleil ne peut
   pas simplement remonter — a 124px de haut il faudrait `top: -39px`, donc
   derriere l'en-tete collant. Il rapetisse donc et se cale au-dessus du titre :
   il occupe alors y 6→82, et le titre commence a 85. */
@media (max-width: 460px) {
  /* 76px laissaient 1,9px de recouvrement : la rotation de -8deg agrandit la
     boite englobante de ~13% (76 -> 86px). C'est cette boite qu'il faut faire
     tenir, pas la largeur ecrite. A 70px elle mesure 79px et s'arrete a y=79,5
     pour un titre qui commence a 85. */
  .hero__mark-soleil { width: 70px; right: -22px; top: 5px; }
}

/* ---------- Photo de façade, plein bord (M7) ---------- */

.hero__photo {
  margin: clamp(44px, 6vw, 76px) 0 0;
  padding: 0;
  position: relative; z-index: 2;
}
/* Le conteneur decoupe : la photo arrive a l'echelle 1,07 et se pose. Sans ce
   `clip` elle deborderait et creerait un scroll horizontal. */
.hero__photo-clip {
  display: block;
  overflow: clip;
  border-radius: var(--r-20) var(--r-20) 0 0;
}
.hero__photo img {
  background: var(--c-cream-deep);
  width: 100%; height: auto;
  aspect-ratio: 1168 / 859;
  object-fit: cover;
  border-radius: var(--r-20) var(--r-20) 0 0;
}

@media (min-width: 1000px) {
  .hero__photo {
    width: calc(100% - 2 * var(--gutter));
    max-width: 1320px;
    margin-inline: auto;
  }
  .hero__photo img { aspect-ratio: 1168 / 620; }
}

/* ---------- En-tête compact sur mobile ---------- */

@media (max-width: 899px) {
  .site-header__inner { flex-wrap: wrap; row-gap: 10px; }
  .site-header__brand { order: 1; }
  .btn-call { order: 2; margin-left: auto; }
  .site-nav { order: 3; width: 100%; margin-inline: 0; justify-content: space-between; }
  .site-nav__link { min-height: 44px; display: flex; align-items: center; }
  .btn-call { min-height: 44px; }
  /* Le bouton passe par les MEMES tokens que le desktop, sinon la regle
     `.site-header .btn-call` (0,1,1) l'emporterait sur `.btn-call` (0,1,0)
     et le bouton resterait a sa taille desktop sur telephone. */
  .site-header {
    --header-logo:     150px;
    --header-cta-fs:   var(--fs-fine);
    --header-cta-pad:  11px 16px;
    --header-cta-icon: 18px;
  }
  .site-header.is-compact {
    --header-logo:     116px;
    --header-cta-fs:   var(--fs-fine);
    --header-cta-pad:  10px 14px;
    --header-cta-icon: 17px;
  }
}
/* Sous 900px le titre remplit la largeur : l'eclat venait coller la derniere
   lettre, exactement le defaut deja corrige en desktop. Le soulignement sous
   « pour » porte alors M5 a lui seul. */
@media (max-width: 899px) {
  .hero__mark-eclat { display: none; }
}

@media (max-width: 480px) {
  /* L'autorisation est deja repetee en pied de page : sur petit ecran elle
     faisait passer le bandeau sur 3 lignes pour rien. */
  /* L'adresse passe sur deux lignes : l'epingle se cale sur la PREMIERE,
     pas au milieu du bloc. */
  .hero__badge { align-items: flex-start; font-size: var(--fs-fine); }
  .hero__badge-icon { margin-top: 2px; }
  .btn-call--lg { padding: 16px 24px; }
}
@media (max-width: 420px) {
  .site-header {
    --header-logo:    112px;
    --header-cta-pad: 11px 14px;
  }
  /* A 360px il fallait 112 + 16 + 219 = 347px pour 320px disponibles : le
     bouton descendait sur sa propre rangee et l'en-tete montait a 190px, soit
     26% d'un ecran de 740px. « Appeler le » disparait, l'icone telephone porte
     le sens, et le lien garde son intitule complet en `aria-label` pour les
     lecteurs d'ecran. Il reste 112 + 16 + ~146 = 274px : le bouton remonte a
     cote du logo. Le gros bouton du heros, lui, garde son texte entier. */

  .site-header.is-compact {
    --header-logo:    94px;
    --header-cta-fs:  var(--fs-fine);
    --header-cta-pad: 10px 12px;
  }
  .site-nav__link { font-size: var(--fs-fine); padding-inline: 6px; }
}


/* ═══ 02-cycles — Nos quatre cycles ═══ */

/* ── 02-cycles — « Nos quatre cycles » ────────────────────────
   Les quatre visuels générés ont été retirés : emplacements assumés
   en attendant les vraies photos de classe.
   « Services assurés » vient APRÈS les cycles (liste réglée, M6).
   ───────────────────────────────────────────────────────────── */

.cycles { position: relative; overflow-x: clip; }

.cycles__title {
  font-size: var(--fs-section);
  line-height: var(--lh-title);
}
.cycles__title-mark { position: relative; display: inline-block; }
.cycles__trait {
  position: absolute;
  left: 0; bottom: -.22em;
  width: 104%; height: .22em;
  color: var(--c-purple);
}
.cycles__lead {
  margin-top: 14px;
  margin-bottom: clamp(32px, 4.5vw, 56px);
  color: var(--c-text);
  font-size: var(--fs-note);
  max-width: 46ch;
}

/* ---------- Les quatre cycles ---------- */

.cycle-list {
  position: relative;
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(24px, 3.4vw, 44px);
  z-index: 2;
}
@media (min-width: 760px) {
  .cycle-list { grid-template-columns: 1fr 1fr; }
  /* Décalage vertical : casse la grille de rectangles alignés */
  .cycle-list > .cycle:nth-child(odd)  { margin-top: clamp(28px, 4vw, 56px); }
  .cycle-list > .cycle:nth-child(even) { margin-top: 0; }
}

.cycle { transition: transform var(--m-state) var(--ease-ui); }

/* ---------- Le médaillon de cycle ---------- */

/* La photo est RONDE et PETITE, et c'est un choix dicte par la source : les
   quatre images sont decoupees dans la video promotionnelle (848x480), seul
   materiau dont la cliente dispose encore. Les diametres exploitables vont de
   276 a 360px. Affiches a 150px, ils restent nets meme sur un ecran 2x ;
   etires sur une carte de 588px de large ils seraient mous.
   Le rond n'est donc pas un ornement : c'est ce qui permet de montrer une
   vraie photo de classe sans montrer ses defauts. */

.cycle {
  display: grid;
  /* Largeur FIGEE, pas `auto` : en `auto` la grille comprimait le medaillon a
     142px pour donner de la place au texte, et une image ronde qui retrecit de
     8px se voit tout de suite a cote des trois autres.
     minmax(0,1fr) sur la 2e colonne : sinon elle ne descend jamais sous la
     largeur de son contenu. */
  grid-template-columns: var(--medaillon) minmax(0, 1fr);
  gap: clamp(16px, 2vw, 26px);
  align-items: start;
  transition: transform var(--m-state) var(--ease-ui);
}

.cycle { --medaillon: 150px; }

.cycle__photo {
  width: var(--medaillon); height: var(--medaillon);
  border-radius: 50%;   /* pas de token : aucun autre element du site n'est rond */
  object-fit: cover;
  border: var(--hairline);
  background: var(--c-cream-deep);   /* tient la place avant le chargement */
}

.cycle__body { max-width: 46ch; padding-top: 4px; }
.cycle__name {
  font-size: var(--fs-card);
  line-height: var(--lh-card);
  margin-bottom: 6px;
}
.cycle__meta {
  font-size: var(--fs-fine);
  color: var(--c-purple);
  margin-bottom: 10px;
}
.cycle__desc { color: var(--c-text); font-size: var(--fs-note); }

/* ---------- Ce qu'on y apprend — deux colonnes réglées ---------- */

/* Deux colonnes, parce que le panneau de la façade en a deux et que la moitié
   droite de cette section était vide sous les cycles. Même vocabulaire que
   `.services` (libellé capitales, filet 2px, rangées filetées) : c'est une
   variante, pas un nouveau motif. Aucun chiffre romain ici — les romaines
   restent la signature des deux listes de M6, les diluer les affaiblirait. */
.appris {
  position: relative;
  z-index: 2;
  margin-top: clamp(56px, 7vw, 96px);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 64px);
}
.appris__label {
  font-size: var(--fs-fine);
  letter-spacing: var(--ls-caps, .08em);
  text-transform: uppercase;
  color: var(--c-heading);
  padding-bottom: 12px;
  border-bottom: 2px solid var(--c-purple);
}
.appris__list { list-style: none; margin: 0; padding: 0; }
.appris__row {
  padding-block: clamp(11px, 1.4vw, 15px);
  border-bottom: var(--hairline);
  font-size: var(--fs-note);
  color: var(--c-heading);
  font-weight: var(--w-medium);
}
/* La précision entre parenthèses du panneau devient une seconde ligne : en
   ligne elle rallongeait la rangée jusqu'à casser sur trois lignes en mobile. */
.appris__note {
  display: block;
  margin-top: 3px;
  font-size: var(--fs-fine);
  font-weight: var(--w-regular);
  color: var(--c-text);
}

@media (max-width: 639px) {
  .appris { grid-template-columns: 1fr; gap: 34px; }
}

/* ---------- M6 — la liste réglée, sous les cycles ---------- */

.services {
  position: relative;
  max-width: 720px;
  margin-top: clamp(56px, 7vw, 96px);
  z-index: 2;
}
.services__label {
  font-size: var(--fs-fine);
  letter-spacing: var(--ls-caps, .08em);
  text-transform: uppercase;
  color: var(--c-heading);
  padding-bottom: 12px;
  border-bottom: 2px solid var(--c-purple);
}
.services__list { list-style: none; margin: 0; padding: 0; }
/* Meme gabarit que `.proof` : chiffre romain A GAUCHE, meme gouttiere. Il
   etait a droite ici et a gauche la-bas — deux versions du meme composant. */
.services__row {
  display: flex; align-items: baseline; gap: clamp(16px, 2.4vw, 28px);
  padding-block: clamp(13px, 1.6vw, 18px);
  border-bottom: var(--hairline);
}
.services__name {
  font-size: var(--fs-card);
  color: var(--c-heading);
  font-weight: var(--w-medium);
}
/* Les chiffres romains (I, II, III, IV) ont ete remplaces par la « graine »,
   l'une des marques dessinees du site : elle etait dans le sprite et ne servait
   nulle part. Un numero d'ordre n'apportait rien — ces listes ne sont pas des
   etapes — et la numerotation romaine jurait avec le trace a main levee du
   reste de la page. Zero requete : le sprite est deja en ligne dans le HTML. */
.services__num {
  flex: none;
  width: 17px; height: 17px;
  margin-top: .28em;          /* aligne sur la 1re ligne, pas sur la boite */
  color: var(--c-purple);
}

/* ---------- Rappel d'appel — sobre, ce n'est pas LE bouton (M3) ---------- */

.cycles__call {
  margin-top: clamp(36px, 4.5vw, 56px);
  position: relative; z-index: 2;
}
.cycles__call-link {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 44px;
  color: var(--c-purple-deep);
  font-size: var(--fs-note);
  text-decoration: underline;
  text-decoration-color: var(--c-purple);
  text-underline-offset: 5px;
  text-decoration-thickness: 1px;
  transition: text-decoration-color var(--m-micro) var(--ease-ui);
}
.cycles__call-link:hover { text-decoration-color: var(--c-purple-deep); }
.cycles__call-icon { width: 19px; height: 19px; flex: none; }

/* ---------- Marques (M5) et débordement (M7) ---------- */

/* Le fil désigne la liste réglée. Ancré à `.services`, il la suit où qu'elle
   soit dans la page — la pointe s'arrête à côté du « I », jamais dessus. */
.cycles__mark-fil {
  width: clamp(76px, 8vw, 104px); height: auto; aspect-ratio: 100/60;
  /* Ancre a `.cycles__call` : la pointe arrive juste apres le lien, quelle que
     soit la longueur a laquelle le texte se recompose. */
  /* 29vw rapprochait la pointe du lien mais recreait 2 collisions : on garde
     34vw, mesure propre sur les 10 largeurs. */
  left: clamp(330px, 34vw, 470px); right: auto;
  /* -26px mordait le lien de 58x17px a 1024 : la fleche monte au-dessus. */
  top: -44px;
  color: var(--c-heading);
  display: none;
}
@media (min-width: 1000px) { .cycles__mark-fil { display: block; } }

/* Ancré à la grille de photos, pas au fond de section */
.cycles__mark-cocon {
  width: clamp(120px, 15vw, 220px); height: auto; aspect-ratio: 1;
  left: clamp(-96px, -5vw, -56px);
  top: clamp(40px, 5vw, 80px);
  color: var(--c-yellow-pale);
  /* -1 : la marque passe DERRIERE les cartes. A 0 elle se posait par-dessus le
     premier cadre, ce qui se lisait comme une bavure. */
  z-index: -1;
}

/* Le soleil franchit le bord bas-droit de la section (M7) */
.cycles__mark-soleil {
  width: clamp(130px, 16vw, 230px); height: auto; aspect-ratio: 1;
  right: clamp(-80px, -5vw, -36px);
  bottom: clamp(-70px, -4.5vw, -30px);
  color: var(--c-yellow-pale);
  z-index: 0;
}

/* Idem en mobile : sans `display: block`, `.mark--bleed` reste masquee et la
   section devient une pile de rectangles (echec M7 releve au round 3). */
@media (max-width: 899px) {
  .cycles__mark-soleil {
    display: block;
    width: 96px;
    right: -38px;
    bottom: -30px;
  }
}



/* ═══ 03-vie — La vie de l'école + témoignages ═══ */

/* ── 03-vie — la vie de l'école + témoignages ─────────────────
   Section clé pour M7 : six photos ne doivent pas former six
   rectangles sagement alignés — c'est le défaut du site actuel.
   ───────────────────────────────────────────────────────────── */

.vie { position: relative; overflow-x: clip; }

.vie__head { max-width: 640px; margin-bottom: clamp(32px, 4.5vw, 60px); }
.vie__title {
  font-size: var(--fs-section);
  line-height: var(--lh-title);
}
.vie__title-mark { position: relative; display: inline-block; }
.vie__trait {
  position: absolute;
  left: 0; bottom: -.22em;
  width: 104%; height: .22em;
  color: var(--c-purple);
}
.vie__lead { margin-top: 14px; color: var(--c-text); font-size: var(--fs-note); }

/* ---------- Galerie : tailles inégales, jamais une grille régulière ---------- */

.gallery {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(28px, 4vw, 56px);
  position: relative; z-index: 2;
}

.shot__fig { margin: 0; }
.shot__fig img {
  /* Fond visible AVANT que l'image soit decodee : l'attente devient un panneau
     creme assume, identique aux emplacements des cycles, au lieu d'un trou.
     C'est ce qui fait lire le chargement comme voulu et non comme un bug. */
  background: var(--c-cream-deep);
  width: 100%; height: auto;        /* sans height:auto les attributs width/height
                                       du HTML écrasent aspect-ratio : le 3:2 saute */
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: 50% 45%;
  border-radius: var(--r-20);
  border: var(--hairline);
}
.shot__cap { padding-top: clamp(12px, 1.4vw, 18px); max-width: 46ch; }
.shot__name {
  font-size: var(--fs-card);
  line-height: var(--lh-card);
  margin-bottom: 6px;
}
.shot__text { color: var(--c-text); font-size: var(--fs-note); }

@media (min-width: 900px) {
  .gallery {
    grid-template-columns: repeat(12, 1fr);
    column-gap: clamp(24px, 3vw, 44px);
    row-gap: clamp(48px, 6vw, 88px);
  }
  .shot--a { grid-column: 1 / span 7; }
  .shot--b { grid-column: 8 / span 5; align-self: end; }
  /* align-self:start sinon la cellule s'etire a la hauteur de la rangee
     et le 100% du rebond se mesure sur du vide. */
  .shot--c { grid-column: 1 / span 5; align-self: start; }
  .shot--d { grid-column: 6 / span 7; margin-top: clamp(28px, 3.5vw, 52px); }
  .shot--e { grid-column: 1 / span 6; }
  .shot--f { grid-column: 7 / span 6; margin-top: clamp(24px, 3vw, 44px); }

  /* M7 — cette photo franchit le bord de la colonne et se fait couper */
  /* -9.5vw donnait -136,8px a 1440 : la photo s'arretait a x=1408, soit 31px
     AVANT le bord, alors que ses coins droits carres annoncent une coupe.
     Il faut au moins -169px pour franchir vraiment ; -13vw donne -187px. */
  .shot--bleed { margin-right: clamp(-230px, -13vw, -60px); }
  .shot--bleed .shot__fig img { border-radius: var(--r-20) 0 0 var(--r-20); }
}

/* ---------- Marques (M5) ---------- */

/* Le rebond a ete retire : il ne designait rien et ne debordait rien. La barre
   dit qu'une telle marque doit disparaitre plutot que decorer. */

/* Le soleil déborde par la gauche, en bas de section */
.vie__mark-soleil {
  width: clamp(120px, 14vw, 205px); height: auto; aspect-ratio: 1;
  left: clamp(-120px, -7.5vw, -76px);   /* mordait la derniere legende */
  bottom: clamp(-72px, -4.5vw, -44px);
  color: var(--c-yellow-pale);
  z-index: 0;
}

/* ---------- Rappel d'appel au milieu de la galerie ----------
   Sur mobile, la galerie faisait cinq écrans sans aucun rappel : c'est là que
   l'attention retombe. Le rappel est sobre, il ne concurrence pas le gros
   bouton de la section d'appel. */

/* Rangee reglee, pas une boite : c'etait le seul bloc encadre d'une section
   qui n'en contient aucun, et il cassait la densite de la page. Il reprend
   maintenant le systeme des deux listes reglees (M6). */
.gallery__cta {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding-block: clamp(14px, 1.8vw, 20px);
  border-top: 2px solid var(--c-purple);
  border-bottom: var(--hairline);
}
.gallery__cta p { font-size: var(--fs-note); color: var(--c-heading); margin-right: auto; }
.gallery__cta a {
  display: inline-flex; align-items: center; gap: 9px;
  min-height: 44px;
  color: var(--c-purple-deep);
  font-size: var(--fs-note);
  font-weight: var(--w-medium);
  text-decoration: underline;
  text-decoration-color: var(--c-purple);
  text-underline-offset: 5px;
  text-decoration-thickness: 1px;
  transition: text-decoration-color var(--m-micro) var(--ease-ui);
}
.gallery__cta a:hover { text-decoration-color: var(--c-purple-deep); }
.gallery__cta svg { width: 19px; height: 19px; flex: none; }

/* ---------- Preuves — reprend la liste réglée (M6) ---------- */

.proofs {
  list-style: none; margin: 0 0 clamp(32px, 4vw, 48px); padding: 0;
  /* Meme largeur que `.services` : c'etait 760 ici et 720 la-bas, deux
     instances du meme composant s'arretant a deux abscisses differentes. */
  max-width: 720px;
  position: relative; z-index: 2;
  border-top: 2px solid var(--c-purple);
}
.proof {
  display: flex; align-items: baseline; gap: clamp(16px, 2.4vw, 28px);
  padding-block: clamp(15px, 1.9vw, 22px);
  border-bottom: var(--hairline);
}
.proof__num {
  flex: none;
  width: 17px; height: 17px;   /* un peu plus grande : le titre l'est aussi */
  margin-top: .3em;
  color: var(--c-purple);
}
.proof__body { display: block; }
.proof__title {
  display: block;
  font-size: var(--fs-card);
  line-height: var(--lh-card);
  font-weight: var(--w-medium);
  color: var(--c-heading);
  margin-bottom: 4px;
}
.proof__note { display: block; font-size: var(--fs-note); color: var(--c-text); }

.temoins__foot {
  display: flex; align-items: center; gap: clamp(16px, 2.4vw, 32px); flex-wrap: wrap;
  position: relative; z-index: 2;
}
.temoins__soon { font-size: var(--fs-fine); color: var(--c-text); max-width: 38ch; }

/* Lien sobre, pas un bouton jaune : le gros moment jaune appartient a la
   bande d'appel, deux ecrans plus bas (M3). */
.temoins__call {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 44px;
  color: var(--c-purple-deep);
  font-size: var(--fs-note);
  font-weight: var(--w-medium);
  text-decoration: underline;
  text-decoration-color: var(--c-purple);
  text-underline-offset: 5px;
  text-decoration-thickness: 1px;
  transition: text-decoration-color var(--m-micro) var(--ease-ui);
}
.temoins__call:hover { text-decoration-color: var(--c-purple-deep); }
.temoins__call svg { width: 20px; height: 20px; flex: none; }

/* ---------- Témoignages ---------- */

.temoins { position: relative; overflow-x: clip; }
.temoins__head { max-width: 620px; margin-bottom: clamp(28px, 3.6vw, 44px); }
.temoins__title {
  font-size: var(--fs-section);
  line-height: var(--lh-title);
}
/* Sans lui, cette section n'avait plus aucune marque designant un contenu (M5),
   et son titre etait le seul des quatre a ne pas etre souligne. */
.temoins__title-mark { position: relative; display: inline-block; }
.temoins__trait {
  position: absolute;
  left: 0; bottom: -.22em;
  width: 104%; height: .22em;
  color: var(--c-purple);
}

/* Le cocon déborde par la droite. Il doit rester à l'écart du titre : posé
   dessus, il se lit comme une tache derrière la première lettre. */
.temoins__mark-cocon {
  width: clamp(110px, 12vw, 175px); height: auto; aspect-ratio: 1;
  right: clamp(-70px, -4vw, -32px);
  top: clamp(40px, 4.5vw, 72px);
  color: var(--c-yellow-pale);
  z-index: 0;
}
/* Sous 900px le titre occupe toute la largeur : la marque le barrait en plein
   milieu. Elle descend alors en bas de section, ou elle deborde sans gener. */
@media (max-width: 899px) {
  /* `display: block` est INDISPENSABLE : `.mark--bleed` est masquee en bloc
     sous 900px par tokens.css. Sans lui, tout ce repositionnement etait du
     code mort — la marque restait invisible et M7 tombait en mobile. */
  .temoins__mark-cocon { display: block; top: auto; bottom: -34px; width: 96px; }
}

/* Le soleil de la vie de l'ecole revient aussi en mobile, mais sous le dernier
   bloc de texte et sortant par la gauche : `overflow-x: clip` le coupe net. */
@media (max-width: 899px) {
  .vie__mark-soleil {
    display: block;
    width: 88px;
    /* En bas de section il n'y a PAS de place : a -30px il mordait la derniere
       legende, a -68px le titre de la section suivante. Mesure a 6 largeurs.
       En haut a droite, en revanche, le titre « La vie de l'ecole » est court
       et laisse la bande libre — et le soleil franchit toujours un bord (M7). */
    left: auto;
    /* Encore 20px d'encre sur le chapeau a 390 et 320px : on sort davantage
       et on remonte au niveau du titre, qui est la ligne la plus courte. */
    right: -54px;
    bottom: auto;
    top: 12px;
  }
}


/* ═══ 04-appel — Appel + pied de page ═══ */

/* ── 04-appel — appel + pied de page ──────────────────────────
   La pièce qui convertit. M3 y est central : au plus 2 objets
   #FFD400 par écran, et chacun mène au téléphone.
   ───────────────────────────────────────────────────────────── */

/* ---------- Section d'appel ---------- */

.section--contact {
  /* Coins hauts arrondis : la bande se lit comme un objet pose sur la creme,
     au lieu d'une rupture de fond franche. */
  border-radius: var(--r-20) var(--r-20) 0 0;
  background: var(--c-purple);
  color: var(--c-cream);
  position: relative;
  overflow-x: clip;
  text-align: center;
}
.contact__wrap { max-width: 820px; }

.contact__title {
  font-size: var(--fs-section);
  line-height: var(--lh-title);
  color: var(--c-cream);          /* sur violet, le gris-violet des titres serait illisible */
}
.contact__note {
  margin-top: 12px;
  color: var(--c-yellow-pale);
  font-size: var(--fs-note);
}

.contact__call { position: relative; margin-top: clamp(28px, 4vw, 46px); }

/* Objet jaune n°1 — mène au téléphone */
.contact__number {
  display: inline-block;
  font-size: clamp(1.9rem, 5.2vw, 3.75rem);
  line-height: 1.1;
  font-weight: var(--w-medium);
  color: var(--c-yellow);
  text-decoration: none;
  padding: 10px 8px;
  border-radius: var(--r-12);
  transition: color var(--m-micro) var(--ease-ui);
}
.contact__number:hover { color: var(--c-yellow-pale); }

.contact__actions {
  margin-top: clamp(22px, 3vw, 32px);
  display: flex; flex-wrap: wrap; gap: 14px; justify-content: center;
}
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px;
  padding: 13px 30px;
  border-radius: var(--r-pill);
  font-size: var(--fs-note);
  font-weight: var(--w-medium);
  text-decoration: none;
  transition: background-color var(--m-micro) var(--ease-ui),
              color var(--m-micro) var(--ease-ui);
}
/* Objet jaune n°2 — mène au téléphone */
.btn--call {
  background: var(--c-yellow);
  color: var(--c-purple-deep);
  --focus-ring: var(--c-purple-deep);
}
.btn--call:hover { background: var(--c-yellow-pale); }

/* WhatsApp n'est PAS jaune : il ne doit pas concurrencer l'appel (M3) */
.btn--whatsapp {
  background: transparent;
  color: var(--c-cream);
  border: 1px solid var(--c-yellow-pale);
}
.btn--whatsapp:hover { background: var(--c-purple-deep); color: var(--c-cream); }

.contact__reassurance {
  margin-top: clamp(22px, 3vw, 30px);
  color: var(--c-yellow-pale);
  font-size: var(--fs-fine);
}

/* Le fil désigne le numéro — cible réelle (M5) */
.contact__fil {
  width: clamp(70px, 7vw, 104px); height: auto; aspect-ratio: 100/60;
  left: clamp(-118px, -7vw, -96px);   /* recouvrait l'encre du numero */
  top: -6px;
  color: var(--c-yellow-pale);
  display: none;
}
/* Sous 1000px la marge manque a GAUCHE du numero : la fleche mordrait le bord.
   Elle ne disparait plus pour autant (la section n'avait alors aucune marque,
   echec M5 au round 3) : elle passe AU-DESSUS du numero, ou la place existe. */
@media (min-width: 1000px) { .contact__fil { display: block; } }
/* Tentative abandonnee : un fil au-dessus du numero. Mesure a 320-900px, il
   mordait a la fois le paragraphe des tarifs et le numero lui-meme — la
   section centree ne laisse aucune marge laterale. La marque de cette section
   en mobile est desormais le soulignement de « enfant », ANCRE au mot donc
   valide a toutes les largeurs (M5). */

/* Le soleil franchit le bord droit de la section contact (M7). Pale, derriere
   le contenu (z-index 0 contre 2), donc jamais sur l'encre du numero. */
.contact__soleil {
  width: clamp(92px, 12vw, 180px); height: auto; aspect-ratio: 1;
  /* A 480px il mordait la ligne « Ouakam, Dakar » de 13x7px : on sort
     davantage par la droite et on descend le point d'ancrage. */
  right: clamp(-72px, -7vw, -46px);
  bottom: clamp(-58px, -3.2vw, -34px);
  color: var(--c-yellow-pale);
  opacity: .5;
  z-index: 0;
}

/* Soulignement ancre au dernier mot du titre : meme motif que le heros
   (« pour »), les cycles (« quatre ») et la vie de l'ecole (« l'ecole »). */
.contact__title-mark { position: relative; display: inline-block; }
.contact__trait {
  position: absolute;
  left: 0; bottom: -.20em;
  width: 104%; height: .20em;
  color: var(--c-yellow-pale);
}

/* Le fil du pied designe le numero principal. Ancre a sa rangee (M5). */
.footer__row--tel { position: relative; }
.footer__fil {
  width: 46px; height: auto; aspect-ratio: 100/60;
  left: -54px;
  top: 2px;
  color: var(--c-yellow-pale);
  opacity: .75;
}
/* Sous 1000px la colonne part du bord gauche : le fil sortirait de l'ecran.
   Il passe au-dessus du numero, pointe vers le bas. */
@media (max-width: 999px) {
  /* Au-dessus, il percutait le titre « Nous joindre » a toutes les largeurs.
     A droite du numero, la colonne pleine largeur laisse la place — mais colle
     au numero, sinon il ne DESIGNE plus rien (M5) et se lit comme un gribouilli
     perdu. Le miroir retourne la pointe vers le numero, qui est a sa gauche. */
  .footer__fil {
    left: 150px; right: auto; top: 0;
    transform: scaleX(-1);
  }
}

/* ---------- Pied de page ---------- */

.site-footer {
  /* La bande d'appel est en --c-purple (#873897), le pied en --c-purple-deep
     (#5A2166) : bord a bord, la marche se lisait comme un defaut d'alignement.
     Les deux couleurs restent celles du systeme — seule la jonction change :
     le pied part du violet de la bande et descend vers le violet profond sur
     160px. `background-color` reste pose dessous : si le degrade n'etait pas
     rendu, le fond resterait plein, jamais transparent. */
  background-color: var(--c-purple-deep);
  background-image: linear-gradient(to bottom, var(--c-purple) 0, var(--c-purple-deep) 160px);
  color: var(--c-cream);
  position: relative;
  overflow-x: clip;
  padding-top: clamp(44px, 5.2vw, 68px);
  /* Le logotype geant est retire : ce padding n'a plus a lui reserver de place.
     Il debordait de 34px SOUS le fond violet (`overflow-x: clip` ne clippe pas
     la verticale), ce qui laissait 69px de creme tout en bas — mesure a
     1600x900. C'etait le « violet pas colle a la page ». */
  padding-bottom: clamp(40px, 4.6vw, 60px);
}

.footer__wrap {
  display: grid; gap: clamp(28px, 4vw, 48px);
  grid-template-columns: 1fr;
  position: relative; z-index: 2;
}
@media (min-width: 640px) { .footer__wrap { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .footer__wrap { grid-template-columns: 1.6fr 1fr 1fr 1fr; } }

.footer__brand { position: relative; }
.footer__logo { width: 124px; height: auto; margin-bottom: 14px; }
.footer__name {
  font-size: var(--fs-card);
  font-weight: var(--w-medium);
  color: var(--c-cream);
  margin-bottom: 8px;
}
.footer__address { font-size: var(--fs-fine); color: var(--c-yellow-pale); line-height: 1.6; }

.footer__heading {
  font-size: var(--fs-fine);
  letter-spacing: var(--ls-caps, .08em);
  text-transform: uppercase;
  color: var(--c-yellow-pale);
  margin-bottom: 12px;
}
.footer__list { list-style: none; margin: 0; padding: 0; }
.footer__link {
  display: inline-flex; align-items: center;
  color: var(--c-cream);
  font-size: var(--fs-note);
  text-decoration: none;
  padding-block: 9px;
  transition: color var(--m-micro) var(--ease-ui);
}
/* M3 : #FFD400 appartient a l appel. Les liens du pied (Facebook, Instagram,
   e-mail) ne menent pas au telephone -> jaune pale, deja l accent sur violet. */
.footer__link:hover { color: var(--c-yellow-pale); }
.footer__legal { font-size: var(--fs-fine); color: var(--c-yellow-pale); margin-bottom: 6px; }

/* Le cocon du pied de page a ete retire : il percutait le sommet du « A » du
   logotype geant en desktop, et le libelle « NOUS JOINDRE » en mobile. Le
   logotype coupe porte deja M7, la fleche de la bande d'appel porte deja M5. */

/* Le logotype geant du pied de page a ete RETIRE (demande cliente : « c'est
   ecrit le nom de l'ecole en gros, pas la peine »). Il portait M7 pour cette
   section ; le nom reste ecrit en clair dans `.footer__name`. */

/* Le libelle « Appeler le » s'escamote jusqu'a 479px, pas seulement 420px :
   mesure a 430px, logo 150 + gap 16 + bouton 229 = 395px pour 390 disponibles,
   le bouton descendait d'une rangee et l'en-tete passait a 209px.
   Avec le libelle court : 150 + 16 + 144 = 310px. L'icone telephone porte le
   sens et le lien garde son intitule complet en `aria-label`.
   Le gros bouton du heros, lui, garde toujours son texte entier. */
@media (max-width: 479px) {
  .site-header .btn-call__label { display: none; }
}

/* Sous 640px, 150px de medaillon ne laissaient que ~180px au texte : les
   descriptions passaient sur six lignes. Le medaillon retrecit. */
@media (max-width: 639px) {
  .cycle { --medaillon: 112px; gap: 16px; }
}
/* Sous 480px, cote a cote il ne restait que 187px au texte — quatre lignes pour
   une description de deux. On empile : le texte reprend toute la largeur. */
@media (max-width: 479px) {
  .cycle {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
    --medaillon: 104px;
  }
}

/* ---------- Cibles tactiles au doigt ---------- */

@media (max-width: 999px) {
  .footer__link { min-height: 44px; padding-block: 11px; }
  .contact__number { padding: 14px 10px; }
  .btn { width: 100%; }
  .contact__actions { flex-direction: column; }
}
