/*
 * P4.1 — Socle desktop.
 * Les valeurs relevées en points dans la maquette Photoshop sont reportées
 * numériquement en pixels CSS à la largeur de référence 1440 px. Employer des
 * points CSS les agrandirait artificiellement d'un tiers dans le navigateur.
 */

@font-face {
  font-family: "Source Sans 3 zeMoritz Web";
  src: url("assets/fonts/source-sans-3-regular.woff2?v=20260821b") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Source Sans 3 zeMoritz Web";
  src: url("assets/fonts/source-sans-3-medium.woff2?v=20260821c") format("woff2");
  font-style: normal;
  font-weight: 500;
  font-display: swap;
}

@font-face {
  font-family: "Source Sans 3 zeMoritz Web";
  src: url("assets/fonts/source-sans-3-semibold.woff2?v=20260822") format("woff2");
  font-style: normal;
  font-weight: 600;
  font-display: swap;
}

@font-face {
  font-family: "Source Sans 3 zeMoritz Web";
  src: url("assets/fonts/source-sans-3-bold.woff2?v=20260821b") format("woff2");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

@font-face {
  font-family: "Barlow Semi Condensed";
  src: url("assets/fonts/barlow-semi-condensed-semibold.woff2") format("woff2");
  font-style: normal;
  font-weight: 600;
  font-display: swap;
}

@font-face {
  font-family: "Barlow Semi Condensed";
  src: url("assets/fonts/barlow-semi-condensed-bold.woff2") format("woff2");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

:root {
  --color-white: #ffffff;
  --color-off-white: #f7f6f2;
  --color-deep-black: #151515;
  --color-orange: #ff7f00;
  --color-orange-mid: #d46000;
  --color-orange-dark: #b04a00;
  --color-anthracite: #3f4143;
  --color-light-gray: #e5e5e2;
  --color-blue-gray: #66717a;
  --color-disabled-1: #82898e;
  --color-disabled-2: #a3aaaf;

  --font-body: "Source Sans 3 zeMoritz Web", "Source Sans 3", "Source Sans Pro", Arial, sans-serif;
  --font-display: "Barlow Semi Condensed", "Arial Narrow", Arial, sans-serif;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  --layout-content-max: 75rem;
  --layout-gallery-max: 90rem;
  --gutter: clamp(1.5rem, 4vw, 3.75rem);
  --section-space: clamp(3.5rem, 7vh, 6.5rem);
  --section-space-small: clamp(2rem, 4vh, 4rem);

  /*
   * Respiration verticale — P4.0 § 3.3 : au-dessus de 900 px de hauteur les
   * contenus ne sont pas agrandis, seuls les blancs s'écartent ; en dessous
   * ils se resserrent jusqu'à un plancher, après quoi la section devient plus
   * haute que la fenêtre plutôt que de comprimer davantage.
   * Chaque valeur part de la cote relevée sur la maquette v4 à 900 px de haut
   * et s'en écarte proportionnellement à ce que la fenêtre gagne ou perd.
   * À 900 px, elles valent donc exactement 8, 41 et 57 px.
   */
  --souffle-court: clamp(6px, calc(8px + (100vh - 900px) * 0.05), 36px);
  --souffle-moyen: clamp(28px, calc(41px + (100vh - 900px) * 0.08), 120px);
  /*
   * Souffle long : pente dissymétrique. En dessous de 900 px la section est
   * déjà serrée, l'écart se resserre doucement (0,10) ; au-dessus il s'ouvre
   * un peu plus franchement (0,157) pour que le bouton ne colle pas au bloc de
   * texte sur les grands écrans, sans s'en détacher non plus. Les deux termes valent 57 px à 900, le `max`
   * sélectionne donc naturellement la bonne pente de part et d'autre.
   */
  --souffle-long: clamp(36px, max(calc(57px + (100vh - 900px) * 0.10),
                                  calc(57px + (100vh - 900px) * 0.157)), 240px);
  /* C05 : contour intérieur blanc, contour extérieur noir profond, dans cet ordre. */
  --focus-inner: 0 0 0 3px var(--color-white);
  --focus-outer: 3px solid var(--color-deep-black);
  --transition-fast: 180ms ease;

  /*
   * Vocabulaire d'animation — une seule remontée, une seule durée d'arrivée,
   * un seul décalage entre voisins, une seule courbe. Tout ce qui arrive sur
   * la page emprunte ces valeurs : c'est ce qui fait qu'un même geste se
   * répète, au lieu qu'une collection d'effets se juxtapose. Aucune ne
   * dépasse les 600 ms de P3 Partie 5 § 3.
   */
  --montee: 12px;
  /*
   * ─── Réglages de l'arrivée liée au défilement ───
   * script.js lit « --montee-defilement » et « --duree-arrivee-clic » au
   * chargement : ces valeurs ne sont déclarées qu'ici, il n'y a pas de chiffre
   * à tenir à jour des deux côtés.
   *
   * --montee-defilement : de combien le bloc arrive de plus bas, à la molette.
   *                       C'est LUI l'effet ; les autres l'accompagnent.
   * --montee-clic       : la même chose, mais quand on arrive par un lien.
   *                       Beaucoup plus ample, parce que le mouvement dispose
   *                       alors d'un temps fixe et non de la durée du geste :
   *                       à durée égale, c'est l'amplitude qui le rend lisible.
   * --duree-arrivee-clic: durée de ce mouvement, en millisecondes. Le
   *                       défilement, lui, dure 450 ms : au-dessous de cette
   *                       valeur les blocs se poseraient avant la page.
   * --opacite-depart    : opacité au départ. 1 la supprime complètement.
   * --flou-depart       : flou gaussien au départ, qui se dissipe avec le
   *                       mouvement et disparaît en même temps que lui. 0 le
   *                       supprime. Au-delà de 2 px le texte devient illisible
   *                       pour qui s'arrête de défiler en cours de course.
   */
  --montee-defilement: 120px;
  --montee-clic: 320px;
  --duree-arrivee-clic: 900ms;
  --opacite-depart: 1;
  --flou-depart: 0.8px;
  --duree-arrivee: 320ms;
  --decalage-arrivee: 70ms;
  --duree-panneau: 300ms;
  --courbe-arrivee: cubic-bezier(0.2, 0, 0, 1);
}

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

html {
  color-scheme: light;
  scroll-behavior: auto;
}

body {
  min-width: 20rem;
  margin: 0;
  overflow-wrap: break-word;
  color: var(--color-deep-black);
  background: var(--color-white);
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: var(--weight-regular);
  line-height: 1.55;
  font-synthesis: none;
}

img,
svg {
  display: block;
  max-width: 100%;
}

/*
 * Sécurité : plusieurs composants imposent un display, ce qui annulerait
 * l'attribut « hidden » du document. Cette règle lui rend la priorité.
 */
[hidden] {
  display: none !important;
}

/*
 * Pastilles de carrousel : elles ne servent qu'à la composition mobile. En
 * desktop les panneaux sont côte à côte et il n'y a rien à commander — le
 * retrait vaut aussi pour le clavier, « display: none » les sortant de
 * l'ordre de tabulation.
 */
.carousel-pastilles {
  display: none;
}

/*
 * L'accroche de 02-4 est enveloppée pour porter, en mobile, le titre ET son
 * invite de glissement. En desktop l'enveloppe ne doit rien être : « contents »
 * la fait disparaître de la mise en page, et le titre garde exactement le
 * calage absolu sur le pavé oblique qu'il avait avant.
 */
.audiences__accroche {
  display: contents;
}

/* L'invite et les chevrons n'existent qu'en mobile. */
.invite-glisser,
.audience-panel__chevron {
  display: none;
}

a {
  color: inherit;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.18em;
}

button,
input,
textarea,
select {
  font: inherit;
}

:where(a, button, [tabindex]):focus-visible {
  outline: var(--focus-outer);
  outline-offset: 3px;
  box-shadow: var(--focus-inner);
}

[tabindex="-1"]:focus {
  outline: none;
}

.content-shell {
  width: min(100%, var(--layout-content-max));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.skip-link {
  position: fixed;
  z-index: 1000;
  top: 1rem;
  left: 1rem;
  padding: 0.75rem 1rem;
  color: var(--color-white);
  background: var(--color-deep-black);
  font-weight: var(--weight-semibold);
  transform: translateY(calc(-100% - 2rem));
  transition: transform var(--transition-fast);
}

.skip-link:focus {
  transform: translateY(0);
}

/*
 * L'ouverture et le header compact ne sont pas deux headers superposés : ce
 * sont deux états d'un même header (P3 Partie 5 § 5). La progression --p va de
 * 0 (ouverture entière) à 1 (état compact) ; elle est écrite par script.js à
 * chaque image du défilement. Toutes les cotes ci-dessous en sont des
 * interpolations, et aucune n'a de transition CSS : la métamorphose n'est plus
 * un basculement déclenché à un seuil, c'est le visiteur qui la conduit.
 *
 * La course est donnée par la géométrie, sans qu'il faille l'inventer : la
 * boîte fait une hauteur de fenêtre, la scène est ancrée en bas, il reste
 * 166 px à l'arrivée. Le défilement disponible vaut donc exactement, au pixel
 * près, la distance dont le header se réduit.
 */
.site-header {
  --p: 0;
  --header-hauteur: max(100dvh, 43.75rem);
  --header-white-height: calc(204px - 94px * var(--p));
  --header-orange-height:
    calc((var(--header-hauteur) - 204px) * (1 - var(--p)) + 56px * var(--p));
  --header-compact-height: 166px;
  position: relative;
  height: var(--header-hauteur);
  overflow: clip;
}

.site-header__stage {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: calc(var(--header-white-height) + var(--header-orange-height));
  display: grid;
  grid-template-rows: var(--header-white-height) minmax(0, var(--header-orange-height));
  overflow: clip;
}

.site-header__white {
  background: var(--color-white);
  display: grid;
  place-items: center;
}

.brand-link {
  width: min(440px, calc(100% - 3rem));
  display: block;
  transform-origin: center;
  /* De 1 à 0,62, la taille compacte relevée sur la maquette. */
  transform: scale(calc(1 - 0.38 * var(--p)));
}

.brand-logo {
  width: 100%;
  height: auto;
  display: block;
}

.site-header__orange {
  position: relative;
  min-height: 0;
  overflow: hidden;
  background: var(--color-orange);
}

.compact-nav {
  position: absolute;
  z-index: 2;
  inset: 0;
  display: flex;
  align-items: center;
  background: var(--color-orange);
  /* Le menu compact apparaît vers la fin de la métamorphose, de 68 % à 95 %. */
  opacity: calc((var(--p) - 0.68) / 0.27);
  visibility: hidden;
  pointer-events: none;
}

.compact-nav__inner {
  width: min(calc(100% - 2rem), 1200px);
  height: 100%;
  margin-inline: auto;
  padding-inline: 50px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.compact-nav__pages,
.compact-nav__socials {
  display: flex;
  align-items: center;
}

.compact-nav__pages {
  gap: 3.25rem;
}

.compact-nav__socials {
  gap: 1.8rem;
}

.compact-nav a {
  font-size: 18px;
  font-weight: var(--weight-regular);
  line-height: 32px;
  text-decoration: none;
}

/*
 * Le burger du header au survol n'existe qu'en composition mobile : le bloc
 * mobile plus bas est le seul à l'habiller. Au-dessus de 900 px il reste
 * pourtant dans le balisage, sans aucune règle, et le navigateur le rend alors
 * en bouton par défaut — un rectangle gris de 16 x 6 px, centré, à cheval sur
 * la limite du blanc et de l'orange.
 *
 * La cote employée est la COMPLÉMENTAIRE de la cote structurante unique du
 * site, pas une seconde cote : au-dessus de 900 px le tronc ne dit rien du
 * burger, et c'est exactement là que cette règle s'applique. Elle ne peut donc
 * pas entrer en concurrence avec le bloc mobile.
 *
 * Posée d'abord dans la feuille de Réalisations le 27 août au matin, puis
 * PROMUE ICI le soir : le défaut a été mesuré sur Présentation aussi
 * (display: block, 16 x 6 px, à x 712 y 102 en 1440 px de large), comme la
 * conversation Réalisations l'avait prédit.
 */
@media (min-width: 900px) {
  .panneau-header .burger {
    display: none;
  }
}

/*
 * La page où l'on se trouve, dans le menu.
 *
 * Ce n'est pas un lien : c'est un « span », et « aria-current » porte
 * l'information pour qui ne voit ni le corps ni la graisse. Le trait du footer
 * ne conviendrait pas ici — sur une bande orange, la marque est le corps et le
 * gras.
 *
 * Promue au tronc commun le 27 août : le menu est le même sur tout le site, et
 * il doit dire partout où l'on est. Elle vivait dans la feuille de Réalisations
 * tant qu'une seule page l'employait.
 * Contraste noir sur orange : 7,21:1.
 */
.compact-nav__current {
  color: var(--color-deep-black);
  font-size: 20px;
  font-weight: var(--weight-bold);
  line-height: 32px;
}

.compact-nav a,
.compact-nav__pending {
  display: inline-flex;
  min-width: 2.75rem;
  min-height: 2.75rem;
  align-items: center;
  justify-content: center;
  transition: transform var(--transition-fast);
}

.compact-nav__pending {
  min-width: 0;
  min-height: 0;
  cursor: pointer;
}

.compact-nav img {
  width: auto;
  height: 22px;
  display: block;
}

/*
 * Curseur des liens dont toute la surface est une image.
 *
 * Sans déclaration, ces liens restent en « cursor: auto », c'est-à-dire « au
 * navigateur de décider ». Chromium décide en regardant le lien : dès qu'il y
 * a un « href », c'est la main. WebKit décide en regardant ce qu'il y a sous
 * le pointeur : il tombe sur le contenu de la balise, le juge sélectionnable
 * et affiche le curseur de texte. Sur un lien qui contient du texte les deux
 * tombent d'accord ; sur un lien qui ne contient qu'une image, ils divergent —
 * d'où la main sur Chrome et le curseur de texte sur Safari, relevés par
 * Florian le 23 août sur les trois logos et rien d'autre.
 *
 * On cesse donc de s'en remettre à « auto » : la main est déclarée. Le logo de
 * l'ouverture est exclu tant qu'il n'est pas un lien, et le geste de sélection
 * est retiré des images elles-mêmes — c'est lui que WebKit cherchait à offrir.
 */
.brand-link[href],
.panneau-header__marque,
.project__mark,
.back-to-top,
.compact-nav a {
  cursor: pointer;
}

.brand-link:not([href]) {
  cursor: default;
}

.brand-logo,
.project__mark img,
.back-to-top img,
.compact-nav img {
  user-select: none;
  -webkit-user-drag: none;
}

/*
 * P3 Partie 5 § 10 : le survol n'est appliqué qu'aux appareils qui possèdent
 * réellement un pointeur précis. « hover: hover » seul laisse passer certains
 * écrans tactiles, qui gardent alors un état de survol collé après le doigt.
 */
@media (hover: hover) and (pointer: fine) {
  .compact-nav a:hover,
  .compact-nav__pending:hover,
  .button:hover,
  .site-footer a:hover,
  .project__mark:hover {
    transform: translateY(-2px);
  }

  /*
   * Les deux logos empruntent « translate » et non « transform » : celui-ci
   * porte déjà leur réduction, pilotée par la progression du header. Les deux
   * propriétés se composent, là où l'une écraserait l'autre.
   */
  .brand-link[href]:hover,
  .panneau-header__marque:hover {
    translate: 0 -2px;
  }

  /*
   * § 13 : ombre douce au survol des boutons orange, et sur eux seulement —
   * une ombre sur les liens et pictogrammes noirs ne ferait que les rendre
   * flous. Le contour de focus n'est jamais remplacé par une ombre (§ 14),
   * d'où l'exclusion : sans elle, cette règle plus spécifique l'effacerait.
   */
  .button--orange:hover:not(:focus-visible) {
    box-shadow: 0 5px 12px rgb(21 21 21 / 18%);
  }
}

/* § 12 : léger enfoncement à l'activation, le temps de l'appui seulement. */
.button--orange:active:not(:focus-visible) {
  box-shadow: inset 0 2px 5px rgb(21 21 21 / 25%);
}

.compact-nav a:active,
.compact-nav__pending:active,
.button:active,
.site-footer a:active,
.project__mark:active {
  transform: translateY(0);
}

.brand-link[href]:active,
.panneau-header__marque:active {
  translate: none;
}

.hero-content {
  position: relative;
  min-height: 100%;
  /* Les deux textes s'estompent pendant la réduction, de 40 % à 72 %. */
  opacity: calc((0.72 - var(--p)) / 0.32);
  visibility: visible;
}

.hero-content__copy {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(calc(100% - 3rem), 760px);
  text-align: center;
  /* Calage vertical relevé sur la maquette v4 : encre du h1 à 415, encre du second paragraphe à 573. */
  transform: translate(-50%, calc(-50% - 35px));
}

.hero-content h1,
.project h2,
.audiences h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  line-height: 0.98;
  letter-spacing: -0.025em;
}

.hero-content h1 {
  max-width: 730px;
  /*
   * La maquette v4 laisse 45 px d'encre entre les deux paragraphes. La valeur
   * « espace après 20 » du relevé Photoshop ne mesure pas la même chose qu'une
   * marge CSS ; c'est la maquette qui fait foi.
   */
  margin: 0 auto 32px;
  /* 02_DECISIONS : Source Sans 3 Medium, 26/32, espace après 20. */
  font-family: var(--font-body);
  font-size: 26px;
  font-weight: var(--weight-medium);
  line-height: 32px;
  font-synthesis: none;
  letter-spacing: normal;
  text-align: center;
}

.hero-content__copy > p {
  max-width: 680px;
  margin: 0 auto;
  font-size: 22px;
  font-weight: var(--weight-regular);
  line-height: 28px;
  text-align: center;
}

.hero-content__next {
  position: absolute;
  right: 50%;
  bottom: 14px;
  margin: 0;
  padding: 0;
  transform: translateX(50%);
}

/*
 * Un seul seuil commande les deux contenus, à 70 % de la métamorphose. En deçà,
 * le menu compact est en « visibility: hidden » : ni le pointeur ni le clavier
 * ne peuvent l'atteindre. Au-delà, c'est le contenu d'ouverture qui l'est. Il
 * n'existe donc à aucun moment d'élément invisible et pourtant accessible, ce
 * qu'interdit P3 Partie 5 § 6. Au moment de la bascule les deux opacités valent
 * environ 0,06 : le passage ne se voit pas.
 */
.site-header.est-compact .hero-content {
  visibility: hidden;
  pointer-events: none;
}

.site-header.est-compact .compact-nav {
  visibility: visible;
  pointer-events: auto;
}

.section {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  scroll-margin-top: 1rem;
}

.section--off-white {
  background: var(--color-off-white);
}

.presentation__inner,
.method__inner,
.domains__inner {
  min-height: inherit;
  padding-block: var(--section-space);
  display: flex;
  flex-direction: column;
}

.presentation {
  min-height: calc(100vh - 166px);
  min-height: calc(100dvh - 166px);
}

.presentation__inner {
  position: relative;
  /* Le bloc se centre dans l'espace restant : la réserve basse le remonte de 40 px. */
  padding-block: 0 80px;
}

.prose.prose--presentation {
  width: min(100%, 725px);
  max-width: 725px;
  margin: auto;
}

.presentation .section-link {
  position: absolute;
  right: 50%;
  bottom: 14px;
  margin: 0;
  padding: 0;
  transform: translateX(50%);
}

.prose {
  max-width: 65rem;
  margin: auto;
  font-size: 18px;
  line-height: 32px;
}

.prose p {
  margin: 0 0 15px;
}

.prose strong {
  color: var(--color-orange-dark);
  font-weight: var(--weight-semibold);
}

.section-link {
  align-self: center;
  min-height: 2.75rem;
  margin-top: auto;
  padding: 1rem;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  text-align: center;
  text-decoration: none;
  font-size: 16px;
  font-weight: var(--weight-regular);
  line-height: 28px;
}

/*
 * Même relation texte/chevron pour les passages 01 → 02-1 et 02-1 → 02-2.
 * Le chevron conserve sa position validée ; seul le texte est ajusté dans sa boîte.
 */
.section-link.section-link--section-transition {
  bottom: 30px;
  padding: 0;
  gap: 0.1rem;
}

/*
 * Le texte du binôme est remonté de 8 px. Un transform le déplacerait sans
 * emmener sa zone cliquable : le libellé se retrouverait hors du lien. Le
 * décalage est donc obtenu par un padding, qui participe au flux.
 */
.section-link.section-link--section-transition > span {
  padding-bottom: 8px;
}

/*
 * Le chevron est un SVG en ligne défini une seule fois en haut du document.
 * Il prend la couleur du lien par currentColor et ne déclenche aucune requête,
 * ce qui le rend visible aussi bien en file:// qu'en ligne. Un masque CSS ou
 * une image externe échouent tous deux quand la page est ouverte en local.
 * Dimensions relevées sur les maquettes v4 : 45 x 23 px sur chaque écran.
 */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.section-link__chevron {
  width: 45px;
  height: 24px;
  display: block;
  fill: currentColor;
}

.section-link--anthracite {
  color: var(--color-anthracite);
}

.section-link--ink {
  color: var(--color-deep-black);
}

.method {
    background: var(--color-white);
    scroll-margin-top: 0;
}

.method__inner {
    position: relative;
    /*
     * La grille est centrée par ses marges automatiques, la réserve basse la
     * remonte de 64 px. Avec un transform, elle sortait de sa propre section
     * dès que la fenêtre passait sous 900 px de haut.
     */
    padding-block: 0 128px;
}

.method-grid {
    /*
     * La grille passe devant le binôme de bas de section : à grande amplitude
     * les blocs le traversent, et sans cela le libellé du lien s'imprimerait
     * au travers des pavés — un élément positionné se peignant au-dessus d'un
     * élément qui ne l'est pas. Le calage est permanent, et non posé le temps
     * de l'animation : changer de contexte d'empilement en cours de route
     * laisse des résidus de tracé.
     */
    position: relative;
    z-index: 1;
    width: 1040px;
    max-width: 100%;
    margin: auto;
    display: grid;
    grid-template-columns: repeat(4, 236px);
    column-gap: 32px;
}

.method-card {
    width: 236px;
    min-height: 0;
    padding: 0;
    background: transparent;
}

.method-card__heading {
    width: 236px;
    margin: 0;
    display: grid;
    justify-items: end;
    font-family: var(--font-display);
    line-height: 50px;
    text-align: right;
}

.method-card h3,
.domain-card h3,
.audience-panel h3,
.trust h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  line-height: 1;
}

.method-card__number,
.method-card__title {
    display: block;
    line-height: 50px;
}

.method-card__number {
    margin: 0;
    color: var(--color-orange-mid);
    font-size: 72px;
    font-weight: var(--weight-bold);
    /* Relevé maquette v4 : haut d'encre du numéro à 144 px, contre 134 px sans ce décalage. */
    transform: translateY(10px);
}

.method-card__title {
    color: var(--color-deep-black);
    font-size: 48px;
    font-weight: var(--weight-semibold);
    white-space: nowrap;
    overflow-wrap: normal;
    word-break: normal;
}

/*
 * Calage vertical de 02-2 sur la maquette v4, relevé au pixel sur le JPG :
 * titre à 210, filet à 267, haut du pavé à 291. Le titre descend de 4 px
 * de moins que le filet et le pavé, ce qui rétablit les 22 px entre le
 * filet et la ligne de base du titre.
 */
.method-card__title {
    transform: translateY(20px);
}

.method-card__rule,
.method-card__body {
    transform: translateY(24px);
}

.method-card__rule {
    width: 236px;
    height: 1px;
    margin: 12px 0 23px;
    display: block;
    background: var(--color-deep-black);
}

.method-card__body {
    width: 236px;
    height: 374px;
    box-sizing: border-box;
    padding: 20px;
    background: var(--color-light-gray);
}

/*
 * L'EMPHASE DES CASES DE LA RUBRIQUE PRESTATIONS — 3 septembre 2026.
 *
 * Semi-gras, et la couleur du texte courant. C'est la même emphase que celle
 * du bloc « Pourquoi faire confiance à zeMoritz » (« .trust__content strong »),
 * et volontairement PAS celle des paragraphes de prose, qui passe en orange.
 * Choix de Florian : dans une case grise, l'orange serait de trop.
 *
 * ⚠ SANS CETTE RÈGLE, un « strong » nu s'afficherait en 700. Les quatre
 * graisses de Source Sans 3 sont chargées, le 700 existe donc vraiment — le
 * défaut ne se verrait pas comme un bogue, seulement comme un gras trop lourd.
 */
.method-card__body strong {
    font-weight: var(--weight-semibold);
}

.method-card__body p {
    margin: 0;
    font-size: 18px;
    line-height: 28px;
    text-align: left;
}

.method .section-link {
    position: absolute;
    right: 50%;
    margin: 0;
    transform: translateX(50%);
}

/* ==========================================================================
 * Arrivées de section — liées au défilement
 *
 * Un seul mécanisme pour 02-2, 02-3, 02-4 et 02-6. L'effet ne se joue pas dans
 * le temps : il suit le geste du visiteur, comme la métamorphose de
 * l'ouverture. Il dure donc exactement le temps que le bloc met à monter dans
 * la fenêtre — lent si l'on descend lentement, rapide si l'on fonce, et
 * terminé quand la section est en place dans les deux cas.
 *
 * La course est accrochée au BLOC ANIMÉ, pas au haut de la section : mesuré,
 * ce bloc se trouve à 131 px du haut de la section en 02-2, mais à 407 px en
 * 02-3, où le montage photographique occupe tout le haut. Un repère pris sur
 * le bord de la section y ferait passer 45 % de l'effet sous le pli. Elle va
 * donc du moment où le haut du bloc — DÉPLACÉ, donc décalé vers le bas de
 * --montee-defilement — franchit le bas de la fenêtre, à celui où sa place
 * définitive atteint 30 % de la hauteur d'écran. Jamais dépendante de la
 * hauteur de la section.
 *
 * L'effet est un MOUVEMENT : les blocs arrivent de plus bas, l'un après
 * l'autre. Le flou ne fait que l'accompagner et s'éteint avec lui ; l'opacité
 * est neutralisée (--opacite-depart vaut 1).
 *
 * --a, écrite par script.js sur la section, va de 0 à 1 et se verrouille une
 * fois pleine : remonter la page ne doit pas effacer ce qu'on vient de lire
 * (P3 : « les animations d'entrée ne se rejouent pas »).
 *
 * Le déplacement emprunte « translate » et non « transform » : le contenu du
 * carrousel de 02-4 réserve déjà « transform » à son glissement latéral, et
 * les deux propriétés se composent sans se gêner.
 * ========================================================================== */

/* Sans JavaScript, tout est simplement en place. */
.method,
.domains,
.audiences,
.project {
  --a: 1;
}

.js .method,
.js .domains,
.js .audiences,
.js .project {
  --a: 0;
}

.js .method-card,
.js .domain-card,
.js .audiences__pave::before,
.js .audience-panel__content,
.js .carousel__panels,
.js .carousel__controls,
.js .project__colonne {
  --i: 0;
  /*
   * Chaque bloc parcourt 64 % de la course, décalé de 12 % sur le précédent :
   * le quatrième démarre à 36 % et tous se posent ensemble. En 02-2 le
   * décalage n'est pas décoratif — il dit que la méthode est une suite,
   * d'abord comprendre, ensuite structurer. La valeur est bornée avant tout
   * calcul : au carré, une progression négative ou supérieure à 1 renverrait
   * le bloc vers le bas.
   */
  --ai: clamp(0, calc((var(--a) - 0.12 * var(--i)) / 0.64), 1);
  /*
   * Le bloc décélère en se posant : (1 − a)², rapide au départ, nul à
   * l'arrivée. Une progression linéaire donnerait un glissement mécanique,
   * à vitesse constante, qui ne se lit pas comme une arrivée.
   */
  /*
   * Déplacement commun, exprimé une seule fois. Les sections qui arrivent par
   * la gauche — 02-4 et 02-6 — le réorientent plus bas ; c'est la seule chose
   * qui les distingue.
   */
  --deplacement: calc(
    var(--montee-defilement) * (1 - var(--ai)) * (1 - var(--ai))
  );
}

/* Arrivées par le bas — 02-2 et 02-3. */
.js .method-card,
.js .domain-card {
  translate: 0 var(--deplacement);
}

/*
 * Le flou n'accompagne que les arrivées par le bas. Les arrivées latérales
 * empruntent l'idiome du carrousel — glissement et fondu — qui n'en a pas.
 */
.js .method-card,
.js .domain-card {
  filter: blur(calc(var(--flou-depart) * (1 - var(--ai))));
}

/*
 * L'opacité est tenue à l'écart du contenu du carrousel, dont les trois
 * panneaux la pilotent déjà pour ne montrer que le public courant.
 */
.js .method-card,
.js .domain-card {
  opacity: calc(var(--opacite-depart) + (1 - var(--opacite-depart)) * var(--ai));
}

/*
 * Arrivées latérales — 02-4 et 02-6. La réponse sort de la question : le bloc
 * vient de la gauche, du titre qui, lui, ne bouge pas. Tomber verticalement à
 * côté d'un titre fixe ne disait rien ; venir de lui dit que la réponse suit
 * la question. C'est l'idiome du carrousel de 02-4 — glissement latéral et
 * fondu — étendu à l'arrivée de ces deux sections.
 *
 * Le fondu court de 0 à 100 % sur toute la course, pavé orange compris : c'est
 * ce départ à zéro qui doit se sentir. Le bloc passe DERRIÈRE les grands
 * titres, qui remontent au-dessus de tout ce qui bouge — c'est là que se joue
 * le moment où il est le plus transparent, et c'est ce qui donne l'impression
 * qu'il en sort.
 *
 * Réserve connue : à mi-opacité au-dessus de l'anthracite, l'orange vire
 * momentanément au brun. Le titre en masque une partie, pas celle qui déborde
 * à sa droite. C'est le prix du départ à zéro, assumé.
 */
.js .audiences__pave::before,
.js .audience-panel__content,
.js .carousel__controls,
.js .project__colonne {
  translate: calc(-1 * var(--deplacement)) 0;
}

/*
 * Les arrivées latérales se déroulent dans les deux derniers tiers de la
 * course. Sans ce décalage, la décélération au carré expédiait l'essentiel du
 * trajet avant même que le grand titre n'entre dans la fenêtre — à 45 % de la
 * course, le bloc était déjà à 9 % de son décalage et opaque depuis longtemps.
 * Le départ en transparence ne se voyait donc jamais. Décalé de 36 %, le bloc
 * est encore à 74 % de son chemin et quasi transparent quand le titre paraît.
 */
.js .audiences__pave::before,
.js .audience-panel__content,
.js .carousel__panels,
.js .carousel__controls,
.js .project__colonne {
  --i: 3;
}

/*
 * Amplitude propre aux arrivées latérales : le bloc doit démarrer DANS le
 * grand titre, pas à côté. Relevé à 1440 px de large, le bord gauche du pavé
 * orange est à x 716 et le titre court de 161 à 642 ; 300 px le placent à
 * x 494 au moment où le titre paraît, soit en plein dedans.
 */
.audiences,
.project {
  --montee-defilement: 300px;
  --montee-clic: 440px;
}

.js .audiences__pave::before,
.js .carousel__panels,
.js .carousel__controls,
.js .project__colonne {
  opacity: var(--ai);
}

/*
 * Le conteneur des panneaux ne porte QUE l'opacité — jamais « translate »,
 * « filter » ni « will-change ». Ces trois propriétés feraient de lui le bloc
 * de référence des positions absolues qu'il contient, et toute la composition
 * du carrousel, calée sur le pavé, se recalerait sur lui. L'opacité seule ne
 * crée pas de bloc de référence, et elle s'applique bien à toute sa
 * descendance : le texte du panneau courant se fond avec le bloc orange.
 */

/*
 * Arrivée par un lien : mêmes points de départ et d'arrivée dans le temps,
 * mais les blocs viennent de bien plus bas. À la molette, c'est la durée du
 * geste qui donne sa lisibilité au mouvement ; au clic, la durée est fixe, et
 * il ne reste que l'amplitude pour le rendre perceptible. La classe est posée
 * et retirée par script.js.
 */
.js .arrivee-au-clic {
  --montee-defilement: var(--montee-clic);
}

/*
 * Un bloc à la fois flouté et déplacé sur une grande distance laisse des
 * traînées : le flou élargit la zone à repeindre, et le compositeur ne
 * réinvalide pas toujours tout ce que le bloc a survolé. Le promouvoir sur sa
 * propre couche pendant l'arrivée règle le problème — et abandonner cette
 * couche à la fin, quand la classe tombe, force le repeint complet de la zone.
 */
.js .method:not(.arrivee-terminee) .method-card,
.js .domains:not(.arrivee-terminee) .domain-card,
.js .audiences:not(.arrivee-terminee) .audience-panel__content,
.js .audiences:not(.arrivee-terminee) .carousel__controls,
.js .project:not(.arrivee-terminee) .project__colonne {
  will-change: translate, filter;
}

/*
 * Pas de « will-change » sur le conteneur des panneaux : il en ferait le bloc
 * de référence des positions absolues qu'il contient, et toute la composition
 * du carrousel se recalerait sur lui. L'opacité seule, elle, ne le fait pas.
 */

/*
 * Une fois posé, plus aucun filtre : « blur(0px) » reste un filtre, et
 * maintiendrait les blocs sur leur propre couche graphique pour le restant de
 * la visite. La classe est posée par script.js au verrouillage.
 */
.js .arrivee-terminee .method-card,
.js .arrivee-terminee .domain-card {
  filter: none;
}

/* 02-2 : les quatre étapes de la méthode, dans l'ordre. */
.js .method-card:nth-child(2) { --i: 1; }
.js .method-card:nth-child(3) { --i: 2; }
.js .method-card:nth-child(4) { --i: 3; }

/* 02-3 : les trois domaines, dans l'ordre. */
.js .domain-card:nth-child(2) { --i: 1; }
.js .domain-card:nth-child(3) { --i: 2; }

/*
 * 02-4 : seul le contenu du panneau arrive. Les flèches restent immobiles —
 * animées, elles se lisaient comme un dysfonctionnement de la commande plutôt
 * que comme une arrivée.
 */

.domains {
  background: var(--color-white);
  /* La section devient une colonne : le montage garde sa taille, le reste
     prend la hauteur disponible et y répartit ses blancs. */
  display: flex;
  flex-direction: column;
}

.supports-montage {
  width: min(100%, var(--layout-gallery-max));
  margin: 0 auto;
  flex: none;
}

.supports-montage img {
  width: 100%;
  height: auto;
}

/*
 * 02-3 — relevé sur la maquette v4 : les trois domaines sont empilés en une
 * seule colonne, cadrés par un unique filet vertical de 1 px placé à x = 302.
 * Le texte commence à x = 362 et chaque description tient sur une seule ligne.
 */
.domains__inner {
  flex: 1;
  min-height: 0;
  /* Réserve basse : la place du binôme de fin de section. */
  padding-block: var(--souffle-moyen) 142px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  justify-content: safe center;
  /* Les 2 px retranchés compensent le padding bas de la liste, qui sert à
     donner au filet sa hauteur exacte de 234 px sans déplacer le bouton. */
  gap: calc(var(--souffle-long) - 2px);
}

/*
 * Le bloc « filet + trois domaines » fait 850 px sur l'écran de référence et
 * se cale à 124 px du bord du gabarit. En réduisant la largeur de la fenêtre,
 * la marge de gauche se resserre d'elle-même jusqu'à un plancher de 148 px —
 * la gouttière minimale de 24 px plus ces 124 px. La marge de droite, elle,
 * n'avait aucun plancher : elle continuait à se resserrer jusqu'à passer sous
 * le texte et à faire défiler toute la page horizontalement.
 *
 * La largeur est donc bornée pour que la marge de droite ne descende jamais
 * sous le même plancher de 148 px. À partir de là, c'est le bloc qui se
 * rétrécit : les descriptions passent à la ligne et le filet vertical
 * s'allonge d'autant, puisqu'il est la bordure gauche du bloc. La section
 * devient alors plus haute que la fenêtre, ce qui est le comportement voulu.
 *
 * Au-dessus d'environ 1170 px de large, rien ne change : la composition
 * validée à 1440 x 900 est intacte.
 */
.domains-list {
  /*
   * Les trois cotes de la maquette — 148 de marge minimale, 124 de décalage,
   * 59 de retrait du texte — sont bornées par une part de la largeur de
   * fenêtre. Elles valent exactement les cotes relevées au-dessus de 1035 px
   * de large et se réduisent proportionnellement en dessous, sans rupture.
   */
  --marge-mini: min(148px, 15vw);
  --decalage: min(124px, 12vw);
  position: relative;
  width: min(850px, calc(100% + var(--gutter) - var(--decalage) - var(--marge-mini)));
  margin: 0 0 0 var(--decalage);
  padding-left: min(59px, 6vw);
  padding-bottom: 2px;
  /*
   * La bordure reste en place, transparente : elle continue de donner à la
   * boîte ses cotes exactes. Le filet visible est repassé en pseudo-élément
   * pour pouvoir être mis à l'échelle, exactement là où passait la bordure.
   */
  border-left: 1px solid transparent;
}

/*
 * Arrivée de 02-3 — le filet vertical est le seul élément qui relie les trois
 * domaines : le voir se tracer, c'est voir la colonne se constituer. Les trois
 * intitulés suivent le trait au fur et à mesure qu'il les atteint.
 */
.domains-list::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -1px;
  width: 1px;
  background: var(--color-deep-black);
  transform-origin: top center;
}

/*
 * Le filet se trace au fil du défilement, comme le reste, et prend de l'avance
 * sur les trois intitulés : il est complet à 55 % de la course, quand le
 * troisième domaine est encore en route. C'est bien le trait qui les amène.
 * Pas de flou ici — un filet de 1 px flouté disparaîtrait.
 */
.js .domains-list::before {
  transform: scaleY(clamp(0, calc(var(--a) / 0.55), 1));
}

/*
 * Les trois domaines passent devant le bouton et le binôme de bas de section,
 * qu'ils survolent à grande amplitude. Comme en 02-2, le calage est permanent :
 * changer de contexte d'empilement en cours d'animation laisse des résidus.
 */
.domains-list {
  z-index: 1;
}

.domain-card {
  padding-top: 8px;
}

/* L'espace entre les trois parties s'ouvre avec la hauteur ; le filet suit. */
.domain-card + .domain-card {
  margin-top: var(--souffle-court);
}

.domain-card h3 {
  margin: 0;
  color: var(--color-orange-dark);
  font-size: 32px;
  font-weight: var(--weight-semibold);
  line-height: 28px;
  text-align: left;
}

.domain-card p {
  margin: 8px 0 0;
  font-size: 18px;
  line-height: 28px;
  text-align: left;
}

.button {
  min-height: 2.75rem;
  padding: 0.85rem 1.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  text-decoration: none;
  font-size: 16px;
  font-weight: var(--weight-semibold);
  line-height: 18px;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.button--orange {
  color: var(--color-deep-black);
  background: var(--color-orange);
}

/* Bouton de 02-3 : 390 x 61 px, centré sur la page (relevé maquette v4). */
.domains__inner > .button {
  width: min(390px, 100%);
  min-height: 61px;
  margin: 0 auto;
  display: flex;
  flex: none;
}

.domains .section-link {
  position: absolute;
  right: 50%;
  margin: 0;
  transform: translateX(50%);
}

/* ==========================================================================
 * 02-4 — Publics
 *
 * La section se compose de deux étages, arrêtés avec Florian le 22 août au
 * soir : un PAVÉ anthracite qui porte toute la géométrie, et sous lui une
 * BANDE blanche de 142 px — exactement celle du bas de 02-5 — qui reçoit le
 * binôme de fin de section. Le binôme retrouve ainsi le centre de la page,
 * comme dans les cinq autres sections, et l'anomalie qui obligeait à le
 * décaler sur le bloc orange disparaît. Sur blanc, le noir profond donne
 * 18 : 1 ; sur l'anthracite il ne donnait que 1,8 : 1, et aucune encre unique
 * ne pouvait passer sur les deux fonds à la fois.
 *
 * Tout ce qui suit est mesuré depuis le PAVÉ, pas depuis la section. Les cotes
 * de la maquette v4 sont donc conservées telles quelles : la composition est
 * celle d'avant, translatée vers le haut de la moitié de la bande.
 *
 * Le bloc orange est le seul élément intangible ; tous les autres s'accrochent
 * à lui. Deux variables suffisent à le décrire, mesurées depuis le bord droit :
 *   --bloc-droite  : son bord droit à mi-hauteur du pavé ;
 *   --bloc-gauche  : son bord gauche à mi-hauteur (570 px plus loin).
 * Au-dessus de 1200 px de large, le bloc est calé sur le centre de la fenêtre,
 * bord droit à 566 px à droite du centre ; en dessous il se fige à 34 px du
 * bord droit et seule la partie anthracite de gauche se réduit (P4.0 § 3.3).
 * Les 566 px valent les 555 px de la maquette d'origine plus les 11 px dont
 * Florian a décalé l'ensemble vers la droite — le grand titre excepté, qui
 * gagne d'autant d'air face à l'oblique : 63,9 px au lieu de 52,6.
 *
 * Relevé sur la maquette v4 (02-4a, 1440 x 900), qui fait foi pour l'intérieur
 * du pavé :
 *   bloc : 570 px de large, pente 0,1263 px/px (7,2°) ;
 *   « Vous êtes… » : deux lignes, encre x 161→525 et 163→633 ;
 *   contenu du carrousel : colonne de 442 px, gardes de 31 px à gauche en haut
 *     et 28 px à droite en bas, là où l'oblique se rapproche le plus ;
 *   flèches : 46 px de diamètre, à cheval sur les bords du bloc ;
 *   binôme : centré sur la page, chevron à 31 px du bas de la section.
 *
 * Hauteur : le pavé vaut la hauteur de fenêtre moins la bande, avec un
 * plancher. Sous 900 px de haut, la section garde ses 900 px et déborde de la
 * fenêtre, la bande blanche glissant sous le pli jusqu'à disparaître — c'est
 * le comportement déjà retenu pour 02-3 et 02-5.
 * ========================================================================== */

.audiences {
  /* Géométrie du bloc oblique : tout s'y raccroche. */
  --bloc-droite: calc(max(50%, 600px) - 566px);
  --bloc-gauche: calc(var(--bloc-droite) + 570px);
  --bande-blanche: 142px;
  /*
   * « Vous êtes… » garde sa taille de maquette tant que la place existe. Sous
   * 1200 px le bloc ne recule plus : le titre est alors pris entre la gouttière
   * de gauche (36 px) et la garde de 30 px devant le bloc, et c'est lui qui
   * cède. La formule fait exactement 191 px à 1200 px : aucun saut au passage.
   */
  --titre-publics: clamp(64px, calc((100vw - 715px) / 2.539), 191px);
  min-height: max(100dvh, 900px);
  /* La bande blanche est la réserve basse de la section. */
  padding-bottom: var(--bande-blanche);
  display: flex;
  flex-direction: column;
  background: var(--color-white);
}

.audiences__pave {
  position: relative;
  flex: 1 1 auto;
  overflow: clip;
  color: var(--color-white);
  background: var(--color-anthracite);
}

/*
 * Le parallélogramme fait deux fois la hauteur du pavé : il déborde donc
 * toujours en haut, quelle que soit la fenêtre, et il est coupé net en bas par
 * la bande blanche. Comme il est centré sur le pavé, le cisaillement se calcule
 * depuis le milieu de celui-ci et les bords tombent exactement sur les valeurs
 * de la maquette. Le fond anthracite et « overflow: clip » lui servent de
 * cache : ni le bloc ni son ombre ne débordent sur les sections voisines.
 */
.audiences__pave::before {
  content: "";
  position: absolute;
  z-index: 0;
  top: 50%;
  right: var(--bloc-droite);
  width: 570px;
  height: 200%;
  background: var(--color-orange);
  transform: translateY(-50%) skewX(-7.2deg);
  box-shadow:
    -18px 0 20px rgb(21 21 21 / 0.55),
    18px 0 20px rgb(21 21 21 / 0.55);
}

.audiences__inner {
  min-height: 0;
  padding: 0;
  display: block;
}

.audiences h2 {
  position: absolute;
  /*
   * Au-dessus de tout ce qui bouge : le pavé orange, le contenu du panneau et
   * les flèches passent DERRIÈRE lui en arrivant, et c'est de lui qu'ils ont
   * l'air de sortir.
   */
  z-index: 5;
  /*
   * Centre d'encre 2 px au-dessus de l'axe du pavé. « Vous » et « êtes… »
   * n'ont aucun jambage descendant : l'encre est plus haute que le centre de
   * la boîte de 0,0497 em, corrigés ici. Exprimée en em, la correction suit la
   * taille du titre quand celui-ci se réduit.
   */
  top: calc(50% - 2px - 0.0497em);
  /*
   * 74 px et non 63 : le bloc ayant reculé de 11 px vers la droite, la constante
   * les rend au titre, qui ne bouge donc pas d'un pixel. Le bord droit de sa
   * boîte reste à la même distance du bord de la fenêtre à toute largeur, ce
   * qui laisse la formule de réduction ci-dessus intacte.
   */
  right: calc(var(--bloc-gauche) + 74px);
  /*
   * La coupure « Vous / êtes… » est écrite dans le document plutôt que laissée
   * au navigateur : Chromium coupe volontiers avant les points de suspension,
   * ce qui donnait trois lignes. Avec la coupure explicite et « nowrap », la
   * boîte fait exactement la largeur de la ligne la plus longue, sur tous les
   * navigateurs et quelle que soit la fonte réellement chargée.
   */
  width: max-content;
  max-width: none;
  color: var(--color-off-white);
  font-size: var(--titre-publics);
  /* Pas d'approche resserrée ici : la maquette montre un « Vous êtes… » plus
     large de 4 % que ce que donne le letter-spacing hérité des autres titres. */
  letter-spacing: normal;
  line-height: 1.005;
  text-align: left;
  white-space: nowrap;
  transform: translateY(-50%);
}

.carousel {
  min-width: 0;
  margin: 0;
}

.carousel__panels,
.js .carousel__panels {
  min-height: 0;
  display: block;
  gap: 0;
}

.audience-panel {
  min-height: 0;
  padding: 0;
}

/*
 * La colonne de texte est calée sur le bloc, pas sur la page : 63 px de recul
 * par rapport à son bord droit, ce qui laisse la garde de 30 px en haut à
 * gauche et de 28 px en bas à droite, là où l'oblique se rapproche le plus.
 */
.audience-panel__content {
  position: absolute;
  z-index: 2;
  top: calc(50% + 2.5px);
  right: calc(var(--bloc-droite) + 62px);
  width: 442px;
  max-width: none;
  margin: 0;
  transform: translateY(-50%);
  color: var(--color-deep-black);
}

.audience-panel__counter {
  width: fit-content;
  /* Le cartouche déborde de 8 px à gauche de la colonne de texte. */
  margin: 0 0 0 -8px;
  padding: 0 8px;
  color: var(--color-white);
  background: var(--color-anthracite);
  border-radius: 0.35rem;
  font-size: 20px;
  font-weight: var(--weight-bold);
  line-height: 28px;
  text-align: center;
}

.audience-panel h3 {
  margin: 0 0 12px;
  color: var(--color-anthracite);
  font-size: 48px;
  line-height: 52px;
  text-align: left;
}

.audience-panel__rule,
.trust__rule {
  height: 6px;
  display: block;
  background: var(--color-white);
}

.audience-panel__rule {
  width: 40px;
  margin: 0 0 19px;
}

.audience-panel p:not(.audience-panel__counter) {
  /* 43 px d'encre à encre entre les deux paragraphes, relevés sur la maquette. */
  margin: 0 0 15px;
  font-size: 18px;
  line-height: 28px;
  text-align: left;
}

.audience-panel p:last-child {
  margin-bottom: 0;
}

/*
 * Passage d'un public à l'autre — les trois panneaux coexistent au lieu d'être
 * montrés et cachés par l'attribut « hidden ». Chacun attend de son côté :
 * un panneau situé avant le panneau courant à gauche, un panneau situé après
 * à droite. Le sens du glissement se déduit donc des positions, sans avoir à
 * mémoriser la direction du dernier clic — et 24 px suffisent à dire « il y en
 * a d'autres à côté » là où un fondu seul dirait « on a remplacé ».
 *
 * Le pavé orange, lui, ne bouge jamais : c'est la signature graphique de la
 * section, pas un élément d'interface.
 *
 * « visibility » retire le panneau sorti du champ du pointeur, du clavier et
 * des technologies d'assistance : les trois textes ne sont jamais annoncés
 * ensemble.
 */
.js .audience-panel__content {
  transition:
    opacity var(--duree-panneau) var(--courbe-arrivee),
    transform var(--duree-panneau) var(--courbe-arrivee),
    visibility 0s linear var(--duree-panneau);
}

.js .audience-panel[data-position="avant"] .audience-panel__content,
.js .audience-panel[data-position="apres"] .audience-panel__content {
  opacity: 0;
  visibility: hidden;
}

.js .audience-panel[data-position="avant"] .audience-panel__content {
  transform: translateY(-50%) translateX(-24px);
}

.js .audience-panel[data-position="apres"] .audience-panel__content {
  transform: translateY(-50%) translateX(24px);
}

.js .audience-panel[data-position="courant"] .audience-panel__content {
  opacity: 1;
  visibility: visible;
  transform: translateY(-50%);
  transition:
    opacity var(--duree-panneau) var(--courbe-arrivee),
    transform var(--duree-panneau) var(--courbe-arrivee),
    visibility 0s linear;
}

/*
 * Première arrivée sur la section — le grand titre est déjà là : il est assez
 * grand pour n'avoir besoin d'aucune aide. Le contenu du panneau monte pour
 * répondre à la question qu'il pose, puis les flèches montent à leur tour pour
 * dire qu'il y a d'autres réponses. Les deux empruntent le mécanisme commun
 * ci-dessus ; « transform » reste au glissement latéral du carrousel.
 *
 * Le pavé anthracite est coupé net en bas et le contenu ne tient qu'à 90 px de
 * cette arête : on pourrait craindre qu'une grande amplitude ne le tranche en
 * pleine ligne. Vérifié, ce n'est jamais le cas — l'arête n'entre dans la
 * fenêtre que lorsque le haut de la section passe sous 142 px, c'est-à-dire
 * tout à la fin de la course, quand le déplacement est déjà retombé sous
 * 15 px. L'amplitude commune peut donc s'appliquer ici aussi.
 */

/* Flèches : posées à cheval sur les bords du panneau, à mi-hauteur. */
.carousel__controls {
  display: none;
}

.js .carousel__controls {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: block;
  transform: none;
  pointer-events: none;
}

.carousel-control {
  position: absolute;
  /* Centre à 2 px au-dessus de l'axe de la section, comme le titre. */
  top: calc(50% - 24px);
  width: 46px;
  height: 46px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  box-shadow: 0 8px 14px rgb(21 21 21 / 0.32);
  cursor: pointer;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
  pointer-events: auto;
}

.carousel-control img {
  width: 100%;
  height: 100%;
}

.carousel-control--previous { right: calc(var(--bloc-gauche) - 28.5px); }
.carousel-control--next { right: calc(var(--bloc-droite) - 16px); }

.carousel-control--previous img {
  transform: rotate(180deg);
}

.carousel-control:disabled {
  box-shadow: 0 5px 9px rgb(21 21 21 / 0.18);
  cursor: default;
}

@media (hover: hover) and (pointer: fine) {
  .carousel-control:not(:disabled):hover {
    transform: translateY(-2px);
  }
}

.carousel-control:not(:disabled):active {
  transform: translateY(0);
  box-shadow: 0 3px 5px rgb(21 21 21 / 0.5);
}

/*
 * Le binôme de 02-4 est posé sur la bande blanche, centré sur la page et à
 * 31 px du bas de la section, exactement comme les cinq autres. Il n'est plus
 * accroché au bloc oblique : c'est le point de toute la reprise. La couleur
 * vient donc de « section-link--anthracite », comme pour les autres binômes
 * posés sur blanc — aucune couleur n'est imposée ici.
 */
.section-link--section-transition.audiences__section-link {
  position: absolute;
  z-index: 4;
  bottom: 31px;
  right: 50%;
  transform: translateX(50%);
  margin: 0;
}

/*
 * Repli sans JavaScript de 02-4 — P3 Partie 5 § 22 et § 46 : les trois publics
 * doivent être présentés successivement dans la page, et leurs textes rester
 * accessibles aux moteurs. Le carrousel n'existant plus, la composition qui
 * lui est propre est démontée : le contenu revient dans le flux (en absolu,
 * les trois panneaux se superposeraient au même endroit du pavé), le bloc
 * oblique disparaît, et l'encre passe en blanc cassé — 9,2 : 1 sur
 * l'anthracite, contre 1,8 : 1 pour le noir profond.
 */
html:not(.js) .audiences__pave {
  padding-block: var(--souffle-moyen);
}

html:not(.js) .audiences__pave::before {
  display: none;
}

html:not(.js) .audiences__inner {
  padding-inline: var(--gutter);
}

html:not(.js) .audiences h2 {
  position: static;
  width: auto;
  margin-bottom: 32px;
  font-size: clamp(48px, 8vw, 96px);
  white-space: normal;
  transform: none;
}

html:not(.js) .audience-panel + .audience-panel {
  margin-top: var(--souffle-moyen);
}

html:not(.js) .audience-panel__content {
  position: static;
  width: auto;
  max-width: 640px;
  color: var(--color-off-white);
  transform: none;
}

html:not(.js) .audience-panel h3 {
  color: var(--color-off-white);
}

/* Le compteur « 1 / 3 » ne veut plus rien dire sans le carrousel. */
html:not(.js) .audience-panel__counter {
  display: none;
}

/* ==========================================================================
 * 02-5 — Pourquoi faire confiance à zeMoritz
 *
 * Particularité de la maquette, absente du prototype d'origine : l'orange
 * n'est pas un fond de section mais une BANDE. Elle est encadrée de blanc,
 * une bande étroite au-dessus et une plus large en dessous, cette dernière
 * portant le binôme de fin de section.
 *
 * Relevé sur la maquette v4 (02-5, 1440 x 900) :
 *   blanc du haut  : y   0 →  62   (63 px)
 *   bande orange   : y  63 → 757   (695 px)
 *   blanc du bas   : y 758 → 899   (142 px), binôme compris
 *   portrait       : x 121 → 446 (326 px), sur toute la hauteur de la bande
 *   colonne texte  : x 582, encre jusqu'à 1180 ; le bloc portrait + texte
 *                    fait 1060 px et se cale à gauche du gabarit de 1200,
 *                    d'où les 140 px libres à droite de la maquette ;
 *   titre 48/52 sur deux lignes, filet blanc 56 x 6, trois paragraphes 18/32.
 *
 * La hauteur de la bande est donnée par son contenu : au-dessus de 900 px de
 * fenêtre les textes ne grandissent pas, seuls les deux blancs s'ouvrent, et
 * ils gardent la proportion 63 : 53 relevée sur la maquette (§ 3.3 de P4.0).
 * ========================================================================== */

.trust {
  /*
   * Réserves hautes et basses de la bande, relevées sur la maquette à 900 px
   * de fenêtre. Au-dessus, elles ne bougent plus : la bande garde sa hauteur
   * et ce sont les deux blancs qui s'ouvrent. En dessous, elles se resserrent
   * jusqu'à un plancher, ce qui laisse la section tenir dans une fenêtre de
   * 768 px de haut au lieu de la déborder.
   */
  --reserve-haute: clamp(32px, calc(82px + (100vh - 900px) * 0.5), 82px);
  --reserve-basse: clamp(36px, calc(90px + (100vh - 900px) * 0.5), 90px);
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--color-white);
}

/*
 * Les deux respirations blanches. Elles partagent l'espace libre dans la
 * proportion de la maquette et ne descendent pas sous leur plancher : en
 * dessous, la section devient plus haute que la fenêtre plutôt que d'écraser
 * la composition.
 */
.trust::before,
.trust::after {
  content: "";
  flex-shrink: 1;
}

/*
 * L'ordre visuel est imposé : le pseudo-élément « after » est le dernier
 * enfant du conteneur, alors que la respiration qu'il porte se place entre la
 * bande et le binôme.
 */
.trust::before {
  order: 1;
  flex-grow: 63;
  flex-basis: 0;
  min-height: 24px;
}

.trust__band {
  order: 2;
  flex: none;
  background: var(--color-orange);
}

.trust::after {
  order: 3;
  flex-grow: 49.4;
  flex-basis: 0;
  min-height: 20px;
}

.trust__inner {
  /* Gabarit de 1200 px, gouttière conservée sous 1315 px de large. */
  width: min(calc(100% - 2 * var(--gutter)), var(--layout-content-max));
  margin-inline: auto;
  display: flex;
  align-items: stretch;
  gap: 134px;
}

.trust__portrait-frame {
  position: relative;
  flex: none;
  width: 326px;
  overflow: clip;
}

/*
 * Cadrage de référence fourni avec la photo : le rectangle x 103 → 799 et
 * y 184 → 1664 du fichier de 926 x 1840. La boîte de l'image est donc agrandie
 * dans le rapport inverse — 926/697 en largeur, 1840/1481 en hauteur — puis
 * décalée pour que ce rectangle vienne exactement remplir le cadre.
 * « object-fit: cover » n'aurait pas suffi : le cadrage demandé est un zoom
 * plus serré que le simple recouvrement. Il reste utilisé pour absorber sans
 * déformation les écarts de proportion quand la bande change de hauteur.
 */
.trust__portrait-frame img {
  position: absolute;
  top: -12.424%;
  left: -14.777%;
  width: 132.855%;
  /*
   * Fichier d'origine, 926 x 1840, cadrage de référence x 103→800, y 184→1665 :
   * 1840 / 1481. La version allongée de 350 px, essayée le 23 août pour nourrir
   * une grande dérive au clic, a été abandonnée avec cette dérive — la matière
   * ajoutée n'apparaissait plus jamais à l'écran et pesait 366 ko de plus.
   */
  height: 124.24%;
  max-width: none;
  object-fit: cover;
}

.trust__content {
  flex: 1 1 auto;
  max-width: 600px;
  /* C'est le texte qui donne sa hauteur à la bande, réserves comprises. */
  padding-block: var(--reserve-haute) var(--reserve-basse);
}

.trust h2 {
  color: var(--color-anthracite);
  margin-bottom: 14px;
  font-size: 48px;
  line-height: 52px;
  text-align: left;
}

.trust__rule {
  width: 56px;
  margin: 0 0 17px;
}

.trust__content p {
  margin: 0 0 15px;
  font-size: 18px;
  line-height: 32px;
  text-align: left;
}

.trust__content p:last-child {
  margin-bottom: 0;
}

.trust__content strong {
  font-weight: var(--weight-semibold);
}

/* Binôme de 02-5 : centré sur la page, dans le blanc du bas. */
.trust__section-link {
  order: 4;
  flex: none;
  align-self: center;
  margin: 0 0 31px;
}

/* ==========================================================================
 * 02-6 — Vous avez un projet en tête ? — et footer
 *
 * La maquette place la section ET le footer sur le même écran de 900 px :
 *   titre, colonne de droite et pictogramme ZZ    : y   0 → 729
 *   footer, filet compris                         : y 729 → 899
 * La section prend donc la hauteur de la fenêtre moins celle du footer.
 *
 * Relevé sur la maquette v4 (02-6, 1440 x 900) :
 *   titre 138/138, sans approche resserrée, orange moyen, trois lignes,
 *     encre y 83 / 218 / 359, à partir de x 197 ;
 *   paragraphe 18/32, cinq lignes à partir de y 107, colonne calée à x 875 ;
 *   trois boutons de 258 x 37 à x 874, hauts à y 294, 344 et 421 — les deux
 *     premiers serrés (14 px), le troisième détaché (41 px) ;
 *   pictogramme ZZ 82 x 131, centré sur la page, bas à y 729 ;
 *   filet du footer y 761, de x 161 à 1276 ;
 *   trois colonnes de footer à x 162, 567 et 1007, deux lignes chacune.
 * ========================================================================== */

.project {
  /*
   * Hauteur du footer relevée sur la maquette. C'est la seule cote qui lie les
   * deux blocs : la section occupe tout ce qui reste de la fenêtre.
   */
  --hauteur-footer: 171px;
  min-height: calc(100dvh - var(--hauteur-footer));
  display: flex;
  flex-direction: column;
  background: var(--color-white);
}

/*
 * Deux respirations encadrent le bloc de texte, dans la proportion 55 : 129
 * relevée sur la maquette. Le pictogramme reste collé au bas de la section.
 * Comme en 02-5, « after » est remis dans l'ordre visuel par « order ».
 */
.project::before,
.project::after {
  content: "";
  flex-shrink: 1;
  flex-basis: 0;
  min-height: 24px;
}

.project::before { order: 1; flex-grow: 57; }
.project__inner { order: 2; }
.project::after { order: 3; flex-grow: 127; }
.project__mark { order: 4; }

.project__inner {
  flex: none;
  width: min(calc(100% - 2 * var(--gutter)), var(--layout-content-max));
  margin-inline: auto;
  display: grid;
  /*
   * Colonnes de la maquette, mais en minmax : sous 1200 px de large elles se
   * réduisent au lieu de pousser la page en défilement horizontal. La
   * composition de référence, elle, est intacte à partir de 1200 px.
   */
  grid-template-columns: minmax(0, 680px) minmax(0, 390px);
  align-content: center;
  /* Le bloc est calé à 73 px du bord du gabarit, relevé maquette. */
  padding-left: min(73px, 6%);
}

.project h2 {
  margin: 0;
  /* Au-dessus de la colonne de droite, qui passe derrière lui en arrivant. */
  position: relative;
  z-index: 2;
  /*
   * La largeur commande la coupure : « Vous avez / un projet / en tête ? ».
   * La ligne la plus longue fait 546 px, la première paire qui déborderait en
   * ferait 681 : entre les deux, la coupure de la maquette est la seule
   * possible. La largeur est exprimée en em : la coupure reste la même quand
   * le titre se réduit sur les fenêtres étroites.
   */
  max-width: 4.32em;
  color: var(--color-orange-mid);
  font-size: min(139px, 11.6vw);
  /* Comme en 02-4, la maquette ne resserre pas l'approche de ce grand titre. */
  letter-spacing: normal;
  /* 138/139 : l'interligne suit la taille quand celle-ci se réduit. */
  line-height: 0.9928;
  text-align: left;
}

.project__colonne {
  padding-top: 43px;
}

/*
 * Arrivée de 02-6 — le grand titre orange est déjà en place : il est assez
 * grand pour n'avoir besoin d'aucune aide. C'est la colonne de droite qui
 * arrive, d'un seul tenant, texte d'introduction et trois boutons ensemble :
 * la question est posée à gauche, la réponse vient à droite.
 */
/*
 * La colonne passe devant le pictogramme ZZ, qu'elle survole en arrivant. Comme
 * ailleurs, le calage est permanent plutôt que posé le temps de l'animation.
 *
 * Et elle arrive PAR LA GAUCHE, non par le bas : elle sort du grand titre
 * « Vous avez un projet en tête ? », qui lui reste immobile. Tomber
 * verticalement à côté d'un titre fixe ne disait rien ; venir de lui dit que
 * la réponse suit la question. C'est l'idiome du carrousel de 02-4 — glissement
 * latéral et fondu — appliqué à une arrivée de section.
 *
 * Le fondu est plein aux 70 % du parcours : le reste est un glissement pur, et
 * un visiteur qui s'arrête de défiler ne se retrouve jamais devant du texte à
 * demi effacé. Pas de flou ici, le carrousel n'en a pas.
 */
.js .project__colonne {
  position: relative;
  z-index: 1;
}

.project__intro {
  max-width: min(365px, 100%);
  margin: 0 0 34px;
  font-size: 22px;
  line-height: 32px;
  text-align: left;
}

.project__actions {
  display: grid;
  justify-items: start;
  gap: 14px;
}

/* Boutons de 02-6 : 258 x 37 px, relevé maquette v4. */
.project__actions .button {
  position: relative;
  width: min(258px, 100%);
  min-height: 37px;
  padding-block: 0;
}

/*
 * Le dessin fait 37 px de haut ; la zone cliquable est ramenée à 44 px par un
 * pseudo-élément, sans toucher à la composition. L'écart de 14 px entre deux
 * boutons est plus grand que les 2 x 3,5 px ajoutés : aucune zone ne se
 * chevauche.
 */
.project__actions .button::after {
  content: "";
  position: absolute;
  inset: -3.5px 0;
}

/* Le troisième bouton est détaché des deux premiers : 41 px au lieu de 14. */
.button--detache {
  margin-top: 26px;
}

.project__mark {
  flex: none;
  align-self: center;
  width: 82px;
  display: block;
}

.project__mark img {
  width: 100%;
  height: auto;
}

.site-footer {
  padding-top: 32px;
  padding-bottom: 64px;
  color: var(--color-deep-black);
  background: var(--color-white);
}

.site-footer__inner {
  width: min(calc(100% - 2 * var(--gutter)), 1116px);
  margin-inline: auto;
  padding-top: 24px;
  display: grid;
  /* Colonnes de la maquette, en minmax : elles se réduisent au lieu de pousser
     la page en défilement horizontal sous 1010 px de large. */
  grid-template-columns: minmax(0, 405px) minmax(0, 440px) minmax(0, 1fr);
  align-items: start;
  border-top: 1px solid var(--color-blue-gray);
}

/* ---------------------------------------------------------------------
 * ⚠ ENTRE 900 ET 1200 px, LE PIED DE PAGE PARTAIT EN RUBAN VERTICAL.
 *
 * Mesuré le 31 août, et VU par Florian sur une tablette Microsoft Surface en
 * portrait : le pied de page montait jusqu'à 1 510 px de haut au lieu de 190,
 * et « Mentions légales · Politique de confidentialité » s'écrivait lettre par
 * lettre, une par ligne. Un site doit pouvoir montrer ses mentions légales.
 *
 * LA CAUSE. Les deux premières colonnes ci-dessus sont écrites en PIXELS
 * FIXES — 405 et 440. Quand la fenêtre se réduit, elles ne cèdent rien : toute
 * la réduction tombe sur la troisième, écrasée jusqu'à 1 px de large. Le
 * navigateur, ne pouvant plus poser un mot, coupe entre les lettres.
 *
 * LA CORRECTION. Dans cette plage, et dans cette plage seulement, les trois
 * colonnes deviennent des PROPORTIONS : elles se réduisent ensemble.
 *
 * Les proportions 400 / 330 / 386 suivent la demande de Florian du 31 août : la
 * colonne du milieu se resserre pour que celle de droite tienne
 * « Politique de confidentialité » d'un seul tenant, et le menu se coupe alors
 * après « Prestations · ».
 *
 * ⚠ ET IL FAUT UNE GOUTTIÈRE EXPLICITE. Sans elle, MESURÉ entre 960 et 1040 px,
 * la dernière lettre du menu venait toucher le « © 2026 » de la colonne
 * suivante — zéro pixel entre les deux. Le gabarit n'en avait jamais eu besoin :
 * à 1440 les colonnes sont si larges que le texte ne les remplit pas. Les 32 px
 * garantissent au moins 33 px d'air sur toute la plage, mesuré.
 *
 * ⚠ LES BORNES SONT VOULUES, TOUTES LES DEUX.
 *   · 900 px, parce qu'en dessous le pied de page n'est plus une grille du
 *     tout : il passe en `display: block`, centré. Cette règle n'y a pas cours.
 *   · 1199 px, parce qu'à 1200 la composition validée reprend la main, avec
 *     ses colonnes de la maquette. MESURÉ : à 1200, 1440 et 1920, les cinq
 *     pages ne bougent pas d'un pixel.
 *
 * Mesuré sur les onze pages, de 320 à 1920 px : pied de page entre 194 et
 * 195 px sur toute la plage, aucun débordement horizontal, et les hauteurs de
 * référence de 1440, 1200, 899 et 375 intactes.
 * ------------------------------------------------------------------- */
@media (min-width: 900px) and (max-width: 1199px) {
  .site-footer__inner {
    grid-template-columns: minmax(0, 400fr) minmax(0, 330fr) minmax(0, 386fr);
    column-gap: 32px;
  }
}

.site-footer__name {
  margin: 0;
  font-family: var(--font-body);
  font-size: 22px;
  font-weight: var(--weight-semibold);
  line-height: 26px;
  text-align: left;
}

.site-footer__name span {
  color: var(--color-orange);
}

.site-footer__identity > p:last-child {
  margin: 0;
  font-size: 16px;
  line-height: 24px;
  text-align: left;
}

.site-footer__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 7.5px;
}

/*
 * Les points de séparation sont des éléments à part entière, hors des liens :
 * en pseudo-éléments des liens, ils se soulevaient et se soulignaient au
 * survol avec eux. Ils restent masqués aux technologies d'assistance.
 */
.site-footer__sep {
  color: var(--color-deep-black);
}

.site-footer__nav,
.site-footer__contact {
  font-size: 16px;
  line-height: 24px;
  text-align: left;
}

.site-footer__milieu {
  padding-top: 3px;
}

.site-footer__contact {
  margin-top: -2px;
  display: flex;
  align-items: center;
  gap: 12px;
}

/*
 * Les liens du footer ne sont pas soulignés sur la maquette : ils forment des
 * groupes de navigation, pas des liens noyés dans du texte courant. Le
 * soulignement revient au survol et au focus, où il sert de repère.
 */
.site-footer a {
  text-decoration: none;
  transition: transform var(--transition-fast);
}

.site-footer a:hover,
.site-footer a:focus-visible {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.site-footer__current {
  /*
   * Le trait de la page courante suit la ligne de base du texte, comme sur la
   * maquette, et non le bas de la boîte : c'est le rôle de text-underline-offset.
   */
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  text-decoration-color: var(--color-orange);
  text-decoration-thickness: 3px;
  text-underline-offset: 3px;
}

.site-footer__socials {
  display: flex;
  align-items: center;
  gap: 6px;
}

.site-footer__socials img {
  width: 17px;
  height: 17px;
}

/* Le lien reste inactif tant que l'URL manque ; le dessin, lui, est celui de la maquette. */
.social-placeholder {
  display: inline-flex;
}

.site-footer__legal {
  padding-top: 9px;
  font-size: 14px;
  line-height: 20px;
  text-align: left;
}

.site-footer__copyright,
.site-footer__pages {
  margin: 0;
}

.site-footer__pages {
  margin-top: 0;
}

/*
 * ⚠ UN NOM DE PAGE NE SE COUPE PAS EN DEUX.
 *
 * Posé le 29 août 2026. Défaut signalé par Florian sur la Politique de
 * confidentialité à 1440 : la ligne du bas de page s'y lisait
 * « Politique de / confidentialité », coupée au milieu du nom.
 *
 * Ce n'est pas le défaut d'une seule page, c'est une ligne qui tient de
 * justesse partout. Mesuré à 1440 : la colonne fait 271 px, et la ligne
 * « Mentions légales · Politique de confidentialité » demande
 *   — 270 px sur l'accueil, Réalisations et Contact  → il reste 1 px ;
 *   — 271 px sur les mentions légales                → il reste 0 px ;
 *   — 275 px sur la politique de confidentialité     → il manque 4 px,
 *     parce que c'est l'entrée LA PLUS LONGUE qui y est marquée page
 *     courante, donc en gras.
 * Quatre pages sur cinq tiennent à un pixel près : il suffit d'un moteur qui
 * dessine les caractères un rien plus large pour que la coupure apparaisse
 * ailleurs.
 *
 * Ce que fait la règle : elle NE SUPPRIME PAS le retour à la ligne, elle
 * l'oblige à tomber ENTRE les deux entrées plutôt qu'au milieu d'un nom.
 * Vérifié : aucune hauteur de page ne bouge, sur aucune des cinq pages.
 *
 * ⚠ POURQUOI ELLE S'ARRÊTE À 1200 px, ET CE N'EST PAS UN SEUIL DE PLUS.
 * 75rem est la cote qui existe déjà dans cette feuille. En dessous, la
 * troisième colonne du pied de page est ÉCRASÉE — 29 px de large à 950 —
 * parce que les deux premières colonnes gardent leurs 405 et 440 px : c'est
 * la plage 900-1200 jamais arbitrée du chantier. Les deux noms s'y empilent
 * en colonne étroite, et le pied de page y est très haut. MESURÉ : la règle
 * appliquée là retire 160 px à CHACUNE des cinq pages à 950 et pousse le
 * texte hors de sa colonne. Elle est donc tenue au-dessus de 1200, où la
 * colonne a sa vraie largeur. Le jour où la plage 900-1200 sera arbitrée,
 * cette limite sera à revoir en même temps que le reste du pied de page.
 */
@media (min-width: 75rem) {
  .site-footer__pages a,
  .site-footer__pages .site-footer__current {
    white-space: nowrap;
  }
}

/*
 * ⚠ LINKEDIN ALLUMÉ — LE DESSIN NE BOUGE PAS D'UN PIXEL.
 *
 * 29 août 2026. Le pictogramme LinkedIn était un « span » en attente
 * d'adresse ; il est devenu un vrai lien. La règle « .compact-nav a » lui a
 * aussitôt donné la cible de 2,75 rem que le site réserve aux liens du menu
 * — et comme elle l'emporte en spécificité sur « .compact-nav__pending »,
 * la boîte est passée de 21 à 44 px de large. MESURÉ : le pictogramme
 * partait 11,5 px à gauche sur les cinq pages en bureau, et 9,5 px en
 * mobile, la rangée étant calée à droite.
 *
 * Les deux règles ci-dessous rendent le dessin exactement à ce que Florian a
 * validé, ET gardent la cible : la boîte reprend la taille du pictogramme,
 * et la cible de 44 px est portée par un pseudo-élément centré sur lui, qui
 * ne prend aucune place dans la mise en page. C'est le procédé des filtres
 * de Réalisations et des boutons de 02-6, employé ici pour la troisième
 * fois.
 *
 * ⚠ LE JOUR OÙ BEHANCE OU WHATSAPP SE RÉVEILLERONT, RELIRE CECI. Ils
 * dorment aujourd'hui, LinkedIn est donc seul dans sa rangée et sa cible ne
 * peut rien recouvrir. À deux pictogrammes, l'écart est de 28,8 px en
 * bureau — 8 px sous 1200 — pour des cibles de 44 : elles se
 * chevaucheraient, et on toucherait l'une en visant l'autre. C'est
 * exactement l'écueil décrit au registre des écarts pour les liens en plein
 * texte. À rejuger à ce moment-là, pas avant.
 */
.compact-nav a.compact-nav__pending {
  min-width: 0;
  min-height: 0;
}

.compact-nav a.compact-nav__pending::after,
.site-footer__socials a::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.75rem;
  height: 2.75rem;
  transform: translate(-50%, -50%);
}

.compact-nav a.compact-nav__pending,
.site-footer__socials a {
  position: relative;
}

/*
 * « Retour en haut ». Le rail est une boîte de hauteur nulle, donc sans
 * encombrement, placée en tête de <main> et rendue collante juste au-dessus du
 * bas de la fenêtre. Le lien est accroché sous elle, ce qui met son bas à
 * 28 px du bas de la fenêtre. Quand le rail atteint le bas de <main> — c'est-
 * à-dire le bas du pictogramme ZZ — il s'y arrête, et le lien avec lui : la
 * flèche ne descend jamais dans le footer. Aucun JavaScript n'intervient.
 */
.rail-retour {
  position: sticky;
  z-index: 20;
  top: calc(100dvh - 28px);
  height: 0;
}

.back-to-top {
  position: absolute;
  right: max(28px, calc((100% - var(--layout-content-max)) / 2 + 28px));
  /*
   * Le disque visible ne remplit pas le carré : il occupe 88 % du dessin. Ces
   * 3 px replacent son bas là où la maquette l'attend — à 28 px du bas de la
   * fenêtre en vol, et sur le bas du pictogramme ZZ une fois à la butée.
   */
  bottom: -3px;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  transition: opacity var(--transition-fast), visibility var(--transition-fast);
}

.back-to-top img {
  width: 43px;
  height: 43px;
}

.js .back-to-top {
  visibility: hidden;
  opacity: 0;
}

.js.has-scrolled .back-to-top {
  visibility: visible;
  opacity: 1;
}

/* ==========================================================================
 * Header au survol
 *
 * Une fois l'ouverture passée, le header n'est plus à l'écran. Amener le
 * pointeur tout en haut fait redescendre une copie exacte du header compact,
 * posée PAR-DESSUS la page : rien n'est déplacé, rien ne se recompose. Elle
 * remonte dès que le pointeur s'en éloigne, ou dès qu'un lien a été cliqué.
 *
 * Le panneau n'ajoute aucune fonction : tout ce qu'il contient reste
 * atteignable par le footer et par la flèche de remontée. Sans JavaScript il
 * n'existe pas, et rien n'est perdu (P3 Partie 5 § 22).
 *
 * L'ombre est le seul endroit de la page où une ombre porte de l'information
 * plutôt que de décorer. Elle fait deux choses : elle distingue ce panneau
 * temporaire du vrai header de 02-1, qui n'en a pas ; et elle détache son bord
 * inférieur quand il passe au-dessus du pavé orange de 02-4, où sa bande
 * orange se confondrait sans elle.
 * ========================================================================== */

.panneau-header {
  position: fixed;
  z-index: 900;
  top: 0;
  right: 0;
  left: 0;
  visibility: hidden;
  box-shadow: 0 6px 16px rgb(21 21 21 / 12%);
  transform: translateY(-100%);
  /* Ce qui se retire ne doit jamais faire attendre : plus court au retour. */
  transition:
    transform 180ms ease-in,
    visibility 0s linear 180ms;
}

.panneau-header.est-ouvert {
  visibility: visible;
  transform: translateY(0);
  transition:
    transform 240ms var(--courbe-arrivee),
    visibility 0s linear;
}

.panneau-header__blanc {
  height: 110px;
  display: grid;
  place-items: center;
  background: var(--color-white);
}

.panneau-header__marque {
  width: min(440px, calc(100% - 3rem));
  display: block;
  /* La même réduction que le logo du header à l'état compact. */
  transform: scale(0.62);
}

.compact-nav--panneau {
  position: static;
  height: 56px;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* ==========================================================================
 * Réduction des animations — P3 Partie 5 § 19-20
 *
 * Les mouvements sont supprimés, jamais les contenus : tout se présente alors
 * directement dans son état final, plutôt que d'être joué très vite. La
 * métamorphose de l'ouverture fait exception : elle ne « joue » pas, elle suit
 * la position de la page, et la neutraliser figerait le header dans un état
 * qui ne correspondrait à rien.
 * ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
  }

  /*
   * Les quatre arrivées se présentent directement dans leur état final : la
   * progression est forcée à 1, ce qui annule d'un coup déplacement et flou.
   * Les contenus sont supprimés nulle part, seuls les mouvements le sont.
   */
  .js .method,
  .js .domains,
  .js .audiences,
  .js .project {
    --a: 1;
  }

  .js .method-card,
  .js .domain-card,
  .js .audience-panel__content,
  .js .project__colonne {
    filter: none;
    will-change: auto;
  }

  .js .audiences__pave::before,
  .js .carousel__panels,
  .js .carousel__controls {
    translate: none;
    opacity: 1;
  }

  .js .audience-panel[data-position="avant"] .audience-panel__content,
  .js .audience-panel[data-position="apres"] .audience-panel__content {
    transform: translateY(-50%);
  }
}


@media (max-width: 75rem) {
  .compact-nav__inner {
    padding-inline: 1rem;
  }

  .method-grid {
    width: 504px;
    grid-template-columns: repeat(2, 236px);
    justify-content: center;
    gap: 48px 32px;
  }

  .method-card {
    min-height: auto;
  }

  .audiences__inner {
    grid-template-columns: 8rem 1fr;
  }
}

/* Réorganisation de sécurité avant les arbitrages graphiques mobiles de P4.3. */
@media (max-width: 52rem) {
  .domains-grid,
  .site-footer__inner {
    grid-template-columns: 1fr;
  }

  /* Repli de sécurité de 02-5 avant P4.3 : le portrait passe au-dessus. */
  .trust__inner {
    flex-direction: column;
    gap: 2rem;
  }

  .trust__portrait-frame {
    width: 100%;
    aspect-ratio: 697 / 1481;
  }

  .trust__content {
    max-width: none;
    padding-block: 2rem;
  }

  .compact-nav__pages {
    gap: 1rem;
  }

  .compact-nav__socials {
    gap: 0.5rem;
  }

  .method-grid {
    width: 236px;
    grid-template-columns: 236px;
    justify-content: center;
  }

  .audiences__inner {
    grid-template-columns: 1fr;
  }

  /*
   * Repli de sécurité avant P4.3 : le calage desktop de 02-4 est entièrement
   * absolu, il faut donc le désarmer explicitement — position, transform et
   * largeur comprises — sans quoi le titre resterait décalé d'une demi-hauteur
   * et le binôme accroché au bloc oblique.
   */
  .audiences h2 {
    position: static;
    width: auto;
    font-size: clamp(4rem, 20vw, 8rem);
    line-height: 1;
    white-space: normal;
    transform: none;
  }

  .section-link--section-transition.audiences__section-link {
    position: static;
    grid-column: 1;
    transform: none;
  }

  .carousel {
    margin-left: 0;
  }

  .audience-panel {
    padding-inline: 2rem;
  }

  .audience-panel__shape {
    clip-path: polygon(4% 0, 100% 0, 96% 100%, 0 100%);
  }

  .site-footer__legal {
    grid-column: 1;
  }

  .site-footer__identity {
    padding-right: 0;
    padding-bottom: 1.5rem;
    border-right: 0;
    border-bottom: 1px solid var(--color-blue-gray);
  }

  .site-footer__legal {
    flex-direction: column;
    align-items: flex-start;
  }

  .site-footer__legal p {
    margin-left: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  [data-parallax] {
    transform: none !important;
  }
}


/* ==========================================================================
 * P4.3 — COMPOSITION MOBILE
 *
 * Bascule unique à 900 px : en dessous, la composition mobile de la maquette
 * v3 (390 x 560 pour l'ouverture, 390 x 6083 pour la page) ; au-dessus, la
 * composition desktop validée le 23 août, à laquelle on ne touche pas.
 *
 * Rien de ce qui suit ne s'applique au-dessus de 900 px, à une exception près,
 * volontaire : la protection de « hidden » ci-dessous, qui vaut partout.
 * ========================================================================== */

/*
 * « hidden » doit rester plus fort que tout affichage déclaré ailleurs.
 * Sans cette règle, un « display: flex » posé sur un porte-icône écrase
 * l'attribut : l'icône disparaît à l'oeil mais garde sa place, et
 * l'alignement des icônes restantes est faux. Behance dans le menu et
 * WhatsApp dans le footer sont dans ce cas : ils sont construits, puis
 * masqués tant que l'URL et le numéro n'existent pas.
 */
[hidden] {
  display: none !important;
}

@media (max-width: 899px) {
  :root {
    /* Marge latérale relevée sur la maquette v3 : 20 px de chaque côté. */
    --mob-marge: 20px;
    /* Largeur de la colonne de contenu, plafonnée au-delà du téléphone. */
    --mob-colonne: min(calc(100% - 2 * var(--mob-marge)), 560px);
    /*
     * Largeur de la bande des carrousels : la colonne plafonnée, plus ses
     * deux marges. En unités de fenêtre et non en pourcentage : un
     * pourcentage dans une variable se résout là où on l'emploie, donc contre
     * la colonne de texte, ce qui rétrécirait la bande au lieu de l'élargir.
     */
    --mob-bande: min(100vw, 600px);
    --mob-bandeau: 76px;
    --mob-blanc-ouverture: 118px;
    --mob-logo-ouverture: 279px;
    --mob-logo-compact: 160px;
    --mob-menu: 53px;
    /* Le seuil de bascule du bandeau, unique et réversible. */
    --mob-seuil: 40px;
  }

  /*
   * Ici se trouvait « html { overflow-x: clip } », posé le 24 août par
   * précaution contre les 100vw des bandes défilantes.
   *
   * Retiré le même jour. La précaution était inutile — aucun débordement
   * horizontal n'est mesuré entre 320 et 1200 px, les deux bandes étant
   * plafonnées par --mob-bande — et elle n'était pas gratuite : une racine
   * dont le débordement n'est plus « visible » devient une boîte de
   * défilement, et iOS ne pilote alors plus tout à fait la page de la même
   * façon. C'est l'un des deux suspects du défilement animé qui sautait sur
   * l'iPhone de Florian.
   */

  /*
   * Toute cible d'ancre doit se poser SOUS le bandeau fixe, sinon celui-ci
   * recouvre le titre visé.
   */
  [id] {
    scroll-margin-top: calc(var(--mob-bandeau) + 12px);
  }

  /* ------------------------------------------------------------------ *
   * 01 — Écran d'ouverture
   *
   * Plus de métamorphose continue : sur mobile l'ouverture est un écran, et
   * le bandeau compact est un objet distinct, posé par-dessus la page dès que
   * l'on défile. Toutes les cotes desktop pilotées par --p sont donc
   * remplacées par des valeurs fixes.
   *
   * « svh » et non « vh » : c'est la fenêtre réellement visible, barres du
   * navigateur comprises. Avec « vh », le binôme du bas passerait sous la
   * barre de Safari, exactement le défaut relevé sur la maquette v1.
   * ------------------------------------------------------------------ */
  .site-header {
    /*
     * La hauteur est un plancher, pas une consigne : sur un écran étroit le
     * texte prend une ligne de plus et l'ouverture doit pouvoir s'allonger
     * plutôt que rogner le binôme. C'est la règle de P4.0 § 3.3, appliquée
     * ici à l'horizontale : ce qui manque, c'est de la place, pas du souffle.
     */
    height: auto;
    min-height: max(560px, 100svh);
    display: grid;
    overflow: visible;
  }

  .site-header__stage {
    position: static;
    height: auto;
    /*
     * « min-content » et non « 0 » : la rangée orange ne descend jamais sous
     * la hauteur de ce qu'elle contient. Sans cela, elle resterait à la
     * hauteur de la fenêtre et le binôme sortirait par le bas.
     */
    grid-template-rows: var(--mob-blanc-ouverture) minmax(min-content, 1fr);
  }

  .brand-link {
    width: var(--mob-logo-ouverture);
    transform: none;
  }

  .site-header__orange {
    overflow: visible;
  }

  /*
   * L'orange est une colonne : le texte prend la hauteur restante et s'y
   * centre, le binôme reste calé en bas. Sur un écran plus haut que 560 px,
   * seul le blanc entre les deux s'ouvre — ni le bandeau, ni le binôme, ni
   * les corps de texte ne bougent.
   */
  .hero-content {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    opacity: 1;
  }

  .hero-content__copy {
    position: static;
    width: var(--mob-colonne);
    margin-inline: auto;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    /*
     * Le pavé n'est pas exactement au milieu sur la maquette : il descend de
     * 5 px. Une réserve haute déplace le centrage de la moitié, ce qui garde
     * l'écart constant quand l'écran s'allonge.
     */
    padding-top: 10px;
    transform: none;
  }

  .hero-content h1 {
    max-width: none;
    /* 37 px d'encre entre les deux paragraphes sur la maquette v3. */
    margin-bottom: 23px;
    font-size: 22.5px;
    line-height: 29px;
  }

  .hero-content__copy > p {
    max-width: none;
    font-size: 19.5px;
    line-height: 26px;
  }

  .hero-content__next {
    position: static;
    margin: 0 auto 22px;
    transform: none;
  }

  /* Le menu compact du header desktop n'a plus lieu d'être : c'est le
     bandeau fixe qui porte la navigation. */
  .site-header .compact-nav {
    display: none;
  }

  /* ------------------------------------------------------------------ *
   * Bandeau fixe et menu burger
   *
   * Le même élément que le panneau de survol du desktop, réemployé : il est
   * déjà fixe, déjà posé par-dessus la page, déjà escamoté hors écran quand
   * il n'a rien à faire. Sur mobile il descend au seuil de défilement au lieu
   * de descendre au pointeur.
   * ------------------------------------------------------------------ */
  .panneau-header__blanc {
    height: var(--mob-bandeau);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-inline: var(--mob-marge);
  }

  .panneau-header__marque {
    width: var(--mob-logo-compact);
    /* Le logo n'est pas centré sur la hauteur du bandeau : il descend de 3 px. */
    margin-top: 5px;
    transform: none;
  }

  .burger {
    width: 48px;
    height: 48px;
    /*
     * La zone tactile déborde le dessin ; le dessin, lui, fait 41 x 35.
     * Comme le logo, le burger n'est pas centré sur la hauteur du bandeau :
     * il descend de 2 px.
     */
    margin: 4px -2px 0 0;
    padding: 0;
    display: grid;
    place-content: center;
    gap: 11.5px;
    border: 0;
    background: none;
    color: var(--color-anthracite);
    cursor: pointer;
  }

  .burger__trait {
    width: 41px;
    height: 4px;
    display: block;
    border-radius: 2px;
    background: currentColor;
    transition:
      transform var(--transition-fast),
      opacity 120ms ease;
  }

  /* Ouvert, les trois traits deviennent la croix de la maquette. */
  .panneau-header.menu-ouvert .burger__trait:nth-child(1) {
    transform: translateY(15.5px) rotate(45deg);
  }

  .panneau-header.menu-ouvert .burger__trait:nth-child(2) {
    opacity: 0;
  }

  .panneau-header.menu-ouvert .burger__trait:nth-child(3) {
    transform: translateY(-15.5px) rotate(-45deg);
  }

  /* La bande orange n'existe que menu ouvert. */
  .compact-nav--panneau {
    height: 0;
    overflow: hidden;
    transition: height var(--duree-panneau) var(--courbe-arrivee);
  }

  .panneau-header.menu-ouvert .compact-nav--panneau {
    height: var(--mob-menu);
  }

  /*
   * L'espacement du menu, resserré le 27 août à la demande de Florian.
   *
   * Le desktop écarte les entrées de 3,25 rem parce qu'il a 1 200 px ; le
   * mobile en a 350, et sur une page qui affiche AUSSI la page courante il y
   * a trois mots à loger, pas deux. Mesuré à 390 px : « Présentation »,
   * « Réalisations » et « Contact » font 266 px à eux seuls, et les deux
   * écarts de 40 px portaient le tout à 346 pour une colonne de 350 — le
   * pictogramme LinkedIn était alors comprimé à ZÉRO et sortait de l'écran.
   *
   * Les trois noms de page tiennent en un mot : ils n'ont pas besoin de plus
   * que la valeur d'une espace ou deux pour se distinguer.
   */
  .compact-nav__inner {
    width: 100%;
    padding-inline: var(--mob-marge);
    gap: 12px;
  }

  .compact-nav__pages {
    gap: 14px;
    /* Les mots ne se coupent pas : c'est l'écart qui cède, jamais le nom. */
    flex-wrap: nowrap;
  }

  /*
   * Sans quoi le bloc des pictogrammes est le seul à céder, et le flex le
   * comprime jusqu'à zéro : le pictogramme reste dans le balisage, garde son
   * rang dans l'ordre de tabulation, et n'est plus visible nulle part. C'est
   * exactement ce qui se passait sur Réalisations.
   */
  .compact-nav__socials {
    gap: 1.25rem;
    flex-shrink: 0;
  }

  /*
   * Sous 391 px, le corps des entrées se réduit avec la fenêtre plutôt que de
   * chasser le pictogramme. C'est une sécurité contre le débordement, pas un
   * arbitrage graphique — le même procédé que le grand titre de 02-6 sous
   * 1 200 px. À 390 px et au-delà, la cote de la maquette est intacte : 18 px (vérifié).
   */
  .compact-nav a {
    font-size: clamp(14px, 4.7vw, 18px);
  }

  /*
   * La page courante garde le gras — c'est lui qui dit « vous êtes ici » —
   * mais son corps suit celui des deux autres entrées au lieu de rester à
   * 20 px fixes : sur 350 px de colonne, trois mots dont un plus gros ne
   * laissaient pas la place du pictogramme. À 385 px et au-delà, elle vaut
   * toujours 20 px, la cote du desktop.
   */
  .compact-nav__current {
    font-size: clamp(15.5px, 5.2vw, 20px);
  }

  /*
   * Behance quitte le menu sur téléphone : il vit dans le footer, où Florian
   * l'a placé le 27 août. Le menu mobile n'a plus la largeur de l'accueillir —
   * 19 px de libre à 390 px, pour 45 demandés — et le lui rendre reprendrait
   * la place de LinkedIn, qu'on vient justement de récupérer.
   *
   * « display: none » et non « hidden » : l'attribut dit « cette ressource
   * n'existe pas encore », la règle dit « pas à cette largeur ». Les deux
   * informations sont distinctes et doivent le rester. Sur ordinateur, Behance
   * reste dans le menu ET dans le footer, comme LinkedIn.
   */
  .compact-nav [data-behance] {
    display: none;
  }

  .compact-nav--panneau .compact-nav__inner {
    height: var(--mob-menu);
  }

  .compact-nav img {
    height: 26px;
  }

  /* ------------------------------------------------------------------ *
   * Les sections ne font plus une hauteur d'écran
   *
   * En desktop, chaque section occupe la fenêtre entière : c'est la structure
   * de la maquette v4. En mobile, la maquette v3 est une page continue, et
   * toutes les sections sont plus hautes que l'écran de toute façon. Forcer
   * une hauteur de fenêtre n'ajouterait que du vide.
   * ------------------------------------------------------------------ */
  .section {
    min-height: 0;
  }

  /*
   * Les binômes de transition sont retirés — décision de Florian du 24 août :
   * ils servent quand une section tient exactement dans l'écran et qu'il faut
   * dire qu'il y a une suite. Ici le contenu coupé au bas de l'écran le dit
   * tout seul. Celui de l'ouverture, lui, reste : c'est le seul écran qui se
   * termine pile.
   */
  main .section-link--section-transition {
    display: none;
  }

  /* ------------------------------------------------------------------ *
   * 02-1 — Présentation générale
   *
   * Une colonne, au fil. Corps en 17 / 28 : le pas de 28 px est celui de la
   * maquette, et 17 px est la seule taille qui reproduise ses neuf lignes de
   * premier paragraphe avec les mêmes coupures.
   * ------------------------------------------------------------------ */
  .presentation__inner {
    /*
     * 122 px d'encre au-dessus du premier paragraphe et 73 px de fond sous le
     * dernier, sur la maquette. Les réserves valent 7 et 8 px de moins : la
     * boîte d'une ligne dépasse son encre.
     */
    padding-block: 115px 52px;
    display: block;
  }

  .prose {
    max-width: none;
    margin: 0;
    font-size: 17px;
    line-height: 28px;
  }

  .content-shell {
    width: var(--mob-colonne);
    padding-inline: 0;
  }

  /* ------------------------------------------------------------------ *
   * 02-2 — La méthode, en carrousel
   *
   * Les quatre étapes deviennent une bande qui glisse au doigt. Le calage
   * est celui de la maquette v3 : chaque panneau fait 290 px, ils sont
   * espacés de 30, et le panneau courant se pose à 40 px du bord gauche —
   * ce qui laisse voir 30 px du suivant, à droite. C'est ce fragment visible
   * qui dit qu'il y a une suite, bien plus sûrement que les pastilles.
   *
   * Aucune bibliothèque : « scroll-snap » fait tout le travail, le glissement
   * est celui du navigateur, et la page reste utilisable sans JavaScript —
   * la bande défile alors à la main, simplement sans pastilles.
   * ------------------------------------------------------------------ */
  .method__inner {
    /*
     * 84 px de réserve pour 97 px d'encre au-dessus du numéro : la boîte
     * d'une ligne dépasse son encre de 13 px à cette taille. En bas, les
     * 101 px qui séparent toutes les sections de la maquette.
     */
    padding-block: 84px 101px;
    display: block;
  }

  /*
   * La bande sort de la colonne de contenu : elle occupe toute la largeur de
   * l'écran, sans quoi le panneau suivant ne pourrait pas être amorcé au ras
   * du bord droit.
   */
  .method-grid {
    /*
     * La bande sort de la colonne de texte, mais pas indéfiniment : au-delà
     * du téléphone elle se plafonne comme la colonne et reste calée sur elle
     * — le panneau commence 20 px à l'intérieur du texte, exactement comme
     * sur la maquette, quelle que soit la largeur.
     */
    width: var(--mob-bande);
    max-width: none;
    margin-inline: calc(50% - var(--mob-bande) / 2);
    display: flex;
    /*
     * Explicite, et pas par défaut : les replis de sécurité du 22 août posent
     * « justify-content: center » sur cette même grille. Centré, un contenu
     * plus large que sa boîte déborde des DEUX côtés — le premier panneau
     * part en négatif et devient inatteignable au défilement.
     */
    justify-content: flex-start;
    gap: 30px;
    /*
     * 40 px de calage à gauche, 60 à droite : 40 + 290 + 60 = 390. Le dernier
     * panneau peut donc venir se poser au même endroit que le premier.
     */
    padding-inline: 40px 60px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline-start: 40px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .method-grid::-webkit-scrollbar {
    display: none;
  }

  .method-card {
    width: 290px;
    flex: 0 0 290px;
    scroll-snap-align: start;
  }

  /*
   * Assombrissement des panneaux voisins — décision de Florian du 24 août.
   * --voisin vaut 0 pour le panneau en place et 1 pour celui qui est à une
   * pleine largeur de là ; le script l'écrit à chaque image du glissement,
   * si bien que l'assombrissement se dissipe à mesure que le panneau arrive
   * et revient quand il s'écarte. Sans JavaScript, tout reste clair.
   */
  .js .method-card {
    filter: brightness(calc(1 - 0.15 * var(--voisin, 0)));
  }

  .method-card__heading {
    width: 100%;
    line-height: 1;
  }

  .method-card__number {
    font-size: 74px;
    line-height: 74px;
    transform: none;
  }

  .method-card__title {
    font-size: 47px;
    line-height: 44px;
    transform: none;
  }

  .method-card__rule {
    width: 100%;
    margin: 19px 0 23px;
    transform: none;
  }

  .method-card__body {
    width: 100%;
    height: 259px;
    padding: 21px;
    transform: none;
  }

  .method-card__body p {
    font-size: 17px;
    line-height: 26px;
  }

  /* Les pastilles, communes aux deux carrousels. */
  .carousel-pastilles {
    /* 37 px entre le bas du panneau et le centre de la rangée. */
    margin: 29px 0 0;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 41px;
  }

  .carousel-pastille {
    width: 14px;
    height: 14px;
    /* La zone tactile fait 48 px de haut sans que le dessin change. */
    margin-block: -17px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--color-blue-gray);
    box-sizing: content-box;
    border-block: 17px solid transparent;
    background-clip: content-box;
    cursor: pointer;
    transition:
      background-color var(--transition-fast),
      transform var(--transition-fast);
  }

  .carousel-pastille[aria-current="true"] {
    background-color: var(--color-orange);
    /* 17 px au lieu de 14, comme sur la maquette. */
    transform: scale(1.21);
  }

  /* ------------------------------------------------------------------ *
   * 02-3 — Domaines d'intervention
   *
   * Le montage passe du bandeau 2880 x 730 au carré 390 x 390 recomposé par
   * Florian : ce n'est pas la même image redimensionnée, c'est un autre
   * cadrage, et c'est « picture » qui en décide. En dessous, le filet
   * vertical et les trois entrées, puis le bouton.
   * ------------------------------------------------------------------ */
  .supports-montage {
    width: var(--mob-bande);
    max-width: none;
    margin-inline: auto;
  }

  .supports-montage img {
    /*
     * Les attributs de l'image imposent le rapport du bandeau desktop tant
     * que le fichier n'est pas chargé. Sans cette ligne, la page réserverait
     * une bande de 99 px puis sauterait à 390 dès l'arrivée du carré.
     */
    aspect-ratio: 1 / 1;
  }

  .domains {
    display: block;
  }

  .domains__inner {
    padding-block: 36px 100px;
    display: block;
  }

  /*
   * Le filet et le retrait du texte reprennent les cotes de la maquette : le
   * trait au ras de la colonne, le texte 22 px plus loin. Les bornes
   * proportionnelles du desktop — marge minimale, décalage — n'ont plus lieu
   * d'être sur une seule colonne.
   */
  .domains-list {
    --marge-mini: 0px;
    --decalage: 0px;
    width: auto;
    margin: 0;
    padding-left: 22px;
    /* Le filet descend 17 px sous la dernière encre. */
    padding-bottom: 13px;
  }

  .domain-card {
    padding-top: 8px;
  }

  /* 20 px entre le haut du filet et la première encre, sur la maquette. */
  .domain-card:first-child {
    padding-top: 16px;
  }

  .domain-card + .domain-card {
    margin-top: 7px;
  }

  .domain-card h3 {
    font-size: 27px;
    line-height: 24px;
  }

  .domain-card p {
    margin: 6px 0 0;
    font-size: 17px;
    line-height: 26px;
  }

  .domains__inner > .button {
    width: 250px;
    min-height: 61px;
    margin: 36px auto 0;
  }

  /* ------------------------------------------------------------------ *
   * 02-4 — Publics, en carrousel
   *
   * La bande anthracite tient toute la largeur ; les panneaux orange
   * glissent dessus. Le premier panneau est l'accroche « Vous êtes… » :
   * anthracite sur anthracite, il ne se distingue pas du fond, et c'est
   * l'orange du suivant, amorcé à droite, qui dit qu'il y a une réponse.
   *
   * Décision de Florian du 24 août : l'accroche reste dans le carrousel. Le
   * désaccord entre les quatre pastilles et le cartouche « 1 / 3 » se règle
   * par les noms — chaque pastille annonce son contenu, jamais son rang — et
   * le cartouche passe en « aria-hidden », comme le dessin qu'il est.
   *
   * Le calage vient de la maquette v3 : accroche de 289 px, panneaux de 354,
   * espacés de 36, le panneau courant posé à 18 px du bord. L'orange du
   * deuxième panneau apparaît donc à 343 px sur l'écran d'accroche, et le
   * troisième reste hors champ quand le deuxième est en place.
   * ------------------------------------------------------------------ */
  .audiences {
    min-height: 0;
    /* Les 101 px qui séparent toutes les sections de la maquette. */
    padding-bottom: 101px;
    display: block;
  }

  .audiences__pave {
    height: 688px;
  }

  /* Le bloc oblique est une composition de grande largeur : il n'a pas cours. */
  .audiences__pave::before {
    display: none;
  }

  .audiences__inner {
    height: 100%;
  }

  .carousel,
  .carousel__panels {
    height: 100%;
  }

  /*
   * « .js » est nécessaire : la règle de base du carrousel desktop est écrite
   * avec ce préfixe, donc plus forte que le nom de classe seul. Sans lui, les
   * panneaux resteraient empilés en bloc.
   */
  .js .carousel__panels,
  .carousel__panels {
    width: var(--mob-bande);
    margin-inline: calc(50% - var(--mob-bande) / 2);
    display: flex;
    justify-content: flex-start;
    gap: 36px;
    padding-inline: 18px 18px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline-start: 18px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .carousel__panels::-webkit-scrollbar {
    display: none;
  }

  /*
   * L'accroche : premier panneau, sans fond, calée en hauteur sur la bande.
   * Le titre et son invite de glissement forment un seul groupe, centré
   * ensemble — c'est ce que montre la maquette du 24 août, où le titre est
   * remonté de 22 px pour faire place au libellé.
   */
  .audiences__accroche {
    width: 289px;
    flex: 0 0 289px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0 0 20px 18px;
    scroll-snap-align: start;
  }

  .audiences h2 {
    position: static;
    z-index: auto;
    /*
     * « max-content » et « nowrap » explicites : le repli de sécurité du
     * 22 août pose « white-space: normal » sur ce titre, et la colonne de
     * l'accroche est plus étroite que « êtes… ». Sans ces deux lignes, les
     * points de suspension partent seuls à la ligne.
     */
    width: max-content;
    margin: 0;
    padding: 0;
    font-size: 110px;
    line-height: 110px;
    white-space: nowrap;
    transform: none;
  }

  /* ------------------------------------------------------------------ *
   * L'invite de glissement
   *
   * Quatrième famille d'effet, et la seule qui ne réponde pas à un geste.
   * L'exception est assumée : ce n'est pas une décoration, c'est ce qui
   * enseigne le geste. Elle s'arrête donc dès que la bande a glissé une
   * fois — une invitation qui réclame une action déjà faite devient une
   * nuisance —, et le chevron reste alors en place, immobile, comme repère.
   * ------------------------------------------------------------------ */
  .invite-glisser {
    --course: 26px;
    margin: 20px 0 0;
    padding-left: 10px;
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--color-white);
    font-size: 17px;
    line-height: 20px;
  }

  .invite-glisser__chevron {
    width: 24px;
    height: 20px;
    flex: none;
    display: block;
    fill: currentColor;
    animation: invite-glisser 1900ms var(--courbe-arrivee) infinite;
  }

  /* Dans les cartouches : le chevron dit qu'il reste une fiche à gauche. Il
     n'est pas posé sur la dernière, où il mentirait. */
  .audience-panel__counter {
    position: relative;
  }

  .audience-panel__chevron {
    --course: 9px;
    position: absolute;
    top: 50%;
    left: calc(100% + 6px);
    margin-top: -10px;
    display: block;
    color: var(--color-white);
  }

  /* La bande a glissé : l'invite a fait son travail. */
  [data-deja-glisse] .invite-glisser__chevron {
    animation: none;
  }

  /*
   * Assombrissement des panneaux voisins, comme en 02-2 : --voisin vaut 0
   * pour celui qui est en place et 1 pour celui qui est à une pleine largeur
   * de là. Sur l'accroche anthracite, l'effet est discret ; sur l'orange, il
   * se voit — c'est là qu'il sert.
   */
  .js .audiences h2,
  .js .audience-panel {
    filter: brightness(calc(1 - 0.15 * var(--voisin, 0)));
  }

  .audience-panel {
    width: 354px;
    flex: 0 0 354px;
    /* Le repli de sécurité du 22 août pose 2 rem de garde interne : à
       reprendre ici, sinon la colonne de texte est décalée de 32 px. */
    padding: 0;
    background: var(--color-orange);
    scroll-snap-align: start;
  }

  /*
   * Les trois panneaux coexistent : la mise en réserve du desktop, qui
   * n'affiche que le panneau courant, n'a plus lieu d'être.
   */
  .js .audience-panel[data-position] .audience-panel__content {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: none;
  }

  .audience-panel__content {
    position: static;
    width: auto;
    padding: 28px 22px 0 24px;
    transform: none;
  }

  .audience-panel__counter {
    margin-left: -2px;
    font-size: 18px;
    line-height: 28px;
  }

  .audience-panel h3 {
    margin: 0 0 21px;
    font-size: 33.5px;
    line-height: 38px;
  }

  .audience-panel__rule {
    margin: 0 0 10px;
  }

  .audience-panel p:not(.audience-panel__counter) {
    font-size: 17px;
    line-height: 26px;
  }

  /* Les flèches sont une commande de pointeur : au doigt, ce sont les
     pastilles et le glissement. */
  .js .carousel__controls {
    display: none;
  }

  .audiences .carousel-pastilles {
    margin-top: 29px;
  }

  /* ------------------------------------------------------------------ *
   * 02-5 — Pourquoi faire confiance
   *
   * Le portrait passe au-dessus, pleine largeur, dans son cadrage mobile ;
   * le bloc orange vient dessous. La composition en deux colonnes du desktop,
   * avec ses réserves proportionnelles et ses deux respirations, n'a plus
   * lieu d'être : c'est une colonne unique, au fil.
   * ------------------------------------------------------------------ */
  .trust {
    min-height: 0;
    /*
     * 100 px entre le bas du bloc orange et l'encre du grand titre de 02-6 ;
     * la boîte de ce titre dépasse son encre de 18 px vers le haut.
     */
    padding-bottom: 82px;
    display: block;
  }

  /* Les deux respirations du desktop sont des enfants de flex : sans flex,
     elles n'ont plus d'objet. */
  .trust::before,
  .trust::after {
    display: none;
  }

  .trust__inner {
    width: 100%;
    margin: 0;
    display: block;
    gap: 0;
  }

  .trust__portrait-frame {
    width: var(--mob-bande);
    margin-inline: auto;
    aspect-ratio: 390 / 444;
    overflow: hidden;
  }

  /*
   * Le recadrage du desktop — image sortie de sa boîte et agrandie de 33 % —
   * n'a plus de raison d'être : le fichier mobile est déjà cadré.
   */
  .trust__portrait-frame img {
    position: static;
    top: auto;
    left: auto;
    width: 100%;
    height: auto;
    aspect-ratio: 390 / 444;
    object-fit: cover;
  }

  .trust__content {
    width: var(--mob-colonne);
    max-width: none;
    margin-inline: auto;
    padding-block: 35px 70px;
  }

  .trust h2 {
    margin-bottom: 17px;
    font-size: 33.5px;
    line-height: 38px;
  }

  .trust__rule {
    margin: 0 0 11px;
  }

  .trust__content p {
    font-size: 17px;
    line-height: 26px;
  }

  /* ------------------------------------------------------------------ *
   * 02-6 — Vous avez un projet en tête ?
   *
   * Le grand titre passe de 139 à 88 px et garde ses trois lignes ; les
   * boutons se centrent et s'empilent. La composition en deux colonnes du
   * desktop, avec sa respiration élastique entre le bloc et le pictogramme,
   * est désarmée.
   * ------------------------------------------------------------------ */
  .project {
    min-height: 0;
    display: block;
  }

  .project::after {
    display: none;
  }

  .project__inner {
    width: var(--mob-colonne);
    margin-inline: auto;
    padding-left: 0;
    display: block;
  }

  .project h2 {
    max-width: none;
    /*
     * 87 et non 88 : à 88 px, « Vous avez » fait 352 px pour une colonne de
     * 350 et le titre passe à quatre lignes. La maquette, elle, laisse la
     * ligne déborder d'un pixel — ce que le navigateur ne fait pas.
     */
    font-size: 87px;
    line-height: 88.5px;
  }

  .project__colonne {
    padding-top: 38px;
  }

  .project__intro {
    max-width: none;
    margin: 0 0 32px;
    font-size: 19.5px;
    line-height: 28px;
  }

  .project__actions {
    justify-items: center;
    gap: 21px;
  }

  .project__actions .button {
    width: 258px;
    min-height: 48px;
  }

  /* 51 px entre le troisième bouton et les deux premiers, contre 21. */
  .button--detache {
    margin-top: 30px;
  }

  .project__mark {
    width: 83px;
    margin: 97px auto 0;
  }

  /* ------------------------------------------------------------------ *
   * Footer
   *
   * Tout se centre et s'empile. Les points médians qui séparent les liens en
   * desktop n'ont plus d'objet : sur une colonne, c'est le retour à la ligne
   * qui sépare. Les liens sont espacés de 44 px, ce que demandait Florian :
   * une cible de 24 px de haut au minimum réglementaire, et de la place
   * autour pour ne pas viser à côté.
   * ------------------------------------------------------------------ */
  .site-footer {
    /* 32 px entre le bas du pictogramme ZZ et le filet. */
    padding-top: 32px;
    padding-bottom: 55px;
  }

  .site-footer__inner {
    width: var(--mob-colonne);
    padding-top: 32px;
    display: block;
    text-align: center;
  }

  .site-footer__identity {
    padding: 0;
    border: 0;
  }

  .site-footer__name,
  .site-footer__identity > p:last-child,
  .site-footer__nav,
  .site-footer__contact,
  .site-footer__legal {
    text-align: center;
  }

  .site-footer__milieu {
    padding-top: 41px;
  }

  .site-footer__nav {
    flex-direction: column;
    align-items: center;
    gap: 20px;
  }

  /* Le point médian sépare une ligne ; il ne sépare pas deux lignes. */
  .site-footer__sep {
    display: none;
  }

  .site-footer__contact {
    margin-top: 20px;
    flex-direction: column;
    align-items: center;
    gap: 31px;
  }

  /* Florian les a grossis et espacés : 25 px au lieu de 17, 19 d'écart. */
  .site-footer__socials {
    gap: 19px;
  }

  .site-footer__socials img {
    width: 25px;
    height: 25px;
  }

  .site-footer__legal {
    padding-top: 59px;
  }

  .site-footer__pages {
    margin: 25px 0 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 23px;
  }

  /* ------------------------------------------------------------------ *
   * Aucune arrivée de section
   *
   * Décision de Florian du 24 août : trois familles d'effet, pas une de plus.
   * Les sections sont donc simplement en place. Le script retire la valeur
   * qu'il écrivait en ligne, sans quoi elle l'emporterait sur celle-ci.
   * ------------------------------------------------------------------ */
  .js .method,
  .js .domains,
  .js .audiences,
  .js .project {
    --a: 1;
  }

  .js .domain-card {
    filter: none;
  }

  /* ------------------------------------------------------------------ *
   * Flèche de remontée
   *
   * Le disque visible n'occupe que 88 % du dessin : une boîte de 44 px laisse
   * donc voir un disque de 38, exactement ce que dessine la maquette v3, et
   * offre la zone tactile de 44 px que réclame le doigt. Rien à changer au
   * dessin : ce sont les marges qui passent de 28 à 20 px.
   *
   * « svh » et non « dvh » : la barre basse de Safari va et vient au
   * défilement ; avec « dvh » la flèche remonterait et redescendrait avec
   * elle. Calée sur la petite fenêtre, elle reste toujours atteignable.
   * ------------------------------------------------------------------ */
  /*
   * En desktop, le rail est collant et s'arrête au bas de <main>, pour que la
   * flèche ne passe pas devant le footer. La maquette mobile la place au
   * contraire en bas à droite de l'écran jusqu'au bout de la page, y compris
   * devant le footer — où elle ne recouvre rien, la colonne de texte étant
   * centrée. Elle est donc simplement fixe.
   */
  .rail-retour {
    position: static;
    top: auto;
  }

  .back-to-top {
    position: fixed;
    /*
     * Le « z-index: 20 » du rail est devenu inopérant en même temps qu'il est
     * passé en « static » : cette propriété est purement et simplement
     * ignorée sur un élément non positionné. Sans elle, la flèche retombait
     * sous toutes les sections qui suivent le rail dans le document et
     * restait enterrée jusqu'au bas de <main> — signalé par Florian le
     * 24 août. Elle porte donc désormais sa propre valeur, qu'elle
     * n'emprunte plus à personne : au-dessus de la page, et bien en dessous
     * des 900 du bandeau fixe et de son menu déroulant.
     */
    z-index: 20;
    top: auto;
    /* 17 px pour la boîte, donc 20 px pour le disque. */
    right: 17px;
    /*
     * En fenêtre normale, le bas fixe est déjà au-dessus de la barre de
     * Safari. « env » ne sert que dans les cas où l'indicateur d'accueil
     * s'invite en dessous.
     */
    bottom: max(17px, env(safe-area-inset-bottom, 0px));
  }
}


/*
 * Le mouvement de l'invite : le chevron glisse vers la gauche jusqu'à la
 * marge, disparaît, et reparaît à sa place d'origine. Décrit par Florian le
 * 24 août. La course est portée par --course, plus longue sur l'accroche que
 * dans les cartouches, où le chevron ne doit pas venir mordre le numéro.
 *
 * Avec « prefers-reduced-motion », la règle générale de réduction ramène
 * l'animation à une seule passe instantanée : le chevron se pose alors sur sa
 * dernière image, c'est-à-dire à sa place et visible. Une relève sans
 * déplacement prend alors le relais — voir plus bas.
 */
@keyframes invite-glisser {
  0%   { transform: translateX(0);                             opacity: 1; }
  55%  { transform: translateX(calc(var(--course, 26px) * -1)); opacity: 1; }
  70%  { transform: translateX(calc(var(--course, 26px) * -1)); opacity: 0; }
  71%  { transform: translateX(0);                             opacity: 0; }
  85%  { transform: translateX(0);                             opacity: 1; }
  100% { transform: translateX(0);                             opacity: 1; }
}


/* ==========================================================================
 * L'invite pour les lecteurs qui refusent le mouvement
 *
 * « Réduire les animations » est une demande à honorer, pas une panne à
 * contourner : le chevron ne doit plus se déplacer d'un seul pixel. Mais
 * l'invite a un travail à faire — dire qu'il reste des fiches à gauche — et
 * un chevron parfaitement immobile ne le fait plus ; il peut même se lire
 * comme un dessin oublié là.
 *
 * Le fondu est la substitution que recommandent les règles d'accessibilité :
 * ce qui déclenche le mal-être, ce sont les déplacements dans le champ de
 * vision, pas les changements d'intensité. Le chevron respire donc sur place,
 * lentement — 2 400 ms contre 1 900, parce qu'une pulsation rapide serait à
 * son tour agressive.
 *
 * Les « !important » ne sont pas un forçage de confort : ils répondent à ceux
 * de la règle générale de réduction, qui ramène sans distinction toute
 * animation à 0,01 ms et une seule passe. Sans eux, cette relève serait
 * éteinte par la règle qu'elle est censée compléter.
 *
 * La coupure « la bande a déjà glissé » est réénoncée telle quelle : une
 * règle de sécurité ne se complète pas, elle se redit — sinon l'invite
 * continuerait de battre après avoir fait son travail.
 * ========================================================================== */

@media (prefers-reduced-motion: reduce) and (max-width: 899px) {
  .invite-glisser__chevron {
    animation-name: invite-respirer !important;
    animation-duration: 2400ms !important;
    animation-timing-function: ease-in-out !important;
    animation-iteration-count: infinite !important;
    transform: none !important;
  }

  [data-deja-glisse] .invite-glisser__chevron {
    animation: none !important;
    opacity: 1;
  }
}

@keyframes invite-respirer {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}


/* ==========================================================================
 * LES DEUX CARROUSELS SUR TABLETTE — 3 septembre 2026
 *
 * ⚠ CE BLOC EST EN FIN DE FEUILLE, ET C'EST VOULU : il reprend la main sur la
 * grande section mobile ci-dessus, à égalité de poids, par sa seule place.
 * Ne pas le remonter.
 *
 * LE DÉFAUT. Les deux bandes s'étiraient jusqu'à 600 px pendant que leurs
 * panneaux gardaient les cotes du téléphone, calés sur le bord GAUCHE : tout
 * le vide tombait à droite. Mesuré à 810 px — l'iPad de Florian en portrait —
 * le panneau courant était 105 à 115 px à gauche du milieu de l'écran, et le
 * suivant se montrait sur 192 à 240 px. L'œil partait le lire en premier.
 *
 * LA CORRECTION. Une seule fenêtre, 500 px, centrée ; le panneau courant
 * centré dedans. La marge intérieure n'est plus un nombre mais la moitié de ce
 * qui reste une fois le panneau posé — la règle vaut donc pour les 354 px des
 * publics comme pour les 290 px de la méthode.
 *
 * ⚠ LA BORNE DE 376 px EST VOULUE : au-dessous, rien ne change, le téléphone
 * de référence garde sa composition validée. Vérifié à 375 et à 320 px.
 *
 * ⚠ ET LE SCRIPT LIT CETTE MARGE, il ne la recopie plus. Voir « calageDe »
 * dans « script.js » : le jour où ces valeurs changent, l'assombrissement des
 * voisins suit tout seul.
 *
 * Mesuré à 600, 810 et 899 px : panneau courant à ZÉRO pixel du centre de
 * l'écran et des pastilles ; amorces de 37 px de chaque côté pour les publics,
 * 75 px pour la méthode ; hauteurs de page inchangées, aucun débordement.
 * ========================================================================== */
@media (min-width: 376px) and (max-width: 899px) {
  :root {
    /* La fenêtre commune aux deux carrousels. Un seul endroit pour la régler. */
    --mob-fenetre: min(var(--mob-bande), 500px);
  }

  .js .carousel__panels,
  .carousel__panels,
  .method-grid {
    width: var(--mob-fenetre);
    margin-inline: calc(50% - var(--mob-fenetre) / 2);
  }

  /*
   * ⚠ LA MARGE INTÉRIEURE SE CALCULE SUR LA FENÊTRE, PAS EN POURCENTAGE.
   * Première écriture, le 3 septembre : « calc((100% - 354px) / 2) ». Or un
   * POURCENTAGE DANS UNE MARGE INTÉRIEURE NE SE RAPPORTE PAS À L'ÉLÉMENT MAIS
   * À SON PARENT — ici la colonne de texte, qui ne fait pas la même largeur
   * que la bande. Mesuré : 103 px au lieu de 73 sur l'iPad, et 10 au lieu de
   * 30 à 414 px. Le résultat semblait juste à 600 px et au-delà parce que la
   * bande se trouvait décalée de 30 px au repos — un accident, pas une règle.
   */
  .js .carousel__panels,
  .carousel__panels {
    padding-inline: calc((var(--mob-fenetre) - 354px) / 2);
    scroll-padding-inline-start: calc((var(--mob-fenetre) - 354px) / 2);
  }

  .method-grid {
    padding-inline: calc((var(--mob-fenetre) - 290px) / 2);
    scroll-padding-inline-start: calc((var(--mob-fenetre) - 290px) / 2);
  }

  /*
   * ⚠ L'ACCROCHE « VOUS ÊTES… » N'EST PAS UN PANNEAU COMME LES AUTRES.
   * Elle fait 289 px quand les trois publics en font 354, et son titre —
   * 280 px de large, à taille FIXE de 110 px — déborde de sa colonne utile de
   * 271 px à cause de la marge intérieure de 18 px. Centrée comme les autres,
   * elle tombait 32 px à gauche du milieu, et le titre 19 px. Elle prend donc
   * la largeur des autres et centre son groupe : titre et invite à zéro pixel
   * du centre, mesuré à 600, 810 et 899 px.
   */
  .audiences__accroche {
    width: 354px;
    flex: 0 0 354px;
    align-items: center;
    padding-left: 0;
  }

  .invite-glisser {
    padding-left: 0;
  }
}
