/* ═══════════════════════════════════════════════════════════════
   CHEZ PAULETTE STUDIO — Squeeze page (gabarit page-squeeze)

   Chargée après service-page.css, dont ce gabarit réutilise trois briques
   déjà écrites : `.signs` (bloc offre), `.hero__form` / `.field` (champs CF7)
   et `.pill-btn` (bouton d'envoi). Ne sont définis ici que les blocs propres
   à la squeeze page : en-tête sans navigation, accroche centrée, section
   formulaire drenchée, pied de page légal.

   Répartition crème / bordeaux : crème (en-tête, accroche, offre) puis
   bordeaux (formulaire, pied de page). Une section bordeaux pour trois
   crème — cf. DESIGN.md.
   ═══════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════
   EN-TÊTE MINIMAL
══════════════════════════════════════════ */

/* Hauteur de l'en-tête, en un seul endroit.
   Le hero plein écran doit en soustraire la valeur exacte : contrairement à la
   page d'accueil, dont la nav se superpose au hero, celui-ci est `sticky` et
   occupe une place réelle dans le flux. Un `100vh` brut y ajouterait la hauteur
   de l'en-tête et pousserait le bas du hero sous la ligne de flottaison.
   `.sq-header` APPLIQUE la variable (`height`, pas `min-height`) : la hauteur
   est ainsi vraie par construction, et non une valeur devinée qui dériverait
   au premier changement de padding. C'est désormais LE LOGO qui dimensionne
   l'en-tête (54 px + 2 × 14 px de respiration) : le bouton qui jouait ce rôle
   a été supprimé, et la hauteur reste la même — c'est le logo qui a grandi
   pour l'occuper.

   Pas de variante mobile : le contenu du hero y dépasse de toute façon
   largement la hauteur d'écran, `min-height` n'y est jamais la contrainte
   active. Une seconde valeur n'aurait fait qu'ajouter une chose à maintenir. */
:root { --sq-header-h: 83px; }

.sq-header {
  background: var(--cream);
  border-bottom: 1px solid var(--gray-200);
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--sq-header-h);
}
.sq-header__inner {
  display: flex;
  align-items: center;
  /* Grille `1fr auto 1fr` et non positionnement absolu : le logo doit rester
     centré quelle que soit la longueur de l'adresse, MAIS l'adresse doit
     respecter le padding du conteneur. Un élément en absolu se cale sur la
     boîte de padding et l'ignore donc — l'adresse venait coller au bord de
     l'écran sur mobile. La grille tient les deux contraintes sans exception. */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding-top: 14px;
  padding-bottom: 14px;
}
.sq-header__brand { grid-column: 2; justify-self: center; }
.sq-header__place { grid-column: 3; justify-self: end; }

/* ── L'ADRESSE DANS L'EN-TÊTE ──
   Le pin porte la seule touche de bordeaux de la barre : à cette taille, un
   pictogramme coloré se lit comme un repère et non comme un bouton. */
.sq-header__place {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-family: var(--font-body);
  font-size: .82rem;
  line-height: 1.2;
  color: var(--gray-700);
  white-space: nowrap;
}
.sq-header__pin { color: var(--primary-700); flex: none; }
.sq-header__place-short { display: none; }

/* Sous 900 px, l'adresse complète entrerait en collision avec le logo centré :
   il ne reste qu'une centaine de pixels de chaque côté. La ville seule suffit,
   et c'est elle que le titre oppose à Paris. */
@media (max-width: 899px) {
  .sq-header__place-full  { display: none; }
  .sq-header__place-short { display: inline; }
}
.sq-header__brand {
  display: inline-flex;
  align-items: center;
}
.sq-header__logo {
  display: block;
  height: 54px;
  width: auto;
}

/* ══════════════════════════════════════════
   ACCROCHE + CARTE D'OFFRE

   Mise en page transposée du « Welcome Pack » de poses-studio.com : média
   plein cadre, texte par-dessus, carte d'offre détachée à droite. La structure
   est reprise, la palette ne l'est pas — leur noir / blanc / orange est
   exactement ce que la charte exclut.

   Le fond est la vidéo du studio — la même que le hero de la page d'accueil,
   avec le même mécanisme de chargement conditionnel. Le texte passe donc en
   crème, et un voile quasi-noir chaud garantit le contraste AA sur toute la
   durée de la boucle. Ce voile n'est PAS teinté bordeaux : il repeindrait le
   bois et la lumière du studio, qui sont justement ce qu'on veut montrer.
══════════════════════════════════════════ */
.sq-hero {
  position: relative;
  isolation: isolate;
  background: var(--cream);
  padding: 72px 0 56px;
  /* Lueur chaude de corniche, comme les LED du studio : l'élévation ne passe
     jamais par une ombre grise sur du crème. */
  background-image: var(--glow-cove);
}

/* Variante avec média : le fond devient bordeaux profond, pas crème, et la
   section occupe l'écran entier — comme le hero de la page d'accueil.

   `min-height` et non `height` : la page d'accueil peut se permettre un
   `height: 100vh` parce que son contenu est court (logo + accroche + boutons).
   Ici le hero porte en plus une carte d'offre de ~450 px ; une hauteur fixe la
   rognerait sur les écrans courts. Avec `min-height`, la section remplit
   l'écran quand elle est plus courte et s'allonge quand il le faut.

   `svh` plutôt que `vh` : sur mobile, `100vh` compte la barre d'URL du
   navigateur comme si elle n'existait pas et déborde de sa hauteur. */
.sq-hero--offer {
  background: var(--surface-dark);
  background-image: none;
  padding: 56px 0 64px;
  overflow: hidden;
  min-height: calc(100svh - var(--sq-header-h));
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* ══════════════════════════════════════════
   ADRESSE ET DATE D'OUVERTURE — LES DEUX COINS HAUTS DU HERO

   Épinglés en absolu plutôt que posés dans le flux : la grille du hero est
   centrée verticalement, et un frère dans le flux se serait centré avec elle
   au lieu de tenir le haut.

   Détachés du header, pas collés dessous. Le header est collant et porte déjà
   un logo à gauche et un bouton à droite ; sans ces 40 px de respiration on
   lirait deux barres empilées. C'est la différence avec la page de POSES dont
   la mise en page vient : chez eux cette ligne EST l'en-tête, ils n'ont pas de
   bouton collant à loger au-dessus.

   Marcellus, et donc aucun `font-weight` : la police n'existe qu'en 400, une
   graisse demandée produirait un faux gras. La présence vient de la taille,
   et le retrait de l'opacité.

   Taille plafonnée nettement sous celle du H1 : ces deux mentions se lisent
   d'un coup d'œil mais ne doivent pas concourir avec le titre, qui reste ce
   qui doit tomber en premier. */
.sq-hero__meta {
  position: absolute;
  top: 40px;
  left: 0;
  right: 0;
  z-index: 1;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  pointer-events: none;
}
/* Blanc Davos plutôt que le crème : demandé « en blanc », et le blanc pur est
   exclu par la charte. Opacité pleine et non 80 % — sur mobile la paire tombe
   sur la zone la plus claire du média, où un crème atténué perdait le contraste
   que WCAG AA impose comme plancher au projet. */
.sq-hero__meta-item {
  font-family: var(--font-display);
  font-size: 1.375rem;
  line-height: 1.3;
  color: var(--davos);
}
/* Seule présente, la date doit rester à droite : `space-between` la collerait
   à gauche, à la place de l'adresse absente. */
.sq-hero__meta-item--end {
  margin-left: auto;
  text-align: right;
}

/* Sous 1000 px les deux coins se télescopent : ils s'empilent, calés à gauche,
   et repassent dans le flux. Le hero garde alors sa respiration haute par son
   propre padding, sans réserver d'espace pour un bloc absolu. */
@media (max-width: 999px) {
  .sq-hero__meta {
    position: static;
    /* Même raison que pour `.sq-hero__grid` : de retour dans le flux, ce bloc
       devient un enfant de la colonne flex du hero et se rétracte autour de
       son texte, ce qui le décale au lieu de le caler à gauche. */
    width: 100%;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    margin-bottom: 28px;
  }
  .sq-hero__meta-item {
    font-size: 0.9375rem;
  }
  .sq-hero__meta-item--end {
    margin-left: 0;
    text-align: left;
  }
}

/* La grille devient un enfant flex : sans cette largeur, elle se rétracte
   autour de son contenu au lieu de tenir la colonne. */
.sq-hero--offer .sq-hero__grid {
  width: 100%;
}
/* Réserve de débord pour les billets.
   La carte était collée au bord du conteneur : il ne restait que 40 px à sa
   droite en 1280 et en 1024, ce qui rendait le « moitié dehors » impossible
   sans rognage. La grille se décale donc vers la gauche — le conteneur, lui,
   ne bouge pas, pour que le titre reste aligné avec le reste de la page.
   La colonne de texte absorbe le retrait sans broncher : elle est fluide. */
@media (min-width: 1000px) {
  .sq-hero--offer .sq-hero__grid {
    padding-right: 120px;
  }
}
.sq-hero--offer.sq-hero--nomedia {
  /* Sans image, le bordeaux plein reste lisible : rien à compenser. */
  background: var(--surface-dark);
}

.sq-hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
}
/* Même cadrage que `.hero__video` de la page d'accueil : la vidéo est centrée
   et recadrée, jamais déformée. */
.sq-hero__video {
  position: absolute;
  top: 50%; left: 50%;
  width: 100%; height: 100%;
  object-fit: cover;
  transform: translate(-50%, -50%);
}

/* ── LE VOILE ──
   Repris du hero de la page d'accueil : quasi-noir chaud `rgba(26,4,6,…)` plus
   une lueur de corniche crème en haut. AUCUNE teinte rouge — un voile bordeaux
   repeint la vidéo, écrase le bois et la lumière chaude du studio, et c'est
   précisément ce qu'il faut voir.

   Il reste indispensable : sans lui, le crème du texte tombe sous 2:1 sur les
   parties claires de la vidéo (les corniches LED). Sa densité est réglée au
   minimum qui tienne AA sur toute la durée de la boucle — mesuré image par
   image, pas estimé. */
.sq-hero__veil {
  position: absolute;
  inset: 0;
  /* Mobile : le texte occupe toute la largeur et le sur-titre se pose tout en
     haut, pile sur les corniches LED du poster — la partie la plus claire de
     l'image. La lueur crème y est donc réduite de moitié (elle ajoutait de la
     lumière là où il en fallait le moins : 2,95:1 mesuré) et le haut du
     dégradé densifié. */
  background:
    radial-gradient(130% 62% at 50% -4%, rgba(233, 224, 210, .11) 0%, rgba(233, 224, 210, 0) 62%),
    linear-gradient(to bottom,
      rgba(26, 4, 6, .70) 0%,
      rgba(26, 4, 6, .64) 55%,
      rgba(26, 4, 6, .74) 100%);
}
@media (min-width: 1000px) {
  /* Deux colonnes : on densifie le côté du texte et on laisse respirer celui de
     la carte, qui pose de toute façon son propre fond clair. */
  .sq-hero__veil {
    background:
      radial-gradient(130% 62% at 50% -4%, rgba(233, 224, 210, .22) 0%, rgba(233, 224, 210, 0) 62%),
      linear-gradient(100deg,
        rgba(26, 4, 6, .82) 0%,
        rgba(26, 4, 6, .66) 46%,
        rgba(26, 4, 6, .38) 100%);
  }
}

.sq-hero__grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 36px;
  align-items: center;
}
@media (min-width: 1000px) {
  .sq-hero__grid {
    grid-template-columns: minmax(0, 1fr) 380px;
    gap: 56px;
  }
}

/* ══════════════════════════════════════════
   HERO « MAXI » — le titre, et un seul bouton

   Un seul geste possible dans cet écran. Le titre tient le HAUT de la section
   (pas de centrage vertical, contrairement au hero d'offre) et le bouton est
   poussé en bas par `margin-top: auto` : quelle que soit la longueur du titre,
   il reste à la même place, au lieu de flotter juste sous la dernière ligne.
══════════════════════════════════════════ */
.sq-hero--maxi {
  background: var(--surface-dark);
  background-image: none;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: calc(100svh - var(--sq-header-h));
  /* Padding haut volontairement court — le titre frôle le bord. Il ne peut pas
     le toucher tout à fait : l'en-tête est `sticky` et occupe une place réelle
     dans le flux (--sq-header-h). Le faire toucher vraiment suppose un en-tête
     flottant en superposition — décision non prise, cf. la discussion. */
  padding: 20px 0 48px;
}

/* Tout est centré dans cet écran — titre, bouton, adresse sur un même axe.
   C'est une demande explicite et non le réflexe par défaut que DESIGN.md
   écarte : ici il n'y a qu'une colonne et qu'un seul geste possible, donc pas
   de second axe avec lequel entrer en concurrence. */
.sq-maxi {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  flex: 1;
  /* Décale le bloc sous l'en-tête. En vh et non en px pour que la respiration
     suive la hauteur d'écran ; plafonné à 42 px, et le plancher de 14 px protège
     le budget vertical de l'étape 4 sur les petits mobiles (mesuré : 97 px de
     marge sous le bouton d'envoi à 390 × 667). */
  padding-top: clamp(14px, 3.2vh, 42px);
}

.sq-maxi__eyebrow {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--ivory);
  margin: 0 0 14px;
}

/* ── LE H1 N'EST PLUS LE GROS TITRE ──
   Il a été rétrogradé en sur-titre : il nomme la pratique (« PILATES MAT &
   REFORMER ») et le corps maxi est descendu sur la première question du
   formulaire (`.sq-steps__q--hero`). Il reste le <h1> parce qu'il reste le
   titre de la page — la hiérarchie visuelle et celle du document n'ont pas à
   coïncider, et un écran dont le seul geste est un formulaire n'a pas besoin
   d'un deuxième titre de niveau 1.

   Marcellus n'a qu'une graisse : AUCUN font-weight, jamais. Les capitales
   viennent du CSS et non de la base, pour que le titre reste en bas-de-casse
   dans wp-admin, dans l'onglet du navigateur et dans les SERP. */
.sq-maxi__title {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.9vw, 1.45rem);
  line-height: 1.25;
  /* Les capitales de Marcellus se touchent sans interlettrage — davantage que
     pour du bas-de-casse, où la valeur était négative (-0.005em). */
  letter-spacing: .18em;
  /* Rattrape le blanc que l'interlettrage ajoute APRÈS la dernière lettre, et
     qui décentrerait la ligne vers la gauche dans une colonne centrée. */
  text-indent: .18em;
  text-transform: uppercase;
  /* Ivoire et non davos : le blanc le plus franc appartient désormais au gros
     titre du bloc de capture, plus bas. */
  color: var(--ivory);
  margin: 0;
  text-wrap: balance;
}

/* La ville, deuxième ligne du sur-titre. AUCUNE propriété `font-*`, `color` ni
   `letter-spacing` ici : tout est hérité du h1, ce qui garantit que les deux
   lignes restent identiques quand on retouche l'une. Ne rien y redéclarer. */
.sq-maxi__city {
  display: block;
  margin-top: .3em;
}

.sq-maxi__lead {
  font-family: var(--font-body);
  font-size: 1.05rem;
  line-height: 1.7;
  color: var(--ivory);
  max-width: 52ch;
  margin: 24px auto 0;
}
.sq-maxi__meta {
  font-family: var(--font-heading);
  font-size: .82rem;
  letter-spacing: .06em;
  color: var(--ivory);
  /* Remontée sous les choix au lieu d'être plaquée en bas du hero. Plaquée,
     elle croisait le décor à 1920, 1440 et 1024 — l'adresse complète est plus
     large qu'un dégagement horizontal ne peut garantir. Ici la bande basse
     appartient au décor seul, et il n'y a plus de collision possible quelle
     que soit la largeur. */
  margin: 26px 0 0;
}
/* ══════════════════════════════════════════
   LE BLOC DE CAPTURE — la seule action de la page

   Proportions reprises de la référence client, avec deux écarts imposés par la
   charte et assumés :

   • Marcellus n'a qu'UNE graisse. Le mot mis en avant de la référence est en
     gras ; ici l'accent se fait par la COULEUR. Un `font-weight` sur du
     Marcellus produirait un faux gras synthétique qui écrase ses évasures,
     c'est-à-dire exactement ce pour quoi la police a été choisie (DESIGN.md).
   • La référence n'a aucune étiquette, seulement des placeholders en capitales.
     DESIGN.md l'interdit — « étiquette au-dessus, jamais en placeholder seul » —
     et la raison est bonne : le placeholder disparaît dès qu'on tape. Les
     étiquettes restent donc, mais alignées à GAUCHE et discrètes. Centrées
     au-dessus des champs, elles étaient une bonne part de ce qui faisait sale.
══════════════════════════════════════════ */
.sq-join {
  width: 100%;
  max-width: 540px;
  margin: clamp(30px, 5vh, 54px) auto 0;
  position: relative;
  z-index: 1;
}

/* ── LA QUESTION DE L'ÉTAPE ──
   Une par étape, à l'intérieur du formulaire : elle change avec l'étape, ce
   qu'un titre posé au-dessus du bloc ne pouvait pas faire. C'est ce qui donne
   au parcours son allure de conversation plutôt que de formulaire.

   `--davos` et non `#fff` : la charte exclut le blanc pur, davos EST le blanc
   du système sur fond bordeaux (DESIGN.md). */
.sq-steps__q {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.7vw, 2.15rem);
  line-height: 1.2;
  color: var(--davos);
  text-align: center;
  margin: 0 0 clamp(20px, 2.6vh, 28px);
  text-wrap: balance;
}

/* ── L'ÉTAPE 1 PORTE LE GROS TITRE DE LA PAGE ──
   Le corps maxi est descendu du <h1> jusqu'ici : c'est l'accueil, et il ne vaut
   que pour le premier écran. Aux étapes 2 à 4 la question reprend sa taille
   normale — la place ainsi rendue va au formulaire, qui s'allonge (six créneaux
   + consentement à l'étape 4, cf. le budget vertical mobile plus bas).

   NE PAS l'appliquer aux quatre questions : ce serait rendre le budget
   vertical de l'étape 4 intenable sur mobile. */
.sq-steps__q--hero {
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  line-height: 1.1;
  letter-spacing: -0.005em;
}

/* ── UNE SEULE LIGNE, ET ELLE DÉBORDE DE LA COLONNE ──
   Le bloc de capture fait 540 px de large ; la phrase et son cœur en réclament
   15,4 em, soit ~790 px au corps maxi. Elle sort donc volontairement de
   `.sq-join` : `width: max-content` lui rend sa largeur naturelle, et le couple
   `left: 50%` / `translateX(-50%)` la recentre sur l'axe de la colonne — sans
   quoi elle déborderait par la droite uniquement.

   LE PLAFOND EN vw N'EST PAS DÉCORATIF. À 15,4 em de large, la ligne occupe
   90,6 % de la fenêtre à 5,9 vw : c'est la valeur maximale qui laisse une marge
   de part et d'autre à toutes les largeurs. La monter fait sortir la phrase de
   l'écran, et `.sq-hero--maxi` porte `overflow: hidden` — elle serait coupée,
   pas scrollable. Toute retouche du texte ou du corps se revérifie ici.

   Mobile exclu à dessein : voir la fin du fichier. */
@media (min-width: 760px) {
  .sq-steps__q--hero {
    font-size: min(3.6rem, 5.9vw);
    white-space: nowrap;
    width: max-content;
    position: relative;
    left: 50%;
    transform: translateX(-50%);
  }
}

/* ── LA PHRASE D'INVITATION, SOUS LE GROS TITRE ──
   Elle vit DANS l'étape 1 du formulaire (cf7.php) et non dans l'extrait de la
   page : le gros titre y est lui aussi, et un texte posé au niveau du hero
   serait forcément passé AU-DESSUS de lui, pas entre lui et les champs.
   Conséquence heureuse : elle disparaît d'elle-même dès l'étape 2, sans une
   ligne de JS ni de sélecteur d'état — elle invite à s'inscrire, ce qui n'a
   plus de sens une fois qu'on a commencé, et l'étape 4 récupère sa hauteur.

   Corps et couleur alignés sur le sur-titre (« PILATES MAT & REFORMER »),
   demande explicite : les deux échelles sont liées, si l'une bouge, bouger
   l'autre. Manrope et non Marcellus — c'est du texte courant, pas du titrage
   (DESIGN.md). Davos, le blanc du système : jamais `#fff`. */
.sq-steps__intro {
  font-family: var(--font-body);
  font-size: clamp(1rem, 1.9vw, 1.45rem);
  line-height: 1.5;
  color: var(--davos);
  text-align: center;
  /* Plus étroit que le titre d'un cran : au-delà la phrase passe à trois
     lignes et repousse les champs. */
  max-width: 34ch;
  margin: 0 auto clamp(20px, 2.8vh, 30px);
  text-wrap: balance;
}

/* Cœur AU TRAIT, jamais plein : c'est un signe d'affection, pas un bouton
   « j'aime ». En SVG inline et jamais en emoji (DESIGN.md) — un emoji cœur
   arriverait rouge vif, hors palette, et rendu différemment sur chaque système.
   Dimensionné en `em` pour suivre le titre à toutes les largeurs, et décoratif
   (`aria-hidden` côté markup) : la phrase se suffit. */
.sq-steps__heart {
  width: .74em;
  height: .74em;
  vertical-align: baseline;
  margin-left: .14em;
  /* Blanc, c'est-à-dire `--davos` via currentColor : le titre le porte déjà,
     donc une seule valeur à maintenir et jamais de dérive entre les deux.
     Ni `#fff` (exclu par la charte) ni `--davos` réécrit ici. */
  flex: none;
}

/* ── LES TROIS CHOIX (étape 3) ──
   Trois colonnes : un ecover en haut, le libellé dessous. Aucune carte, aucune
   surface — l'image est détourée et se pose sur la vidéo, comme le reste du
   hero.

   Côte à côte à TOUTES les largeurs, mobile compris. Empilées, trois blocs
   image + texte feraient trois écrans ; c'est la même raison qui avait fait
   garder les arches en ligne. À 390 px chaque colonne fait ~104 px, ce qui
   suffit à un ecover et à deux mots.

   Les visuels arrivent par `--pick-1..3`, posées en style inline par le pattern
   depuis des champs ACF (CF7 ne sait pas rendre une image par option). L'ordre
   des variables suit celui des options du formulaire : les intervertir décale
   les images d'une colonne. */
.field--picks {
  border: 0;
  margin: 0;
  padding: 0;
}
.field--picks .wpcf7-radio {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(10px, 2.2vw, 22px);
  align-items: stretch;
}
.field--picks .wpcf7-list-item { margin: 0; display: flex; }
.field--picks .wpcf7-list-item label {
  display: flex;
  width: 100%;
  cursor: pointer;
}
.field--picks input[type="radio"] {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.field--picks .wpcf7-list-item-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 8px 14px;
  border-radius: var(--radius-card, 1.25rem);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: .8rem;
  line-height: 1.3;
  letter-spacing: .02em;
  color: var(--davos);
  text-align: center;
  /* Deux lignes réservées : « Je teste les deux » en occupe deux là où « Le
     tapis » n'en prend qu'une, et sans cette réserve les trois colonnes ne
     s'alignaient pas par le bas. */
  transition: background-color var(--dur-fast, 180ms) ease;
}

/* L'emplacement de l'ecover. `contain` : ce sont des visuels détourés, on ne
   les recadre jamais. Sans image, le bloc réserve sa place avec un lavis chaud
   très faible — un trou serait pire qu'un emplacement visiblement en attente. */
.field--picks .wpcf7-list-item-label::before {
  content: "";
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  background: rgba(233, 224, 210, .07) center / contain no-repeat;
  border-radius: 12px;
  transition: transform var(--dur-base, 320ms) var(--ease-out-expo, ease);
}
.field--picks .wpcf7-list-item:nth-child(1) .wpcf7-list-item-label::before { background-image: var(--pick-1); }
.field--picks .wpcf7-list-item:nth-child(2) .wpcf7-list-item-label::before { background-image: var(--pick-2); }
.field--picks .wpcf7-list-item:nth-child(3) .wpcf7-list-item-label::before { background-image: var(--pick-3); }

@media (hover: hover) {
  .field--picks .wpcf7-list-item-label:hover { background: rgba(233, 224, 210, .09); }
  .field--picks .wpcf7-list-item-label:hover::before { transform: translateY(-4px); }
}

/* Sélectionné : la colonne se pose sur un fond bordeaux. C'est le seul moment
   du parcours où la couleur de marque frappe, et c'est le bon — c'est le geste
   qui engage. */
.field--picks input[type="radio"]:checked + .wpcf7-list-item-label {
  background: var(--primary-700);
}
.field--picks input[type="radio"]:focus-visible + .wpcf7-list-item-label {
  outline: 2px solid var(--davos);
  outline-offset: 3px;
}

/* Rappel d'édition, jamais visible du public. */
.sq-join__todo {
  font-family: var(--font-body);
  font-size: .74rem;
  line-height: 1.5;
  color: var(--davos);
  background: rgba(94, 32, 40, .55);
  border: 1px dashed rgba(233, 224, 210, .4);
  border-radius: 10px;
  padding: 8px 12px;
  margin: 12px 0 0;
  text-align: center;
}

/* Précision sous les champs : ce qu'on fait de la donnée, dit à l'endroit où
   on la demande plutôt que dans une mention légale plus bas. */
.sq-steps__aside {
  font-family: var(--font-body);
  font-size: .8rem;
  line-height: 1.6;
  color: var(--vin-200, #D5C1B6);
  text-align: center;
  max-width: 40ch;
  margin: 12px auto 0;
}

/* Le remplacement d'une étape par l'autre est un changement de contenu : une
   transition d'opacité courte le signale sans faire attendre. */
@media (prefers-reduced-motion: no-preference) {
  .sq-steps--active .sq-steps__step { animation: sq-step-in .26s ease-out both; }
}

/* ── LES CHAMPS ──
   Hauteur généreuse : c'est le premier facteur de « premium » sur la référence,
   dont les champs font près du double d'un champ ordinaire. Un champ serré se
   lit comme un formulaire administratif. */
/* ── L'ÉTIQUETTE EST DANS LE CHAMP, PAS AU-DESSUS ──
   Traitement de la référence : capitales espacées à l'intérieur du champ, rien
   au-dessus. L'étiquette reste dans le markup mais devient invisible
   (`screen-reader-text`) — un champ sans étiquette du tout n'est pas
   annonçable par un lecteur d'écran.

   ⚠ ÉCART ASSUMÉ AVEC DESIGN.md, qui demande « étiquette au-dessus, jamais en
   placeholder seul ». La raison de cette règle reste vraie : le repère
   disparaît dès qu'on tape. On l'accepte ici parce que deux champs nommés
   Prénom et Nom ne laissent aucun doute une fois remplis, ce qui ne serait pas
   le cas d'un formulaire long ou de champs ambigus. Ne pas généraliser.

   Manrope en capitales espacées, comme les boutons du thème : le champ et le
   bouton se répondent. Marcellus était exclu — DESIGN.md l'interdit sous
   24 px, où ses évasures se ferment. */
.sq-join__form .field { gap: 0; }
.sq-join__form .field__input::placeholder {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: .82rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--gray-500);
  opacity: 1;               /* Firefox l'atténue par défaut */
}
.sq-join__form .field__opt { color: var(--vin-300, #C0A39B); text-transform: none; letter-spacing: 0; }
.sq-join__form .field__req { color: var(--vin-300, #C0A39B); }
.sq-join__form .field__input {
  min-height: 58px;
  padding: 16px 20px;
  border-radius: 14px;
  background: var(--white);
  border-color: transparent;
  font-size: 1rem;
  text-align: left;
}
.sq-join__form .field__input:focus {
  border-color: var(--vin-400, #A7807B);
  box-shadow: 0 0 0 3px rgba(233, 224, 210, .22);
}
.sq-join__form .field__select { min-height: 58px; }

/* L'indicateur d'étape est masqué : il annonce du travail à faire au moment
   précis où il coûte le plus cher. La référence n'en a pas. Le markup le
   conserve pour les lecteurs d'écran (squeeze-form.js le met à jour). */
.sq-join__form .sq-steps__progress {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.sq-join__form .hero__consent { color: var(--ivory); }
.sq-join__form .hero__consent a { color: var(--davos); }
/* ── LES CRÉNEAUX SUR FOND SOMBRE ──
   `.field__slots` est dessiné dans patterns.css pour une section crème : fond
   blanc, bordure grise, texte encre. Posé sur la vidéo, l'ensemble devient
   illisible. Même traitement que les trois choix ci-dessus, pour que les deux
   dernières étapes se ressemblent. */
.sq-join__form .field__slots label {
  background: rgba(233, 224, 210, .12);
  border-color: rgba(233, 224, 210, .34);
  color: var(--davos);
}
.sq-join__form .field__slots .wpcf7-list-item-label { color: var(--davos); }
.sq-join__form .field__slots input[type="checkbox"] {
  accent-color: var(--davos);
}
@media (hover: hover) {
  .sq-join__form .field__slots label:hover {
    background: rgba(233, 224, 210, .2);
    border-color: rgba(233, 224, 210, .55);
  }
}
.sq-join__form .field__slots label:has(input:checked) {
  background: var(--primary-700);
  border-color: var(--primary-700);
}

/* Le consentement s'aligne à gauche : sa case est posée en absolu à gauche,
   un texte centré à côté d'une case calée à gauche donne deux axes.

   `margin-top` : sur le tunnel des Premières, la réassurance (centrée) et le
   consentement (aligné à gauche) se suivent immédiatement — ils vivaient sur
   deux étapes distinctes avant la fusion et ne s'étaient jamais rencontrés.
   Collés, les deux axes se lisent comme un seul paragraphe cassé. */
.sq-join__form .hero__consent {
  text-align: left;
  max-width: 46ch;
  margin-inline: auto;
  margin-top: 14px;
}

/* ── LE BOUTON ──
   Plus étroit que la rangée de champs et centré, comme sur la référence : à
   pleine largeur il se range parmi les contrôles du formulaire, alors qu'il
   doit se lire comme un objet à part. Plein écran sur mobile en revanche — le
   pouce ne vise pas, il pose. */
.sq-join__form .sq-steps__next,
.sq-join__form .hero__submit {
  display: flex;
  width: auto;
  min-width: 300px;
  max-width: 100%;
  margin: clamp(20px, 3vh, 30px) auto 0;
  padding: 21px 40px;
  font-size: .82rem;
}

.sq-join__note {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-family: var(--font-body);
  font-size: .82rem;
  line-height: 1.5;
  color: var(--ivory);
  text-align: left;
  margin: clamp(16px, 2.4vh, 22px) 0 0;
}
.sq-join__star { color: var(--vin-300, #C0A39B); flex: none; }

/* ── BUDGET VERTICAL MOBILE ──
   Le bouton doit rester visible sans défiler : c'est toute la raison d'avoir
   mis le formulaire dans le hero, et mobile est la cible de conception
   (PRODUCT.md). Ne pas desserrer sans re-mesurer. */
@media (max-width: 759px) {
  .sq-hero--maxi  { padding: 16px 0 26px; }
  .sq-maxi__title { font-size: .95rem; letter-spacing: .14em; text-indent: .14em; }
  .sq-join        { margin-top: 24px; }
  .sq-join__form .field__input { min-height: 54px; padding: 14px 18px; }
  .sq-join__form .sq-steps__next,
  .sq-join__form .hero__submit { width: 100%; min-width: 0; padding: 19px 24px; }
  .sq-join__note  { font-size: .76rem; }
  .sq-maxi__meta  { margin-top: 18px; font-size: .74rem; }

  /* Étape 4 : six pastilles de créneaux + consentement + envoi. Aux valeurs de
     bureau le hero y montait à 861 px pour 761 d'écran, et le bouton d'envoi —
     le bouton de conversion — passait sous la ligne de flottaison. Chaque
     valeur ci-dessous est un morceau de ces 100 px repris. */
  .sq-steps__q     { font-size: 1.3rem; margin-bottom: 16px; }
  /* Après la règle ci-dessus, et pas avant : même spécificité, c'est l'ordre
     source qui tranche. Placée plus haut, elle serait annulée.

     DEUX LIGNES ICI, ET C'EST VOULU. La ligne unique du desktop tiendrait à
     390 px au prix d'un corps de ~1,35 rem — à peine plus que le sur-titre en
     capitales juste au-dessus, donc plus de gros titre du tout. Mobile étant la
     cible de conception (PRODUCT.md), on garde le corps et on laisse la phrase
     se replier sur deux lignes. Ne pas « harmoniser » avec le desktop en
     ajoutant `white-space: nowrap` : ça écraserait l'écran d'accueil. */
  .sq-steps__q--hero { font-size: 2.15rem; margin-bottom: 18px; }
  .sq-steps__aside { font-size: .72rem; line-height: 1.45; margin-top: 9px; }
  .sq-join__form .field__slots { gap: .4rem; }
  .sq-join__form .field__slots label { padding: 8px 12px; font-size: .78rem; }
  .sq-join__form .hero__consent { font-size: .68rem; line-height: 1.45; }
  .sq-join__form .field--picks .wpcf7-list-item-label { font-size: .68rem; gap: 9px; padding: 8px 4px 10px; }
}

/* Centré tant qu'il n'y a qu'une colonne, aligné à gauche dès qu'il y en a
   deux : un texte centré à côté d'une carte donne deux axes concurrents. */
.sq-hero__copy {
  text-align: center;
  max-width: 62ch;
  margin-inline: auto;
}
@media (min-width: 1000px) {
  .sq-hero__copy { text-align: left; margin-inline: 0; }
}

.sq-hero__eyebrow {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: .72rem;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--gray-500);
  margin-bottom: 18px;
}
/* Marcellus n'a qu'une graisse : la hiérarchie se fait à la taille et à la
   couleur. Aucun font-weight ici, jamais. */
.sq-hero__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5.4vw, 3.4rem);
  line-height: 1.06;
  color: var(--primary-700);
  margin-bottom: 22px;
  text-wrap: balance;
}
.sq-hero__lead {
  font-family: var(--font-body);
  font-size: 1.05rem;
  line-height: 1.7;
  color: var(--gray-700);
  max-width: 60ch;
  margin: 0 auto;
}
/* Sur le média, tout le texte repasse en crème.
   Le sur-titre et la ligne d'ouverture ne sont PAS en `--amber` : à 11 px, ce
   rosé sourd plafonnait à 3,6:1 sur le voile — en dessous du seuil AA, et ces
   deux lignes sont trop petites pour bénéficier du seuil « grand texte ».
   Mesuré, pas supposé. La hiérarchie se fait donc à la taille et à
   l'interlettrage, pas à la couleur. */
.sq-hero--offer .sq-hero__eyebrow { color: var(--ivory); }
.sq-hero--offer .sq-hero__title   { color: var(--davos); }
.sq-hero--offer .sq-hero__lead    { color: var(--ivory); }
@media (min-width: 1000px) {
  .sq-hero--offer .sq-hero__lead { margin-inline: 0; }
}

/* ── LA CARTE ──
   Seule surface claire de la section : c'est ce qui la détache du média sans
   avoir besoin d'une bordure. L'ombre est teintée bordeaux (jamais grise). */
.sq-offer {
  background: var(--white);
  border-radius: var(--radius-card);
  /* PAS de `overflow: hidden` : les billets doivent pouvoir déborder de la
     carte pour se poser sur la vidéo. C'est le bandeau qui porte désormais ses
     propres coins arrondis (voir `.sq-offer__label`) — c'était la seule chose
     que le rognage servait à obtenir. */
  box-shadow: var(--shadow-lg);
  position: relative;
  max-width: 420px;
  width: 100%;
  margin-inline: auto;
}
@media (min-width: 1000px) {
  .sq-offer { margin-inline: 0; max-width: none; }
}
/* ── LES BILLETS D'OR ──
   Deux billets pour deux séances : c'est le seul ancrage qui ne soit pas
   décoratif, et c'est pourquoi ils se posent sur la carte plutôt qu'ailleurs.

   POSÉS SUR LA LIGNE « 9,50 € la séance », à cheval sur le bord droit de la
   carte : une moitié dans la zone vide de la carte (229 px de large, la seule
   respiration du bloc), l'autre au-dessus de la vidéo.

   Ancrés EN ABSOLU SUR CETTE LIGNE et non à une distance du haut de la carte :
   l'intitulé peut passer sur deux lignes ou la précision disparaître, les
   billets suivent. Un décalage en pixels aurait glissé au premier changement
   de texte.

   ── LE DÉBORD EST CONTRAINT PAR L'ÉCRAN, PAS PAR LE GOÛT ──
   La carte est collée au bord du conteneur : il reste 360 px à sa droite en
   1920, mais seulement 40 px en 1280 et en 1024. Un débord fixe serait donc
   tranché net par `overflow: hidden` du hero sur les écrans courants. Largeur
   et débord suivent l'espace réellement disponible : le vrai 50/50 tient à
   partir de 1600 px, en dessous le billet mord moins sur la vidéo mais reste
   toujours entier. Mesuré à chaque palier, pas estimé. */
.sq-offer__tickets {
  --tk-w: 320px;    /* largeur du visuel */
  --tk-out: 160px;  /* ce qui déborde à droite de la carte */

  position: absolute;
  top: 50%;
  right: calc(-1 * var(--tk-out));
  width: var(--tk-w);
  height: auto;
  /* Remontés de 26 %, et pas simplement centrés sur la ligne.
     Un visuel incliné occupe une boîte bien plus haute que lui : 320 × 214
     tourné à 9° couvre 245 px de haut. Centré pile, son coin bas plongeait
     donc sur « Rien n'est débité aujourd'hui », première ligne longue de la
     carte. Au-dessus de cette ligne il n'y a que du texte court calé à gauche :
     la zone y est réellement libre. */
  transform: translateY(-76%) rotate(-9deg);
  z-index: 2;
  pointer-events: none;
  /* Ombre teintée bordeaux, jamais grise : sur du crème un gris fait une tache
     sale (cf. DESIGN.md). */
  filter: drop-shadow(0 14px 26px rgba(94, 32, 40, .38));
}

/* 1600 px et plus : espace suffisant pour le vrai moitié-dedans/moitié-dehors. */
@media (max-width: 1599px) {
  .sq-offer__tickets { --tk-w: 300px; --tk-out: 150px; }
}
@media (max-width: 1379px) {
  .sq-offer__tickets { --tk-w: 270px; --tk-out: 135px; }
}
@media (max-width: 999px) {
  .sq-offer__tickets { --tk-w: 215px; --tk-out: 16px; }   /* 24 px dispo en mobile */
}

/* Sous 400 px la carte occupe presque tout l'écran : le billet passerait sur le
   prix. Il rétrécit pour rester dans la zone vide. */
@media (max-width: 400px) {
  .sq-offer__tickets { --tk-w: 178px; --tk-out: 12px; }
}

/* Mouvement réduit : la rotation est décorative, on la calme sans la retirer. */
@media (prefers-reduced-motion: reduce) {
  .sq-offer__tickets { transform: translateY(-76%) rotate(-4deg); }
}

/* La ligne devient le repère de positionnement des billets. */
.sq-offer--tickets .sq-offer__highlight {
  position: relative;
}

.sq-offer__label {
  background: var(--primary-900);
  color: var(--davos);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: .68rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  text-align: center;
  padding: 11px 16px;
  margin: 0;
  /* Le bandeau arrondit lui-même ses deux coins hauts.
     La carte a un `border-radius`, mais elle n'a plus `overflow: hidden` (les
     billets doivent pouvoir en déborder) : rien ne rogne donc plus le bandeau,
     qui repassait carré par-dessus les coins arrondis de la carte. Les deux
     valeurs doivent rester identiques, sinon un liseré clair apparaît dans
     l'angle. */
  border-radius: var(--radius-card) var(--radius-card) 0 0;
}

.sq-offer__body {
  padding: 26px 24px 24px;
}

.sq-offer__title {
  font-family: var(--font-display);
  font-size: 1.75rem;
  line-height: 1.1;
  color: var(--ink);
  margin: 0;
}
.sq-offer__meta {
  font-family: var(--font-body);
  font-size: .82rem;
  color: var(--gray-500);
  margin: 4px 0 0;
}
.sq-offer__highlight {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--primary-700);
  margin: 14px 0 0;
}

/* Le prix. Marcellus, sans font-weight — la présence vient de la taille. */
.sq-offer__price {
  margin: 10px 0 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
}
.sq-offer__price-now {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 6vw, 3.1rem);
  line-height: 1;
  color: var(--ink);
}
/* Pas de `line-through` : la mention se lit « au lieu de 58 € », le mot « au
   lieu de » porte déjà la comparaison. Barrer par-dessus la redoublait, et le
   barré sur un petit corps gêne la lecture du montant. */
.sq-offer__price-was {
  font-family: var(--font-body);
  font-size: .82rem;
  color: var(--gray-500);
}
.sq-offer__note {
  font-family: var(--font-body);
  font-size: .82rem;
  color: var(--gray-500);
  margin: 6px 0 0;
}

.sq-offer__cta {
  display: flex;
  width: 100%;
  margin-top: 20px;
  text-align: center;
}

/* ── OUVERTURE AU CLIC (squeeze-offer.js) ──
   Sans JS, la note reste dans son état normal ci-dessus et le CTA va droit à
   l'ancre `#formulaire` : rien ci-dessous ne s'applique. C'est le script qui
   ajoute `.js-collapsible` au chargement (donc qui replie la note) puis
   `.sq-offer--open` au clic, juste avant de déclencher lui-même le défilement
   vers le formulaire — la carte doit avoir fini de grossir sous les yeux
   avant que la page ne parte. */
.sq-offer.js-collapsible .sq-offer__note {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
  overflow: hidden;
  transition: max-height .45s ease, opacity .3s ease, margin-top .45s ease;
}
.sq-offer.js-collapsible.sq-offer--open .sq-offer__note {
  max-height: 60px;
  opacity: 1;
  margin-top: 6px;
  transition: max-height .45s ease, opacity .35s ease .12s, margin-top .45s ease;
}

/* Le rebond reste sur la carte, jamais sur les billets : eux sont ancrés en
   absolu sur la ligne du prix (cf. plus haut) et suivraient un `scale` porté
   par un autre élément avec un décalage visible. */
@keyframes sq-offer-grow {
  0%   { transform: scale(1); }
  55%  { transform: scale(1.025); }
  100% { transform: scale(1); }
}
.sq-offer--open { animation: sq-offer-grow .5s ease; }

@media (prefers-reduced-motion: reduce) {
  .sq-offer.js-collapsible .sq-offer__note,
  .sq-offer.js-collapsible.sq-offer--open .sq-offer__note {
    transition: none;
  }
  .sq-offer--open { animation: none; }
}

.sq-offer__includes {
  list-style: none;
  margin: 20px 0 0;
  padding: 18px 0 0;
  border-top: 1px solid var(--gray-200);
  display: grid;
  gap: 11px;
}
.sq-offer__includes li {
  display: grid;
  grid-template-columns: 15px 1fr;
  gap: 10px;
  align-items: start;
  font-family: var(--font-body);
  font-size: .875rem;
  line-height: 1.5;
  color: var(--gray-700);
}
.sq-offer__check {
  color: var(--primary-700);
  margin-top: 3px;
  flex: none;
}

/* Avertissement d'édition — visible des seules personnes qui peuvent le
   corriger, jamais du public. */
.sq-hero__notice {
  max-width: 60ch;
  margin: 0 auto;
  padding: 14px 18px;
  border: 1px dashed var(--gray-300);
  border-radius: 10px;
  font-family: var(--font-body);
  font-size: .85rem;
  line-height: 1.55;
  color: var(--ivory);
  text-align: left;
}

/* ══════════════════════════════════════════
   BLOC OFFRE — reprise de `.signs`
   Le fond crème du pattern est conservé ; seul l'espacement est resserré,
   l'accroche ayant déjà posé le contexte juste au-dessus.
══════════════════════════════════════════ */
.signs {
  padding: 56px 0 88px;
}
.signs__title {
  text-transform: none;
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  line-height: 1.14;
}

/* ══════════════════════════════════════════
   FORMULAIRE À ÉTAPES

   Rien ici ne masque quoi que ce soit : c'est squeeze-form.js qui pose
   `hidden` sur les étapes suivantes, et lui seul. Sans JavaScript, `.sq-steps--active`
   n'est jamais ajoutée, les deux étapes restent affichées et le formulaire se
   comporte comme sa version en une seule page.
══════════════════════════════════════════ */
.sq-steps__progress {
  font-family: var(--font-heading);
  font-size: .74rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gray-500);
  margin: 0 0 18px;
}
.sq-steps__progress strong {
  color: var(--primary-700);
  font-weight: 600;
}

.sq-steps__next {
  width: 100%;
  margin-top: 4px;
}

/* `.pill-btn` pose `display: inline-flex`, qui l'emporte sur la règle
   `[hidden] { display: none }` du navigateur (même spécificité, déclarée plus
   tard). Sans cette règle, le bouton « Continuer » reste affiché quand le
   JavaScript ne s'exécute pas : un bouton mort au milieu du formulaire.
   La même remarque vaut pour les étapes que le script replie. */
.sq-steps [hidden] {
  display: none !important;
}

/* Le remplacement d'une étape par l'autre est un changement de contenu, pas un
   déplacement : une transition d'opacité courte suffit à le signaler sans
   faire attendre. */
@media (prefers-reduced-motion: no-preference) {
  .sq-steps--active .sq-steps__step {
    animation: sq-step-in .22s ease-out both;
  }
}
@keyframes sq-step-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* Prénom et email sur une seule ligne, mais PAS à parts égales — contrairement
   à `.hero__form-row`, qui coupe en deux moitiés strictes.

   Les deux champs n'ont pas le même appétit : « Camille » tient en huit signes,
   « camille.roux@example.com » en vingt-cinq. Le rapport 2/3 donne à l'adresse
   la moitié de largeur en plus qu'elle demande, sans que le prénom paraisse
   étranglé. `minmax(0, …)` est indispensable : sans lui, la largeur minimale
   d'un champ de formulaire empêche la colonne de se réduire et la ligne déborde.

   À retenir si les libellés changent : le placeholder « PRÉNOM » est en
   capitales espacées, c'est lui qui fixe le plancher de la colonne de gauche. */
.hero__form-stack {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: 12px;
}

/* Le temps que ça prend, juste avant le bouton. Remplace la phrase de
   réassurance des fondatrices, qui doublait la mention de consentement.

   En blanc — c'est-à-dire `--davos`, le blanc du système : jamais `#fff`, que
   la charte exclut. Chronomètre en SVG inline et jamais en emoji (DESIGN.md) :
   un emoji arriverait dans les couleurs du système d'exploitation, hors
   palette, et rendu différemment sur chaque appareil. Dimensionné en `em` pour
   suivre le texte, et décoratif — la mention se suffit à la lecture vocale. */
.sq-steps__timing {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-body);
  font-size: .85rem;
  line-height: 1.4;
  color: var(--davos);
  margin: 16px 0 0;
}

.sq-steps__watch {
  width: 1.05em;
  height: 1.05em;
  flex: none;
}

/* ══════════════════════════════════════════
   TYPOGRAPHIE DES DEUX TITRES — « Les Premières » uniquement
   ══════════════════════════════════════════
   Le sur-titre (« PILATES MAT & REFORMER / SARTROUVILLE ») et le gros titre
   (« Rejoins l'aventure Chez Paulette ») passent de Marcellus à Manrope en
   gras. Les corps ne bougent pas : seule la fonte change.

   PORTÉE LIMITÉE AU GABARIT. `.sq-maxi__title` et `.sq-steps__q--hero` servent
   aussi `offre-d-ouverture`, qui doit rester inchangée. D'où le préfixe sur la
   classe de `body` plutôt qu'une redéfinition globale.

   Manrope EST variable (200-800) : lui appliquer un gras est légitime, alors
   que Marcellus n'a qu'une graisse et que la charte interdit de lui en
   synthétiser une. Le changement lève donc cette contrainte plutôt que de la
   contourner.

   (Spectral a été essayée puis écartée : elle imposait une quatrième famille
   au site, et DESIGN.md l'avait déjà écartée au lot 2.) */
body.page-template-page-squeeze-premieres .sq-maxi__title,
body.page-template-page-squeeze-premieres .sq-steps__q--hero {
  font-family: var(--font-body);
  font-weight: 700;
}

/* L'interlettrage du sur-titre valait pour les capitales de Marcellus, qui se
   touchent sans lui. Les capitales de Manrope sont déjà espacées : on le
   ramène de .18em à .1em, sinon la ligne se disloque. Le `text-indent` qui
   rattrapait le blanc final suit la même réduction. */
body.page-template-page-squeeze-premieres .sq-maxi__title {
  letter-spacing: .1em;
  text-indent: .1em;
}

/* ══════════════════════════════════════════
   ÉTAT D'ENVOI — « Les Premières »
   ══════════════════════════════════════════
   La feuille de style de Contact Form 7 n'est PAS chargée sur ce thème : son
   `.wpcf7-spinner` arrive donc sans dimensions (mesuré à 0 × 0 px) et ne
   signale rien. Entre le clic et la réponse il peut s'écouler une à trois
   secondes avec un vrai SMTP — sans retour, on appuie deux fois.

   Une ligne de texte plutôt qu'un spinner remis d'aplomb : elle dit ce qui se
   passe, elle est lue par les lecteurs d'écran (`aria-live`), et elle ne
   dépend d'aucune animation — donc elle fonctionne à l'identique sous
   `prefers-reduced-motion`, que la charte impose de respecter. */
.sq-join__form .wpcf7-spinner {
  display: none;
}

.sq-join__form .hero__sending {
  display: none;
  font-family: var(--font-body);
  font-size: .8rem;
  color: var(--davos);
  text-align: center;
  margin: 12px 0 0;
}

.sq-join__form .wpcf7-form[data-status="submitting"] .hero__sending {
  display: block;
}

/* Le bouton se retire pendant l'envoi : c'est ce qui empêche le double envoi,
   et c'est visible, contrairement au `disabled` posé par CF7. */
.sq-join__form .wpcf7-form[data-status="submitting"] .hero__submit {
  opacity: .55;
  pointer-events: none;
}

/* La mention de consentement remplace la case à cocher : elle informe sans
   bloquer. Sous le bouton, parce qu'elle qualifie le geste qu'on vient de
   faire — au-dessus, elle repousserait l'action d'un cran. */
.sq-join__form .hero__consent-note {
  font-family: var(--font-body);
  font-size: .7rem;
  line-height: 1.5;
  color: var(--vin-300, #C0A39B);
  text-align: center;
  max-width: 44ch;
  margin: 14px auto 0;
}

.sq-join__form .hero__consent-note a {
  color: var(--davos);
  text-decoration: underline;
  text-underline-offset: .18em;
}

/* ══════════════════════════════════════════
   LE PANNEAU DE FIN — « Les Premières »
   ══════════════════════════════════════════
   La vue qui remplace le formulaire une fois l'inscription partie. Ce n'est
   PAS une étape : pas de bouton, rien à valider, aucune sortie sinon
   Instagram. Elle reprend le titre héro et le cœur des étapes plutôt que
   d'inventer un habillage à elle — c'est la même conversation qui se termine.

   Aucune surface autour du TITRE : comme le reste du hero, il se pose
   directement sur la vidéo du studio, en crème. Ce qui vient dessous reste à
   dessiner. */
.sq-done {
  text-align: center;
  max-width: 34ch;
  margin: 0 auto;
}

/* La mesure s'élargit avec l'écran. Sans cette règle, le bloc restait figé à la
   largeur du mobile pendant que le corps du texte grossissait : la mesure se
   RESSERRAIT quand l'écran grandissait, et le paragraphe passait de 3 à 4
   lignes sur grand écran. C'était l'inverse de ce qu'il faut.
   Plafonné en `min()` pour rester nettement en deçà de la largeur du titre,
   qui déborde librement au-delà de 760 px. */
@media (min-width: 760px) {
  .sq-done {
    max-width: min(34rem, 58vw);
  }
}

/* ── LA PLAQUE ──
   Le seul bloc de l'écran à porter une surface.

   BORDEAUX ET NON CRÈME. Le titre juste au-dessus est en crème sur la vidéo :
   un bloc crème dessous lui prendrait la lumière et l'écran se lirait comme
   deux blancs qui se disputent. Le bordeaux fait l'inverse — il assoit le
   texte, laisse le titre dominer, et met enfin la couleur de marque sur un
   écran qui n'en portait pas.

   AUCUNE SURFACE, VOLONTAIREMENT. Plusieurs conteneurs ont été essayés ici
   (plaque bordeaux, arc segmentaire, carte crème) : aucun ne tenait face au
   titre, qui flotte nu sur la vidéo juste au-dessus. Deux objets encadrés à la
   suite, sur un fond photographique, se disputent le regard.
   Ce qui règle la lisibilité et l'élégance à cet endroit, c'est la MESURE et le
   corps, pas un cadre.

   ÉCHELLE ALIGNÉE SUR `.sq-steps__intro`, la phrase d'invitation de l'étape 1.
   Les deux occupent la même place dans le parcours — la ligne qui suit le gros
   titre — et rien ne justifiait deux échelles pour un même rôle. Si l'une des
   deux bouge, bouger l'autre. */
/* La lettre cachetée, entre le titre et la phrase : elle illustre « tu
   recevras » et donne un temps entre les deux blocs de texte.

   Taille réduite de moitié à la demande du client. Le cachet de cire n'y est
   plus lisible comme un cachet — il se lit comme une pastille, et le glyphe ✦
   qui y est embossé se referme. C'est assumé : la lettre devient un signe et
   non une illustration. Décorative (`alt=""` côté markup), la phrase qui suit
   porte le sens. */
.sq-done__letter {
  display: block;
  width: clamp(48px, 13vw, 66px);
  height: auto;
  margin: 0 auto clamp(18px, 2.6vh, 26px);
}

.sq-done__body {
  font-family: var(--font-body);
  font-size: clamp(1rem, 1.9vw, 1.45rem);
  line-height: 1.5;
  color: var(--davos);
  /* Un blanc franc avant la sortie Instagram : ce qui suit n'est pas la suite
     de la phrase, c'est un autre moment — l'information d'un côté, l'action de
     l'autre. Un espacement de paragraphe ordinaire les aurait laissés se lire
     d'un seul bloc. */
  margin: 0 0 clamp(32px, 4.5vh, 48px);
  /* `pretty` et non `balance` : le texte porte maintenant ses propres retours
     à la ligne (`<br>`). `balance` répartirait en plus chaque segment sur des
     lignes de longueur égale et se battrait avec les coupures voulues ;
     `pretty` se contente d'éviter les mots orphelins en fin de paragraphe. */
  text-wrap: pretty;
}

.sq-done__more {
  font-family: var(--font-body);
  font-size: clamp(.85rem, 1.4vw, .95rem);
  line-height: 1.55;
  color: var(--vin-300, #C0A39B);
  margin: 0;
}

/* Souligné plutôt qu'en pilule : le bouton primaire de cette page est celui
   qui inscrit. Lui donner le même poids ici mettrait Instagram au niveau de
   l'inscription, alors qu'il n'arrive qu'après elle. */
.sq-done__link {
  color: var(--davos);
  text-decoration: underline;
  text-underline-offset: .22em;
  text-decoration-thickness: 1px;
  /* Cible tactile de 44 px sans casser le fil du texte (PRODUCT.md). */
  display: inline-block;
  padding: 10px 0;
}

.sq-done__link:hover,
.sq-done__link:focus-visible {
  color: var(--sable-100, #E9E0D2);
  text-decoration-thickness: 2px;
}

/* Ce qui accompagnait le formulaire n'a plus lieu d'être une fois qu'il a
   disparu. Masqué seulement quand le panneau a pris la main : en cas d'échec
   d'envoi, le message d'erreur de CF7 doit rester visible.

   `.wpcf7-response-output` : le message de succès natif de CF7, qui répéterait
   sous le panneau ce que celui-ci vient de dire.
   `.sq-join__note` : « Moins de 30 secondes, et rien à régler aujourd'hui » —
   une promesse sur l'effort d'un formulaire déjà envoyé.

   La date d'ouverture (`.sq-maxi__meta`), elle, RESTE : c'est précisément ce
   qu'on vient de dire qu'on annoncerait. */
.sq-is-done .wpcf7-response-output,
.sq-is-done .sq-join__note {
  display: none;
}

/* Même traitement que le passage d'une étape à l'autre : c'est la suite de la
   même conversation, pas une page qui s'ouvre. */
@media (prefers-reduced-motion: no-preference) {
  .sq-done:not([hidden]) {
    animation: sq-step-in .32s var(--ease-out-expo, cubic-bezier(.16, 1, .3, 1)) both;
  }
}

/* ══════════════════════════════════════════
   PIED DE PAGE LÉGAL
══════════════════════════════════════════ */
.sq-footer {
  background: var(--surface-dark);
  color: var(--ivory);
  border-top: 1px solid rgba(233, 224, 210, .14);
  padding: 24px 0;
}
.sq-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
}
.sq-footer__copy {
  font-family: var(--font-body);
  font-size: .82rem;
  color: var(--ivory);
  margin: 0;
}
.sq-footer__legal {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin: 0;
  padding: 0;
}
.sq-footer__legal a {
  font-family: var(--font-body);
  font-size: .82rem;
  color: var(--ivory);
  text-decoration: none;
  opacity: .82;
}
.sq-footer__legal a:hover,
.sq-footer__legal a:focus-visible {
  opacity: 1;
  text-decoration: underline;
}

/* ══════════════════════════════════════════
   MOBILE
══════════════════════════════════════════ */
@media (max-width: 767px) {
  .sq-header__logo { height: 44px; }

  .sq-hero { padding: 48px 0 40px; }
  .sq-hero--offer { padding: 40px 0 44px; }
  .sq-offer__body { padding: 22px 18px 20px; }

  .signs { padding: 40px 0 56px; }
  /* `.signs` centre son titre et son CTA sous 768px ; le corps suit, sinon
     la colonne se lisait décentrée. */
  .signs__copy ul { text-align: left; }

  .sq-footer__inner { justify-content: center; text-align: center; }
}

/* ══════════════════════════════════════════
   LA SUITE AU STUDIO — après l'inscription
   (pattern `merci-offres`, révélé par squeeze-form.js)
══════════════════════════════════════════ */

/* ── DEUX PORTES, ET RIEN D'AUTRE ──
   Cet écran n'est pas une fiche produit : c'est un aiguillage. Ni prix, ni
   liste d'atouts, ni date — tout cela vit sur les pages d'offre, à un clic.
   Ce qui compte ici tient en cinq objets par carte : une pastille qui situe,
   un nom, un visuel, une promesse, un bouton.

   Tout est CENTRÉ, et c'est ce qui distingue cet écran du reste du site : une
   colonne de texte alignée à gauche demande à être lue, deux blocs centrés
   demandent à être choisis. */
.sq-after {
  background: var(--cream);
  padding: clamp(44px, 7vh, 80px) 0 clamp(48px, 8vh, 88px);
  /* L'en-tête de squeeze page est `position: sticky` : sans cette marge, tout
     défilement qui amène la section en haut de l'écran glisse le titre
     dessous, où il devient illisible. Mesuré au navigateur. */
  scroll-margin-top: calc(var(--sq-header-h) + 12px);
}

@media (prefers-reduced-motion: no-preference) {
  .sq-after:not([hidden]) {
    animation: sq-step-in .4s var(--ease-out-expo, cubic-bezier(.16, 1, .3, 1)) both;
    animation-delay: .1s;
  }
}

/* ── LE MUR, ET NON UN APLAT ────────────────────────────────────────────────
   Le crème est une référence de peinture (RAL 9001) : un mur mat, pas un fond
   d'écran. Mesuré avant ce bloc, `.sq-after` rendait UNE seule couleur
   distincte et 0,00 ‰ d'écart-type local — mathématiquement plat, ce qu'aucune
   surface peinte n'est.

   Les deux couches sont définies dans `global.css`, avec le pourquoi de
   chacune. Ici, la seule chose qui compte :

   ⚠ `background-size` EST OBLIGATOIRE. Sans taille explicite, le motif se
   rééchantillonne sur un écran retina, se lisse, et le grain disparaît là où
   il sert le plus. C'est la cause du 0,57 ‰ d'une tentative précédente.

   ── POURQUOI SUR LA SECTION ET PAS SUR LES CARTES ──
   Les cartes restent lisses, et c'est le sujet du bloc autant que la matière :
   un mur texturé DERRIÈRE des cartes lisses, c'est une profondeur qu'aucune
   ombre ne donne. Grainer les deux les recollerait dans le même plan.

   ── LE PLAN ──
   `isolation: isolate` ferme le contexte d'empilement pour que le `z-index: 0`
   du calque ne puisse pas remonter au-dessus de l'en-tête collant. Le contenu
   est remonté à 1 : sans ça, le calque passerait DEVANT les cartes.

   Borné à `--autonome` (la page /merci/) le temps de l'essai — si la matière
   est validée, elle se généralise en retirant ce suffixe. */
.sq-after--autonome,
.page-template-page-merci .sq-footer {
  position: relative;
  isolation: isolate;
}

.sq-after--autonome::before,
.page-template-page-merci .sq-header::after,
.page-template-page-merci .sq-footer::before {
  content: "";
  position: absolute;
  inset: 0;
  /* 1 et non 0 : quand la section porte une image de fond, celle-ci occupe le
     niveau 0 et le grain doit passer PAR-DESSUS — c'est lui qui recolle le
     voile à la matière du reste de la page, et qui masque le banding que la
     compression WebP laisse dans les dégradés doux de la photo. */
  z-index: 1;
  pointer-events: none;
  background-image: var(--grain-dent), var(--grain-lent);
  background-size: 180px 180px, 1200px 1200px;
}

/* ── LE MUR NE S'ARRÊTE PAS À L'EN-TÊTE ──
   Sans ce bloc, l'en-tête restait à plat : 4,3 niveaux de luminance plus clair
   que la section juste en dessous, mesurés — une marche nette au ras de la
   bordure, qui donnait au bandeau l'air d'être d'une autre couleur.

   Le décalage vertical est ce qui recolle les deux : chaque élément cale son
   motif sur SA propre boîte, donc la section recommençait la tuile à zéro là
   où l'en-tête l'avait laissée à 83 px. On lui fait donc reprendre le motif
   exactement où l'en-tête le quitte, et le champ devient continu.

   ⚠ L'en-tête est `sticky` : dès qu'on défile, son grain glisse contre celui
   de la section. C'est voulu et invisible — à 5 ‰ d'écart, la jonction ne se
   lit pas, et l'en-tête étant opaque, il n'y a plus de bordure à raccorder
   une fois qu'il chevauche la section. */
.sq-after--autonome::before {
  background-position: 0 calc(-1 * var(--sq-header-h)), 0 calc(-1 * var(--sq-header-h));
}

/* ── ET LE MUR VA JUSQU'AU BORD DE L'ÉCRAN ──
   Sur un écran plus haut que la page, le crème du `body` apparaît sous le pied
   de page. Mesuré sur une vue de 1300 px : 288 px d'aplat à UNE seule couleur,
   0,00 ‰, juste à côté de la section grainée — soit exactement la couture que
   tout ce bloc cherche à éviter.

   Le motif se cale ici sur la boîte du `body`, dont l'origine est celle du
   document, donc celle de l'en-tête : le champ reste le même des deux côtés
   sans avoir à décaler quoi que ce soit. */
body.page-template-page-merci {
  background-color: var(--cream);
  background-image: var(--grain-dent), var(--grain-lent);
  background-size: 180px 180px, 1200px 1200px;
}

/* ── ET SUR LE BORDEAUX, L'ENCRE S'INVERSE ──
   Mêmes fréquences, mêmes tuiles, encre RAL 9001 : on éclaire au lieu de
   creuser. C'est la moitié de la direction que `mix-blend-mode: overlay` ne
   pouvait pas tenir, puisqu'il préserve les noirs. */
.page-template-page-merci .sq-footer::before {
  background-image: var(--grain-dent-clair), var(--grain-lent-clair);
}

.sq-after--autonome > .sq-after__inner,
.page-template-page-merci .sq-header__inner,
.page-template-page-merci .sq-footer__inner {
  position: relative;
  z-index: 2;
}

/* ── LA VIDÉO DU STUDIO EN FOND ─────────────────────────────────────────────
   Demandée par Corentin le 19 septembre 2026, à la place de la vue fixe des
   vestiaires : la MÊME vidéo que le hero de la squeeze page, sous un voile
   plus dense encore.

   ⚠ LA SECTION BASCULE EN SOMBRE, ET TOUT LE TEXTE AVEC. Ce n'est pas un
   choix esthétique qu'on pourrait défaire à moitié : le bordeaux du titre
   mesure 1,4:1 sur cette vidéo voilée, soit illisible, et AUCUNE densité de
   voile sombre ne le rattrape — plus le voile fonce, plus le bordeaux
   disparaît. Sur un fond sombre le texte est crème, ou il n'est pas.

   C'est exactement le contrat du hero de la squeeze page, à qui cette section
   emprunte le fichier, le mécanisme de chargement et le vocabulaire de voile.
   Rien n'est dupliqué. */
.sq-after--fond .sq-after__decor {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Même cadrage que les autres fonds du thème : centré et recadré, jamais
   déformé. */
.sq-after--fond .sq-after__decor-media {
  position: absolute;
  top: 50%; left: 50%;
  width: 100%; height: 100%;
  object-fit: cover;
  transform: translate(-50%, -50%);
  display: block;
}

/* ── LE VOILE ──
   Quasi-noir chaud `rgba(26,4,6,…)`, repris du hero. AUCUNE teinte rouge : un
   voile bordeaux repeint la vidéo, écrase le bois et la lumière chaude du
   studio, et c'est précisément ce qu'il faut voir.

   Plus dense que celui du hero (.70/.64/.74) parce que Corentin l'a demandé
   plus sombre, et parce que le contexte l'exige : ici deux grandes cartes
   crème occupent le centre, et un fond trop clair les ferait flotter sans
   attache. Densifié en haut, où se posent le sur-titre et le titre.

   ⚠ SA DENSITÉ EST UN RÉGLAGE D'ACCESSIBILITÉ. Les corniches LED de la vidéo
   sont les zones les plus claires de la boucle, et c'est là que le texte crème
   se perd. Baisser ces valeurs sans remesurer casse la lisibilité en silence,
   sur certaines images de la boucle seulement. */
.sq-after--fond .sq-after__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom,
    rgba(26, 4, 6, .86) 0%,
    rgba(26, 4, 6, .80) 45%,
    rgba(26, 4, 6, .84) 100%);
}

/* ── LE TEXTE PASSE EN CRÈME ──
   Chaque couleur est reprise une par une plutôt qu'héritée d'un `color` posé
   sur la section : les deux cartes sont DANS la section et doivent garder leur
   texte bordeaux sur leur fond crème. Un héritage global les emporterait. */
.sq-after--fond .sq-after__salut,
.sq-after--fond .sq-after__title {
  color: var(--cream);
}

.sq-after--fond .sq-after__lead,
.sq-after--fond .sq-after__place {
  /* Légèrement retiré du crème pur : la hiérarchie se tient par la valeur, pas
     par la taille seule. Reste très au-dessus du seuil AA, mesuré. */
  color: color-mix(in oklab, var(--cream) 82%, transparent);
}

/* ── ET LE GRAIN CHANGE D'ENCRE ──
   Le mouchetis bordeaux posé la veille creuse le crème ; sur un fond quasi-noir
   il ne mord sur rien. C'est la polarité inverse qui s'applique, exactement
   comme au pied de page. */
.sq-after--fond::before {
  background-image: var(--grain-dent-clair), var(--grain-lent-clair);
}

.sq-after__inner { text-align: center; }

/* ── LES TITRES EN CAPITALES ──
   Manrope en 800, et pas Marcellus : celui-ci n'a qu'UNE graisse, lui demander
   du gras produirait un faux gras de synthèse qui écrase ses évasures
   (DESIGN.md). Manrope est déjà auto-hébergée en variable 200→800 — aucune
   police supplémentaire, aucun appel au CDN.

   L'interlettrage est NÉGATIF sur les grandes tailles : en capitales grasses,
   l'espacement par défaut fait flotter les mots. C'est ce resserrement qui
   donne le bloc compact du modèle. */
.sq-after__title {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(1.5rem, 3.5vw, 2.45rem);
  line-height: 1.05;
  letter-spacing: -.02em;
  text-transform: uppercase;
  color: var(--vin-700);
  margin: 0 auto;
  /* ── LA MESURE NE DOIT PAS CASSER LA QUESTION ──
     Une question posée en deux temps n'a plus la même vitesse de lecture :
     elle doit tenir d'un trait sur grand écran, et `balance` s'occupe des
     largeurs où elle doit céder.

     ⚠ CETTE VALEUR SUIT LA LONGUEUR DU TITRE, ELLE N'EST PAS ARBITRAIRE. Elle
     valait 30ch pour « Comment veux-tu nous rejoindre ? » (31 signes) ; le
     titre du 19 septembre en fait 38 et cassait donc en deux. Réécrire le
     titre plus long sans toucher ici le recasserait. */
  max-width: 40ch;
  text-wrap: balance;
}

/* ── LE SECONDAIRE EST BORDEAUX, PAS TAUPE ──
   Le modèle n'a pas un seul gris : tout, du titre à la dernière ligne, vit
   dans la famille bordeaux. C'est ce qui lui donne son unité — une seule
   couleur portant tout l'écran, contre un crème.

   Le taupe `--ink-2` reste juste et passe AA ; il fait simplement basculer la
   section en bicolore, et l'écran se met à ressembler à du texte courant
   posé sur une page. `vin-600` sur crème tient 7,4:1, très au-dessus du
   plancher. */
/* ── LE CHAPEAU COURT N'EXISTE QUE SUR TÉLÉPHONE ──
   Les deux paragraphes sont dans le HTML, un seul est affiché. `display: none`
   retire aussi du sommaire d'accessibilité : un lecteur d'écran n'entend
   jamais les deux phrases. C'est ce qui rend ce doublon acceptable.

   ⚠ `--large` N'EST POSÉ QUE S'IL EXISTE UNE VERSION COURTE (voir le pattern).
   Sans elle, la phrase longue ne porte pas ce modificateur, aucune règle ne la
   masque, et elle s'affiche sur les deux mises en page. */
.sq-after__lead--mobile { display: none; }

.sq-after__lead {
  font-family: var(--font-body);
  font-size: clamp(.92rem, 1.35vw, 1rem);
  line-height: 1.55;
  color: var(--vin-600);
  /* PAS DE PLAFOND DE MESURE, à la demande : bridée, la phrase se cassait en
     deux lignes courtes au milieu d'une section large, et deux lignes courtes
     centrées sous un grand titre se lisent comme un bégaiement. Elle prend
     toute la largeur du conteneur et se pose d'un trait. */
  max-width: none;
  margin: 12px auto 0;
  text-wrap: pretty;
}

.sq-after__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: clamp(14px, 1.8vw, 24px);
  margin-top: clamp(22px, 3.2vh, 34px);
  /* ── LA LARGEUR EST PLAFONNÉE, ET C'EST CE QUI TIENT L'ÉCHELLE ──
     Sur toute la largeur du conteneur, chaque carte atteignait 587 px et sa
     hauteur suivait : 708 px, contre 601 pour les cartes de l'étape 1 du
     tunnel. Un même parcours ne peut pas avoir deux échelles de carte.
     Bornée ici, chaque carte retombe autour de 538 px, la mesure relevée. */
  max-width: 1102px;
  margin-inline: auto;
}

/* Une seule offre : la carte se recentre au lieu de s'étirer sur toute la
   largeur, où elle se lirait comme une bannière. */
.sq-after__grid--une {
  grid-template-columns: minmax(0, 460px);
  justify-content: center;
}

/* ── LA CARTE ──
   Les deux sont identiques, et cette symétrie EST le message : deux chemins de
   même valeur, pas une offre principale et son repli. C'est ce qui a changé
   depuis la version drenchée, où le bordeaux hiérarchisait.

   Fond légèrement plus clair que la section : posée sur le crème, la carte se
   détache par la lumière plutôt que par un cadre. */
.sq-after__card {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
  /* Les flancs sont plus étroits que le haut et le bas : sur la maquette,
     l'image ne laisse que 3,4 % de la largeur de carte de chaque côté (22 px
     pour 662). À 28 px, la mienne flottait dans un cadre trop généreux et la
     carte se lisait comme une fiche, pas comme une affiche. */
  padding: clamp(18px, 2.2vw, 24px) clamp(13px, 1.6vw, 18px) clamp(20px, 2.4vw, 26px);
  text-align: center;
  /* ── MÊME FOND QUE LA SECTION, ET C'EST L'OMBRE QUI DÉTACHE ──
     Une carte d'un crème légèrement différent se lit comme une tache : on voit
     qu'il y a deux beiges avant de voir qu'il y a un objet. Le modèle sépare
     par l'ÉLÉVATION, pas par la teinte — la carte est le même papier, posé
     au-dessus. */
  background: var(--cream);
  /* ⚠ OMBRE TEINTÉE BORDEAUX, JAMAIS GRISE. Les jetons du thème le sont déjà
     (`rgba(94,32,40,…)`) : un `box-shadow` neutre sur du crème produit une
     tache sale et froide (DESIGN.md). Je ne les avais pas utilisés — la carte
     n'avait aucune élévation, et c'est ce qui la faisait paraître imprimée
     sur le fond plutôt que posée dessus. */
  box-shadow: var(--shadow-sm), var(--shadow-md),
              /* Une troisième passe, très large et très diluée : c'est elle
                 qui donne à la carte l'air de flotter plutôt que d'être
                 décollée. Toujours au bordeaux du thème, jamais au gris. */
              0 22px 48px rgba(94, 32, 40, .07);
  /* Le filet ne fait plus le travail de séparation : il ne sert qu'à tenir le
     bord de l'ombre. D'où le bordeaux très dilué, et non le gris neutre
     d'avant — « aucune couleur froide ». */
  border: 1px solid color-mix(in oklab, var(--vin-700) 9%, transparent);
  border-radius: var(--radius-card);
}

/* ── LA PASTILLE ──
   Elle situe l'offre en trois mots. Fond rosé très pâle plutôt qu'un simple
   filet : c'est le seul aplat de la carte, et il ancre le regard en haut. */
.sq-after__badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 clamp(10px, 1.4vh, 13px);
  padding: 6px 14px;
  border-radius: 999px;
  /* Pêche chaud plutôt que rosé grisé : relevé à #F3E0D2 sur le modèle.
     `--linen-amber` est le neutre tiède de la charte, il y mène directement. */
  /* ⚠ RELEVÉ #F3E0D2 SUR LE MODÈLE, ET LA PALETTE NE VA PAS JUSQUE-LÀ.
     Cette pêche tire davantage vers le jaune que n'importe quel neutre de la
     charte : la reproduire exactement demanderait d'inventer une couleur hors
     gamme, sur un nuancier qui est une référence de PEINTURE. On s'en approche
     par le haut de l'échelle tiède, et on s'arrête là. */
  background: color-mix(in oklab, var(--linen-amber) 38%, var(--cream));
  color: var(--vin-700);
  font-family: var(--font-body);
  font-size: .63rem;
  font-weight: 600;
  letter-spacing: .09em;
  line-height: 1.4;
  text-transform: uppercase;
}

/* ── L'ICÔNE DE LA PASTILLE ──
   Cadrée sur la hauteur de capitale du libellé et non sur sa taille de police :
   à `1em`, une glyphe pleine comme la couronne déborde visuellement au-dessus
   des capitales et la ligne perd son assise. */
.sq-after__badge-icon {
  /* Plus grande que la hauteur de capitale : ces deux dessins sont pleins et
     détaillés (la couronne a trois pointes, le lotus huit pétales). À la
     taille du texte, ils se réduisaient à une tache illisible. */
  width: 1.15em;
  height: 1.15em;
  flex: none;
}

/* ── LES DEUX PASTILLES NE SONT PAS DE LA MÊME COULEUR, ET C'EST LE SUJET ──
   Relevé sur la maquette du 19 septembre : l'ouverture est en rose, « à ton
   rythme » reste sur le sable tiède. Les deux cartes proposent la même chose —
   un pass — et rien dans leur mise en page ne dit laquelle est datée. C'est la
   couleur qui porte cette différence : le rose appelle, le sable rassure.

   Les mettre à la même couleur, c'est reprendre au visiteur l'information qui
   décide de son choix. */
.sq-after__card--ouverture .sq-after__badge {
  background: var(--rose-pastille);
}

/* ── LA PASTILLE DE RARETÉ ──
   Le seul rouge de l'écran. Il ne tient que parce qu'il est seul : servi une
   seconde fois, il devient une couleur de mise en page et ne signale plus rien.

   ⚠ ELLE N'EST PAS CALCULÉE. Le site n'a aucune donnée de capacité depuis le
   passage à Bookday — les champs `ouv_cN_places` ont été vidés par migration,
   exprès. C'est une phrase tapée à la main, et elle doit être vraie :
   l'avertissement complet est porté par le champ, dans `inc/merci.php`. */
.sq-after__urgence {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 12px auto 0;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--rose-pastille);
  color: var(--rouge-rarete);
  font-family: var(--font-body);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* La flamme garde sa couleur propre : en `currentColor` elle devient une tache
   rouge illisible à cette taille, alors que l'orange la dessine. */
.sq-after__flamme {
  width: .95em;
  height: .95em;
  flex: none;
  color: var(--flamme);
}

.sq-after__name {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(1.15rem, 2.2vw, 1.5rem);
  line-height: 1.1;
  letter-spacing: -.015em;
  text-transform: uppercase;
  color: var(--vin-700);
  /* Le nom est passé SOUS le visuel le 19 septembre : sa marge a suivi. Elle
     était en bas quand il coiffait la carte. */
  margin: clamp(11px, 1.6vh, 15px) 0 0;
  text-wrap: balance;
}

/* ── LE VISUEL ──
   `cover` et non `contain` : les deux images sont des SCÈNES au même format
   (1678×937), pas des détourages — celle du pass a été composée sur la lumière
   de celle des chaussettes pour qu'elles aient l'air du même shooting. `cover`
   les fait remplir le cadre bord à bord, ce que le modèle montre.

   Le fond reste posé : si quelqu'un met plus tard une image d'un autre format,
   elle se recadrera, et s'il met un détourage à fond transparent, il tombera
   sur une teinte de la gamme plutôt que sur du blanc. */
.sq-after__shot {
  width: 100%;
  /* ── 7:5, ET CE N'EST PAS UN CHOIX D'INSTINCT ──
     Mesuré sur la maquette : sa boîte d'image fait 617×447 px, soit 1,38.
     J'étais en 16:10 (1,60), donc nettement plus plat — et c'est ce qui donnait
     aux cartes une silhouette large là où le modèle les veut hautes. La scène
     du pass a été recomposée à ce format pour n'être pas recadrée. */
  aspect-ratio: 7 / 5;
  /* Un cran sous le rayon de la carte : deux rayons identiques imbriqués font
     lire deux cadres concentriques au lieu d'un objet dans une carte. */
  border-radius: 16px;
  overflow: hidden;
  background: color-mix(in oklab, var(--vin-200) 30%, var(--cream));
}

.sq-after__img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  object-fit: cover;
}

.sq-after__promise {
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(1rem, 1.85vw, 1.25rem);
  line-height: 1.14;
  letter-spacing: -.012em;
  text-transform: uppercase;
  color: var(--vin-700);
  /* La promesse est passée AU-DESSUS du visuel : marge en bas, pas en haut. */
  margin: 0 0 clamp(13px, 1.9vh, 18px);
  text-wrap: balance;
}

.sq-after__line {
  font-family: var(--font-body);
  padding-inline: clamp(4px, 1vw, 12px);
  font-size: .85rem;
  line-height: 1.55;
  color: var(--vin-600);
  margin: 8px 0 0;
  /* Assez large pour tenir sur une ligne à la taille du modèle : à 34ch elle
     se cassait en deux, et deux lignes courtes sous une promesse en capitales
     font retomber la carte. */
  max-width: 42ch;
  text-wrap: pretty;
}

/* ── LE BOUTON ──
   En pilule pleine, capitales espacées : c'est le seul objet cliquable de la
   carte et il doit se lire comme tel avant d'être lu comme un texte.

   `margin-top: auto` le colle au bas : les deux cartes alignent leurs boutons
   même quand une promesse tient sur deux lignes et l'autre sur une.

   Cible tactile de 54 px, au-delà des 44 px du plancher (PRODUCT.md). */
.sq-after__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  align-self: stretch;
  margin-top: auto;
  padding: 13px 22px;
  /* 48 px : la hauteur des boutons de l'étape 1 du tunnel, et toujours
     au-dessus du plancher tactile de 44 px (PRODUCT.md). */
  min-height: 48px;
  border-radius: 999px;
  background: var(--vin-700);
  color: var(--davos);
  font-family: var(--font-heading);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .095em;
  line-height: 1.3;
  text-transform: uppercase;
  text-decoration: none;
  transition: background .15s ease, transform .15s ease;
}

.sq-after__cta:hover,
.sq-after__cta:focus-visible {
  background: var(--vin-800);
  color: var(--davos);
}

@media (prefers-reduced-motion: no-preference) {
  .sq-after__cta:hover { transform: translateY(-2px); }
}

/* La flèche ne rétrécit pas quand le libellé s'allonge. */
.sq-after__arrow { flex: none; }

/* ── LES DEUX BOUTONS AU MÊME NIVEAU ────────────────────────────────────────
   La grille étire les deux cartes à la même hauteur, mais leur contenu n'a pas
   la même longueur : la pastille de rareté n'est que sur l'une, et les boutons
   se décalaient de 25 px. Deux cibles principales désalignées côte à côte, et
   la plus basse passe pour secondaire.

   ⚠ POURQUOI L'ÉCART EST PORTÉ PAR L'ÉLÉMENT DU DESSUS ET NON PAR LE BOUTON.
   La règle d'avant était `.sq-after__line + .sq-after__cta { margin-top: … }`,
   un sélecteur de frère adjacent — spécificité 0,2,0, qui écrasait sans bruit
   le `margin-top: auto` posé sur `.sq-after__cta` en 0,1,0. Résultat : seule la
   carte AVEC pastille descendait en pied, l'autre restait collée à sa phrase.
   C'est exactement le genre de panne qu'on ne voit pas en relisant le CSS.

   L'écart est donc porté par CE QUI PRÉCÈDE le bouton, et `:has()` dit
   exactement cela : « l'élément qui a un bouton juste après ». Une liste de
   classes ne conviendrait pas — selon la carte, le voisin du haut est la
   pastille de rareté, la phrase, ou le nom — et donnerait un double écart sur
   celles qui en portent plusieurs.

   `margin-top: auto` n'a alors plus de concurrent : il absorbe tout le mou et
   pose le bouton en bas de carte. Les marges ne fusionnent pas en flex, donc
   les deux s'additionnent proprement. */
.sq-after__card > *:has(+ .sq-after__cta) { margin-bottom: clamp(15px, 2.1vh, 21px); }

.sq-after__place {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-body);
  font-size: .82rem;
  line-height: 1.5;
  color: var(--ink-2);
  margin: clamp(22px, 3.2vh, 30px) 0 0;
}
.sq-after__place svg { flex: none; }

/* ══════════════════════════════════════════
   MOBILE — LA CARTE BASCULE À L'HORIZONTALE
══════════════════════════════════════════ */

/* ── POURQUOI CHANGER DE MISE EN PAGE PLUTÔT QUE DE TOUT RÉDUIRE ──
   Empilée, la carte faisait 497 px de haut : deux cartes, et il fallait
   défiler deux écrans pour voir les DEUX options d'un choix. Or c'est un
   aiguillage — comparer est l'action, et une option qu'on ne voit qu'après
   avoir défilé n'est pas comparée, elle est trouvée.

   Réduire les tailles ne réglait pas ça : le coût vient du nombre d'éléments
   empilés, pas de leur taille. La carte passe donc en deux colonnes — le
   visuel à gauche, les trois lignes de texte à droite — et retombe autour de
   340 px. La phrase et le bouton restent pleine largeur : la première est une
   ligne de lecture, le second une cible.

   Grille explicite et non `flex` : elle permet au visuel d'occuper trois
   rangées sans envelopper les textes dans un conteneur de plus, donc sans
   toucher au markup que le desktop partage. */
@media (max-width: 767px) {
  .sq-after { padding: 32px 0 40px; }
  /* ⚠ CE PLAFOND SUIT LA LONGUEUR DU TITRE, comme celui du desktop. À 16ch —
     la valeur calibrée pour « Comment veux-tu nous rejoindre ? » — le titre du
     19 septembre était enfermé dans 259 px quelle que soit la largeur de
     l'écran, et cassait sur le trait d'union : « COMMENT VEUX- / TU
     COMMENCER ». Une césure au milieu d'un mot composé se lit deux fois. */
  .sq-after__title { max-width: 22ch; }

  /* ── LA CARTE MOBILE EST UNE PILE, PLUS UNE GRILLE À DEUX COLONNES ──────
     Réorganisée le 19 septembre 2026 : le visuel prend toute la largeur de la
     carte, et le nom vient se poser DEDANS, en bas.

     ⚠ LA GRILLE RESTE, AVEC UNE SEULE COLONNE, ET CE N'EST PAS UN RESTE. Elle
     est ce qui superpose le nom et le visuel : les deux occupent LA MÊME
     CELLULE (rangée 3), le nom calé en bas. Sans elle il faudrait soit
     déplacer le `<h3>` dans le `<div>` du visuel — ce qui casserait la mise en
     page desktop, où le nom est un bloc sous l'image — soit le positionner en
     absolu contre la carte, donc à une distance devinée du bas de l'image.
     Ici, rien n'est deviné et le HTML ne bouge pas. */
  .sq-after__lead--mobile { display: block; }
  .sq-after__lead--large  { display: none; }

  .sq-after__card {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    /* ── LA CINQUIÈME RANGÉE ABSORBE LE MOU ──
       Entre 620 et 767 px, les deux cartes sont encore CÔTE À CÔTE alors que
       leur mise en page est déjà celle du mobile : la grille les étire à la
       même hauteur, mais l'une porte une pastille de rareté et l'autre non.
       Toutes les rangées en `auto`, le contenu ne remplit pas la carte et les
       deux boutons se décalent — la panne qu'on vient de corriger sur desktop.

       En donnant `1fr` à la rangée de la pastille, tout l'excédent tombe JUSTE
       AU-DESSUS du bouton, sur les deux cartes. `align-items: start` garde la
       pastille collée en haut de sa rangée, donc elle ne flotte pas. */
    grid-template-rows: auto auto auto auto 1fr auto;
    align-items: start;
    /* Centré comme sur desktop : la carte mobile n'est plus une fiche à deux
       colonnes mais une affiche empilée, et un fer à gauche y laissait la
       pastille, le bouton et le nom sur trois axes différents. */
    text-align: center;
    padding: 14px 14px 16px;
  }

  .sq-after__badge {
    grid-row: 1;
    justify-self: center;
    margin: 0 0 8px;
  }

  /* La promesse remonte sous la pastille : c'est elle qui annonce, le nom est
     descendu signer le visuel. */
  .sq-after__promise {
    grid-row: 2;
    margin: 0 0 10px;
    font-size: .95rem;
  }

  /* ── LE VISUEL VA D'UN BORD À L'AUTRE ──
     Sa largeur est celle du contenu de la carte, donc l'écart à droite est
     exactement celui de gauche : c'est le `padding` de la carte qui le donne,
     des deux côtés, sans valeur à tenir à jour. */
  /* ── 16:10 ET NON 7:5 ──
     Le visuel pèse la moitié de la hauteur de la carte : c'est lui, et rien
     d'autre, qui décide de sa taille. En passant de 1,40 à 1,60, il perd 31 px
     sans qu'aucun sujet ne sorte du cadre — les deux scènes sont composées en
     paysage, avec de l'air en haut. Le reste de la réduction vient des marges,
     rognées d'un ou deux pixels chacune. */
  .sq-after__shot {
    grid-row: 3;
    grid-column: 1;
    aspect-ratio: 16 / 10;
  }

  /* ── LE NOM, DANS L'IMAGE ──
     ⚠ LE DÉGRADÉ N'EST PAS UN EFFET, C'EST CE QUI REND LE NOM LISIBLE. Les
     deux photos ne se ressemblent pas du tout sous le texte : bois moyen sur
     l'une, sable très clair sur l'autre. Aucune encre ne passe sur les deux —
     posé en bordeaux sur le sable des Premiers Pas, le nom disparaît. Le
     dégradé crée le fond que la photo ne garantit pas, et le nom passe en
     crème.

     Le rayon ne reprend que les DEUX COINS DU BAS, ceux du visuel : le nom est
     un calque frère, donc l'`overflow: hidden` de l'image ne le rogne pas. */
  .sq-after__name {
    grid-row: 3;
    grid-column: 1;
    align-self: end;
    z-index: 1;
    margin: 0;
    padding: 38px 14px 13px;
    color: var(--cream);
    /* ⚠ LES DEUX PREMIERS ARRÊTS COUVRENT LA BANDE DE TEXTE, ET C'EST LE
       RÉGLAGE D'ACCESSIBILITÉ. Un premier dégradé plus doux (.88 → .66 à
       46 %) laissait le haut des capitales dans la zone claire : 4,67:1 sur la
       photo des Premiers Pas, pour un seuil de 4,5. Ça passait, et ça ne
       tenait pas — la photo vient d'un champ, et une image plus claire posée
       demain aurait fait tomber le nom sous le seuil sans que rien ne le
       signale. À .90 jusqu'à 45 %, même une photo blanche donnerait 13:1 : la
       lisibilité ne dépend plus de l'image. Les arrêts suivants ne servent
       qu'à éteindre le voile sans marche visible. */
    background: linear-gradient(to top,
      rgba(26, 4, 6, .93) 0%,
      rgba(26, 4, 6, .90) 45%,
      rgba(26, 4, 6, .72) 68%,
      rgba(26, 4, 6, .30) 86%,
      rgba(26, 4, 6, 0) 100%);
    border-radius: 0 0 16px 16px;
  }

  /* Pleine largeur : la phrase se lit d'un trait, et le bouton reprend toute
     la cible tactile disponible. */
  .sq-after__line {
    grid-row: 4;
    max-width: none;
    padding-inline: 0;
    margin: 12px 0 0;
  }

  .sq-after__urgence {
    grid-row: 5;
    justify-self: center;
    margin: 10px 0 0;
  }

  .sq-after__cta {
    grid-row: 6;
    margin-top: 12px;
  }

  /* En grille, l'écart est porté par la rangée : la marge de desktop posée sur
     le voisin du bouton n'a plus lieu d'être. */
  .sq-after__card > *:has(+ .sq-after__cta) { margin-bottom: 0; }
}

}

/* ══════════════════════════════════════════
   /merci/ — UNE SEULE SECTION, SUR CRÈME
══════════════════════════════════════════ */

/* ── IL N'Y A PLUS DE VIDÉO SUR CET ÉCRAN, ET C'EST CE QUI DÉBLOQUE LE ROUGE ──
   Une scène vidéo occupait le haut de la page. Son voile est un scrim bordeaux
   (`rgba(26,4,6,.86)`) : la question en bordeaux dessus donnait 1,03:1, deux
   valeurs identiques, donc une ligne absente. Aucune encre rouge de la charte
   ne s'en sortait — elles sont toutes sombres par construction.

   La vidéo retirée, le fond redevient crème et la question peut enfin prendre
   le bordeaux de marque : 10,83:1. Le problème n'était pas la couleur, c'était
   le fond sous elle. */

/* ── LA CONFIRMATION, EN SUR-TITRE ──
   Marcellus et le cœur, repris du panneau d'inscription : la personne doit
   reconnaître la phrase qu'elle vient de déclencher.

   AUCUN font-weight — Marcellus n'a qu'une graisse (DESIGN.md). Elle passe en
   `vin-600` quand la question est en `vin-700` : à encre égale, les deux
   lignes se disputeraient le premier regard, alors que l'une annonce et
   l'autre demande. */
.sq-after__salut {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.2vw, 1.85rem);
  line-height: 1.16;
  letter-spacing: -.005em;
  color: var(--vin-600);
  margin: 0 0 clamp(6px, 1vh, 11px);
  text-wrap: balance;
}

.sq-after__salut .sq-steps__heart {
  width: .72em;
  height: .72em;
  vertical-align: -.06em;
  margin-left: .12em;
}

/* ══ TENIR SANS DÉFILER ══════════════════════
   L'écran doit montrer les DEUX portes d'un coup : un choix dont une moitié
   est sous la ligne de flottaison n'en est pas un.

   ── LA HAUTEUR DE L'ILLUSTRATION EST EN vh, ET C'EST LA CLÉ ──
   Un plafond en pixels cale le budget pour UNE hauteur d'écran et déborde sur
   toutes les autres : un 1366×768 et un 1920×1080 n'ont pas le même mou. En
   `vh`, l'illustration rend d'elle-même la place qui manque et la carte suit.
   C'est le seul poste assez gros pour absorber l'écart — les textes et le
   bouton, eux, ont des planchers.

   Le `min()` tient les deux règles à la fois : jamais plus de 268 px sur un
   grand écran, jamais plus de 27 % de la hauteur disponible sur un petit.

   ⚠ CES RÈGLES SONT PORTÉES PAR `--autonome`, PAS PAR LA PAGE. La section vit
   aussi en repli sur la page d'inscription, où elle s'ouvre SOUS un hero et
   n'a donc aucune raison de se comprimer : là-bas, on a déjà défilé. */
@media (min-width: 768px) {
  .sq-after--autonome { padding: clamp(30px, 4.6vh, 54px) 0 clamp(26px, 4vh, 44px); }
  /* Relevé d'un cran à la demande : les deux visuels sont des SCÈNES
     photographiques et non des objets détourés, et une scène a besoin d'être
     lue. Le couple min()/vh garde la garantie de tenir sans défiler — vérifié
     à nouveau sur les cinq hauteurs d'écran après ce relèvement. */
  .sq-after--autonome .sq-after__shot { max-height: min(300px, 30vh); }

  /* Cartes resserrées : leur largeur commande la hauteur de l'illustration,
     donc celle de la carte entière. */
  .sq-after--autonome .sq-after__grid { max-width: 1004px; margin-top: clamp(18px, 2.4vh, 28px); }

  .sq-after--autonome .sq-after__card { padding: clamp(16px, 1.9vw, 21px) clamp(12px, 1.5vw, 17px) clamp(17px, 2vw, 22px); }
  .sq-after--autonome .sq-after__badge { margin-bottom: clamp(8px, 1.1vh, 11px); }
  /* Marges inversées avec les blocs le 19 septembre : la promesse coiffe la
     carte, le nom est passé sous le visuel. */
  .sq-after--autonome .sq-after__promise { margin-bottom: clamp(9px, 1.3vh, 12px); }
  .sq-after--autonome .sq-after__name { margin-top: clamp(11px, 1.5vh, 15px); }
  .sq-after--autonome .sq-after__cta { min-height: 46px; padding: 12px 20px; }
  /* ⚠ MÊME PIÈGE QUE PLUS HAUT, EN PIRE : ce sélecteur de frère valait 0,3,0
     et écrasait le `margin-top: auto` du bouton sur la SEULE carte sans
     pastille — 46 px de décalage entre les deux boutons, mesurés. L'écart se
     porte ici aussi par le voisin du dessus. */
  .sq-after--autonome .sq-after__card > *:has(+ .sq-after__cta) { margin-bottom: clamp(12px, 1.7vh, 17px); }
  .sq-after--autonome .sq-after__place { margin-top: clamp(16px, 2.2vh, 24px); }
}
