/* ============================================================
   87seconds — V2 RESPONSIVE · socle
   ------------------------------------------------------------
   Remplace le système « deux canvases mis à l'échelle » (base.css)
   par un vrai responsive : DOM unique, flux naturel, typo fluide.

   Principe de la typo fluide : les deux maquettes Figma (390 et 1440)
   donnent les deux ancres de chaque token. On interpole linéairement
   entre les deux et on borne aux extrémités :

       clamp(<val 390>, calc(<val 390> + <delta> * (100vw - 390px) / 1050), <val 1440>)

   → sous 390px, on garde la valeur mobile ; au-delà de 1440px, on garde
     la valeur desktop (plus d'agrandissement infini).

   Points de rupture (choisis sur le contenu, pas sur des appareils) :
     < 640   téléphone
     ≥ 640   grand téléphone / tablette portrait
     ≥ 900   bascule desktop : nav horizontale, sections en colonnes
     ≥ 1200  confort desktop
   ============================================================ */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body { min-height: 100vh; background: #fff; overflow-x: hidden; font-family: var(--f-alb); color: var(--black); }
/* `height: auto` est indispensable depuis que les <img> portent leurs dimensions
   intrinsèques : sans lui, l'attribut `height` s'impose quand le CSS ne fixe que la
   largeur, et l'image se déforme. Les règles plus spécifiques (`height: 100%` des
   fonds de section, des vignettes...) continuent de primer. */
img, video, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* ---------- Tokens ---------- */
:root {
  --night: #0F1122;
  --cloud: #F4F4FB;
  --black: #000000;
  --ink:   #090909;
  --green: #278B4E;
  /* Fond du formulaire HubSpot, relevé sur le rendu de l'iframe (cross-origin :
     aucune règle d'ici ne peut la lire ni la modifier ; les points d'accès publics de
     HubSpot refusent ce type de formulaire, et le script n'expose aucune couleur côté
     page — vérifié). Depuis la V133 la carte n'a plus de retrait : le formulaire
     l'occupe bord à bord et cette couleur ne se voit plus que dans les quatre coins
     arrondis. Elle n'a donc plus à être exacte au point près, mais elle doit rester
     proche — sinon les coins trahissent l'écart. */
  --form-blue: #9DC1E2;

  --f-display: 'Special Gothic Expanded One', sans-serif;
  /* RÈGLE TYPOGRAPHIQUE : Unbounded ne s'emploie QU'EN CAPITALES. Toute règle qui
     pose `var(--f-unb)` doit donc poser `text-transform: uppercase` — sauf si son
     contenu est purement numérique. Aucun sélecteur CSS ne permet de cibler par
     police : le contrôle se fait au rendu, en parcourant les pages. */
  --f-unb:     'Unbounded', sans-serif;
  --f-alb:     'Albert Sans', sans-serif;

  /* Typographie fluide — ancres : maquette 390 → maquette 1440 */
  --fs-h1:        clamp(42px, calc(42px + 22 * (100vw - 390px) / 1050), 64px);
  --fs-h1-xb:     clamp(42px, calc(42px + 20 * (100vw - 390px) / 1050), 62px);
  --fs-seclabel:  clamp(24px, calc(24px + 12 * (100vw - 390px) / 1050), 36px);
  --fs-catch:     clamp(26px, calc(26px +  9 * (100vw - 390px) / 1050), 35px);
  --fs-catch-b:   clamp(22px, calc(22px + 10 * (100vw - 390px) / 1050), 32px);
  --fs-body:      clamp(20px, calc(20px +  4 * (100vw - 390px) / 1050), 24px);
  --fs-step:      clamp(26px, calc(26px +  6 * (100vw - 390px) / 1050), 32px);
  --fs-statnum:   clamp(40px, calc(40px +  8 * (100vw - 390px) / 1050), 48px);
  --fs-statlab:   clamp(20px, calc(20px +  4 * (100vw - 390px) / 1050), 24px);
  --fs-kpi:       clamp(22px, calc(22px +  5 * (100vw - 390px) / 1050), 27px);
  --fs-desc:      clamp(20px, calc(20px +  7 * (100vw - 390px) / 1050), 27px);
  --fs-97:        clamp(65px, calc(65px + 15 * (100vw - 390px) / 1050), 80px);
  --fs-97-cap:    clamp(26px, calc(26px +  9 * (100vw - 390px) / 1050), 35px);
  --fs-ready:     clamp(34px, calc(34px + 26 * (100vw - 390px) / 1050), 60px);
  --fs-baseline:  clamp(18px, calc(18px +  6 * (100vw - 390px) / 1050), 24px);
  --fs-ui:        clamp(14px, calc(14px +  2 * (100vw - 390px) / 1050), 16px);
  /* Typo de l'en-tête, séparée de --fs-ui qui sert à douze autres endroits :
     l'en-tête doit rétrécir sans emporter les boutons et le pied de page. */
  --fs-nav:       clamp(13px, calc(13px +  1 * (100vw - 390px) / 1050), 14px);
  --fs-small:     clamp(12px, calc(12px +  2 * (100vw - 390px) / 1050), 14px);

  /* Rythme fluide */
  --gutter:   clamp(20px, calc(20px + 98 * (100vw - 390px) / 1050), 118px);
  /* 80 en mobile (et non 50) : avec une capsule-titre remontée de 32px à cheval sur la
     section suivante, un padding de 50 ne laissait que 18px entre le bouton de fin de
     section et la capsule — visuellement étouffé. */
  --sec-pad:  clamp(80px, calc(80px + 20 * (100vw - 390px) / 1050), 100px);
  --gap-lg:   clamp(32px, calc(32px + 118 * (100vw - 390px) / 1050), 150px);
  --gap-md:   clamp(24px, calc(24px + 56 * (100vw - 390px) / 1050), 80px);
  --gap-sm:   clamp(12px, calc(12px + 12 * (100vw - 390px) / 1050), 24px);

  --header-h:  clamp(72px, calc(72px + 78 * (100vw - 390px) / 1050), 150px);
  /* BANDEAUX DE TÊTE — un bandeau ne doit jamais masquer entièrement la section
     qui le suit : il faut toujours en voir le début, sinon rien n'annonce qu'il y
     a du contenu dessous. `--banner-peek` est la bande laissée visible,
     `--banner-max` la hauteur maximale qui en découle. Plancher : sous 720px de
     fenêtre le bandeau garde la taille qu'il a à 720 et la page défile normalement.
     `svh` et non `vh` : sur un navigateur à barre d'outils rétractable, `vh` vaut
     la hauteur BARRE RÉTRACTÉE et le bandeau dépasserait au chargement ; la ligne
     `vh` juste avant sert de repli à ceux qui ignorent `svh`.
     La page d'accueil s'en sert pour REMPLIR (hauteur = --banner-max, voir
     r-home.css) ; les autres bandeaux pour se PLAFONNER, en gardant leur cote de
     maquette tant qu'elle tient. */
  --banner-peek: clamp(56px, 7.5vh, 100px);
  /* Hauteur d'un bandeau : la fenêtre MOINS la bande laissée visible. Il suit donc
     toujours la hauteur de la fenêtre, dans les deux sens — il grandit sur un grand
     écran, il rétrécit sur un petit — et son rétrécissement s'arrête à un plancher.
     Deux planchers : la scène d'accueil garde le sien (720 − bande), les bandeaux
     secondaires s'arrêtent à 656px. */
  --hero-fill:   max(calc(720px - var(--banner-peek)), calc(100vh  - var(--banner-peek)));
  --hero-fill:   max(calc(720px - var(--banner-peek)), calc(100svh - var(--banner-peek)));
  --banner-fill: max(656px, calc(100vh  - var(--banner-peek)));
  --banner-fill: max(656px, calc(100svh - var(--banner-peek)));
  --content-max: 1204px;
}

/* ---------- Conteneur ---------- */
.wrap { width: 100%; max-width: calc(var(--content-max) + 2 * var(--gutter)); margin-inline: auto; padding-inline: var(--gutter); }
.section { position: relative; padding-block: var(--sec-pad); }

/* Fond visuel plein cadre d'une section */
.sec-bg { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
/* `video` au même titre qu'`img` : depuis la V132 le fond de « What we do » est une
   vidéo en desktop, et un fond de section se cadre de la même façon quel qu'il soit. */
.sec-bg img, .sec-bg video { width: 100%; height: 100%; object-fit: cover; }

/* Texte rempli par image (background-clip) */
.clip { background-repeat: no-repeat; -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }

/* ---------- Typographies ---------- */
.sec-label { font-size: var(--fs-seclabel); line-height: 1.2; letter-spacing: -0.01em; text-transform: uppercase; color: var(--black); text-align: center; }
.sec-label .l { font-family: var(--f-unb); font-weight: 300; }
.sec-label .b { font-family: var(--f-unb); font-weight: 700; }

/* Pastille-titre : pilule blanche cerclée de noir, centrée sur la limite de section */
.cap { display: inline-flex; align-items: center; justify-content: center; background: #fff; border: 2px solid var(--black); border-radius: 100px; padding: 11px clamp(20px, 4vw, 33px); max-width: 100%; }
.cap-row { display: flex; justify-content: center; }
/* Variante « à cheval » : la pastille est centrée sur la limite haute de la section
   (le décalage de 32px = la moitié de sa hauteur, 65px dans la maquette). */
.cap-astride { position: relative; z-index: 3; margin-top: calc(-1 * var(--sec-pad) - 32px); margin-bottom: calc(var(--sec-pad) - 32px); }
/* Variante EXACTE : le socle ci-dessus remonte la pastille d'un demi-65px **figé**
   (la cote de la maquette). Dès que la typographie fluide fait grandir ou rétrécir
   la pastille, elle n'est donc plus centrée sur la limite : 32/38 à 1440, 32/23 à
   390. Ici on la remonte de la moitié de sa hauteur réelle, quelle qu'elle soit —
   la boîte, elle, reste posée sur la limite, ce qui dégage le contenu suivant. */
.cap-astride--exact { margin-top: calc(-1 * var(--sec-pad)); margin-bottom: 0; transform: translateY(-50%); }

/* ---------- Boutons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  background: #fff; border: 2px solid var(--black); border-radius: 13px;
  font-family: var(--f-unb); font-weight: 700; font-size: var(--fs-ui);
  letter-spacing: -0.01em; text-transform: uppercase; color: var(--black);
  padding: 16px 26px 16px 32px; text-align: center;
  transition: background-color .25s ease, color .25s ease;
}
.btn .arr { width: 14.5px; height: 14.9px; flex: none; transition: transform .25s ease; }
.btn:hover { background: var(--black); color: #fff; }
.btn:hover .arr { transform: translateX(4px); filter: invert(1); }

.link-arrow { display: inline-flex; align-items: center; gap: 10px; font-family: var(--f-alb); font-size: var(--fs-ui); color: var(--black); }
.link-arrow img { width: 12px; height: 12px; transition: transform .25s ease; }
.link-arrow:hover img { transform: translateX(4px); }

/* Effets signature */
.glow-dot { border-radius: 50%; background: #fff; box-shadow: 0 0 10px rgba(255,255,255,1), 0 0 24px rgba(255,255,255,.9); }

/* ---------- Bandeau défilant ---------- */
/* Deux morceaux seulement ici : le rognage, et l'image-clé partagée. La piste
   contient la séquence DEUX fois et l'animation la translate de 50 %, d'où une
   boucle sans couture ; `overflow:hidden` est indispensable, sans lui la piste
   dupliquée s'étale sur toute la page. La piste elle-même (`.ag-track`, sa durée
   et sa pause en « mouvement réduit ») est dans `r-expertise.css`, avec le seul
   bandeau du site — celui des agences, sur Create. */
.marquee { overflow: hidden; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* ============================================================
   HEADER — un seul markup, deux mises en page
   < 900px : burger + logo centré + langue
   ≥ 900px : logo + nav + langue + « contact us » vertical
   ============================================================ */
.hdr { position: absolute; inset: 0 0 auto; z-index: 90; height: var(--header-h); pointer-events: none; }
.hdr > * { pointer-events: auto; }
/* Le bandeau occupe TOUTE la largeur (pas la colonne de texte) : dans la maquette le
   logo est à 39-44px du bord et « EN » / « CONTACT US » à ~65px du bord droit. */
.hdr-in { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 100%; padding-block: 10px;
  max-width: none; padding-inline: clamp(20px, 2.5vw, 36px); }

.hdr-logo { flex: none; width: clamp(58px, calc(58px + 30 * (100vw - 390px) / 1050), 88px); }
.hdr-logo img { width: 100%; height: auto; }

/* `position:relative` indispensable : main.js injecte le menu déroulant DANS .hdr-nav,
   et .hd-drop est en absolu. Sans repère ici, il se positionnait par rapport à .hdr
   (le header entier) et partait complètement à côté. */
.hdr-nav { display: none; position: relative; }
@media (min-width: 900px) {
  .hdr-in { align-items: flex-start; padding-top: clamp(20px, 3.4vw, 40px); }
  .hdr-nav { display: flex; gap: clamp(6px, 1.1vw, 15px); margin-right: auto; margin-left: clamp(12px, 2vw, 24px); padding-top: clamp(14px, 2vw, 28px); }
  .hdr-burger { display: none; }
}
.hdr-nav a { position: relative; display: block; padding: 6px 8px; border-radius: 4px; font-family: var(--f-unb); font-weight: 700; font-size: var(--fs-nav); text-transform: uppercase; white-space: nowrap; color: var(--black); }
.hdr-nav a::after { content: ""; position: absolute; left: 8px; right: 8px; bottom: 2px; height: 2px; background: currentColor; transform: scaleX(0); transform-origin: left; transition: transform .25s ease; }
.hdr-nav a:hover::after, .hdr-nav a[aria-current="page"]::after { transform: scaleX(1); }

.hdr-burger { width: 20px; height: 18px; position: relative; flex: none; }
.hdr-burger span { position: absolute; left: 0; height: 2px; background: var(--black); border-radius: 20px; transition: background-color .3s ease; }
.hdr-burger span:nth-child(1) { top: 0; width: 20px; }
.hdr-burger span:nth-child(2) { top: 8px; width: 20px; }
.hdr-burger span:nth-child(3) { top: 16px; width: 10px; }

.hdr-tools { display: flex; align-items: center; gap: 16px; flex: none; }
.hdr-tools .lang { font-family: var(--f-alb); font-size: var(--fs-nav); text-transform: uppercase; color: var(--black); }

.hdr-contact { display: none; }
/* La typographie du lien vit ICI, pas dans le bloc desktop : elle y était enfermée,
   si bien qu'en sticky mobile — le seul endroit où le lien s'affiche sous 900px —
   « contact us » retombait sur la police du corps (Albert Sans 400, 16px, bas de
   casse). Il porte donc partout la typo d'interface de l'en-tête, celle de la
   navigation. Seuls la rotation et l'espace conservé du gabarit vertical restent
   propres au desktop. */
.hdr-contact span { font-family: var(--f-unb); font-weight: 700; font-size: var(--fs-nav); text-transform: uppercase; color: var(--black); }
@media (min-width: 900px) {
  /* Maquette : « EN » et « CONTACT US » partagent le même axe vertical (left 1354).
     Les deux sont donc calés sur la même gouttière droite, EN au-dessus. */
  .hdr-tools { position: absolute; right: clamp(20px, 3.6vw, 52px); top: clamp(46px, 5.2vw, 75px); flex-direction: column; padding-top: 0; }
  .hdr-contact { display: flex; align-items: center; justify-content: center; position: absolute; right: clamp(20px, 3.6vw, 52px); top: clamp(92px, 10.5vw, 112px); width: 20px; height: 100px; }
  .hdr-contact span { transform: rotate(-90deg); white-space: pre; }
  /* V136 — « NOUS CONTACTER » mesure 168 px contre 117 pour « CONTACT US ». Le
     texte pivoté est centré sur une boîte de 100 px : il dépasse donc de 34 px
     en haut au lieu de 9, et venait recouvrir le lien de langue (−14 px d'écart
     à 1440, 0 à 900). On descend la boîte de la moitié de l'allongement, ce qui
     rend au français EXACTEMENT l'écart de l'anglais sous le lien de langue. */
  html[lang="fr"] .hdr-contact { top: calc(clamp(92px, 10.5vw, 112px) + 26px); }
}

/* Variante sombre */
.hdr[data-theme="dark"] .hdr-nav a,
.hdr[data-theme="dark"] .hdr-tools .lang,
.hdr[data-theme="dark"] .hdr-contact span { color: #fff; }
.hdr[data-theme="dark"] .hdr-burger span { background: #fff; }
.hdr[data-theme="dark"] .hdr-logo img { filter: brightness(0) invert(1); transform: scale(.94); }

/* Sticky — fond et flou portés par ::before (voir V5 : un backdrop-filter sur
   l'élément en ferait un « backdrop root » et priverait le menu déroulant du sien) */
.hdr.is-stuck { position: fixed; top: 0; left: 0; right: 0; height: clamp(62px, 10vw, 96px); background: transparent; box-shadow: 0 1px 0 rgba(15,17,34,.08); }
.hdr.is-stuck::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: rgba(244, 244, 251, .88);
  backdrop-filter: blur(30px) contrast(.29) brightness(1.55) saturate(180%);
  -webkit-backdrop-filter: blur(30px) contrast(.29) brightness(1.55) saturate(180%);
}
.hdr.is-stuck[data-theme="dark"]::before {
  background: rgba(15, 17, 34, .82);
  backdrop-filter: blur(30px) contrast(.75) brightness(.4) saturate(150%);
  -webkit-backdrop-filter: blur(30px) contrast(.75) brightness(.4) saturate(150%);
}
/* En sticky, tout repasse en ligne. « CONTACT US » se remet à l'horizontale et
   passe AVANT « EN » (demande client) — simple inversion des `order` : la
   répartition `space-between` de la barre, elle, ne bouge pas, donc le burger et
   le logo gardent leur place. */
.hdr.is-stuck .hdr-in { align-items: center; padding-top: 0; gap: 12px; }
.hdr.is-stuck .hdr-logo { width: clamp(44px, 6vw, 68px); }
.hdr.is-stuck .hdr-nav { padding-top: 0; }
.hdr.is-stuck .hdr-tools { position: static; flex-direction: row; padding-top: 0; order: 2; }
.hdr.is-stuck .hdr-contact { display: flex; position: static; width: auto; height: auto; order: 1; }
/* Sticky MOBILE : le logo est CENTRÉ et le couple « CONTACT US » / « EN » est
   groupé à droite, comme en desktop.
   `space-between` seul ne pouvait pas donner les deux : il répartissait le vide à
   parts égales, ce qui décalait le logo dès que le lien contact s'ajoutait (44px
   de large contre 114 pour le lien) et laissait 52px entre le lien et la langue,
   là où le desktop n'en pose que 12. Le logo sort donc du flux — centré sur la
   barre, comme dans le board `123:18739` — et `margin-left:auto` absorbe tout le
   vide restant pour souder le groupe de droite. */
@media (max-width: 899px) {
  .hdr.is-stuck .hdr-in { position: relative; }
  .hdr.is-stuck .hdr-logo { position: absolute; left: 50%; transform: translateX(-50%); }
  .hdr.is-stuck .hdr-contact { margin-left: auto; }
}
/* Sous 376px (iPhone SE, Android 360), la barre n'a plus de quoi loger un logo
   CENTRÉ et un groupe de droite de 144 : à 360 le logo mordait le lien de 6px.
   Le lien se resserre donc d'un cran — 12,5px au lieu de 14 — ce qui rend 6px de
   dégagement. Le socle typographique du site étant calé sur 390, c'est le seul
   endroit de l'en-tête qui descend plus bas. */
@media (max-width: 375px) {
  .hdr.is-stuck .hdr-contact span { font-size: 12.5px; }
}
/* À l'horizontale, le lien perd la rotation ET l'espace conservé : la double espace
   de « contact  us » n'existe que pour aérer le gabarit vertical du desktop. */
.hdr.is-stuck .hdr-contact span { transform: none; white-space: normal; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hdr.is-stuck::before { background: rgba(244, 244, 251, .97); }
  .hdr.is-stuck[data-theme="dark"]::before { background: rgba(15, 17, 34, .97); }
}

/* Menu déroulant « What we do » (injecté par main.js) */
.hd-drop {
  position: absolute; top: calc(100% + 14px); left: -14px; min-width: 210px;
  display: flex; flex-direction: column; gap: 2px; padding: 10px; border-radius: 16px;
  background: rgba(255,255,255,.16);
  backdrop-filter: blur(30px) contrast(.29) brightness(1.55) saturate(180%);
  -webkit-backdrop-filter: blur(30px) contrast(.29) brightness(1.55) saturate(180%);
  border: 1px solid rgba(255,255,255,.5); box-shadow: 0 18px 50px rgba(15,17,34,.22);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity .25s ease, transform .25s ease, visibility 0s .25s; z-index: 100;
}
.hd-drop.is-open { opacity: 1; visibility: visible; transform: none; transition: opacity .25s ease, transform .25s ease; }
.hd-drop::before { content: ""; position: absolute; left: 0; right: 0; top: -16px; height: 16px; }
.hd-drop a { display: block; padding: 10px 18px; border-radius: 9px; font-family: var(--f-unb); font-weight: 700; font-size: 15px; letter-spacing: -0.01em; text-transform: uppercase; white-space: nowrap; color: var(--black); transition: background-color .2s ease; }
.hd-drop a::after { content: none; }
.hd-drop a:hover { background: rgba(255,255,255,.5); }
.hdr[data-theme="dark"] .hd-drop { background: rgba(15,17,34,.42); border-color: rgba(255,255,255,.28); backdrop-filter: blur(30px) contrast(.75) brightness(.4) saturate(150%); -webkit-backdrop-filter: blur(30px) contrast(.75) brightness(.4) saturate(150%); }
.hdr[data-theme="dark"] .hd-drop a { color: #fff; }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hd-drop { background: rgba(255,255,255,.93); }
  .hdr[data-theme="dark"] .hd-drop { background: rgba(15,17,34,.93); }
}

/* Panneau de navigation plein écran (burger) */
.mnav { position: fixed; inset: 0; z-index: 200; background: var(--cloud); display: flex; flex-direction: column; padding: 88px var(--gutter) 40px; opacity: 0; visibility: hidden; transform: translateY(-8px); transition: opacity .3s ease, transform .3s ease, visibility 0s .3s; }
.mnav.is-open { opacity: 1; visibility: visible; transform: none; transition: opacity .3s ease, transform .3s ease; }
.mnav-close { position: absolute; top: 22px; right: 20px; width: 28px; height: 28px; }
.mnav-close::before, .mnav-close::after { content: ""; position: absolute; left: 2px; right: 2px; top: 13px; height: 2px; background: var(--black); border-radius: 2px; }
.mnav-close::before { transform: rotate(45deg); }
.mnav-close::after { transform: rotate(-45deg); }
.mnav-logo { display: block; width: 64px; position: absolute; top: 8px; left: 20px; }
.mnav nav { display: flex; flex-direction: column; gap: 28px; margin-top: 24px; }
.mnav nav a { font-family: var(--f-unb); font-weight: 700; font-size: clamp(22px, 6vw, 26px); text-transform: uppercase; color: var(--black); }
.mnav-foot { margin-top: auto; display: flex; flex-direction: column; gap: 18px; }
.mnav-foot .lang-row { display: flex; gap: 14px; font-family: var(--f-alb); font-size: var(--fs-ui); text-transform: uppercase; }
.mnav-foot .lang-row a[aria-current="true"] { text-decoration: underline; }

/* ============================================================
   FOOTER — barre de liens
   ============================================================ */
.ftbar { width: 100%; }
.ftbar-links { display: flex; flex-wrap: wrap; gap: clamp(16px, 3vw, 42px); font-family: var(--f-display); font-size: var(--fs-small); letter-spacing: 0.02em; text-transform: uppercase; color: var(--black); }
.ftbar hr { border: 0; border-top: 1px solid var(--black); width: 100%; margin: 13px 0; }
.ftbar-bottom { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; justify-content: space-between; }
.ftbar-legal { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; font-family: var(--f-alb); font-size: clamp(12px, 2.5vw, 12px); line-height: 1.5; letter-spacing: 0.02em; color: var(--black); }
.ftbar-social { display: flex; gap: 8px; align-items: center; }
.ftbar-social img { width: 29px; height: 29px; }
.ftbar[data-theme="dark"] .ftbar-links, .ftbar[data-theme="dark"] .ftbar-legal { color: #fff; }
.ftbar[data-theme="dark"] hr { border-top-color: #fff; }
.ftbar[data-theme="dark"] .ftbar-social img { filter: invert(1); }
.ftbar a:hover { opacity: .65; }

/* ============================================================
   FOOTER — bloc CTA, commun à TOUTES les pages
   ------------------------------------------------------------
   Structure, typographie et traitement mobile du personnage sont identiques
   partout. Seule la GÉOMÉTRIE DESKTOP change d'un gabarit à l'autre (ratio de
   la scène, cadrage du personnage, position de la colonne CTA) : elle passe
   donc par des variables que chaque feuille de page redéfinit. Les valeurs par
   défaut sont celles de la homepage (scène V1 1440 × 766).
   ============================================================ */
/* PAS d'`overflow:hidden` : dans la maquette le personnage déborde vers le HAUT, par-dessus
   la section précédente, et est coupé à gauche. Le débordement latéral est absorbé par
   `overflow-x:hidden` sur le body. */
/* Mobile : personnage CENTRÉ et placé AU-DESSUS du texte, tête débordant en haut.
   ------------------------------------------------------------------------------
   Le PNG mesure 1920 × 1496 mais le personnage détouré n'en occupe qu'une partie,
   et il n'y est pas centré (mesuré sur le canal alpha du fichier) :
     • centre horizontal du sujet : 34,1 % de l'image (et non 50 %)
     • sujet vertical : de 21,4 % à 70,4 % de l'image
   Centrer la BOÎTE le décalait donc de 16 % vers la gauche, et réserver toute la
   hauteur de l'image laissait ~30 % de vide entre lui et le texte. Tous les calculs
   ci-dessous portent sur le SUJET, pas sur le fichier.
     --man-w  : largeur de l'image (le sujet en fait 53,9 %)
     --man-h  : sa hauteur, ratio 1496/1920 = 0,779
     translate: -34,1 % → amène le centre du sujet sur le centre de la scène
     top      : place le haut du sujet 40px au-dessus du footer (tête débordante)
     padding  : bas du sujet + 30px de respiration
   Les % d'un `padding-top` se calculent sur la LARGEUR, comme ceux de `width` :
   les deux valeurs restent cohérentes à toutes les largeurs. */
.ft {
  position: relative; color: var(--black);
  /* Aucun `overflow` en DESKTOP, sur aucun axe : le personnage doit déborder en HAUT
     (la tête passe sur le bloc précédent) et à GAUCHE (la main et le pied sont coupés
     par le bord de l'écran, comme dans la maquette). Un débord à gauche ne crée pas de
     défilement en lecture de gauche à droite : il est sans danger.
     Les deux débords qui posaient problème sont traités à la source, sur l'image :
     sa largeur est calée sur la maquette (elle ne dépasse plus à droite) et sa hauteur
     est plafonnée au bas du footer (voir `.ft-man`). */
  /* Géométrie desktop, redéfinissable par page.
     `--ft-min` : la proportion de la maquette (766 / 1440 = 53,19 %) servant de
     hauteur MINIMALE. Le footer peut s'allonger si son contenu le demande — c'est
     ce qui empêche la barre de liens de sortir du fond (voir V34). */
  --ft-min: min(766px, 53.19vw);
  /* Cadrage desktop du personnage, relevé sur le nœud Figma du footer (112:7333,
     1440 × 835, dont 60px de débord haut : le bleu commence à y60) :
       • le SUJET va de x −90 (main et pied coupés par le bord) à x 636 ;
       • le texte du CTA commence à x 711, soit 75px de dégagement ;
       • le haut du sujet est 50px au-dessus du bleu.
     Converti pour notre canevas 1920 × 1496, dont le sujet occupe x 138→1171 et
     y 317→1050 : largeur d'image 1349, calée à x −187, y −273.
     L'ancien cadrage montait à 1700 de large et le sujet s'arrêtait à x 913 —
     176px SOUS le texte, qui devenait illisible, d'autant plus en français où
     l'accroche est plus longue.
     La cote est reprise telle quelle : c'est la COLONNE DE TEXTE qui était mal
     placée (trop large et trop à gauche), pas le personnage. Une fois la colonne
     recalée sur la maquette, le dégagement tombe juste tout seul — 47px à 900,
     75px à 1440. Bornée en haut, la composition se fige au-delà de 1440 comme le
     reste du footer, sinon le personnage grossissait dans une scène qui, elle, ne
     grandit plus, et on n'en voyait qu'un gros plan. */
  /* RECALAGE (demande client) sur le footer de la maquette la plus récente —
     `112:5646`, mesuré sur son rendu : le sujet y occupe TOUTE la hauteur de la bande
     (‑54 au-dessus du bleu, 569 en dessous, soit 623 de haut) et va de la main coupée
     par le bord gauche jusqu'à x 790. Notre cadrage précédent, calé sur le nœud
     `112:7333`, ne lui en donnait que 507 : le personnage paraissait petit et haut
     perché dans la scène.
     L'agrandissement est INTERPOLÉ de 900 à 1440 plutôt qu'appliqué tel quel : à 900
     la colonne de texte est proportionnellement plus large et plus à gauche, et la
     cote de maquette y ferait passer le sujet sous l'accroche. À 900 on garde donc le
     cadrage actuel (49px de dégagement), à 1440 celui de la maquette. */
  --man-l: clamp(-207px, calc(-116.9px - 90.1 * (100vw - 900px) / 540), -116px);
  --man-t: clamp(-323.5px, calc(-168.5px - 155 * (100vw - 900px) / 540), -168px);
  --man-ar: 1920/1496;
  --man-dw: clamp(843px, calc(843px + 789 * (100vw - 900px) / 540), 1632px);
  /* `vw` et non `%` : une custom property est substituée TEXTUELLEMENT, donc un `%`
     se résout selon la propriété d'arrivée — sur la largeur dans `width`, mais sur la
     HAUTEUR dans `top`. La même variable donnait deux valeurs différentes et la tête
     dépassait de 96px au lieu de 40. `vw` est absolu : identique partout. */
  --man-w: min(158vw, 950px);
  --man-h: calc(.779 * var(--man-w));
  /* Débord de la tête au-dessus du footer, en une seule variable : elle sert à la
     fois de `top` et de rallonge au plafond de hauteur de l'image. */
  --man-top: calc(-40px - .214 * var(--man-h));
  padding-block: calc(.49 * var(--man-h) - 10px) 20px;
}
/* Le PNG est un sujet détouré dans un très large canevas transparent. Sous le footer,
   ce canevas dépassait de 222px et allongeait le document — c'est la bande blanche
   après le footer. On plafonne donc la BOÎTE de l'image au bas du footer
   (`max-height` = hauteur du footer + le débord de la tête) et on recadre par le bas
   avec `object-position: top` : la tête garde son débord, le vide disparaît.
   Le sujet n'est pas touché : il s'arrête 172px au-dessus du bas du footer.
   Ne pas remplacer par un `overflow` sur `.ft` — il rognerait aussi la tête — ni par
   `clip-path`, qui rogne à la peinture et laisse le débordement de mise en page. */
.ft-man {
  position: absolute; z-index: 1; pointer-events: none;
  left: 50%;
  translate: -34.1% 0;
  top: var(--man-top);
  width: var(--man-w);
  max-width: none;
  max-height: calc(100% - var(--man-top));
  object-fit: cover;
  object-position: top center;
}
/* En MOBILE le personnage est centré et son canevas transparent dépasse à droite
   (211px à 390, 324 à 600), ce qui faisait défiler la page horizontalement. Le sujet,
   lui, est largement à l'intérieur (29 → 361 sur 390) : on peut donc rogner l'axe
   horizontal sans rien couper de visible. L'axe vertical reste libre pour la tête.
   `clip` + `visible` est la seule combinaison mixte autorisée par la spécification. */
@media (max-width: 899px) {
  .ft { overflow-x: clip; overflow-y: visible; }
}
.ft-in { position: relative; z-index: 2; display: flex; flex-direction: column; gap: clamp(40px, 6vw, 50px); }
.ft-cta { display: flex; flex-direction: column; gap: 29px; align-items: center; }
.ft-sign { display: flex; flex-direction: column; gap: 10px; align-items: center; }
.ft-sign img { width: clamp(101px, calc(101px + 50 * (100vw - 390px) / 1050), 151px); height: auto; }
.ft-ready { font-family: var(--f-alb); font-weight: 300; font-size: var(--fs-ready); line-height: 1.2; letter-spacing: -0.01em; text-transform: uppercase; text-align: center; color: var(--black); }
.ft-ready .b { font-family: var(--f-unb); font-weight: 700; }

@media (min-width: 900px) {
  /* Desktop : la composition de la V1 — bloc CTA à droite, barre de liens en bas.
     ------------------------------------------------------------------------------
     Le contenu est dans le FLUX et non en absolu, et la proportion de la maquette
     (1440 × 766) ne sert plus que de hauteur MINIMALE.

     Pourquoi : avec `aspect-ratio`, la hauteur du footer ne dépendait que de la
     largeur, tandis que la barre de liens était posée à 89,43 % pour une hauteur
     fixe d'environ 74px. En dessous de 1316px de large, les 10,57 % restants ne
     suffisaient plus et la barre sortait du fond — de 22px à 900px de large, 16 à
     1024, 6 à 1200. Dans le flux, le footer s'allonge de lui-même quand son
     contenu le demande : le fond couvre toujours tout. (Défaut V34.)

     `width:100%` reste indispensable avec un ratio : sans largeur explicite, une
     hauteur minimale ferait recalculer la LARGEUR depuis la hauteur. */
  .ft { padding: 0; width: 100%; min-height: var(--ft-min); }
  /* `max-width:none` : le reset global (max-width:100%) rabotait le coureur de 1700 à
     1440 et il ne débordait plus en haut/à gauche comme dans la maquette.
     `translate: none` : annule le centrage utilisé en responsive, sinon le personnage
     repart de 50 % de sa largeur vers la gauche. */
  /* `--man-top` reprend la cote desktop : `max-height` du socle suit automatiquement. */
  .ft { --man-top: var(--man-t); }
  .ft-man { left: var(--man-l); top: var(--man-top); translate: none; width: var(--man-dw); max-width: none; aspect-ratio: var(--man-ar); }
  /* Deux rangées : le bloc CTA occupe l'espace disponible et s'y centre, la barre
     de liens se cale en bas. `min-height` porte ici aussi la proportion de maquette,
     pour que le footer garde son allure quand le contenu est plus court. */
  /* L'espace au-dessus du logo 87s est ramené de 104 à 52px (demande client : « la
     moitié »). Il ne venait qu'à 40 % du retrait : le reste était le centrage du bloc
     CTA dans sa rangée `1fr`. Réduire le seul retrait n'aurait rendu que 10px — le
     centrage rattrapait la moitié de ce qu'on lui enlevait. Le bloc est donc calé EN
     HAUT de sa rangée et le retrait porte seul la valeur voulue. */
  .ft-in { position: relative; z-index: 2; display: grid; grid-template-rows: 1fr auto;
    min-height: var(--ft-min); gap: clamp(24px, 3vw, 40px);
    padding-block: clamp(24px, 3.6vw, 52px) clamp(8px, 0.91vw, 14px); }
  /* Colonne de texte du CTA, relevée sur le nœud Figma du footer (112:7333) :
     x 711 → 1322 sur 1440. Or 1322 est exactement le bord droit de la colonne de
     contenu du site (gouttière de 118) : la colonne CTA se cale donc simplement à
     droite de `.ft-in`, sans marge, et vaut 611 / 1204 = 50,75 % de sa largeur.
     Elle valait 39,1 % avec 3,8 % de marge, soit un bord droit à 96,2 % de l'écran
     au lieu de 91,81 % ; l'accroche étant en `nowrap` et débordant symétriquement de
     son bloc, le texte français venait toucher le bord. Le logo 87s est centré dans
     cette colonne, comme dans la maquette. */
  .ft-cta { grid-row: 1; align-self: start; justify-self: end; width: 50.75%; margin-right: 0; gap: clamp(16px, 2.2vw, 26px); }
  /* L'accroche doit TENIR dans cette colonne, sinon son débord symétrique ronge la
     marge droite d'un côté et vient sur le personnage de l'autre. Plafond = largeur
     de colonne ÷ largeur du texte en multiples du corps : 10,00 pour l'anglais, d'où
     4,24vw, ramené à 4,2vw pour absorber les arrondis — ce qui laisse intacts les
     60px de la maquette à 1440 et ne mord que sous cette largeur. */
  .ft-ready { font-size: min(var(--fs-ready), 4.2vw); }
  .ft-sign img { width: 10.49vw; max-width: 151px; }
  /* NB : le corps de `.ft-ready` est plafonné en vw pour le FR — voir « VARIANTES FR »
     plus bas (le texte est en `nowrap` et déborderait de l'écran). */
  .ft-ready { white-space: nowrap; }
  .ft .ftbar { grid-row: 2; align-self: end; }
}

/* ============================================================
   VARIANTES FR — l'accroche du footer est plus longue que l'anglaise
   ------------------------------------------------------------
   Le français allonge les libellés d'environ 30 % ici. Largeur mesurée au
   navigateur, en multiples du corps (largeur du texte ÷ font-size) :

     « PRÊTS À VOUS CONNECTER » 13,22 contre « READY TO CONNECT » 10,00 (+32 %)

   À corps égal, le bloc passait de 2 lignes (la maquette) à 4.

   Le HERO de la homepage, lui, n'a PAS de variante : il reste en anglais sur la
   page FR (décision client, V24), donc même texte et même typographie que la
   page EN. Ne pas réintroduire de plafond FR sur `.h-title` : à texte identique,
   il rendrait le titre de la page FR plus petit que celui de la page EN.
   ============================================================ */
html[lang="fr"] {
  /* 350 ÷ 13,22 = 26,5px maximum à 390 de large. La V1 laissait ici les 34px de
     l'anglais, et le texte FR y passait donc déjà sur 4 lignes — corrigé, la maquette
     ne montre que 2 lignes (voir CHANGELOG V22). */
  --fs-ready-fr:  clamp(26px, calc(26px + 34 * (100vw - 390px) / 1050), 60px);
}
html[lang="fr"] .ft-ready { font-size: var(--fs-ready-fr); }

@media (min-width: 900px) {
  /* En desktop `.ft-ready` est en `nowrap` et son bloc est centré à 72,25 % de la scène
     (left 55,9 % + la moitié de 32,7 %) : le texte débordant symétriquement de sa boîte,
     il ne reste que 27,75 % de la largeur à droite, soit 55,5 % pour le texte entier.
     Le FR demandait 616px à 900 de large pour 500 disponibles — il sortait de l'écran
     (rogné par l'`overflow-x:hidden` du body). D'où le plafond : 55,5 % ÷ 13,22 = 4,2vw,
     ramené à 4,15vw pour garder ~4px de marge à toutes les largeurs (60px à 1440,
     la valeur de la maquette, est conservée à 0,4 % près). */
  /* Le texte FR ne doit plus déborder de sa colonne du tout : depuis que celle-ci
     est calée sur la maquette (42,43 %), tout débord ronge la marge droite ou vient
     sur le personnage. Le plafond est donc celui qui le fait TENIR dans la colonne :
     42,43 % ÷ 13,22 (largeur du texte en multiples du corps) = 3,21vw, ramené à
     3,2vw. Soit 46px à 1440 contre 60 en anglais — c'est le prix d'une accroche 32 %
     plus longue, et le texte reste sur ses 2 lignes de maquette.
     L'ancien décalage du bloc vers la gauche en FR n'a plus lieu d'être : il
     compensait un débord qui n'existe plus. */
  html[lang="fr"] .ft-ready { font-size: min(var(--fs-ready-fr), 3.2vw, 46px); }
}

/* ---------- Éléments partagés hero / footer ---------- */
/* Section à fond bleu (What we do, Global presence, expertise…) */
.blue { position: relative; color: #fff; }
.blue .sec-bg img, .blue .sec-bg video { object-position: center; }
/* Signature « AI • CONTENT ORCHESTRATION » sous le logo 87s */
.h-baseline { font-family: var(--f-unb); font-weight: 700; font-size: var(--fs-baseline); line-height: 1.2; letter-spacing: -0.01em; text-transform: uppercase; text-align: center; color: var(--ink); }

/* ---------- Apparitions au scroll ---------- */
/* On anime `translate` (propriété indépendante) et NON `transform` : sinon la règle
   `.rv.in { transform:none }` écrase la transform propre de l'élément — c'est ce qui
   aplatissait le badge « AWARDED BY » et décalait de 128px les colonnes de What we do,
   dont le centrage repose sur translateX(-50%). `translate` se compose avec `transform`. */
.rv { opacity: 0; translate: 0 28px; transition: opacity .7s ease, translate .7s ease; }
.rv.in { opacity: 1; translate: 0 0; }
.rv-d1 { transition-delay: .12s; }
.rv-d2 { transition-delay: .24s; }
.rv-d3 { transition-delay: .36s; }
@media (prefers-reduced-motion: reduce) { .rv { opacity: 1; translate: 0 0; transition: none; } }

/* ---------- Accessibilité ---------- */
:focus-visible { outline: 2px solid var(--night); outline-offset: 2px; }

/* ============================================================
   MODALE DE CONTACT — injectée par `main.js` sur toutes les pages
   ------------------------------------------------------------
   Portée depuis la feuille V1 `base.css`, que les pages V2 ne chargeaient pas :
   sans ces règles la modale retombait en FLUX après le footer et y ajoutait
   19px de blanc au bas de chacune des 34 pages. Même piège qu'en V33 avec
   `.marquee` — une classe employée par une feuille absente. (`base.css` et les
   quatre autres feuilles de la V1 ont été supprimées du livrable en V158 : plus
   aucune page ne les chargeait.)
   ============================================================ */
.contact-modal { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: rgba(15, 17, 34, .55);
  opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility 0s .3s; }
/* `backdrop-filter` UNIQUEMENT à l'ouverture : posé sur la modale fermée, il teinte
   toute la page alors même qu'elle est en `opacity: 0` et `visibility: hidden` — le
   filtre s'applique au fond quoi qu'il arrive. Vérifié en retirant l'élément du DOM :
   le voile disparaissait. (La feuille V1 a le même défaut.) */
.contact-modal.is-open { opacity: 1; visibility: visible; transition: opacity .3s ease;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
/* Aucun retrait : le formulaire occupe la carte bord à bord. C'est la seule façon de
   ne PAS avoir à faire coïncider deux bleus — celui de la carte et celui du
   formulaire, qui vit dans une iframe cross-origin qu'on ne peut ni lire ni styler.
   Tant qu'il y avait un cadre de 40px autour, le moindre écart se voyait comme un
   liseré. Le bouton de fermeture reste posé sur le coin haut-droit du formulaire, où
   il n'y a que du fond. */
.contact-modal-card { position: relative; width: min(560px, 100%); max-height: min(86vh, 720px); overflow: auto;
  background: var(--form-blue); border-radius: 20px; padding: 0;
  transform: translateY(16px) scale(.985); transition: transform .3s ease; box-shadow: 0 30px 80px rgba(15, 17, 34, .4); }
.contact-modal.is-open .contact-modal-card { transform: none; }
/* La croix reste NOIRE sur pastille blanche. Sur le bleu du formulaire, une croix
   blanche tomberait à 1,6:1 de contraste — pratiquement invisible ; en noir elle est
   à 13,2:1. La pastille blanche la détache du fond maintenant que la carte est bleue. */
.contact-modal-close { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border-radius: 50%;
  border: 2px solid var(--black); background: #fff; transition: background-color .2s ease; }
.contact-modal-close::before, .contact-modal-close::after { content: ""; position: absolute; top: 50%; left: 50%;
  width: 18px; height: 2px; background: var(--black); border-radius: 2px; }
.contact-modal-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.contact-modal-close::after  { transform: translate(-50%, -50%) rotate(-45deg); }
.contact-modal-close:hover { background: var(--black); }
.contact-modal-close:hover::before, .contact-modal-close:hover::after { background: #fff; }
.contact-modal-body { min-height: 160px; }
/* Plancher de hauteur du formulaire HubSpot. Son script pose une hauteur EN LIGNE
   sur `.hs-form-frame` d'après le contenu de son iframe ; tant qu'il ne l'a pas
   mesurée — ou s'il la mesure à 0 — la zone se replierait à néant et la pop-up
   s'ouvrirait vide. `min-height` ne peut pas être écrasé par la hauteur en ligne :
   il garantit une zone utilisable, et le formulaire grandit au-delà sans contrainte. */
.contact-modal .hs-form-frame,
.contact-modal .hs-form-frame iframe { min-height: min(520px, 68vh); }
/* Repli affiché si le script HubSpot ne se charge pas (bloqueur, réseau, consentement). */
/* La carte n'ayant plus de retrait, le message de repli porte le sien : sans lui il
   viendrait se coller au bord arrondi. */
.contact-modal-repli { font-family: var(--f-alb); font-size: 16px; line-height: 1.4; color: var(--black); padding: 40px 32px; }
.contact-modal-repli a { font-weight: 700; text-decoration: underline; }
@media (prefers-reduced-motion: reduce) { .contact-modal, .contact-modal-card { transition: none; } }
