/* Généré par sync.mjs depuis www/src/styles : ne pas modifier ici */
@font-face { font-family: 'Inter'; font-weight: 400; src: url('font/Inter/inter-latin-400-normal.woff2') format('woff2'); font-display: swap; }
/* ==========================================================================
   Tokens : couleurs, typographie, espacements, grille
   Source unique du site et du studio (ne jamais coder une valeur en dur quand un token existe)
   ========================================================================== */

@font-face { font-family: 'Mega Giga'; src: url('font/Mega/Mega-Giga.woff2') format('woff2'), url('font/Mega/Mega-Giga.woff') format('woff'); font-display: swap; }
@font-face { font-family: 'PP Neue Montreal'; font-weight: 400; src: url('font/NeueMontreal/PPNeueMontreal-Book.woff2') format('woff2'), url('font/NeueMontreal/PPNeueMontreal-Book.woff') format('woff'); font-display: swap; }
@font-face { font-family: 'PP Neue Montreal'; font-weight: 500; src: url('font/NeueMontreal/PPNeueMontreal-Medium.woff2') format('woff2'), url('font/NeueMontreal/PPNeueMontreal-Medium.woff') format('woff'); font-display: swap; }

:root {
  /* Couleurs */
  --bg: #ECEEF2;           /* fond de page, fond des pastilles */
  --surface: #FFFFFF;      /* boutons, cartes, Menu au scroll */
  --ink: #100229;          /* titres, labels */
  --text: #514764;         /* textes courants, un cran plus gris que les titres */
  --muted: #898196;        /* texte secondaire */
  --tag: #867990;          /* texte des tags, liens légaux */
  --line: #E0E3EA;         /* filets, fond des miniatures et des cellules */
  --neon: #8EAB28;         /* dark-neon : labels, règles, coins, flèches, chiffres */
  --neon-soft: #D0DDA2;    /* graduations secondaires des règles */
  --neon-glow: #C8FF2E;    /* néon lumineux : liquide de l'Erlenmeyer et du bécher */

  /* Polices */
  --font-display: 'Mega Giga', sans-serif;
  --font-label: 'PP Neue Montreal', sans-serif;
  --font-text: 'Inter', sans-serif;

  /* Grille 8px */
  --s1: 8px; --s2: 16px; --s3: 24px; --s4: 32px; --s5: 40px; --s6: 48px;
  --s8: 64px; --s12: 96px; --s16: 128px; --s18: 144px;

  /* Grille de page : conteneur fluide, 12 colonnes */
  --max: 1440px;      /* largeur max gouttières comprises */
  --gutter: 64px;
  --gap: 16px;
  --label-gap: 22px;  /* écart titre ↔ ligne de règle, calé sur les chiffres clés du header */

  /* Courbes d'animation : deux seulement (+ linear pour les boucles continues) */
  --ease-in-out: cubic-bezier(.7, 0, .2, 1);  /* mouvements : roll des mots, Menu, FAQ, Voronoi, case studies */
  --ease-out: cubic-bezier(.22, 1, .36, 1);   /* survols, flèches, fondus, couleurs */
  /* leurs miroirs dans le temps : une sortie qui rejoue l'entrée à l'envers (fermeture du Menu) */
  --ease-in-out-reverse: cubic-bezier(.8, 0, .3, 1);
  --ease-out-reverse: cubic-bezier(.64, 0, .78, 0);
}

/* Points de rupture (mêmes valeurs que styles/casestudy/_variables.scss) :
   1180 tablette paysage · 980 tablette · 780 mobile · 520 petit mobile.
   Les variables CSS ne marchent pas dans @media : ces valeurs sont écrites en dur dans chaque fichier. */
@media (max-width: 780px) { :root { --gutter: 32px; } }
@media (max-width: 520px) { :root { --gutter: 24px; } }

/* ==========================================================================
   Base : reset, typographie, couleurs utilitaires, grille
   ========================================================================== */

* { box-sizing: border-box; margin: 0; padding: 0; }
body { overflow-x: clip; background: var(--bg); color: var(--ink); -webkit-font-smoothing: antialiased; }
img { display: block; }
a { color: inherit; text-decoration: none; }

/* Transition de page : fondu court entre l'ancienne et la nouvelle page (navigation native, sans JS).
   Navigateurs sans support (Firefox) : navigation classique. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 250ms; animation-timing-function: var(--ease-out); }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }
::selection { background: var(--neon); color: var(--ink); }
/* Pas de mot seul en dernière ligne (veuves) */
p, h1, h2, h3, h4, li, blockquote, figcaption, dd { text-wrap: pretty; }
h1, .t-display { text-wrap: balance; }   /* titres : lignes de longueur égale, pas de mot seul en dernière ligne */

/* Rognage cap-height → baseline, comme le vertical trim de Figma : les alignements se mesurent sur les capitales */
.trim { text-box: trim-both cap alphabetic; }

/* Texte lu par les moteurs et les lecteurs d'écran, invisible à l'écran */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

/* ---------- Typo ---------- */
.t-display { font: 400 42px/46px var(--font-display); letter-spacing: -0.02em; text-transform: uppercase; }
.t-title { font: 500 18px/24px var(--font-label); letter-spacing: -0.01em; text-transform: uppercase; }
.t-label { font: 500 16px/24px var(--font-label); letter-spacing: -0.01em; text-transform: uppercase; }
.t-label-book { font: 400 16px/24px var(--font-label); letter-spacing: -0.01em; text-transform: uppercase; }
.t-body { font: 400 16px/24px var(--font-text); letter-spacing: -0.03em; color: var(--text); }
/* Meta : boutons, Menu, titres de section, chiffres clés */
.t-meta { font: 500 14px/24px var(--font-label); letter-spacing: -0.01em; text-transform: uppercase; }
/* Tag : étiquettes des cases, bas du footer */
.t-tag { font: 400 13px/18px var(--font-text); letter-spacing: -0.03em; text-transform: uppercase; }
/* Citation : texte des témoignages (QuoteBoard) */
.t-quote { font: 400 26px/34px var(--font-text); letter-spacing: -0.03em; color: var(--ink); }
@media (max-width: 780px) { .t-quote { font-size: 24px; line-height: 32px; } }
.c-neon { color: var(--neon); }
.c-muted { color: var(--muted); }

/* ---------- Layout ---------- */
.page { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
/* .split : colonne gauche (4 col.) + contenu (8 col.), sur la grille de 12 */
.grid12, .split { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); }
.split > :first-child { grid-column: 1 / span 4; }
.split > :last-child { grid-column: 5 / -1; }

/* Mobile : .split passe sur une colonne, les colonnes gauches vides disparaissent */
@media (max-width: 780px) {
  .split { grid-template-columns: minmax(0, 1fr); row-gap: var(--s4); }
  .split > :first-child, .split > :last-child { grid-column: 1 / -1; }
  .split > div:empty:not([class]) { display: none; }   /* colonnes d'espacement, pas les règles */
}

/* ==========================================================================
   Composants (src/ui/*.jsx) : règle, coins, boutons, pastille, tags,
   cartes de cases, cartes de services, logo, sparadrap
   ========================================================================== */

/* ---------- Règle graduée : 7 segments, graduations secondaires au milieu ---------- */
.ruler {
  height: 8px;
  background:
    linear-gradient(var(--neon), var(--neon)) top / 100% 1px no-repeat,
    linear-gradient(var(--neon), var(--neon)) left top / 1px 8px no-repeat,
    linear-gradient(var(--neon), var(--neon)) right top / 1px 8px no-repeat,
    repeating-linear-gradient(to right, var(--neon) 0 1px, transparent 1px calc(100% / 7)) top / 100% 6px no-repeat,
    repeating-linear-gradient(to right, transparent 0 calc(100% / 14), var(--neon-soft) calc(100% / 14) calc(100% / 14 + 1px), transparent calc(100% / 14 + 1px) calc(100% / 7)) top / 100% 5px no-repeat;
}
.ruler--up { transform: scaleY(-1); }

/* Ligne de section : titre à gauche, règle à droite, sur la même ligne (la ligne passe à mi-hauteur du titre) */
.section-line { align-items: start; }
.section-line .ruler { margin-top: 5px; }
.section-line--up .ruler { margin-top: -2px; }   /* règle retournée : sa ligne est en bas de la boîte de 8px */

/* ---------- Coins : quatre équerres néon de 7px ---------- */
.corners { position: relative; }
.corner { position: absolute; width: 7px; height: 7px; border: 0 solid var(--neon); border-width: 1px 0 0 1px; pointer-events: none; }
.corner--tl { left: 0; top: 0; }
.corner--tr { right: 0; top: 0; transform: rotate(90deg); }
.corner--br { right: 0; bottom: 0; transform: rotate(180deg); }
.corner--bl { left: 0; bottom: 0; transform: scaleY(-1); }

/* ---------- Bouton (V4 Press + roll des mots) ----------
   Un seul gabarit (64px). Règle des icônes : flèche → = lien interne (translate au survol),
   icône = action externe (aucun effet), enveloppe = copie de l'adresse email */
.btn {
  display: inline-flex; align-items: center; gap: var(--s6);
  height: 64px; padding: 0 var(--s3);
  color: var(--ink); user-select: none;
}
.btn__bg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.btn__bg path { fill: var(--surface); }
.btn:not(.is-ready) { background: var(--surface); }
.btn__label, .btn__arrow { position: relative; }
.btn__label { display: flex; gap: 0.28em; }
.btn__arrow { color: var(--neon); transition: transform 300ms var(--ease-out); }
.btn:hover .btn__arrow { transform: translateX(4px); }
button.btn { appearance: none; border: 0; background: none; cursor: pointer; }   /* la police vient de .t-meta */
.btn__icon { position: relative; display: block; width: 20px; height: 20px; color: var(--neon); flex: none; }
.btn__icon svg { display: block; width: 100%; height: 100%; overflow: visible; }
/* l'enveloppe a 10 unités de marge dans son viewBox : boîte plus grande pour le même poids que le calendrier */
.btn--email .btn__icon { width: 26px; height: 26px; margin: -3px; }
.icon-email .mail, .icon-email .valid, .icon-email .bottom-mail { transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out); }
.icon-email .top-mail { fill: var(--surface); }
.icon-email .valid, .icon-email .bottom-mail { opacity: 0; }
.btn--email:hover .icon-email .bottom-mail { opacity: 1; transform: translate(-10px, -10px); }
.btn--email:hover .icon-email .valid { transform: scale(.6); transform-origin: center; }
.btn--email.is-copied .icon-email .mail, .btn--email.is-copied .icon-email .bottom-mail { opacity: 0; }
.btn--email.is-copied .icon-email .valid { opacity: 1; stroke: var(--ink); transform: scale(1); }
@media (prefers-reduced-motion: reduce) { .icon-email .mail, .icon-email .valid, .icon-email .bottom-mail { transition: none; } }

/* Roll des mots : la copie arrive du haut, l'original sort par le bas */
.word { position: relative; display: block; overflow: hidden; }
.word__inner { display: block; transition: transform 550ms var(--ease-in-out); transition-delay: calc(var(--i) * 60ms); }
.word__inner::before { content: attr(data-text); position: absolute; left: 0; bottom: 100%; }
.btn:hover .word__inner, .nav:hover .word__inner, .roll:hover .word__inner { transform: translateY(100%); }
.roll { display: inline-flex; gap: 0.28em; }
.roll--neon .word__inner::before { color: var(--neon); }

/* ---------- Menu ---------- */
.nav { display: flex; align-items: center; justify-content: center; gap: var(--s2); height: 40px; padding: 0; flex: none; }
.nav__label { display: flex; }
.nav.is-fixed { position: fixed; z-index: 50; margin: 0; transition: background-color 200ms var(--ease-out); }
.nav.is-scrolled { background: var(--surface); }
.burger { display: grid; gap: 3px; width: 11px; }
.burger i { display: block; height: 1px; background: var(--ink); transition: transform 300ms var(--ease-in-out), opacity 200ms var(--ease-out); }
button.nav { appearance: none; border: 0; background: none; color: var(--ink); cursor: pointer; }
/* Menu ouvert : le hamburger devient une croix */
.nav[aria-expanded="true"] .burger i:nth-child(1) { transform: translateY(4px) rotate(45deg); }
.nav[aria-expanded="true"] .burger i:nth-child(2) { opacity: 0; }
.nav[aria-expanded="true"] .burger i:nth-child(3) { transform: translateY(-4px) rotate(-45deg); }

/* ---------- Pastille numéro : deux cercles 24px décalés, orbite au survol (scripts/ui.js) ---------- */
.badge { position: relative; flex: none; width: 40px; height: 24px; margin-top: -6px; }
.badge__num, .badge__ring {
  position: absolute; left: 0; top: 0; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; background: var(--bg); border: 1px solid var(--neon);
  font: 500 13px/1 var(--font-label); letter-spacing: -0.01em; color: var(--ink);
}
.badge__num { z-index: 2; }
.badge__ring { z-index: 1; transform: translateX(16px) scale(.8); }   /* rond de derrière réduit au repos */
.badge__num span, .badge__arrow { display: block; text-box: trim-both cap alphabetic; transition: opacity 280ms var(--ease-out), color 280ms var(--ease-out); }
.badge__arrow { opacity: 0; color: var(--ink); }
.has-badge:hover .badge__num span { color: var(--neon); }
.has-badge:hover .badge__arrow { opacity: 1; transition-delay: 160ms; }

/* ---------- Tags ---------- */
.tags { display: flex; align-items: center; gap: var(--s1); white-space: nowrap; }
.tag { color: var(--tag); }
.tags__sep { color: var(--neon); }

/* ---------- Case (carte projet à visuel) ---------- */
.case { display: grid; gap: var(--s4); align-content: start; }
.case--lg { grid-column: span 7; }
.case--sm { grid-column: span 5; }
.case[href] { cursor: pointer; }
.case__head { display: grid; grid-template-columns: 72px 1fr; }
.case__body { display: grid; gap: var(--s2); justify-items: start; }
/* Nom du client et secteur sur la même ligne, secteur calé à droite */
.case__name { display: flex; justify-content: space-between; align-items: center; gap: var(--s2); width: 100%; }
.case__sector { color: var(--tag); white-space: nowrap; }
.case__media { display: block; }
/* Miniature : cadre gris fixe (404:296), le visuel y est posé en entier, jamais recadré */
/* Marge de 4 % de la largeur autour du visuel, la même sur toutes les cartes (et le visuel du lab, home.css) :
   le visuel donne sa hauteur au cadre, plus de ratio fixe qui laisserait des marges inégales */
.case__media figure { overflow: hidden; background: var(--line); padding: 4%; display: grid; place-items: center; }
.case__media img { display: block; width: 100%; height: auto; transition: transform 380ms var(--ease-out); }
.case:hover .case__media img { transform: translateY(-4px) scale(1.02); }
.case__media .corner { opacity: 0; transition: opacity 200ms var(--ease-out); }
.case:hover .case__media .corner { opacity: 1; }
.case__placeholder { width: 100%; aspect-ratio: 404 / 296; }
/* Visuel en contexte (coverBleed : photo, mockup avec son décor) : bord à bord, sans fond ni marge ;
   au survol, zoom seul (un décalage laisserait voir le bord du cadre) */
.case__media figure.case__media--bleed { padding: 0; }
.case:hover .case__media--bleed img { transform: scale(1.02); }
/* Visuel d'habillage en fond (coverBackdrop) : calé en bas au centre, zoomé ; le cover par-dessus,
   marges en haut et sur les côtés, collé en bas, entier */
.case__media figure.case__media--backdrop { padding-bottom: 0; background-color: var(--line); background-repeat: no-repeat; background-position: center bottom; }
.case:hover .case__media--backdrop img { transform: none; }
.case--wide { grid-column: 1 / -1; }
/* Visuel calé en haut (coverTop) : marges en haut et sur les côtés, le bas est rogné */
.case__media figure.case__media--top { aspect-ratio: 404 / 296; padding-bottom: 0; place-items: start center; }
.case__media--top img { height: auto; object-fit: initial; transform-origin: top center; }
/* Écrans superposés : composition 4:3 plein cadre, même survol que les autres cartes, le second écran suit avec un léger retard */
.case__media figure:has(.case__stack) { padding: 0; place-items: start; }
.case__stack { position: relative; display: block; width: 100%; aspect-ratio: 4 / 3; }
.case__media .case__stack img { position: absolute; height: auto; object-fit: initial; }
.case__media .case__stack img + img { transition-delay: 60ms; }

/* ---------- Légende d'une expérimentation du lab (page Lab, visuel mis en avant sur la home) ----------
   Sous le visuel, sur une ligne : nom à gauche, description courte calée à droite */
.lab__caption { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s4); margin-top: var(--s3); }
.lab__name { flex: none; color: var(--ink); }
.lab__desc { max-width: 46ch; color: var(--muted); text-align: right; }
/* ≤ 375 : la description passe sous le nom, alignée à gauche */
@media (max-width: 375px) {
  .lab__caption { flex-direction: column; align-items: flex-start; gap: var(--s2); }
  .lab__desc { text-align: left; }
}

/* ---------- Carte de service ---------- */
.service {
  position: relative; display: grid; grid-template-rows: repeat(4, auto) 1fr; align-content: start; gap: var(--s4);
  padding: var(--s6); background: var(--surface); border-radius: 2px; border-top-left-radius: 0;
}
/* Onglet façon intercalaire, collé au bord haut, bord droit biseauté */
.service::before {
  content: ""; position: absolute; left: 0; bottom: 100%; width: 224px; height: 32px; background: var(--surface);
  clip-path: polygon(0 0, calc(100% - 24px) 0, 100% 100%, 0 100%);
}
.service .t-body { max-width: 34ch; line-height: 24px; }
.service .t-title { text-transform: none; }   /* sous-titre en casse normale */
.service__mark { display: flex; gap: 6px; }
.service__mark i { width: 10px; height: 8.66px; background: var(--neon); clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.service__title { font-size: clamp(22px, 2vw, 28px); line-height: 1.15; margin-top: var(--s1); }
/* Visuel simplifié en attendant les vrais écrans : faux écran face caméra sur une zone grise */
.service__visual { position: relative; align-self: end; aspect-ratio: 786 / 360; margin-top: var(--s4); }
.service__visual::before { content: ""; position: absolute; left: 0; right: 0; top: 20%; bottom: 0; background: var(--visual-bg, none) center / cover no-repeat, var(--line); }   /* texture : data/services.js */
.service__screen { position: absolute; left: 10.5%; right: 10.5%; top: 6%; bottom: 0; background: color-mix(in srgb, var(--line), var(--ink) 7%); border: 5px solid var(--ink); border-bottom: 0; border-radius: 2px 2px 0 0; }
.service__cam { position: absolute; top: 0; left: 40%; width: 20%; height: 8px; background: var(--ink); }
.service__screen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top; }
/* Puce triangle des listes */
.bullet { flex: none; width: 8px; height: 6.93px; background: var(--neon); clip-path: polygon(50% 0, 100% 100%, 0 100%); align-self: flex-start; margin-top: calc((1lh - 6.93px) / 2); }
/* Toujours sur la première ligne du texte, même quand il passe sur deux lignes : centré sur sa hauteur de ligne,
   ou sur sa hauteur de capitale quand le texte est rogné (.trim) */
.bullet:has(+ .trim) { margin-top: calc((1cap - 6.93px) / 2); }

/* ---------- Logo : fiole, bulles en boucle ---------- */
.logo-mark { display: block; }
.logo-mark svg { display: block; overflow: visible; }
.logo-mark__flask { fill: var(--ink); }
.logo-mark__bubble { fill: var(--neon); }
.logo-mark__bubble--1 { animation: bubble1 1.8s linear infinite; }
.logo-mark__bubble--2 { animation: bubble2 1.8s linear infinite; }
.logo-mark__bubble--3 { animation: bubble3 2s linear infinite; }
@keyframes bubble1 { 0% { transform: translateY(0); opacity: 1 } 100% { transform: translateY(-50px); opacity: 0 } }
@keyframes bubble2 { 0%, 49% { transform: translateY(0); opacity: 0 } 50% { transform: translateY(0); opacity: 1 } 100% { transform: translateY(-40px); opacity: 0 } }
@keyframes bubble3 { 0%, 29% { transform: translateY(0); opacity: 0 } 30% { transform: translateY(20px); opacity: 1 } 100% { transform: translateY(-20px); opacity: 0 } }
@media (prefers-reduced-motion: reduce) { .logo-mark__bubble { animation: none; } }

/* ---------- Sparadrap : étiquette néon posée de travers ---------- */
.sticker {
  display: flex; width: 272px; height: 72px; padding: var(--s1); gap: var(--s1); transform: rotate(-4deg);
  background: var(--neon); color: var(--ink); box-shadow: 0 6px 16px -8px rgba(16, 2, 41, .35);
}
.sticker__body { flex: 1; display: flex; flex-direction: column; justify-content: space-between; }
.sticker__title { align-self: flex-end; font: 500 15px/1 var(--font-label); letter-spacing: .03em; text-transform: uppercase; }
.sticker__meta { margin-top: auto; font: 400 9px/1.25 var(--font-text); letter-spacing: .02em; }
.sticker__stripes { flex: none; width: 48px; background: repeating-linear-gradient(-45deg, var(--ink) 0 6px, transparent 6px 12px); }
/* Titre à verbes : astérisque qui tourne, verbe dont la largeur suit le mot affiché, « by AI… » à la suite */
.sticker__verbs { display: flex; align-items: flex-end; gap: .3em; white-space: nowrap; }
.sticker__verbs > span { text-box: trim-both cap alphabetic; }
.sticker__verb { transition: width 400ms var(--ease-out); }
.sticker__measure { position: absolute; visibility: hidden; pointer-events: none; }

/* ---------- Chiffres clés ---------- */
.stats { height: 40px; display: flex; flex-direction: column; justify-content: space-between; }
.stats__list { display: flex; gap: var(--s6); list-style: none; }

/* ---------- Icônes sociales ---------- */
.socials { display: flex; gap: var(--s3); }
.socials a, .socials span { display: flex; color: var(--ink); transition: color 250ms var(--ease-out); }
.socials a:hover { color: var(--neon); }
.socials svg { display: block; width: 20px; height: 20px; fill: currentColor; }

/* ---------- Responsive ---------- */
/* Groupes de boutons (header, services, footer) : passent à la ligne quand la colonne est trop étroite */
.intro__ctas, .services__ctas, .footer__ctas { flex-wrap: wrap; }

@media (max-width: 1180px) {
  .service { padding: var(--s4); }
}
@media (max-width: 980px) {
  .service__title { font-size: 28px; }
  /* Cartes empilées : texte à gauche, visuel à droite */
  .service { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s4); }
  .service > * { grid-column: 1; }
  .service > .service__visual { grid-column: 2; grid-row: 1 / -1; margin-top: 0; }
}
@media (max-width: 780px) {
  /* Titre de section : la règle reste sur la même ligne et prend la place restante */
  .split.section-line { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s3); row-gap: 0; }
  .split.section-line > * { grid-column: auto; }
  /* Boutons d'un même groupe : se partagent la ligne, ou passent l'un sous l'autre */
  .intro__ctas .btn, .services__ctas .btn, .footer__ctas .btn { flex: 1 1 auto; justify-content: space-between; gap: var(--s3); }
  /* Chiffres clés : valeur au-dessus du libellé, trois colonnes */
  .stats { height: auto; gap: var(--s3); container: stats / inline-size; }
  .stats__list { display: grid; grid-template-columns: repeat(3, auto); justify-content: space-between; gap: var(--gap); }
  .service { grid-template-columns: minmax(0, 1fr); }
  .service > .service__visual { grid-column: 1; grid-row: auto; margin-top: var(--s4); }
  .case__head { grid-template-columns: 56px 1fr; }
  .case__name { flex-wrap: wrap; row-gap: var(--s1); }
}

/* Chiffres clés (≤ 780) : valeur et libellé sur la même ligne tant que les trois tiennent (≈ 530px de texte),
   sinon valeur au-dessus du libellé */
@container stats (max-width: 530px) {
  .stats__list li { display: flex; flex-direction: column; gap: var(--s2); }
}

/* Très petits écrans (≤ 320) : chiffres clés en liste verticale, valeur et libellé sur la même ligne */
@media (max-width: 320px) {
  .stats__list { display: flex; flex-direction: column; gap: var(--s2); }
  .stats__list li { display: block; }
}

/* ---------- Switch : petit interrupteur (Voronoi / grille des clients) ---------- */
.switch { appearance: none; position: relative; flex: none; width: 24px; height: 12px; padding: 0; border: 0; border-radius: 6px; background: var(--line); cursor: pointer; transition: background 300ms var(--ease-out); }
.switch::after { content: ''; position: absolute; left: 2px; top: 2px; width: 8px; height: 8px; border-radius: 50%; background: var(--ink); transition: transform 300ms var(--ease-in-out); }
.switch[aria-checked="true"] { background: var(--neon); }
.switch[aria-checked="true"]::after { transform: translateX(12px); }
.switch:focus-visible { outline: 1px solid var(--neon); outline-offset: 2px; }

/* ---------- Hélice ADN (Helix, site 2025) : stockée dans le design system, pas utilisée sur le site pour l'instant ---------- */
.helix { --helix-light: color-mix(in srgb, var(--ink) 35%, var(--bg)); display: flex; justify-content: space-between; overflow: clip visible; padding: 4px 0; }
.helix span { --delay: calc((var(--i) - var(--n) + 1) * 200ms); flex: none; position: relative; width: 12px; height: 60px; }
.helix i { position: absolute; left: 50%; width: 1px; height: 102%; background: var(--ink); opacity: .35; animation: helix-line 750ms ease-in var(--delay) infinite alternate; }
.helix b { position: absolute; left: 2px; box-sizing: border-box; width: 7px; height: 7px; background: var(--bg); border: 1px solid var(--helix-light); border-radius: 50%; animation: 3s ease-in-out var(--delay) infinite; }
.helix b:first-of-type { top: 0; animation-name: helix-top; }
.helix b:last-of-type { bottom: 0; animation-name: helix-bottom; }
@keyframes helix-top { 0%, 100% { transform: translateY(-4px) scale(1); top: 0; } 50% { transform: translateY(0) scale(.4); top: 97%; } }
@keyframes helix-bottom { 0%, 100% { transform: translateY(4px) scale(.4); bottom: 0; } 50% { transform: translateY(0) scale(1); bottom: 97%; } }
@keyframes helix-line { from { transform: scaleY(1) translateX(-1px); } to { transform: scaleY(0) translateX(-1px); } }
@media (prefers-reduced-motion: reduce) { .helix i, .helix b { animation-play-state: paused; } }

/* ---------- Citations clients (QuoteBoard) : logo 3 colonnes, citation, auteur et photos à partir de la colonne 5 ---------- */
.quotes { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); }
.quotes__logo { grid-column: 1 / span 3; aspect-ratio: 1; align-self: start; display: grid; place-items: center; background: var(--line); }
.quotes__logo img { grid-area: 1 / 1; width: 36%; height: auto; opacity: 0; transition: opacity 300ms var(--ease-out); }
.quotes__body { grid-column: 5 / -1; display: grid; row-gap: var(--s8); position: relative; }
/* citations superposées : le bloc prend la hauteur de la plus longue, pas de saut au changement */
.quotes__texts { display: grid; }
.quotes__texts > * { grid-area: 1 / 1; opacity: 0; visibility: hidden; transition: opacity 300ms var(--ease-out), visibility 0s 300ms; }
.quotes__texts > .is-on, .quotes__logo .is-on { opacity: 1; visibility: visible; transition-delay: 0s; }
/* auteur sur la ligne des photos, calé à droite et centré sur leur hauteur : nom, puis poste · entreprise */
.quotes__who { position: absolute; right: 0; bottom: 0; height: 48px; display: grid; align-content: center; justify-items: end; gap: var(--s2); text-align: right; }
/* photos des auteurs sur une ligne, superposées, la première au-dessus (--z posé par QuoteBoard) ; l'active est en couleur */
.quotes__people { display: flex; align-items: center; }   /* sans ça les boutons s’étirent et leur anneau devient ovale */
.quotes__author { appearance: none; border: 0; background: none; padding: 0; cursor: pointer; position: relative; margin-left: calc(-1 * var(--s1)); border-radius: 50%; box-shadow: 0 0 0 3px var(--bg); z-index: var(--z); }
.quotes__author.is-on { z-index: 100; }   /* l'actif passe devant ses voisins : son anneau reste entier */
.quotes__author:first-child { margin-left: 0; }
.quotes__author.is-marked { box-shadow: 0 0 0 3px var(--neon); }
/* défilement automatique : l'anneau de l'auteur actif se remplit comme un minuteur, puis passe au suivant (scripts/ui.js) ; pause au survol */
@property --quote-timer { syntax: '<percentage>'; inherits: false; initial-value: 0%; }
[data-quotes-auto] .quotes__author.is-on::before { content: ''; position: absolute; inset: -3px; border-radius: 50%; background: conic-gradient(var(--neon) var(--quote-timer), transparent 0); mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px)); animation: quote-timer 8s linear forwards; }
[data-quotes-auto]:hover .quotes__author.is-on::before { animation-play-state: paused; }
@keyframes quote-timer { to { --quote-timer: 100%; } }
.quotes__avatar { display: block; width: 48px; height: 48px; border-radius: 50%; object-fit: cover; filter: grayscale(1); transition: filter 200ms var(--ease-out); }
.quotes__author:hover .quotes__avatar, .quotes__author.is-on .quotes__avatar { filter: none; }
@media (max-width: 780px) {
  .quotes__logo { display: none; }
  .quotes__body { grid-column: 1 / -1; }
}
/* trop étroit pour partager la ligne avec les photos : l'auteur repasse sous la citation */
@media (max-width: 520px) {
  .quotes__who { position: static; height: auto; justify-items: start; text-align: left; margin-top: var(--s4); }
}

/* ==========================================================================
   Layout commun : header de la home (hero), header des pages intérieures, footer
   ========================================================================== */

/* ---------- Hero (home) ----------
   Grille à 4 lignes : haut (label + Menu) · règle · titre · bas.
   À gauche : photo puis intro (lignes 1 à 3), logo en haut à droite de la colonne, boutons en bas. */
.hero { grid-template-rows: auto 8px 1fr auto; row-gap: var(--s1); padding-top: var(--s8); padding-bottom: var(--s12); }
.intro { grid-column: 1 / 5; grid-row: 1 / 4; display: flex; flex-direction: column; align-items: flex-start; }
.photo { width: 112px; height: 144px; background: var(--surface); overflow: hidden; }
.photo img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.intro__text { width: 300px; margin-top: var(--s4); line-height: 22px; }   /* interligne serré conservé pour l'intro du header */
.hero .logo-mark { grid-column: 1 / 5; grid-row: 1; justify-self: end; align-self: start; margin: -8px var(--s8) -11px 0; }   /* la ligne 1 finit 5px sous le centre de la fiole : le label (cap 10px) et le Menu se centrent dessus */
.hero__top { grid-column: 5 / -1; grid-row: 1; align-self: end; display: flex; justify-content: space-between; align-items: flex-end; }
.hero__ruler { grid-column: 5 / -1; grid-row: 2; margin-top: calc(var(--label-gap) - var(--s1)); }   /* + row-gap 8 = --label-gap */
.hero > .hero__ruler { margin-top: 6px; }   /* home : règle sous le Menu centré sur la fiole (+ row-gap 8 = 14px sous le label) */
/* Menu posé sur la règle : largeur d'un segment (1/7), les coins du bas tombent sur les graduations */
.hero .nav { width: calc(100% / 7); margin: -8px 0 -14px; top: 1px; }
/* Titre centré verticalement entre la règle du haut et celle des chiffres clés (la ligne 3 va d'une règle à l'autre) */
.headline { grid-column: 5 / -1; grid-row: 3; align-self: center; position: relative; padding: var(--s8) 0; }
.headline__title { position: relative; z-index: 3; display: grid; gap: var(--s1); font-weight: 400; }
/* Taille calée sur la largeur de la colonne (8/12) : 42px à 1440, réduite en dessous pour que la ligne la plus longue tienne */
/* Tailles fixes par point de rupture (plus de clamp : le titre ne rétrécit plus en continu). À 42px la ligne la plus longue fait 597px,
   « PRODUCTS » 423px : 42 tient dès 1032 en 8 colonnes et partout en pleine largeur (≤ 980) */
.headline .t-display { line-height: 1.1; }
@media (min-width: 981px) and (max-width: 1180px) { .headline .t-display { font-size: 36px; } }
.headline__row { display: flex; align-items: center; gap: var(--s2); }
.headline .sticker { position: absolute; z-index: 4; right: 19%; top: 122px; }
/* Erlenmeyer à la place du sparadrap (home alternative) : base de 192px, canvas de 560px centré dessus (cf. .notes__flask) */
.hero__flask { position: absolute; z-index: 30; right: calc(19% - var(--s6) - var(--s1)); top: 122px; width: 192px; height: 192px; }
/* Sparadrap glissé sous la base de l’Erlenmeyer, incliné (home alternative) : titre seul */
.hero__flask ~ .sticker { right: calc(19% + 17px + var(--s1)); top: calc(79px + var(--s6)); z-index: 29; transform: rotate(-10deg); }   /* mord sur le bas de « websites » */
.hero__flask ~ .sticker { width: auto; height: auto; }   /* hauteur donnée par le texte : même marge dessus et dessous */
.hero__flask ~ .sticker .sticker__body { justify-content: center; padding: var(--s1) var(--s2); }
.hero__flask ~ .sticker .sticker__title { align-self: flex-start; text-box: trim-both cap alphabetic; }
.hero__flask ~ .sticker .sticker__meta { display: none; }
.hero__flask ~ .sticker .sticker__stripes { width: calc(1cap + 2 * var(--s1)); font: 500 15px/1 var(--font-label); }   /* carré à la hauteur du texte et de ses marges (1cap : la police du titre) */
.hero__flask-lens { position: absolute; inset: 0; border-radius: 50%; }
.hero__flask-lens.is-on { backdrop-filter: url(#flask-lens); }   /* Chromium seulement ; ailleurs, pas de déformation */
.hero__flask-canvas { position: absolute; left: -184px; top: -184px; width: 560px; height: 560px; pointer-events: none; }
.hero__flask-hit { position: absolute; z-index: 1; inset: 0; border-radius: 50%; cursor: grab; touch-action: none; -webkit-tap-highlight-color: transparent; }
.hero__flask-hit.is-dragging { cursor: grabbing; }
.intro__ctas { grid-column: 1 / 5; grid-row: 4; align-self: end; display: flex; gap: var(--s2); }
.hero .stats { grid-column: 5 / -1; grid-row: 4; align-self: end; }
/* Sous le titre : verbes en noir, comme le libellé */
.hero .stats .c-neon { color: var(--ink); }
/* Chiffres clés calés sur les boutons (bureau) : boîte de 64px, texte centré comme le libellé des boutons,
   règle sortie au-dessus (sa ligne au ras du haut des boutons, les graduations ne comptent pas) */
@media (min-width: 981px) {
  .hero .stats { position: relative; height: 64px; justify-content: center; }
  .hero .stats .ruler { position: absolute; left: 0; right: 0; bottom: 100%; }
}

/* ---------- Header des pages intérieures : logo + disponibilité + Menu sur la règle ---------- */
.page-head { grid-template-rows: auto 8px; row-gap: var(--s1); padding-top: var(--s8); padding-bottom: var(--s8); }
/* Logo sur la ligne 1 comme sur la home : il donne sa hauteur à la ligne, Menu et règle tombent au même endroit */
/* fiole et textes posés sur la même ligne de base que « Available for freelance » (bas de la ligne 1).
   Le dessin de la fiole s'arrête 5.6px avant le bas de son SVG (53/60 de 48px) : on le fait descendre d'autant,
   et la marge du haut rend ces 5.6px pour que la ligne garde sa hauteur */
.page-head .crumbs { grid-column: 1 / 5; grid-row: 1; align-self: stretch; margin-top: calc(-8px + 5.6px); display: flex; align-items: flex-end; gap: var(--s2); min-width: 0; }
.page-head .crumbs .logo-mark { margin-bottom: -5.6px; }
/* fil d'Ariane : / néon comme les tags, pages parentes en gris, page courante en --ink */
.crumbs__sep { color: var(--neon); }
.crumbs__link { color: var(--muted); white-space: nowrap; transition: color 300ms var(--ease-out); }
.crumbs__link:hover { color: var(--ink); }
.crumbs__current { color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.page-head .hero__top { grid-row: 1; }
.page-head .hero__ruler { grid-row: 2; }
.page-head .nav { width: calc(100% / 7); margin: -8px 0 calc(-1 * var(--label-gap)); top: 1px; }
/* Une fois fixé (scripts/ui.js), la position vient du top mesuré : les marges ci-dessus le décaleraient de 8px */
.hero .nav.is-fixed, .page-head .nav.is-fixed { margin: 0; }

/* ---------- Intro des pages intérieures (PageIntro) : titre au-dessus du texte, colonne de droite ---------- */
.page-intro { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: var(--s6); margin: var(--s8) 0 var(--s12); }
.page-intro > * { grid-column: 5 / -1; }
.page-intro h1 { white-space: pre-line; }   /* un \n dans le titre (data/) force le retour à la ligne */
.page-intro .t-body { max-width: 60ch; }
@media (max-width: 780px) { .page-intro > * { grid-column: 1 / -1; } }
/* un titre en Mega Giga peut dépasser un écran de 360 : il se cale sur la largeur, comme le headline */
/* « PRODUCTS » à 30px : 302px, tient dès 350 ; en dessous (320), la taille suit la largeur pour qu'il tienne (423px à 42px) */
@media (max-width: 520px) { .headline .t-display { font-size: min(30px, calc((100vw - 2 * var(--gutter)) / 10.4)); } }
@media (max-width: 520px) { .page-intro h1 { font-size: min(42px, calc((100vw - 2 * var(--gutter)) / 10.4)); line-height: 1.1; } }

/* ---------- Footer ---------- */
.footer { margin: var(--s16) auto 0; padding-bottom: var(--s8); }
/* « Contact » à gauche et la règle à droite sur la même ligne, puis texte + réseaux / grand titre, puis boutons / liens */
.footer__grid { grid-template-rows: auto auto auto; row-gap: 0; align-items: start; }
.footer__label { grid-column: 1 / 5; grid-row: 1; }
.footer__ruler { grid-column: 5 / -1; grid-row: 1; margin-top: 5px; }
.footer .logo-mark { grid-column: 1 / 5; grid-row: 1; justify-self: end; align-self: start; margin: -21px var(--s5) 0 0; position: relative; z-index: 1; }
.footer__cta { grid-column: 1 / 5; grid-row: 2; padding-top: calc(var(--s8) - 14px); display: grid; align-content: start; justify-items: start; gap: var(--s4); }
.footer__cta .t-body { max-width: 36ch; }
/* titre centré entre les deux règles (graduations vers l'extérieur) : la ligne 1 de la grille déborde de 14px sous la règle du haut, retirés en haut ; le texte de gauche suit */
.footer__title { grid-column: 5 / -1; grid-row: 2; padding: calc(var(--s8) - 14px) 0 var(--s8); font-size: clamp(32px, 2.7vw, 42px); line-height: 1.1; }
.footer__ctas { grid-column: 1 / 5; grid-row: 3; align-self: start; display: flex; gap: var(--s2); }
.footer__links { grid-column: 5 / -1; grid-row: 3; position: relative; }
/* Erlenmeyer (sections/Flask.astro) à cheval sur la règle des liens, au bout à droite : base centrée à 48px du bord, 24px sous le trait */
.footer .hero__flask { right: calc(var(--s6) - 96px); left: auto; top: calc(var(--s3) - 96px); }
.footer__nav { display: grid; grid-auto-flow: column; grid-auto-columns: max-content; justify-content: start; column-gap: var(--s12); align-content: start; margin-top: var(--label-gap); }
.footer__col { display: grid; align-content: start; gap: var(--s3); }
.footer__col ul { list-style: none; display: grid; gap: var(--s1); }
/* Case studies répartis en 2 colonnes (4 + 4), remplies de haut en bas ; toutes les colonnes du footer à la largeur des noms, même écart (--s12) */
.footer__col--cases ul { grid-template-columns: repeat(2, max-content); justify-content: start; grid-template-rows: repeat(4, auto); grid-auto-flow: column; column-gap: var(--s12); }
.footer__col a, .footer__col span { color: var(--ink); }
.footer__col span.is-soon { color: var(--muted); }
.footer__bottom { margin-top: calc(var(--s16) - 172px); align-items: end; }   /* compense la hauteur du cadran */
/* Cadran : sa base est sur la même ligne que la règle de droite */
.footer__mark { position: relative; margin-bottom: var(--label-gap); }
.footer__mark svg { display: block; stroke: var(--neon); stroke-width: 1px; }
.footer__mark .footer__mark-fill { fill: url(#fireGrad); stroke: none; }
.footer__fire { position: absolute; left: 0; top: 0; width: 180px; height: 180px; pointer-events: none; }
.footer__gauge { position: absolute; left: 180px; top: 0; width: 29px; height: 180px; cursor: ns-resize; touch-action: none; outline: none; }
.footer__gauge:focus-visible { box-shadow: 0 0 0 2px var(--neon); }
/* Fiole de test (dev uniquement) : posée à droite du cadran, même gabarit que celle des notes (home.css) */
.footer__mark::after { content: ""; position: absolute; left: 0; bottom: 0; width: calc(100% + var(--gap)); height: 1px; background: var(--neon); }
.footer__legal { display: flex; justify-content: space-between; margin-top: var(--label-gap); }
.footer__legal a, .footer__legal span.is-soon { color: var(--tag); margin-left: var(--s3); }

/* ---------- Menu : la feuille blanche s'ouvre depuis le bouton Menu, son contenu apparaît en fondu à la fin ----------
   Le bouton Menu (fixe, z-index 50) reste au-dessus et sert de fermeture. --menu-top / --menu-right / --menu-w viennent
   de scripts/ui.js (position du bouton) : la feuille l'entoure avec 32px de marge en haut, 40px sur les côtés et en bas. Aucune mise à l'échelle.
   Ouverture (750ms) : forme + voile 0→550, fond 0→150, contenu 450→750.
   Fermeture = l'ouverture rejouée à l'envers : mêmes durées, délais en miroir (750 − fin), courbes en miroir (*-reverse).
   Contenu 0→300, forme + voile 200→750, fond 600→750. */
.menu { position: fixed; inset: 0; z-index: 40; overflow-y: auto; visibility: hidden; transition: visibility 0s linear 750ms; }
.menu.is-open { visibility: visible; transition: none; }
.menu::before { content: ''; position: fixed; inset: 0; background: var(--ink); opacity: 0; transition: opacity 550ms var(--ease-in-out-reverse) 200ms; }
.menu.is-open::before { opacity: .16; transition: opacity 550ms var(--ease-in-out); }
.menu__sheet {
  position: absolute; z-index: 1; isolation: isolate; top: var(--menu-top, var(--s4)); right: max(var(--s1), var(--menu-right, var(--gutter)));
  width: min(456px, calc(100vw - 2 * var(--s1)));   /* contenu de 376px ; hauteur : celle du contenu */
  display: flex; flex-direction: column; gap: var(--s4);
  padding: calc(var(--s4) + 40px + var(--s4)) var(--s5) var(--s5);   /* le bouton Menu (40px) occupe le haut */
  /* fermée : la forme a la taille du bouton (32px de marge en haut, 40px à droite, 40px de haut) */
  clip-path: inset(var(--s4) var(--s5) calc(100% - var(--s4) - 40px) calc(100% - var(--s5) - var(--menu-w, 120px)) round 2px);
  transition: clip-path 550ms var(--ease-in-out-reverse) 200ms;
}
.menu.is-open .menu__sheet { clip-path: inset(0 round 2px); transition: clip-path 550ms var(--ease-in-out); }
/* la forme naît et finit en fondu à la taille du bouton : pas de rectangle blanc qui apparaît ou disparaît d'un coup */
.menu__sheet::before { content: ''; position: absolute; z-index: -1; inset: 0; background: var(--surface); border-radius: 2px; opacity: 0; transition: opacity 150ms var(--ease-out-reverse) 600ms; }
.menu.is-open .menu__sheet::before { opacity: 1; transition: opacity 150ms var(--ease-out); }
/* contenu en cascade : chaque élément monte de 8px avec 40ms d'écart (--i posé dans Menu.astro) ; à la fermeture, tout part ensemble */
.menu__in { opacity: 0; transform: translateY(var(--s1)); transition: opacity 300ms var(--ease-out-reverse), transform 300ms var(--ease-out-reverse); }
.menu.is-open .menu__in { opacity: 1; transform: none; transition: opacity 400ms var(--ease-out), transform 600ms var(--ease-out); transition-delay: calc(400ms + var(--i) * 40ms); }
.menu__pages { list-style: none; display: grid; gap: var(--s1); }
.menu__page { font-size: 28px; line-height: 1.1; color: var(--ink); }
.menu__recent { display: grid; gap: var(--s2); }
.menu__cases { list-style: none; display: grid; gap: var(--s1); }
/* nom (roll au survol de la ligne, sans changement de couleur) · tags calés à droite · flèche */
.menu__case { display: flex; align-items: center; gap: var(--s2); color: var(--ink); }
.menu__case:hover .word__inner { transform: translateY(100%); }
.menu__tags { margin-left: auto; }
.menu__arrow { color: var(--neon); transition: transform 300ms var(--ease-out); }
.menu__case:hover .menu__arrow { transform: translateX(4px); }
.menu__foot { display: flex; justify-content: space-between; align-items: center; gap: var(--s3); }
.menu__foot .roll { color: var(--ink); }
html.menu-open { overflow: hidden; }
/* Recul de la page (scripts/ui.js) : chaque bloc visible se réduit, départs décalés du haut vers le bas.
   `scale` seul, pour ne pas écraser les transform déjà posés (notes inclinées, survols). */
.recede { transition: scale 550ms var(--ease-in-out-reverse) var(--recede-out, 0ms); }
.recede.is-receded { scale: .96; transition: scale 550ms var(--ease-in-out) var(--recede-in, 0ms); }
@media (prefers-reduced-motion: reduce) { .menu, .menu::before, .menu__sheet, .menu__sheet::before, .menu__in, .recede { transition: none; } }

/* ==========================================================================
   Responsive
   ========================================================================== */

/* ---------- Tablette (≤ 980) : header empilé — logo + Menu, disponibilité, règle, titre, intro, boutons, chiffres ---------- */
@media (max-width: 980px) {
  .hero, .page-head { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: none; row-gap: 0; padding-top: var(--s4); }
  .hero__top { display: contents; }
  .hero .logo-mark, .page-head .crumbs { grid-column: 1; grid-row: 1; justify-self: start; align-self: center; margin: 0; }
  .page-head .crumbs { align-items: center; }   /* fiole et Menu sur la même ligne : le texte se centre sur eux */
  .page-head .crumbs .logo-mark { margin-bottom: 0; }
  /* Menu en haut à droite, hors de la règle : sa largeur suit son contenu */
  .hero .nav, .page-head .nav { grid-column: 2; grid-row: 1; align-self: center; width: auto; padding: 0 var(--s2); margin: 0; top: 0; }
  .hero__top > p { grid-column: 1 / -1; grid-row: 2; margin-top: var(--s6); }
  /* même écart sous « Available for freelance » partout (la home ne garde pas ses 6px du bureau) */
  .hero__ruler, .hero > .hero__ruler, .page-head .hero__ruler { grid-column: 1 / -1; grid-row: 3; margin-top: var(--label-gap); }
  .headline { grid-column: 1 / -1; grid-row: 4; align-self: start; top: 0; padding: var(--s8) 0; }
  /* Sparadrap dans l'espace au-dessus du titre, à peine posé sur la première ligne */
  .headline { padding-top: var(--s12); }
  .headline .sticker { right: 0; top: var(--s5); transform: rotate(-4deg) scale(.8); transform-origin: right top; }
  .intro { grid-column: 1 / -1; grid-row: 5; flex-direction: row; align-items: flex-end; gap: var(--s3); }
  .intro__text { width: auto; max-width: 32ch; margin-top: 0; }
  .intro__ctas { grid-column: 1 / -1; grid-row: 6; margin-top: var(--s6); }
  .hero .stats { grid-column: 1 / -1; grid-row: 7; margin-top: var(--s8); }
  .hero { padding-bottom: var(--s12); }
}

/* ---------- 521 – 780 : titre sur deux lignes en pleine largeur ---------- */
/* Taille calée pour que « TURNING IDEAS INTO » (792px à 42px) remplisse la colonne ; sous 521, un mot par ligne */
@media (min-width: 521px) and (max-width: 780px) {
  .headline__title { display: block; font-size: calc((100vw - 2 * var(--gutter)) * .0525); }
  .headline__row { display: inline; }
  .headline .t-display { font-size: inherit; }
}

/* ---------- Très petits écrans (≤ 320) : photo de l'intro masquée ---------- */
@media (max-width: 320px) {
  .intro .photo { display: none; }
}

/* ---------- Mobile (≤ 780) ---------- */
@media (max-width: 780px) {
  .hero__flask { display: none; }
  /* Titre : un mot par ligne sous 521 (au-dessus, rangées en ligne, cf. tablette) */
  .headline__row { flex-direction: column; align-items: flex-start; gap: var(--s1); }
  .headline .sticker { transform: rotate(-4deg) scale(.7); }
  /* Titre resserré entre la règle et la suite : 48px au-dessus sur toutes les pages */
  .headline { padding: var(--s6) 0 var(--s5); }
  .page-head { padding-bottom: 0; }
  .page-intro { margin-top: var(--s6); }
  .photo { width: 88px; height: 112px; flex: none; }

  /* Footer : Contact + règle, titre, texte et réseaux, boutons, liens, cadran, mentions */
  .footer { margin-top: var(--s12); }
  .footer__grid { grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s3); }
  .footer__label { grid-column: 1; grid-row: 1; }
  .footer__ruler { grid-column: 2; grid-row: 1; }
  .footer .logo-mark { display: none; }
  .footer__title { grid-column: 1 / -1; grid-row: 2; padding: var(--s8) 0 var(--s6); font-size: clamp(24px, calc((100vw - 2 * var(--gutter)) * .075), 42px); }
  .footer__cta { grid-column: 1 / -1; grid-row: 3; padding-top: 0; }
  .footer__ctas { grid-column: 1 / -1; grid-row: 4; margin-top: var(--s6); }
  .footer__links { grid-column: 1 / -1; grid-row: 5; margin-top: var(--s8); }
  .footer__nav { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s6); }
  .footer__col--cases { grid-column: span 2; }
  .footer__mark { display: none; }   /* cadran masqué en mobile */
  /* Bas du footer : signature à gauche et copyright à droite au-dessus de la règle, les trois liens répartis en dessous */
  .footer__bottom.split { grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--s3); row-gap: 0; margin-top: var(--s8); align-items: end; }
  .footer__bottom > *, .footer__legal { display: contents; }
  .footer__mark-col > p { grid-column: 1; grid-row: 1; }
  .footer__legal > span:first-child { grid-column: 2; grid-row: 1; }
  .footer__bottom .ruler { grid-column: 1 / -1; grid-row: 2; margin-top: var(--label-gap); }
  .footer__legal > span:last-child { grid-column: 1 / -1; grid-row: 3; display: flex; justify-content: space-between; gap: var(--s3); margin-top: var(--label-gap); }
  .footer__legal a, .footer__legal span.is-soon { margin-left: 0; }
}

/* ==========================================================================
   Sections de la home : cases, liste, logos (Voronoi), services, about
   ========================================================================== */

/* ---------- Cases en quinconce : première ligne, une grande (8 col.) et une petite (4 col.) ---------- */
.cases { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: var(--s16); align-items: start; }
.cases__label + .cases { margin-top: var(--label-gap); }
/* petite case plus étroite que la grande, pour que l'écart de taille se lise comme voulu */
.cases > .case--lg { grid-column: span 8; }
.cases > .case--sm { grid-column: span 4; }
/* 40px entre deux cases côte à côte (même écart qu'entre les boutons du header et les chiffres clés) :
   la case de gauche se resserre, celle de droite reste calée sur la grille et les règles */
.cases { --case-gap: var(--s5); }
.cases > .case:first-child { margin-right: calc(var(--case-gap) - var(--gap)); }
/* Citations clients (sections/Quotes.astro) */
.quotes-section { margin-top: var(--s16); }
.quotes-section .section-line { margin-bottom: var(--s6); }

/* ---------- Expérimentation du lab en pleine largeur (LabFeature, pages secteur) : visuel posé sur le fond gris avec marges ---------- */
.feature { margin-top: var(--s16); }
.feature__media { position: relative; background: var(--line); padding: 4%; }   /* même marge que les cartes de cases (ui.css › .case__media) */
.feature__media--bleed { padding: 0; }   /* visuel qui a son propre décor (photo, mockup) : sans fond ni marge */
/* Switch entre les deux vues : en haut à droite, dans la marge, calé sur le bord droit du visuel */
.feature__media img { display: block; width: 100%; height: auto; }
/* Écran posé sur la photo (data/lab.js › screen) : remplit la zone de l'écran, rogné par le bas */
.feature__media .feature__screen { position: absolute; object-fit: cover; object-position: top; }
.feature__media .corner { opacity: 0; transition: opacity 200ms var(--ease-out); }
.feature__media:hover .corner { opacity: 1; }

/* ---------- Liste des autres cases : même largeur que la grande case au-dessus ---------- */
.cta-more { margin-top: var(--s6); }

/* ---------- Logos (Trusted by) ---------- */
.clients { margin: var(--s18) auto 0; position: relative; }
.clients__sub { margin-top: var(--label-gap); }
.clients__aside-slot { position: relative; }
/* le texte descend à 40px sous « Trusted by 50+ clients », le switch reste à 22 */
.clients__aside { position: absolute; z-index: 1; left: 0; top: calc(var(--s5) - var(--label-gap)); display: grid; gap: var(--s4); justify-items: start; width: 240px; }
.clients__switch { display: flex; justify-self: end; }   /* switch calé tout à droite, au bout de la règle */
.clients .ruler, .clients__switch, .clients .btn { position: relative; z-index: 1; }
/* Voronoi : la forme déborde de 100px au-dessus et en dessous des règles, 64px de chaque côté de la règle */
.voronoi {
  --cw: calc((100% - 11 * var(--gap)) / 12);
  position: relative; display: block; height: 600px; touch-action: pan-y;   /* le doigt fait défiler la page */
  width: calc(8 * var(--cw) + 7 * var(--gap) + 128px);
  margin: -76px 0 -76px calc(4 * var(--cw) + 4 * var(--gap) - 64px);   /* les cellules débordent des graduations ; les logos, eux, restent entre les deux (scripts/voronoi.js) */
  transition: margin-bottom 700ms var(--ease-in-out);
  overflow-anchor: none;   /* les logos bougent en continu : ils ne doivent pas servir d'ancre de scroll */
}
.voronoi.is-compressed { margin-bottom: -156px; }
/* Voronoi et grille dans une même scène : la vue affichée est dans le flux, l'autre se superpose (masquée) ;
   au switch, morphing de l'une à l'autre dans .clients__morph et la hauteur suit (scripts/clients-switch.js) */
.clients__stage { position: relative; display: flow-root; transition: height 900ms var(--ease-in-out); }
.clients__stage:not(.is-flow-grid) .clients-grid { position: absolute; top: 0; left: 0; right: 0; }
.clients__stage.is-flow-grid .voronoi { position: absolute; top: 0; left: 0; }
.clients__stage:not(.is-voronoi) .voronoi { visibility: hidden; pointer-events: none; }
.clients__stage.is-voronoi .clients-grid { visibility: hidden; }
.clients__stage .clients-grid li { opacity: 0; }
.clients__stage.is-grid .clients-grid li:not(.is-extra) { opacity: 1; }
/* logos absents du Voronoi : arrivent en fondu à la suite de la grille, repartent ensemble */
.clients__stage .clients-grid li.is-extra { transition: opacity 300ms var(--ease-out); }
.clients__stage.is-extras .clients-grid li.is-extra { opacity: 1; transition-duration: 600ms; transition-delay: calc(var(--i) * 80ms); }
.clients__morph { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
:is(.voronoi, .clients__morph) .cell { fill: var(--line); }
:is(.voronoi, .clients__morph) .vlogo-text { font: 500 14px var(--font-label); letter-spacing: -0.01em; text-transform: uppercase; fill: var(--ink); pointer-events: none; }
/* Grille : mêmes colonnes que la règle (8 sur 12), cases serrées, même marge en bas qu'en haut (règle ↔ grille) */
.clients-grid {
  --cw: calc((100% - 11 * var(--gap)) / 12);
  list-style: none; display: grid; grid-template-columns: repeat(6, 1fr); grid-auto-rows: 104px; gap: var(--s1);
  margin: var(--s3) 0 var(--s8) calc(4 * var(--cw) + 4 * var(--gap));
}
.clients-grid li { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s1); background: var(--line); border-radius: 2px; font: 500 14px/18px var(--font-label); letter-spacing: -0.01em; text-transform: uppercase; color: var(--ink); text-align: center; }
.clients-grid img { margin: -11px 0 -3px; }   /* carré de 60px réduit à 48 : le dessin fait ~26px */
.clients-grid__logo { width: 70%; height: 32px; background: var(--ink); mask: var(--logo) center / contain no-repeat; -webkit-mask: var(--logo) center / contain no-repeat; }
/* Mobile (≤ 520) : noms et logos un cran plus petits (logos du Voronoi réduits dans scripts/voronoi.js) */
@media (max-width: 520px) {
  :is(.voronoi, .clients__morph) .vlogo-text { font-size: 12px; }
  .clients-grid li { font-size: 12px; line-height: 16px; }
  .clients-grid img { width: 38px; height: 38px; margin: -9px 0 -2px; }
  .clients-grid__logo { height: 26px; }
}

/* ---------- Services ---------- */
.services { margin: var(--s18) auto; }   /* même écart au-dessus que celui des logos sous les citations */
.services .section-line { position: relative; z-index: 1; }
.services__cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap); margin: var(--s12) 0 var(--s8); }
.services__list { list-style: none; }
.services__list li { display: flex; align-items: center; gap: var(--s2); padding: var(--s1) 0; }
.services__bottom { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--s4); }
.services__ctas { display: flex; gap: var(--s2); flex: none; }

/* ---------- AI-native ---------- */
.ainative { margin: var(--s16) auto 0; }
.ainative__intro, .ainative__body { display: grid; align-content: start; gap: var(--s4); margin-top: var(--s6); text-wrap: pretty; }
.ainative__intro > .t-body { max-width: 36ch; }
/* Bureau : les deux colonnes partagent leurs rangées, l'intro se cale sur la hauteur du bandeau du process */
@media (min-width: 781px) {
  .ainative__intro, .ainative__body { grid-row: span 2; grid-template-rows: subgrid; gap: var(--s8); }
  .ainative__intro > .t-body { align-self: center; }
  .ainative .update { margin-top: 0; }
}
.ainative__points { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
/* triangle sur la ligne du titre, texte aligné sous le titre */
.ainative__point { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--s2); row-gap: var(--s2); }
.ainative__point > :not(.bullet) { grid-column: 2; }
.ainative__point > .t-body { max-width: 60ch; }
/* Bandeau du process (sections/Update.astro) : largeur des trois arguments, fond gris, date et titre à gauche, bouton calé à droite */
.update { position: relative; display: flex; align-items: center; justify-content: space-between; gap: var(--s4); background: var(--line); padding: var(--s3); margin-top: var(--s4); }
/* sparadrap miniature : annotation de date, détachée et de travers sur le coin haut gauche du bouton */
.update__cta { position: relative; }
.update .sticker--note { position: absolute; z-index: 1; left: calc(-1 * var(--s2)); top: calc(-1 * var(--s2)); width: auto; height: auto; padding: calc(var(--s1) / 2) var(--s1); transform: rotate(-6deg); }
.sticker--note .sticker__title { align-self: center; font-size: 11px; text-box: trim-both cap alphabetic; }
.sticker--note .sticker__meta { display: none; }
.sticker--note .sticker__stripes { display: none; }
@media (max-width: 780px) { .update { flex-direction: column; align-items: flex-start; } }

/* ---------- About (Process | Lab) ---------- */
.about { margin: var(--s16) auto 0; position: relative; }
.about__main, .about__strip { position: relative; z-index: 1; }
.split > .about__cols { grid-column: 5 / -1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gap); }
/* subgrid : les boutons restent sur la même ligne quelle que soit la longueur des textes */
.about__col { grid-row: span 4; display: grid; grid-template-rows: subgrid; row-gap: 0; justify-items: start; align-items: start; }
/* Figure de Lissajous à gauche du Lab : sur les 4 rangées de la sous-grille, sans en imposer la hauteur (le canvas est hors flux),
   carrée à la hauteur du Lab, calée à gauche */
.about__schema { grid-row: span 4; align-self: stretch; justify-self: stretch; position: relative; }
.about__schema canvas { position: absolute; left: 0; top: 0; height: 100%; aspect-ratio: 1; }
.about__col > .ruler { justify-self: stretch; margin-top: var(--label-gap); }
.about__col > .t-body { max-width: 46ch; margin-top: var(--s6); }
.about__col > .btn { margin-top: var(--s4); }
/* Bandeau d'images qui défile (emplacements du lab), ralenti au survol.
   Seule la largeur est réglée (rythme ci-dessous, ou stripSize dans data/lab.js) : la hauteur suit le format du visuel, jamais recadré.
   Le bandeau prend la hauteur du plus haut visuel. Largeur de base : environ trois visuels par largeur d'écran (rythme moyen 0,8),
   plafonnée à celle d'un écran de --max : au-delà (écrans larges, 21:9), les visuels gardent leur taille et le bandeau en montre davantage. */
.about__strip { --strip-w: min(40vw, var(--max) * .4); display: flex; align-items: flex-start; width: 100vw; margin: var(--s8) 0 0 calc(50% - 50vw); overflow: hidden; }
.about__track { display: flex; align-items: flex-start; gap: var(--gap); padding-right: var(--gap); flex: none; animation: about-scroll 60s linear infinite; }
.about__track figure { flex: none; width: calc(var(--strip-w) * var(--k, 1)); aspect-ratio: var(--ratio, 16 / 12); background: var(--line); }
.about__track figure:has(img, video) { background: none; }
.about__track img, .about__track video { display: block; width: 100%; height: auto; }
/* Cadre de couleur (stripFrame) : en haut, à gauche et à droite, le visuel posé sur le bas ; la hauteur suit le visuel */
.about__track figure.is-framed { aspect-ratio: auto; background: var(--frame); padding: var(--s4) var(--s4) 0; }
.about__track figure:nth-child(4n + 2) { --k: .733; }
.about__track figure:nth-child(4n + 3) { --k: .867; }
.about__track figure:nth-child(4n + 4) { --k: .6; }
/* Version 3D (scripts/ribbon.js) : les visuels sur un ruban en cercle ; le bandeau HTML reste dessous, masqué */
.about__ribbon { display: none; }
.about__strip.is-3d { position: relative; padding-bottom: var(--s4); }   /* un peu de marge : les visuels de devant dépassent à peine leur taille HTML */
.about__strip.is-3d .about__ribbon { display: block; position: absolute; inset: 0; width: 100%; height: 100%; }
.about__strip.is-3d .about__track { visibility: hidden; }
@keyframes about-scroll { to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) { .about__track { animation: none; } }

/* ---------- FAQ ---------- */
.faq { margin: var(--s12) auto 0; }
.faq__list { margin-top: var(--s4); }
/* numéro néon devant la question, comme les triangles de la liste des services */
.faq__question { display: flex; align-items: center; gap: var(--s2); padding: var(--s1) 0; cursor: pointer; list-style: none; }
.faq__question::-webkit-details-marker { display: none; }
.faq__question .t-body { transition: color 300ms var(--ease-out); }
.faq__question:hover .t-body { color: var(--ink); }
.faq__question:focus-visible { outline: 1px solid var(--neon); outline-offset: 4px; }
/* Plus néon, tourne en croix à l'ouverture */
.faq__icon { position: relative; flex: none; width: 11px; height: 11px; transition: transform 280ms var(--ease-in-out); }
.faq__icon i { position: absolute; left: 0; top: 5px; width: 11px; height: 1px; background: var(--neon); }
.faq__icon i + i { transform: rotate(90deg); }
.faq__item[open] .faq__icon { transform: rotate(45deg); }
.faq__num { flex: none; font-variant-numeric: tabular-nums; }   /* largeur du chiffre seul : même écart au texte que les triangles */
.faq__question h3 { flex: 1; min-width: 0; }
/* réponse alignée sur le texte de la question : le numéro y est répété, invisible, pour prendre sa largeur exacte */
.faq__answer { display: flex; gap: var(--s2); padding: var(--s2) 0 var(--s3); }
.faq__answer .faq__num { visibility: hidden; }
.faq__answer p { max-width: 60ch; color: var(--muted); }   /* plus clair que la question, et détaché d'elle */
/* Ouverture / fermeture : la hauteur de la réponse s'anime jusqu'à auto (Chrome, Safari récents ; ailleurs, sans animation) */
.faq { interpolate-size: allow-keywords; }
.faq__item::details-content { height: 0; overflow: clip; transition: height 400ms var(--ease-in-out), content-visibility 400ms allow-discrete; }
.faq__item[open]::details-content { height: auto; }
@media (prefers-reduced-motion: reduce) { .faq__item::details-content { transition: none; } }

/* ==========================================================================
   Responsive
   ========================================================================== */

/* ---------- Tablette (≤ 980) : cases sur deux colonnes, services empilés ---------- */
@media (max-width: 980px) {
  .cases { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--case-gap); row-gap: var(--s12); }
  .cases > .case { grid-column: auto; }
  .cases > .case:first-child { margin-right: 0; }

  .services__cards { grid-template-columns: minmax(0, 1fr); row-gap: calc(var(--s6) + var(--s4)); margin-top: var(--s12); }   /* + hauteur de l'onglet */
  .services__bottom { flex-direction: column; align-items: flex-start; gap: var(--s6); }
}

/* ---------- Mobile (≤ 780) ---------- */
@media (max-width: 780px) {
  .cases { grid-template-columns: minmax(0, 1fr); }

  /* Logos : texte et bouton au-dessus, Voronoi de bord à bord, moins haut */
  .clients { margin-top: var(--s16); }
  .clients__aside { position: static; width: auto; max-width: 40ch; }
  .voronoi { width: calc(100% + 2 * var(--gutter)); height: 520px; margin: var(--s2) calc(-1 * var(--gutter)) 0; }
  .voronoi.is-compressed { margin-bottom: -80px; }
  .clients-grid { grid-template-columns: repeat(3, 1fr); margin-left: 0; }

  .services { margin: var(--s16) auto; }
  .services__bottom { align-items: stretch; }

  /* About : colonnes empilées, bandeau moins haut */
  .split > .about__cols { grid-column: 1 / -1; grid-template-columns: minmax(0, 1fr); row-gap: var(--s12); }
  .about__col { grid-row: auto; grid-template-rows: none; }
  .about__schema { display: none; }   /* plus besoin d'aligner les boutons des deux colonnes */
  .about__strip { --strip-w: 267px; }

  .faq__list { margin-top: var(--s2); }
}

/* ---------- Bouton « voir tout » sous le travail (WorkGallery) ---------- */
.work-alt__more { align-items: start; margin-top: var(--s8); }
/* Règle des sections (Trusted by, Services) inversée : sur les 8 premières colonnes (deux cartes de services),
   bouton calé à droite ; la ligne de la règle (haut de sa boîte) s'aligne sur le haut du bouton */
.work-alt__more .ruler { grid-column: 1 / span 8; }
.work-alt__more .cta-more { grid-column: 9 / -1; justify-self: end; margin-top: 0; }
@media (max-width: 640px) {
  .work-alt__more { display: flex; gap: var(--s2); }   /* trop étroit pour 12 colonnes : la règle prend la place restante */
  .work-alt__more .ruler { flex: 1; }
}

/* ---------- Grille de travail de la home : bandes de 2 colonnes en maçonnerie, ponctuées d'un visuel pleine largeur, écarts de 8px (data/gallery.js) ---------- */
.gallery { display: grid; gap: var(--s1); margin-top: var(--label-gap); }
.gallery__band {
  --masonry-gap: var(--s1);
  list-style: none;
  display: grid; grid-template-columns: var(--tracks, repeat(var(--cols), minmax(0, 1fr))); gap: var(--masonry-gap); grid-auto-flow: dense;
}   /* --tracks : largeurs des colonnes de la bande (data/gallery.js › widths) */
.gallery__band.is-columns { display: flex; align-items: flex-start; }   /* avec JS : visuels rangés colonne par colonne, écarts exacts (scripts/masonry.js › initColumns) */
.gallery__band .masonry-col { display: grid; gap: var(--masonry-gap); min-width: 0; }
/* Fond gris et marge de 4 %, comme les cartes de cases (ui.css › .case__media) ; bord à bord pour un visuel en contexte */
.gallery__item { align-self: start; overflow: hidden; background: var(--line); padding: 4%; }
.gallery__band[style*="--cols: 1"] .gallery__item { padding: 2%; }   /* pleine largeur : même marge en pixels qu'un visuel de deux colonnes */
.gallery__item--bleed, .gallery__band[style*="--cols: 1"] .gallery__item--bleed { padding: 0; background: none; }
.gallery__item iframe { border: 0; }
.gallery__item--crop img, .gallery__item--crop video { object-fit: cover; object-position: top; }   /* bas rogné, seulement quand c'est demandé (data/gallery.js › cropTo) */
.gallery__item--flush { padding-bottom: 0; }   /* marge en haut et sur les côtés, écran collé en bas (data/gallery.js › flush) */
.gallery__item--bleed.gallery__item--pad { background: var(--fill); }
.gallery__item--pad img { object-fit: contain; object-position: center var(--pad-align, center); }   /* image entière, hauteur complétée par la couleur de son fond (data/gallery.js › padTo, fill) */
.gallery__item--inset { padding: var(--inset); }   /* visuel réduit : marge plus large sur le fond gris (data/gallery.js › inset) */
/* image agrandie, haut aligné sur le visuel voisin, bas qui déborde (data/gallery.js › frame, spill) ; arrondi propre au visuel */
.gallery__band .gallery__item.gallery__item--spill { aspect-ratio: var(--frame); padding: var(--spill-top) 0 0; }   /* aussi en pleine largeur (marge de 2 % sinon) */
.gallery__item.gallery__item--spill img { width: var(--spill-w); margin-inline: auto; border-radius: 8px; }
/* rail d'écrans (data/gallery.js › slides) : écrans à 70 % de la case, le premier centré, le suivant dépasse jusqu'au bord */
.gallery__band .gallery__item:has(.gallery__slides) { padding-inline: 0; }   /* marge en haut et en bas seulement : les écrans glissent jusqu'au bord de la case */
.gallery__slides { container-type: inline-size; overflow: hidden; }
.gallery__rail { display: flex; gap: var(--s2); padding-left: 15cqw; }
/* mouvement repris du one-pager (components/casestudy/casestudy-onepager.vue) : chaque écran part avec un léger décalage (--d),
   l'écart s'ouvre pendant le trajet et se referme à l'arrivée */
.gallery__item .gallery__rail img { flex: none; width: 70cqw; transform: translateX(calc(var(--i, 0) * -1 * (100% + var(--s2)))); transition: transform 1600ms var(--ease-in-out) var(--d, 0ms); }
/* visuel lié à une case study : toute la case est le lien ; infobulle client / typologie, décalée sous la souris */
.gallery__link { position: absolute; inset: 0; z-index: 2; }
.gallery__tip { position: fixed; top: var(--s2); left: var(--s2); z-index: 50; pointer-events: none; padding: var(--s1) var(--s2); background: var(--surface); color: var(--ink); border-radius: 2px; white-space: nowrap; }
.gallery__tip[hidden] { display: none; }
.gallery__item img, .gallery__item video, .gallery__item iframe { display: block; width: 100%; height: auto; aspect-ratio: var(--r); }
.gallery__item { position: relative; }
.gallery__item[data-n]::before { content: attr(data-n); position: absolute; top: var(--s1); left: var(--s1); z-index: 1; font: 500 14px/1 var(--font-label); color: red; opacity: 0; }   /* temporaire : numéro fixe des visuels (data/gallery.js › id) pendant la composition de la grille, visible au survol, à retirer */
.gallery__item[data-n]:hover::before { opacity: 1; }
.gallery ~ .work-alt__more { justify-content: flex-end; }   /* sans règle graduée : le bouton reste calé à droite quand la ligne passe en flex */

@media (max-width: 520px) {
  .gallery__band { grid-template-columns: minmax(0, 1fr); }
  .gallery__band .gallery__item:not(.gallery__item--bleed) { padding: 4%; }
  .gallery__band .gallery__item--flush { padding-bottom: 0; }
}
