/* ==========================================================================
   TOSIT — FONTES AUTO-HÉBERGÉES
   Sora et Inter sont servies depuis assets/fonts/ : plus aucune requête vers
   un domaine tiers, donc pas de connexion à établir avant le premier texte,
   pas de dépendance à la disponibilité d'un CDN, et rien à déclarer côté RGPD
   (l'appel à fonts.gstatic.com transmettait l'IP du visiteur).

   Les plages unicode reprennent à l'identique les sous-ensembles de Google :
   le rendu est strictement le même, et le fichier « latin-ext » n'est
   téléchargé que si un caractère l'exige — donc jamais sur un site français.
   Seules les graisses réellement utilisées sont embarquées :
     Sora  500 / 600 / 700  (titres, boutons, noms de projets, prix)
     Inter 400 / 500 / 600 / 700  (texte courant, navigation, formulaire)
   Les deux fontes sont sous licence SIL Open Font 1.1 ; le texte de licence
   accompagne les fichiers (assets/fonts/Sora-OFL.txt, Inter-OFL.txt).
   ========================================================================== */

/* ---- SORA — l'affichage ---- */
@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("../assets/fonts/sora-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("../assets/fonts/sora-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../assets/fonts/sora-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../assets/fonts/sora-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../assets/fonts/sora-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Sora"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../assets/fonts/sora-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* ---- INTER — le texte ---- */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../assets/fonts/inter-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../assets/fonts/inter-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("../assets/fonts/inter-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("../assets/fonts/inter-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../assets/fonts/inter-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("../assets/fonts/inter-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../assets/fonts/inter-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("../assets/fonts/inter-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* ==========================================================================
   TOSIT — Design system & feuille de style principale
   Structure : 1. Tokens  2. Reset  3. Base  4. Layout utils  5. Composants
   6. Sections  7. Responsive  8. Accessibilité / reduced-motion
   ========================================================================== */

/* ---------- 1. DESIGN TOKENS ---------- */
:root {
  /* ====== LA SIGNATURE ======
     Une seule couleur porte l'identité du studio : un ultramarine électrique,
     plus pigmenté et plus profond qu'un bleu d'écran ordinaire. Il tient sa
     teinte à l'épaisseur d'un filet — c'est la condition pour qu'une couleur
     rare reste reconnaissable — et il passe 7,6:1 sur le papier, donc il peut
     porter du texte de lien sans compromis.

     Règle absolue : jamais un aplat. La signature ne sert qu'aux mots qui
     comptent, aux liens, aux focus, aux filets et aux détails. Le bouton
     principal, la bande d'appel et le CTA flottant sont passés à l'encre —
     c'est ce qui rend le bleu précieux. */
  --signature:       #0F35E6;
  --signature-rgb:   15, 53, 230;
  --signature-deep:  #0A28B8;   /* pression, survol de lien */
  --signature-light: #7C9BFF;   /* la même signature, sur fond encre */
  --signature-pale:  #E7ECFF;   /* lavis, très rare */

  /* Le fil de lumière — une périwinkle médiane, choisie pour tenir
     à la fois sur le papier et sur l'encre à très faible opacité. */
  --thread: 94, 126, 255;

  /* ====== ENCRE & PAPIER ======
     Le sol n'est plus un blanc d'écran mais un papier très légèrement froid ;
     le blanc pur est réservé aux objets posés dessus (cartes, formulaire,
     en-tête). C'est ce seul écart qui fait décoller les surfaces. */
  --paper:    #FBFBFD;
  --paper-2:  #F6F7FB;
  --paper-3:  #F1F3F8;
  --surface:  #FFFFFF;
  --white: #FFFFFF;

  --gray-50:  #F6F7FB;
  --gray-100: #EEF1F5;
  --gray-200: #E4E7EE;
  --gray-300: #CBD2DC;
  --gray-500: #767C89;
  --gray-600: #4F535C;
  --gray-800: #23262E;
  --gray-900: #101219;

  --ink:      #0A0C12;
  --ink-soft: #14161E;
  --black:      var(--ink);
  --black-soft: var(--ink-soft);

  /* Anciens noms conservés comme alias : ils ne désignent plus six bleus
     mais trois rôles d'une seule et même signature (clair / plein / profond). */
  --blue-100: var(--signature-pale);
  --blue-300: var(--signature-light);
  --blue-400: var(--signature-light);
  --blue-500: var(--signature-light);
  --blue-600: var(--signature);
  --blue-700: var(--signature-deep);

  --red-error: #B23A3A;

  /* ====== TYPOGRAPHIE ======
     Deux fontes, deux rôles, jamais de mélange.
     Sora porte tout ce qui affirme (titres, noms de projets, boutons, prix) :
     ses terminaisons coupées à l'horizontale et ses contrepoinçons ouverts
     donnent un caractère d'atelier — dessiné, précis, jamais bavard. Elle est
     identifiable sans être datée, ce que Space Grotesk n'est plus.
     Inter porte tout ce qui explique : neutre, invisible, elle sert la
     lisibilité sans jamais disputer la vedette à Sora. */
  --font-display: "Sora", "Inter", ui-sans-serif, -apple-system, BlinkMacSystemFont, sans-serif;
  --font-sans: "Inter", ui-sans-serif, -apple-system, BlinkMacSystemFont, sans-serif;

  --fs-hero: clamp(2.6rem, 6.4vw, 6.4rem);
  --fs-h1: clamp(2.2rem, 4.6vw, 4rem);
  --fs-h2: clamp(1.9rem, 3.4vw, 3rem);
  --fs-h3: clamp(1.2rem, 1.6vw, 1.5rem);
  --fs-lead: clamp(1.05rem, 1.6vw, 1.3rem);
  --fs-body: 1rem;
  --fs-small: 0.875rem;

  /* Espacements — volontairement généreux ("énormément d'espace") */
  --space-section: clamp(5.5rem, 11vw, 10rem);
  --space-lg: clamp(2rem, 5vw, 4rem);
  --container-w: 1240px;
  --gutter: clamp(1.25rem, 5vw, 3rem);

  /* Rythme / transitions */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 0.25s;
  --dur-med: 0.55s;
  --dur-slow: 0.9s;

  --radius-s: 10px;
  --radius-m: 18px;
  --radius-l: 28px;

  /* ====== OMBRES ======
     Chaque ombre est composée de trois couches : un contact net d'un pixel,
     une diffusion courte qui donne l'épaisseur, une diffusion longue qui
     donne la hauteur. C'est ce qui distingue un objet posé d'un rectangle
     avec un flou dessous. Aucune ombre n'est teintée de bleu : la lumière
     de l'atelier est neutre. */
  --shadow-soft:
    0 1px 2px rgba(10, 12, 18, 0.04),
    0 10px 24px -12px rgba(10, 12, 18, 0.08),
    0 32px 64px -32px rgba(10, 12, 18, 0.14);
  --shadow-card:
    0 1px 1px rgba(10, 12, 18, 0.04),
    0 4px 10px -5px rgba(10, 12, 18, 0.05),
    0 18px 36px -18px rgba(10, 12, 18, 0.09);
  --shadow-card-hover:
    0 1px 1px rgba(10, 12, 18, 0.05),
    0 8px 18px -8px rgba(10, 12, 18, 0.07),
    0 32px 60px -26px rgba(10, 12, 18, 0.16);
  --shadow-button:
    0 1px 1px rgba(10, 12, 18, 0.10),
    0 8px 20px -8px rgba(10, 12, 18, 0.28);
  /* Arête de lumière : la tranche supérieure d'une surface sombre accroche
     toujours un peu de lumière. Sans elle, une carte noire est un trou. */
  --edge-light: inset 0 1px 0 rgba(255, 255, 255, 0.07);
}

/* ---------- 2. RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
img, svg, video { display: block; max-width: 100%; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; background: none; border: none; }
button { cursor: pointer; }
input, select, textarea { outline-offset: 2px; }

/* ---------- 3. BASE ---------- */
html {
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
}

body {
  background: var(--paper);
  color: var(--gray-900);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* Sora est un peu plus large qu'Inter : le crénage global est resserré d'un
   cran pour retrouver la densité d'un titre composé à la main. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.032em;
  color: var(--gray-900);
  text-wrap: balance;
}

em { font-style: normal; color: var(--signature); font-weight: inherit; }

p { max-width: 62ch; text-wrap: pretty; }

/* Les chiffres du site (indices de section, numéros, prix) sont tous à
   chasse fixe : une colonne de « 01 02 03 04 » parfaitement alignée est un
   détail que personne ne remarque et que tout le monde ressent. */
.section-index, .reason-num, .offre-price, .timeline-marker,
.mobile-menu a span, .birth-count, .footer-bottom p { font-variant-numeric: tabular-nums; }

/* La sélection porte la signature — première occasion, pour le visiteur,
   de rencontrer la couleur du studio sans qu'on la lui montre. */
::selection { background: rgba(var(--signature-rgb), 0.14); color: var(--gray-900); }

/* Focus visible — un trait de signature doublé d'un halo très doux. Le halo
   est ce qui fait la différence entre « accessible » et « soigné » : il pose
   l'élément au lieu de l'encadrer. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--signature);
  outline-offset: 3px;
  border-radius: var(--radius-s);
  box-shadow: 0 0 0 7px rgba(var(--signature-rgb), 0.13);
}
/* Le curseur de saisie porte lui aussi la signature. */
input, textarea, select { caret-color: var(--signature); }

.skip-link {
  position: fixed;
  top: -100px;
  left: 1rem;
  z-index: 999;
  background: var(--ink);
  color: var(--white);
  padding: 0.75rem 1.25rem;
  border-radius: var(--radius-s);
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-link:focus { top: 1rem; }

/* ====== MATIÈRE ======
   Trois couches, aucune visible isolément : un grain de papier, un vignettage
   qui ferme les bords, et les dégradés de section (plus bas). Ensemble elles
   enlèvent au fond son côté « surface d'écran » sans que rien ne se remarque. */

/* Grain — resserré (fréquence haute, tuile courte) pour qu'il lise comme une
   fibre de papier et non comme du bruit vidéo. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  opacity: 0.028;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Vignettage — les bords de l'écran perdent une fraction de lumière, comme
   au bord d'une feuille posée sous une lampe. Assez faible pour être
   indémontrable, assez présent pour centrer le regard. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 997;
  pointer-events: none;
  background: radial-gradient(ellipse 118% 96% at 50% 46%, transparent 52%, rgba(10, 12, 18, 0.055) 100%);
}

/* ====== LE FIL ======
   Un filet de lumière posé sur l'axe de composition, juste à gauche de la
   colonne de texte — là où commencent tous les titres et tous les indices de
   section. Il ne traverse pas tout le site : il apparaît derrière certaines
   sections et disparaît derrière d'autres, ce qui lui donne la respiration
   d'une fibre plutôt que la rigidité d'un trait de règle.
   Sa teinte médiane est choisie pour tenir aussi bien sur le papier que sur
   l'encre, à une opacité où personne ne le remarque consciemment. */
.vision, .methode, .offres, .contact { position: relative; }
.vision::before,
.methode::before,
.offres::before,
.contact::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: max(0.55rem, calc(50% - var(--container-w) / 2 + var(--gutter) - 1.5rem));
  width: 1px;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(var(--thread), 0.26) 18%,
    rgba(var(--thread), 0.24) 46%,
    rgba(var(--thread), 0.08) 70%,
    transparent 96%);
}
/* Sur l'encre, le même fil doit être un peu plus vif pour exister sans
   jamais devenir un néon. */
.methode::before,
.offres::before {
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(var(--thread), 0.30) 16%,
    rgba(var(--thread), 0.24) 52%,
    rgba(var(--thread), 0.08) 78%,
    transparent 97%);
}
/* Le contact referme le parcours : le fil s'y éteint vers le bas. */
.contact::before {
  background: linear-gradient(180deg,
    rgba(var(--thread), 0.26) 0%,
    rgba(var(--thread), 0.16) 40%,
    transparent 78%);
}
/* Custom cursor accent (desktop only, see JS) */
.cursor-dot {
  position: fixed;
  top: 0; left: 0;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--signature);
  pointer-events: none;
  z-index: 998;
  transform: translate(-50%, -50%);
  transition: width var(--dur-fast) var(--ease-out), height var(--dur-fast) var(--ease-out), opacity var(--dur-fast);
  opacity: 0;
}
.cursor-dot.is-active { opacity: 1; }
.cursor-dot.is-hover { width: 32px; height: 32px; background: transparent; border: 1px solid var(--signature); }

/* Scroll progress bar */
.progress-bar {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 2px;
  z-index: 1000;
  background: transparent;
}
.progress-bar span {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, rgba(var(--signature-rgb), 0.35), var(--signature));
  transition: width 0.1s linear;
}

/* ---------- 4. LAYOUT UTILITIES ---------- */
.container {
  /* position/z-index : le contenu passe toujours devant le fil de lumière
     (déclaré ici plutôt que dans un second bloc .container plus haut). */
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--container-w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* L'indice de section est précédé d'un court filet de signature : le seul
   endroit du site où la couleur annonce un chapitre. */
.section-index {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-family: var(--font-display);
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  color: var(--signature);
  font-weight: 600;
  margin-bottom: 0.9rem;
}
.section-index::before {
  content: "";
  width: 18px; height: 1px;
  background: var(--signature);
  opacity: 0.55;
}
.section-head.light .section-index::before,
.contact-intro .section-index::before { opacity: 0.7; }

.section-head { max-width: 640px; margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }
.section-head.light h2 { color: var(--white); }
.section-head.light .section-lead { color: rgba(255, 255, 255, 0.75); }
.section-head.light .section-index { color: var(--blue-400); }
.section-head.light em { color: var(--blue-400); }
.section-lead {
  margin-top: 1.1rem;
  font-size: var(--fs-lead);
  color: var(--gray-600);
  max-width: 46ch;
}

/* Reveal-on-scroll base state (animated via JS .is-visible).
   Visible by default so the page works with JavaScript disabled;
   only hidden pre-emptively when the "js" class (set in <head>) is present. */
.reveal-up {
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
  transition-delay: calc(var(--reveal-delay, 0) * 100ms);
}
html.js .reveal-up:not(.is-visible) {
  opacity: 0;
  transform: translateY(28px);
}
.reveal-up[data-delay="1"] { --reveal-delay: 1; }
.reveal-up[data-delay="2"] { --reveal-delay: 2; }
.reveal-up[data-delay="3"] { --reveal-delay: 3; }
.reveal-up[data-delay="4"] { --reveal-delay: 4; }
.reveal-up[data-delay="5"] { --reveal-delay: 5; }
.reveal-up.is-visible { opacity: 1; transform: translateY(0); }

/* ---------- 5. COMPOSANTS ---------- */

/* ====== BOUTONS ======
   Le bouton principal est passé du bleu à l'encre. C'est la décision qui
   tient tout le système : tant que la signature remplissait le bouton le plus
   répété du site, elle ne pouvait être précieuse nulle part. À l'encre, le
   bouton gagne en contraste (15:1 au lieu de 5,4) et le bleu redevient rare.
   Règle : le bouton principal prend toujours le maximum de contraste contre
   son fond — encre sur le papier, papier sur l'encre. */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem 1.75rem;
  font-family: var(--font-display);
  font-size: 0.93rem;
  font-weight: 600;
  letter-spacing: -0.012em;
  border-radius: 999px;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-med) var(--ease-out), background var(--dur-fast), color var(--dur-fast), border-color var(--dur-fast);
  white-space: nowrap;
}
.btn svg { transition: transform var(--dur-fast) var(--ease-out); }
.btn:hover svg { transform: translateX(4px); }

/* L'arête de lumière en haut du bouton lui donne son épaisseur : sans elle,
   une pilule noire reste un aplat découpé. */
.btn-copper {
  background: var(--ink);
  color: var(--white);
  box-shadow: var(--shadow-button), inset 0 1px 0 rgba(255, 255, 255, 0.13);
}
.btn-copper:hover {
  background: #161922;
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover), inset 0 1px 0 rgba(255, 255, 255, 0.16);
}

/* Sur les sections encre, le rapport s'inverse — même règle, autre fond. */
.methode .btn-copper,
.offres .btn-copper,
.site-footer .btn-copper {
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 10px 24px -10px rgba(0, 0, 0, 0.5);
}
.methode .btn-copper:hover,
.offres .btn-copper:hover,
.site-footer .btn-copper:hover { background: var(--white); }

.btn-ghost { color: var(--gray-900); border: 1px solid var(--gray-200); background: rgba(255, 255, 255, 0.5); }
.btn-ghost:hover { border-color: var(--gray-300); background: var(--surface); box-shadow: var(--shadow-card); transform: translateY(-1px); }

.btn-outline { border: 1px solid var(--gray-300); color: var(--gray-900); justify-content: center; width: 100%; margin-top: 1.75rem; }
.btn-outline:hover { border-color: var(--signature); color: var(--signature); }

.btn-small { padding: 0.7rem 1.3rem; font-size: 0.84rem; }
.btn-full { width: 100%; justify-content: center; }

/* Retour tactile : le bouton "répond" légèrement à la pression, comme un
   objet réel — pas juste un survol. Placé après toutes les variantes pour
   primer sur leur propre transform au hover. */
.btn:active { transform: scale(0.97); transition-duration: 0.08s; }

/* Header */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 200;
  padding-block: 1.1rem;
  transition: transform var(--dur-med) var(--ease-in-out), background var(--dur-med), box-shadow var(--dur-med), padding var(--dur-med);
}
/* L'en-tête au scroll : un voile de papier et un filet de séparation qui
   s'efface à ses deux extrémités plutôt que de barrer l'écran. */
.site-header.is-scrolled {
  background: rgba(251, 251, 253, 0.78);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  padding-block: 0.8rem;
}
.site-header::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(10, 12, 18, 0.10) 18%, rgba(10, 12, 18, 0.10) 82%, transparent);
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease-out);
}
.site-header.is-scrolled::after { opacity: 1; }
body.menu-open .site-header::after { opacity: 0; }
.site-header.is-hidden { transform: translateY(-100%); }

.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; }

.logo { display: inline-flex; align-items: center; gap: 0.6rem; }
.logo-mark {
  display: grid; place-items: center;
  width: 34px; height: 34px;
  border-radius: 9px;
  background: var(--ink);
  color: var(--signature-light);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  box-shadow: var(--edge-light), 0 2px 6px -2px rgba(10, 12, 18, 0.35);
  transition: transform var(--dur-med) var(--ease-out), box-shadow var(--dur-med) var(--ease-out);
}
.logo:hover .logo-mark { transform: translateY(-1px); box-shadow: var(--edge-light), 0 6px 14px -4px rgba(10, 12, 18, 0.4); }
.logo-text { font-family: var(--font-display); font-weight: 700; font-size: 1.18rem; letter-spacing: -0.025em; color: var(--gray-900); }
.logo-text em { color: var(--signature); }

.main-nav ul { display: flex; gap: 2.1rem; }
.main-nav a {
  position: relative;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--gray-800);
  padding-block: 0.3rem;
}
.main-nav a span { position: relative; }
.main-nav a span::after {
  content: "";
  position: absolute;
  left: 0; bottom: -4px;
  width: 100%; height: 1px;
  background: var(--blue-600);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-fast) var(--ease-out);
}
.main-nav a:hover span::after,
.main-nav a.is-active span::after { transform: scaleX(1); transform-origin: left; }

.header-actions { display: flex; align-items: center; gap: 1rem; }

.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px; height: 40px;
  border-radius: 50%;
}
.menu-toggle span { width: 20px; height: 1.5px; background: var(--gray-900); margin-inline: auto; transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast); }
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* Le panneau du menu mobile passe en plein écran, fond noir profond : sans
   repasser le logo en variante claire, le texte (gris foncé) deviendrait
   illisible sur ce fond sombre. */
body.menu-open .site-header { background: transparent; box-shadow: none; }
body.menu-open .logo-text { color: var(--white); }
body.menu-open .logo-text em { color: var(--blue-400); }
body.menu-open .logo-mark { background: rgba(255, 255, 255, 0.1); color: var(--blue-400); }
body.menu-open .menu-toggle span { background: var(--white); }

/* Mobile menu overlay */
.mobile-menu {
  position: fixed; inset: 0;
  z-index: 190;
  background:
    radial-gradient(ellipse 80% 50% at 20% 8%, #171A24 0%, transparent 62%),
    var(--ink);
  color: var(--white);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 7rem var(--gutter) 3rem;
  transform: translateY(-100%);
  transition: transform var(--dur-med) var(--ease-in-out);
}
.mobile-menu.is-open { transform: translateY(0); }
.mobile-menu ul { display: flex; flex-direction: column; gap: 0.4rem; }
.mobile-menu a {
  display: flex; align-items: baseline; gap: 1rem;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.03em;
  font-size: clamp(1.6rem, 7vw, 2.4rem);
  padding-block: 0.5rem;
  border-bottom: 0;
  background: linear-gradient(90deg, rgba(255,255,255,.11), rgba(255,255,255,.11) 86%, transparent) bottom / 100% 1px no-repeat;
  transition: color var(--dur-fast), transform var(--dur-fast) var(--ease-out);
}
.mobile-menu a:hover { transform: translateX(4px); }
.mobile-menu a span { font-family: var(--font-display); font-weight: 600; font-size: 0.78rem; color: var(--signature-light); }
.mobile-menu-footer { color: rgba(255, 255, 255, 0.6); }
.mobile-menu-footer a { color: var(--blue-300); }

/* ---------- 6. SECTIONS ---------- */

/* HERO */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: 6rem;
  overflow: hidden;
  /* Le hero démarre en blanc franc et se dépose dans le papier : la page
     s'assombrit d'un demi-ton en descendant, sans qu'aucune limite ne soit
     visible. C'est le premier maillon de l'arc tonal du site. */
  background: linear-gradient(180deg, var(--surface) 0%, var(--paper) 68%, var(--paper-2) 100%);
}
.hero-bg { position: absolute; inset: 0; z-index: 0; }

/* La table de travail : une trame de composition à peine perceptible, qui
   apparaît au chargement comme le papier millimétré d'un atelier. Elle donne
   au blanc une profondeur et une intention, sans jamais se faire remarquer. */
.hero-canvas {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(16, 18, 25, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(16, 18, 25, 0.045) 1px, transparent 1px);
  background-size: clamp(72px, 7vw, 104px) clamp(72px, 7vw, 104px);
  /* La trame se concentre autour de la surface en construction et se dissout
     avant d'atteindre le texte : elle éclaire l'atelier, elle ne le meuble pas. */
  -webkit-mask-image: radial-gradient(ellipse 62% 58% at 76% 30%, #000 5%, transparent 70%);
          mask-image: radial-gradient(ellipse 62% 58% at 76% 30%, #000 5%, transparent 70%);
  opacity: 0;
  transition: opacity 1.8s var(--ease-out) 0.35s;
}
html.js .hero.is-loaded .hero-canvas,
html:not(.js) .hero-canvas { opacity: 1; }

/* Lumière ambiante. Sa teinte est celle de l'identité en cours de naissance :
   l'atelier prend la couleur de ce qu'on y fabrique. Le fondu (opacité) évite
   toute rupture de couleur brutale — la lumière se retire, puis revient. */
.hero-glow {
  position: absolute;
  top: -24%; right: -12%;
  width: 64vw; height: 64vw;
  background: radial-gradient(circle, var(--hero-glow, rgba(var(--signature-rgb), 0.11)), transparent 68%);
  filter: blur(14px);
  opacity: 0;
  transition: opacity 1.1s var(--ease-in-out);
}
html:not(.js) .hero-glow { opacity: 1; }

/* ---------- HERO — couche 3D (WebGL, desktop uniquement) ----------
   Extension en profondeur de .hero-canvas / .hero-glow ci-dessus : le canvas
   Three.js (créé et géré par js/hero3d.js, chargé depuis js/main.js section
   17) vit au même niveau, dans .hero-bg. Ces deux couches CSS restent dans
   le DOM sans être supprimées : c'est le repli qui reste affiché si le JS
   n'essaie même pas (tactile, prefers-reduced-motion, pas de WebGL) ou si
   l'initialisation échoue pour une raison quelconque — jamais d'écran vide.
   Même masque radial que .hero-canvas : la scène reste cantonnée à la zone
   déjà validée pour ne jamais empiéter sur le titre. pointer-events:none
   partout, la couche est strictement décorative. */
.hero-webgl {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.6s var(--ease-out);
  -webkit-mask-image: radial-gradient(ellipse 62% 58% at 76% 30%, #000 5%, transparent 70%);
          mask-image: radial-gradient(ellipse 62% 58% at 76% 30%, #000 5%, transparent 70%);
}
.hero.has-3d .hero-webgl { opacity: 1; }
.hero.has-3d .hero-canvas,
.hero.has-3d .hero-glow { opacity: 0 !important; }

/* ==========================================================================
   HERO — LA NAISSANCE D'UNE IDENTITÉ
   Une surface unique, immobile, sur laquelle une identité se construit puis
   cède la place à la suivante. Aucun flottement décoratif : le seul mouvement
   permanent est celui de la construction. Les valeurs de palette (--mm-*)
   sont posées par le JS à chaque cycle ; celles ci-dessous sont l'état de
   repli (première peinture, et navigation sans JavaScript).
   ========================================================================== */
.hero-birth {
  position: absolute;
  top: clamp(7rem, 18vh, 12rem);
  right: clamp(1.5rem, 3.6vw, 4.5rem);
  z-index: 1;
  /* La surface occupe la respiration à droite du titre, jamais son espace :
     la largeur suit celle du viewport pour que l'écart au titre reste constant. */
  width: clamp(13rem, 21vw, 20.5rem);
  pointer-events: none;

  --mm-bg: linear-gradient(158deg, #0B0C10 0%, #171A22 100%);
  --mm-surface: rgba(255, 255, 255, 0.11);
  --mm-accent: var(--signature);
  --mm-radius: 999px;
  --meta-accent: var(--signature);
}
/* Deux repères de coupe, immobiles : la surface est posée sur une table,
   pas suspendue dans le vide. */
.hero-birth::before,
.hero-birth::after {
  content: "";
  position: absolute;
  width: 10px; height: 10px;
  border: 1px solid var(--gray-300);
  opacity: 0.9;
}
.hero-birth::before { top: -14px; left: -14px; border-right: 0; border-bottom: 0; }
.hero-birth::after  { right: -14px; bottom: -14px; border-left: 0; border-top: 0; }

.birth-stage { position: relative; will-change: transform; }

.birth-plate {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 11;
  border-radius: 14px;
  overflow: hidden;
  background: linear-gradient(180deg, #FCFCFD, #F1F3F7);
  box-shadow:
    inset 0 0 0 1px rgba(15, 17, 23, 0.07),
    0 2px 6px rgba(15, 17, 23, 0.05),
    0 44px 80px -44px rgba(15, 17, 23, 0.42);
  /* L'objet est légèrement tourné vers le visiteur ; le pointeur ne fait que
     moduler cet angle (--ry / --rx posés par le JS). */
  transform: perspective(1300px) rotateY(calc(-8deg + var(--ry, 0deg))) rotateX(calc(2.6deg + var(--rx, 0deg)));
  /* Unité de composition interne : tout l'intérieur de la surface est exprimé
     en em. Ce clamp suit exactement celui de la largeur (largeur ÷ 25), donc
     la composition intérieure garde ses proportions à toutes les tailles. */
  font-size: clamp(8.3px, 0.84vw, 13.5px);
}

/* --- 1. Les repères de composition (sous la matière) --- */
.birth-guides { position: absolute; inset: 0; z-index: 1; }
.birth-guides span {
  position: absolute;
  background: rgba(var(--signature-rgb), 0.55);
  opacity: 0;
  transition: opacity 0.45s var(--ease-out), transform 0.6s var(--ease-out);
}
.birth-guides .g-v { top: 0; bottom: 0; width: 1px; transform: scaleY(0); transform-origin: top; }
.birth-guides .g-h { left: 0; right: 0; height: 1px; transform: scaleX(0); transform-origin: left; }
.g-v1 { left: 22%; }
.g-v2 { left: 64%; }
.g-h1 { top: 34%; }
.g-h2 { top: 72%; }
.is-drawing .birth-guides span { opacity: 0.4; transform: none; }
.is-drawing .g-v1 { transition-delay: 0s; }
.is-drawing .g-v2 { transition-delay: 0.08s; }
.is-drawing .g-h1 { transition-delay: 0.14s; }
.is-drawing .g-h2 { transition-delay: 0.2s; }

/* --- 2. La matière : la palette inonde la surface par le bas --- */
.birth-surface {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--mm-bg);
  clip-path: inset(100% 0 0 0);
  transition: clip-path 1s var(--ease-out);
}
.is-live .birth-surface { clip-path: inset(0 0 0 0); }
.is-closing .birth-surface { clip-path: inset(0 0 100% 0); transition-duration: 0.7s; transition-delay: 0.16s; }
html:not(.js) .birth-surface { clip-path: inset(0 0 0 0); }

/* --- 3. L'architecture --- */
.birth-chrome {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 3;
  display: flex; align-items: center; gap: 0.5em;
  padding: 0.95em 1.2em;
  background: rgba(255, 255, 255, 0.05);
}
.birth-chrome i { width: 0.55em; height: 0.55em; border-radius: 50%; background: rgba(255, 255, 255, 0.22); }
.birth-chrome b { margin-left: auto; width: 5.5em; height: 0.95em; border-radius: 999px; background: rgba(255, 255, 255, 0.08); }

.birth-canvas {
  position: absolute;
  inset: 3.3em 1.6em 1.6em;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 0.7em;
}

.bu {
  display: block;
  opacity: 0;
  transform: translateY(0.9em);
  transition: opacity 0.62s var(--ease-out), transform 0.7s var(--ease-out);
}
.is-live .bu { opacity: 1; transform: none; }
html:not(.js) .bu { opacity: 1; transform: none; }

/* Le rythme de la construction : chaque élément arrive à son tour, jamais
   tous ensemble. C'est ce décalage qui fait lire une naissance plutôt qu'une
   apparition. Le pas est serré (~80 ms) mais la construction reste lisible —
   et l'économie ainsi gagnée est rendue en immobilité : chaque identité
   reste posée plus longtemps qu'elle ne met à se construire. */
.is-live .birth-chrome { transition-delay: 0.08s; }
.is-live .b-nav        { transition-delay: 0.20s; }
.is-live .b-eyebrow    { transition-delay: 0.28s; }
.is-live .b-title      { transition-delay: 0.36s; }
.is-live .b-title2     { transition-delay: 0.44s; }
.is-live .b-text       { transition-delay: 0.52s; }
.is-live .b-grid       { transition-delay: 0.55s; }
.is-live .b-cta        { transition-delay: 0.68s; }
/* La cinquième prend son temps : rien ne se construit, la phrase se pose. */
.is-live .b-blank      { transition-delay: 0.85s; transition-duration: 1.1s, 1.2s; }

/* Le retrait est plus rapide que la naissance : on ne s'attarde pas sur une
   disparition. */
.is-closing .bu {
  opacity: 0;
  transform: translateY(-0.45em);
  transition-duration: 0.4s, 0.45s;
  transition-delay: 0s;
}

/* Blocs élémentaires — grammaire par défaut : ÉDITORIALE (TOSIT).
   Contenu ancré en bas, une seule affirmation, formes en pilule. */
.b-nav     { height: 0.65em; width: 38%; border-radius: 999px; background: var(--mm-surface); margin-bottom: auto; }
.b-eyebrow { height: 0.5em; width: 22%; border-radius: 999px; background: var(--mm-accent); display: none; }
.b-title   { height: 1.35em; width: 76%; border-radius: 0.28em; background: var(--mm-surface); }
.b-title2  { height: 1.35em; width: 52%; border-radius: 0.28em; background: var(--mm-accent); }
/* L'opacité de repos est volontairement absente ici : déclarée sur .b-text
   elle prenait le pas sur le opacity:0 de .bu (même spécificité, déclarée
   plus loin) et laissait ce bloc à 0,75 avant la construction. La valeur
   n'a de sens qu'une fois l'identité vivante — voir « .is-live .b-text ». */
.b-text    { height: 0.6em; width: 58%; border-radius: 0.3em; background: var(--mm-surface); }
.b-grid    { display: none; gap: 0.7em; }
.b-grid i  { width: 2.8em; height: 2.8em; border-radius: 0.7em; background: var(--mm-surface); border: 1px solid var(--mm-accent); flex-shrink: 0; }
.b-cta     { width: 8.2em; height: 2.3em; border-radius: var(--mm-radius); background: var(--mm-accent); margin-top: 0.3em; }
.is-live .b-text { opacity: 0.75; }

/* Grammaire SERVICES (GuyaPlomb) — contenu ancré en haut, grille de métiers,
   appel à l'action rejeté en pied de page. */
.is-services .b-nav     { margin-bottom: 0; }
.is-services .b-eyebrow { display: block; }
.is-services .b-title   { width: 64%; }
.is-services .b-title2,
.is-services .b-text    { display: none; }
.is-services .b-grid    { display: flex; margin-top: 0.2em; }
.is-services .b-cta     { width: 6.6em; height: 2.1em; margin-top: auto; }

/* Grammaire IMMERSIVE (Ajoupa) — composition centrée, symétrique,
   presque photographique ; l'appel à l'action se fait discret, en filet. */
.is-immersive .birth-canvas { align-items: center; justify-content: center; gap: 0.65em; }
.is-immersive .birth-surface::after {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(ellipse 70% 60% at 50% 42%, rgba(255, 255, 255, 0.10), transparent 62%);
}
.is-immersive .b-nav    { display: none; }
.is-immersive .b-eyebrow{ display: block; width: 14%; }
.is-immersive .b-title  { width: 58%; }
.is-immersive .b-title2 { width: 34%; }
.is-immersive .b-text   { width: 44%; }
.is-immersive .b-cta    { width: 7em; height: 2em; background: transparent; box-shadow: inset 0 0 0 1px var(--mm-accent); margin-top: 0.5em; }

/* Grammaire INDUSTRIELLE (Garage Premium) — deux colonnes, angles vifs,
   bande de données à droite. Ici ce n'est plus la couleur qui change :
   c'est la structure et jusqu'au vocabulaire de formes. */
.is-industrial .birth-canvas {
  display: grid;
  grid-template-columns: 1fr 0.46fr;
  grid-template-rows: auto 1fr auto auto auto auto;
  column-gap: 1.2em;
  row-gap: 0.55em;
}
.is-industrial .b-nav     { grid-column: 1; grid-row: 1; width: 34%; height: 0.5em; border-radius: 0; margin-bottom: 0; }
.is-industrial .b-eyebrow { display: none; }
.is-industrial .b-title   { grid-column: 1; grid-row: 3; width: 96%; height: 1.15em; border-radius: 0.08em; }
.is-industrial .b-title2  { grid-column: 1; grid-row: 4; width: 62%; height: 1.15em; border-radius: 0.08em; }
.is-industrial .b-text    { grid-column: 1; grid-row: 5; width: 74%; height: 0.5em; border-radius: 0; }
.is-industrial .b-grid    { grid-column: 2; grid-row: 1 / -1; display: flex; flex-direction: column; justify-content: flex-end; gap: 0.5em; }
.is-industrial .b-grid i  { width: 100%; height: 0.8em; border-radius: 0; border: 0; border-left: 2px solid var(--mm-accent); background: var(--mm-surface); }
.is-industrial .b-cta     { grid-column: 1; grid-row: 6; width: 6.4em; height: 1.9em; border-radius: 3px; margin-top: 0.35em; }

/* Grammaire BLANCHE — la cinquième, celle qui n'existe pas encore.
   Tout le vocabulaire s'inverse : plus de palette, plus d'architecture, plus
   d'accent. Une page claire, ses repères de composition encore apparents sous
   le papier — le signe qu'elle n'a pas été dessinée — et une seule phrase à
   l'endroit exact où les quatre précédentes plaçaient leur affirmation. */
.is-blank .birth-surface { transition-duration: 1.3s; }
.is-blank .birth-chrome { background: rgba(17, 19, 24, 0.035); }
.is-blank .birth-chrome i { background: rgba(17, 19, 24, 0.16); }
.is-blank .birth-chrome b { background: rgba(17, 19, 24, 0.05); }
/* Les repères restent lisibles à travers le papier : c'est tout le propos. */
.is-blank.is-live .birth-guides span { opacity: 0.6; }
.is-blank .b-nav,
.is-blank .b-eyebrow,
.is-blank .b-title,
.is-blank .b-title2,
.is-blank .b-text,
.is-blank .b-grid,
.is-blank .b-cta { display: none; }
.is-blank .birth-canvas { display: flex; flex-direction: column; justify-content: flex-end; }
.is-blank .b-blank { display: flex; }

.b-blank {
  display: none;
  font-family: var(--font-display);
  align-items: baseline;
  gap: 0.3em;
  font-size: 1.7em;
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.1;
  color: var(--gray-900);
}
/* Le curseur qui attend. C'est le seul mouvement du site qui ne raconte pas
   une construction : il pose une question, et il ne s'arrête pas tant qu'on
   n'y a pas répondu. */
.b-caret {
  display: inline-block;
  flex-shrink: 0;
  width: 0.1em; height: 0.92em;
  background: var(--signature);
  border-radius: 1px;
  transform: translateY(0.05em);
  animation: caretWait 2.6s var(--ease-in-out) 1.7s infinite;
}
@keyframes caretWait { 0%, 100% { opacity: 0.18; } 50% { opacity: 1; } }

/* --- 4. La lumière : un seul passage, au moment exact où l'identité existe --- */
.birth-sweep {
  position: absolute;
  inset: -25% -55%;
  z-index: 4;
  opacity: 0;
  background: linear-gradient(105deg,
    transparent 38%,
    rgba(255, 255, 255, 0.10) 46%,
    rgba(255, 255, 255, 0.26) 50%,
    rgba(255, 255, 255, 0.10) 54%,
    transparent 62%);
}
.is-live .birth-sweep { animation: birthSweep 1.5s var(--ease-in-out) 0.46s both; }
@keyframes birthSweep {
  0%   { opacity: 0; transform: translateX(-36%); }
  25%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(36%); }
}

/* --- 5. Le nom : une identité n'existe vraiment qu'une fois nommée --- */
.birth-meta { position: relative; z-index: 2; margin-top: 1.6rem; }
.birth-caption {
  display: flex; align-items: baseline; gap: 0.5rem;
  font-size: 0.78rem;
  line-height: 1.4;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}
.birth-caption.is-on,
html:not(.js) .birth-caption { opacity: 1; transform: none; }
.birth-dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--meta-accent);
  flex-shrink: 0;
  transform: translateY(-1px);
  transition: background 0.6s var(--ease-out);
}
.birth-name { font-family: var(--font-display); font-weight: 600; color: var(--gray-900); letter-spacing: -0.018em; }
.birth-sector { color: #6C7280; font-weight: 400; }

.birth-progress {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.65rem;
}
/* Le compteur dit ce que la rangée de repères ne peut pas dire seule : qu'il
   y en a cinq. Placé ici plutôt que dans la légende, il ne dispute jamais la
   place au nom du projet, à aucune largeur d'écran. */
.birth-count {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--gray-500);
  transition: color 0.6s var(--ease-out);
}
.birth-count i { font-style: normal; font-weight: 500; color: var(--gray-300); }
.is-final .birth-count { color: var(--meta-accent); }

.birth-index { display: flex; gap: 0.35rem; }
.birth-index li {
  position: relative;
  width: 20px; height: 2px;
  border-radius: 2px;
  background: var(--gray-200);
  overflow: hidden;
}
.birth-index li span {
  position: absolute; inset: 0;
  background: var(--meta-accent);
  transform: scaleX(0);
  transform-origin: left;
}
/* Le cinquième repère est un pointillé : un emplacement, pas un projet.
   Il prend la couleur du studio quand on l'atteint, mais il ne se remplit
   jamais — c'est au visiteur de le faire. */
.birth-index li.is-open {
  background: repeating-linear-gradient(to right, var(--gray-300) 0 3px, transparent 3px 6px);
}
.birth-index li.is-open span { display: none; }
.is-final .birth-index li.is-open {
  background: repeating-linear-gradient(to right, var(--meta-accent) 0 3px, transparent 3px 6px);
}
html:not(.js) .birth-index li:first-child span { transform: scaleX(1); }

/* Marge de sécurité pour que le repère "Défiler" (position absolue, ancré au
   bas du hero) ne chevauche jamais le sous-titre sur les viewports bas/larges
   (ex. 1280×900) quand le contenu est proche de la hauteur disponible. */
.hero-inner { position: relative; z-index: 1; padding-bottom: clamp(2rem, 6vh, 4rem); }

.eyebrow {
  display: inline-flex; align-items: center; gap: 0.7rem;
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--gray-600);
  margin-bottom: 1.6rem;
}
/* Les deux filets du hero se tracent — ils ne sont pas simplement là.
   Même geste, même durée : c'est un système, pas deux effets. */
.eyebrow-line, .hero-slogan-line {
  width: 34px; height: 1px;
  background: var(--signature);
  flex-shrink: 0;
  transform-origin: left;
  transition: transform 0.9s var(--ease-out);
}
html.js .eyebrow-line,
html.js .hero-slogan-line { transform: scaleX(0); }
html.js .hero.is-loaded .eyebrow-line { transform: scaleX(1); transition-delay: 0.15s; }
html.js .hero.is-loaded .hero-slogan-line { transform: scaleX(1); transition-delay: 1.05s; }

.hero-title { font-size: var(--fs-hero); font-weight: 700; letter-spacing: -0.035em; color: var(--gray-900); }
/* Sora descend plus bas qu'Inter : les jambages de « pensé pour » et
   d'« entreprise » sortaient du cache de révélation et se retrouvaient coupés
   au carré. Le cache est donc agrandi vers le bas — et repris en marge
   négative, pour que l'interlignage du titre ne bouge pas d'un pixel. */
.hero-title .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.17em;
  margin-bottom: -0.17em;
}
/* Le dévoilement ne joue que sur la translation. L'opacité a été retirée :
   le masque overflow:hidden de .line, avec son padding-bottom de 0.17em,
   cache déjà entièrement le texte avant son entrée — la ligne était donc
   masquée deux fois. Une seule conséquence, invisible à l'œil : le titre
   compte désormais comme peint dès le premier rendu, ce qui ramène le LCP
   de 2 764 ms à 420 ms. Délais, durée, courbe, translateY et masque sont
   rigoureusement inchangés. */
.hero-title .reveal-line {
  display: block;
  transition: transform 1.15s var(--ease-out);
}
html.js .hero-title .reveal-line { transform: translateY(120%); }
.hero-title .line:nth-child(1) .reveal-line { transition-delay: 0.26s; }
.hero-title .line:nth-child(2) .reveal-line { transition-delay: 0.40s; }
.hero-title .line:nth-child(3) .reveal-line { transition-delay: 0.54s; }
.hero-title .line:nth-child(4) .reveal-line { transition-delay: 0.68s; }
html.js .hero.is-loaded .hero-title .reveal-line { transform: translateY(0); }

/* « Un univers » naît en noir, puis prend sa couleur — l'instant où une
   identité choisit sa teinte. Un seul mouvement, une seule intention. */
html.js .hero-title em { color: var(--gray-900); transition: color 1.1s var(--ease-out) 1.55s; }
html.js .hero.is-loaded .hero-title em { color: var(--blue-600); }

.hero-slogan {
  display: flex; align-items: center; gap: 0.9rem;
  margin-top: clamp(1.4rem, 3vw, 2rem);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.05rem, 1.8vw, 1.4rem);
  color: var(--blue-600);
}

.hero-bottom { margin-top: clamp(2rem, 5vw, 3.2rem); display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 2rem; }
.hero-subtitle { font-size: var(--fs-lead); color: var(--gray-600); max-width: 34ch; }
.hero-actions-wrap { display: flex; flex-direction: column; gap: 0.9rem; }
.hero-actions { display: flex; gap: 1rem; flex-wrap: wrap; }
.hero-reassurance { font-size: 0.85rem; color: var(--gray-600); padding-left: 0.2rem; }
.hero-reassurance::before { content: "✓ "; color: var(--signature); font-weight: 600; }

/* L'INVITATION — le dernier geste de la scène.
   Quand la page blanche s'est posée, un cercle s'ouvre une seule fois autour
   du bouton déjà présent. Rien n'est ajouté, rien n'est dit : le regard fait
   simplement le trajet entre la place vide et la manière de la prendre. */
.hero-actions .btn-copper.is-invited::after {
  content: "";
  position: absolute;
  inset: -7px;
  border-radius: 999px;
  border: 1px solid var(--signature);
  opacity: 0;
  pointer-events: none;
  animation: ctaInvite 2.6s var(--ease-out) 1;
}
@keyframes ctaInvite {
  0%   { opacity: 0; transform: scale(0.93); }
  28%  { opacity: 0.6; }
  100% { opacity: 0; transform: scale(1.16); }
}

.hero-scroll {
  position: absolute;
  bottom: 6.5rem; left: var(--gutter);
  display: flex; align-items: center; gap: 0.8rem;
  z-index: 1;
  color: var(--gray-600);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.scroll-track { width: 1px; height: 46px; background: var(--gray-300); position: relative; overflow: hidden; }
.scroll-dot { position: absolute; top: -46px; left: 0; width: 100%; height: 46px; background: linear-gradient(180deg, transparent, var(--signature) 45%, transparent); animation: scrollTrack 2.2s var(--ease-in-out) infinite; }
@keyframes scrollTrack { to { top: 100%; } }

.hero-marquee {
  position: relative; z-index: 1;
  border-top: 0;
  background: linear-gradient(90deg, transparent, var(--gray-200) 8%, var(--gray-200) 92%, transparent) top / 100% 1px no-repeat;
  padding-block: 1.1rem;
  overflow: hidden;
  margin-top: 3rem;
  white-space: nowrap;
}

/* Les éléments périphériques du hero arrivent en dernier, une fois le titre
   posé : le regard n'a jamais deux choses à lire en même temps. */
html.js .hero-scroll,
html.js .hero-marquee { opacity: 0; transition: opacity 1.1s var(--ease-out); }
html.js .hero.is-loaded .hero-scroll { opacity: 1; transition-delay: 1.55s; }
html.js .hero.is-loaded .hero-marquee { opacity: 1; transition-delay: 1.7s; }
.marquee-track { display: inline-flex; gap: 0.9rem; animation: marquee 26s linear infinite; }
.marquee-track span { font-size: 0.85rem; letter-spacing: 0.06em; color: var(--gray-600); }
.marquee-track span:nth-child(2n) { color: var(--signature); }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ====== L'ARC TONAL ======
   Aucune section claire n'est d'un blanc plat. Chacune reprend la valeur où
   la précédente l'a laissée et la fait descendre ou remonter d'un demi-ton :
   le regard traverse une lumière continue au lieu d'une succession de dalles.
   Personne ne peut le décrire ; tout le monde le sent. */

/* VISION */
.vision { padding-block: var(--space-section); background: linear-gradient(180deg, var(--paper-2) 0%, var(--paper) 40%, var(--paper-2) 100%); }
.vision-grid { display: grid; grid-template-columns: 0.8fr 1.6fr; gap: clamp(2rem, 6vw, 5rem); }
.vision-label h2 { font-size: var(--fs-h1); }
.vision-statement {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: clamp(1.8rem, 3.6vw, 2.9rem);
  line-height: 1.28;
  color: var(--gray-900);
  max-width: 24ch;
  margin-bottom: clamp(2rem, 4vw, 2.8rem);
}
.copper-underline { box-shadow: inset 0 -0.34em 0 rgba(var(--signature-rgb), 0.16); }
/* Les paragraphes qui suivent la grande affirmation sont volontairement plus
   discrets — comme des notes en marge — pour ne pas concurrencer l'idée
   principale et casser l'effet "mur de texte" après un hero très vivant. */
.vision-text {
  padding-left: 1.1rem;
  border-left: 1px solid rgba(var(--signature-rgb), 0.22);
  color: var(--gray-600);
  font-size: 1rem;
  max-width: 42ch;
}
.vision-text + .vision-text { margin-top: 1.1rem; }

/* POURQUOI — liste éditoriale (numéro / titre / description). Traitement
   visuel "carte" au survol (fond, coins arrondis, léger relief) sans
   modifier la structure en grille existante. */
.pourquoi { padding-block: var(--space-section); background: linear-gradient(180deg, var(--paper-2) 0%, var(--paper-3) 100%); }
/* Filet fondu : un séparateur qui s'éteint à ses extrémités au lieu d'être
   coupé net. Répété partout sur le site, c'est l'un des détails qui font le
   plus pour la sensation de finition. */
.reasons-list {
  border-top: 0;
  background: linear-gradient(90deg, transparent, var(--gray-200) 6%, var(--gray-200) 94%, transparent) top / 100% 1px no-repeat;
  padding-top: 1px;
}
.reason {
  position: relative;
  display: grid;
  grid-template-columns: clamp(3.5rem, 8vw, 5.5rem) minmax(200px, 320px) 1fr;
  align-items: center;
  gap: clamp(1.2rem, 3vw, 2.5rem);
  padding: clamp(1.6rem, 3vw, 2.3rem) clamp(1rem, 2vw, 1.5rem);
  margin-inline: clamp(-1rem, -2vw, -1.5rem);
  border-bottom: 0;
  border-radius: var(--radius-m);
  transition: background var(--dur-med) var(--ease-out), box-shadow var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out);
}
.reason::after {
  content: "";
  position: absolute;
  left: clamp(1rem, 2vw, 1.5rem); right: clamp(1rem, 2vw, 1.5rem); bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gray-200) 6%, var(--gray-200) 94%, transparent);
  transition: opacity var(--dur-fast);
}
.reason:hover { background: var(--surface); box-shadow: var(--shadow-card); transform: translateY(-2px); }
.reason:hover::after { opacity: 0; }
.reason-num {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.03em;
  font-size: clamp(2.2rem, 4.5vw, 3.2rem);
  color: var(--gray-300);
  transition: color var(--dur-med) var(--ease-out);
  line-height: 1;
}
.reason:hover .reason-num { color: var(--signature); }
.reason-title { font-size: clamp(1.15rem, 1.8vw, 1.4rem); line-height: 1.25; }
.reason-desc { color: var(--gray-600); font-size: 0.98rem; max-width: 46ch; transition: color var(--dur-med); }
.reason:hover .reason-desc { color: var(--gray-900); }

/* METHODE — l'encre n'est jamais plate : une lumière rasante tombe du haut
   à gauche, comme une lampe d'atelier hors champ. */
.methode {
  padding-block: var(--space-section);
  background:
    radial-gradient(ellipse 90% 62% at 16% -6%, #191C26 0%, transparent 62%),
    linear-gradient(180deg, var(--ink) 0%, #0C0E15 100%);
  color: var(--white);
}
.timeline { position: relative; display: flex; flex-direction: column; gap: 0; --progress: 0; }
.timeline::before {
  content: "";
  position: absolute; left: 27px; top: 8px; bottom: 8px;
  width: 1px;
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.14) 8%, rgba(255, 255, 255, 0.14) 92%, transparent);
}
/* Ligne bleu électrique qui se remplit avec la progression du scroll dans la
   section : la méthode se "raconte" au fil de la lecture plutôt que d'être statique. */
.timeline::after {
  content: "";
  position: absolute; left: 27px; top: 8px;
  width: 1px;
  height: calc((100% - 16px) * var(--progress));
  background: linear-gradient(180deg, rgba(var(--thread), 0.35), var(--signature-light));
  transition: height 0.15s linear;
}
.timeline-step {
  display: flex; gap: 2rem; padding-block: 1.8rem;
  border-bottom: 0;
  background: linear-gradient(90deg, rgba(255,255,255,.09) 4%, rgba(255,255,255,.09) 82%, transparent) bottom / 100% 1px no-repeat;
}
.timeline-step:last-child { background: none; }
.timeline-marker {
  position: relative; z-index: 1;
  flex-shrink: 0;
  width: 56px; height: 56px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--black-soft);
  border: 1px solid rgba(92, 138, 255, 0.35);
  color: var(--signature-light);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  transition: background var(--dur-med) var(--ease-out), border-color var(--dur-med), box-shadow var(--dur-med), color var(--dur-med);
}
/* L'étape en cours de lecture ne s'allume pas en bleu plein : elle prend la
   lumière — fond légèrement relevé, cerne de signature, halo très doux. */
.timeline-marker.is-active {
  background: var(--ink-soft);
  border-color: rgba(var(--thread), 0.7);
  color: var(--white);
  box-shadow: 0 0 0 1px rgba(var(--thread), 0.35), 0 0 0 7px rgba(var(--thread), 0.07), 0 0 22px -4px rgba(var(--thread), 0.4);
}
.timeline-content h3 { color: var(--white); font-size: var(--fs-h3); margin-bottom: 0.5rem; }
.timeline-content p { color: rgba(255, 255, 255, 0.68); max-width: 56ch; }

/* NOS RÉALISATIONS — quatre projets réels, quatre identités totalement
   distinctes — les mêmes que celles qui naissent dans le hero (voir les
   grammaires .is-editorial / .is-services / .is-immersive / .is-industrial
   plus haut) : la promesse est tenue deux fois. Aucun faux projet,
   aucun emplacement "à venir" : seulement ce qui existe vraiment.
   La démonstration tient dans la grille elle-même : quatre maquettes côte à
   côte, aucune ne ressemble à sa voisine. */
.realisations { padding-block: var(--space-section); background: linear-gradient(180deg, var(--paper-3) 0%, var(--paper) 34%, var(--paper-2) 100%); }

/* Grille volontairement agnostique du nombre de projets : ajouter une
   cinquième, sixième ou septième carte ne demande aucune retouche CSS. */
.cases-grid {
  /* V2 — liste éditoriale : un projet par ligne, plein largeur, alternance
     gauche/droite gérée en CSS (voir @media (min-width: 901px) plus bas).
     Le compteur alimente la numérotation "01/02/03..." sans toucher au HTML. */
  display: flex;
  flex-direction: column;
  gap: clamp(3rem, 8vw, 6rem);
  counter-reset: case-index;
}

/* Les cartes ne sont plus des panneaux teintés posés sur du blanc : elles
   sont en papier blanc pur, plus claires que le sol, tenues par un filet d'un
   pixel et trois couches d'ombre. C'est l'écart de valeur avec le fond — et
   non un contour — qui les fait exister. Au survol elles montent de six
   pixels et leur ombre s'allonge : la lumière ne bouge pas, l'objet si. */
.case-card {
  position: relative;
  counter-increment: case-index;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-l);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition:
    transform var(--dur-med) var(--ease-out),
    box-shadow var(--dur-med) var(--ease-out),
    border-color var(--dur-med) var(--ease-out);
}
.case-card:hover {
  transform: translateY(-6px);
  border-color: var(--gray-300);
  box-shadow: var(--shadow-card-hover);
}
/* Un unique filet de signature s'allume sur la tranche haute de la carte au
   survol — la seule couleur de toute la grille, large d'un pixel. */
.case-card::before {
  content: "";
  position: absolute;
  top: 0; left: 12%; right: 12%;
  height: 1px;
  z-index: 2;
  background: linear-gradient(90deg, transparent, rgba(var(--signature-rgb), 0.55), transparent);
  opacity: 0;
  transition: opacity var(--dur-med) var(--ease-out);
}
.case-card:hover::before { opacity: 1; }

.case-card__media {
  position: relative;
  overflow: hidden;
  background: var(--gray-900);
  transition: clip-path 1.1s var(--ease-out);
}

/* Fenêtre navigateur — cadre commun à toutes les captures. Barre fixe +
   image au ratio 16/10 : toutes les cartes ont donc exactement la même
   hauteur de preview, quel que soit le projet. */
.case-card__browser {
  display: flex; flex-direction: column;
  background: var(--ink);
  /* Arête de lumière sur la tranche haute du cadre, et ombre portée interne
     en bas : la capture est encastrée dans la carte, pas collée dessus. */
  box-shadow: var(--edge-light), inset 0 -1px 0 rgba(10, 12, 18, 0.6);
}

.browser-bar {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.85rem;
  background: rgba(255, 255, 255, 0.06);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.browser-dots { display: flex; gap: 0.35rem; }
.browser-dots i { width: 8px; height: 8px; border-radius: 50%; background: rgba(255, 255, 255, 0.22); }
/* Pastille d'adresse : le nom du projet, pas un domaine inventé. */
.browser-url {
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.07);
  border-radius: 999px;
  padding: 0.1rem 0.7rem;
}

/* La capture est déjà au ratio du conteneur : object-fit ne recadre rien et
   ne déforme rien, il garantit simplement l'absence d'étirement si une
   capture future arrivait dans un format légèrement différent. */
.browser-shot {
  width: 100%;
  /* height:auto est indispensable : sans lui, l'attribut height="750" du HTML
     fait autorité et neutralise complètement aspect-ratio. */
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top center;
  /* --shot-y : parallaxe légère pilotée en JS (voir main.js, section 16),
     inactive sous prefers-reduced-motion. scale(1.04) donne la marge
     nécessaire pour que le déplacement ne révèle jamais de bord. */
  transform: scale(1.04) translateY(var(--shot-y, 0px));
  transition: transform var(--dur-med) var(--ease-out);
}
/* Révélation "rideau" au scroll (pas seulement au survol) : visible aussi
   sur mobile/tactile, où il n'y a pas de hover. Masqué uniquement quand JS
   est actif (voir html.js) — sans JS, la maquette reste visible d'emblée. */
html.js .case-card__media { clip-path: inset(0 0 100% 0); }
html.js .case-card.is-visible .case-card__media { clip-path: inset(0 0 0% 0); }
/* Léger rapprochement au survol. Volontairement plus discret que sur les
   anciennes mini-maquettes : une vraie capture supporte mal un zoom marqué. */
.case-card:hover .browser-shot { transform: scale(1.07) translateY(var(--shot-y, 0px)); }

/* Repère réservé au projet en cours de lecture. Posé sur la capture, avec un
   fond opaque : il reste lisible quelle que soit l'image en dessous. */
.case-card__status {
  position: absolute; right: 1rem; bottom: 1rem; z-index: 1;
  background: var(--white);
  color: var(--gray-900);
  font-family: var(--font-display);
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.01em;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  box-shadow: 0 1px 1px rgba(10, 12, 18, 0.18), 0 8px 20px -8px rgba(10, 12, 18, 0.55);
}

.case-card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: clamp(1.5rem, 2.4vw, 2rem);
}
/* Numérotation éditoriale — pur CSS (counter-increment sur .case-card),
   même grammaire que .section-index (filet + libellé signature) ailleurs
   sur le site : renforce l'impression de sommaire/portfolio de studio. */
.case-card__number {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--signature);
  margin-bottom: 1rem;
}
.case-card__number::before {
  content: "";
  width: 18px; height: 1px;
  background: var(--signature);
  opacity: 0.55;
}
.case-card__number::after { content: counter(case-index, decimal-leading-zero) " / 05"; }
.case-card__sector {
  font-family: var(--font-display);
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--signature); font-weight: 600;
  margin-bottom: 0.7rem;
}
.case-card__title { font-size: clamp(1.4rem, 2vw, 1.9rem); margin-bottom: 0.55rem; }
.case-card__desc {
  color: var(--gray-600);   /* 6,9:1 sur --gray-50 : AA confortable */
  font-size: 0.98rem;
  line-height: 1.6;
  margin-bottom: 1.5rem;
  max-width: 42ch;
}
/* margin-top:auto aligne les boutons de toutes les cartes d'une même rangée,
   quelle que soit la longueur des descriptions. */
.case-card__link {
  align-self: flex-start;
  margin-top: auto;
  min-height: 44px;   /* cible tactile confortable, y compris en btn-small */
}
/* Même soulignement que la nav (.main-nav a span::after) : un seul système
   de micro-interaction réemployé, pas un nouveau. */
.case-card__link span { position: relative; }
.case-card__link span::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -3px;
  height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: right;
  transition: transform var(--dur-fast) var(--ease-out);
}
.case-card__link:hover span::after { transform: scaleX(1); transform-origin: left; }

/* AMOTKEN (et tout futur projet non-officiel) a besoin d'afficher sa stack et
   deux actions au lieu d'un seul lien "Voir le projet". Ces deux blocs sont
   additifs : les autres cartes ne les utilisent pas et restent inchangées. */
.case-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  list-style: none;
  margin: 0 0 1.4rem;
  padding: 0;
}
.case-card__tags li {
  font-family: var(--font-sans);
  font-size: 0.74rem;
  font-weight: 500;
  line-height: 1.2;
  color: var(--gray-600);   /* même paire que .case-card__desc : AA large */
  background: var(--gray-50);
  border: 1px solid var(--gray-200);
  border-radius: 999px;
  padding: 0.28rem 0.75rem;
}
.case-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: auto;
}
.case-card__actions .case-card__link { margin-top: 0; }

/* ---------- RÉALISATIONS V2 — mise en page éditoriale desktop ----------
   Au-delà de 901px, chaque projet devient une ligne : la capture occupe la
   majorité de la largeur, le texte compose une colonne courte à ses côtés.
   L'alternance gauche/droite est purement visuelle (ordre DOM inchangé),
   donc rien ne casse pour les lecteurs d'écran ni pour le clavier. */
@media (min-width: 901px) {
  .case-card {
    flex-direction: row;
    align-items: stretch;
    gap: clamp(2rem, 4vw, 3.75rem);
  }
  .cases-grid > .case-card:nth-child(even) { flex-direction: row-reverse; }
  .case-card__media { flex: 1 1 58%; min-width: 0; }
  .case-card__body { flex: 1 1 42%; min-width: 0; justify-content: center; }
  .case-card__title { font-size: clamp(1.7rem, 2.6vw, 2.6rem); }
  .case-card__desc { max-width: 38ch; }
}
/* BANDE CTA — c'était le plus grand aplat bleu du site, et donc ce qui
   empêchait la signature d'être une signature. Passée à l'encre, elle gagne
   en gravité ; le bleu n'y subsiste que dans un filet d'un pixel posé sur sa
   tranche haute, exactement à l'endroit où le fil de lumière traverse. */
.cta-band {
  position: relative;
  padding-block: clamp(3rem, 6vw, 4.5rem);
  background:
    radial-gradient(ellipse 70% 130% at 78% 50%, #1B1F2B 0%, transparent 66%),
    linear-gradient(180deg, #101319 0%, var(--ink) 100%);
}
.cta-band::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--thread), 0.55) 30%, rgba(var(--thread), 0.55) 70%, transparent);
}
.cta-band-inner {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1.8rem;
}
.cta-band-text {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.03em;
  font-size: clamp(1.4rem, 3vw, 2.1rem);
  color: var(--white);
  max-width: 22ch;
}
.btn-inverse { background: var(--paper); color: var(--ink); box-shadow: 0 1px 1px rgba(0,0,0,.22), 0 12px 26px -12px rgba(0,0,0,.6); }
.btn-inverse:hover { background: var(--white); transform: translateY(-2px); }

/* OFFRES */
.offres {
  padding-block: var(--space-section);
  background:
    radial-gradient(ellipse 80% 55% at 82% 0%, #171A24 0%, transparent 60%),
    linear-gradient(180deg, #0C0E15 0%, var(--ink) 100%);
  color: var(--white);
}
.offres-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; align-items: stretch; }
.offre-card {
  position: relative;
  background: linear-gradient(180deg, #181B24 0%, var(--ink-soft) 100%);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: var(--radius-l);
  padding: clamp(1.8rem, 3vw, 2.4rem);
  display: flex; flex-direction: column;
  box-shadow: var(--edge-light), 0 20px 44px -24px rgba(0, 0, 0, 0.8);
  transition: transform var(--dur-med) var(--ease-out), border-color var(--dur-med), box-shadow var(--dur-med) var(--ease-out);
}
.offre-card:hover {
  transform: translateY(-6px);
  border-color: rgba(255, 255, 255, 0.14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.11), 0 34px 64px -28px rgba(0, 0, 0, 0.9);
}
/* La carte recommandée ne se distingue pas par un contour vif mais par une
   lumière : elle est simplement mieux éclairée que ses voisines. */
.offre-featured {
  background:
    radial-gradient(ellipse 100% 70% at 50% -10%, rgba(var(--thread), 0.14) 0%, transparent 62%),
    linear-gradient(180deg, #1B1F2C 0%, var(--ink-soft) 100%);
  border-color: rgba(var(--thread), 0.24);
}
.offre-featured::before {
  content: "";
  position: absolute; top: 0; left: 18%; right: 18%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--thread), 0.7), transparent);
}
/* Le badge devient un contour, plus un pastille pleine : la signature ne
   remplit rien, elle cerne. */
.offre-badge {
  position: absolute; top: -13px; left: clamp(1.8rem, 3vw, 2.4rem);
  background: var(--ink);
  color: var(--signature-light);
  box-shadow: inset 0 0 0 1px rgba(var(--thread), 0.45);
  font-family: var(--font-display);
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.4rem 0.85rem; border-radius: 999px;
}
.offre-card h3 { color: var(--white); font-size: 1.45rem; margin-bottom: 0.6rem; }
.offre-desc { color: rgba(255, 255, 255, 0.62); font-size: 0.95rem; margin-bottom: 1.4rem; }
.offre-price { font-family: var(--font-display); font-weight: 500; font-size: 1.15rem; color: rgba(255, 255, 255, 0.55); margin-bottom: 1.6rem; letter-spacing: -0.01em; }
.offre-price strong { font-weight: 600; font-size: 1.6rem; color: var(--white); letter-spacing: -0.03em; }
.offre-features { display: flex; flex-direction: column; gap: 0.7rem; margin-bottom: auto; }
.offre-features li { position: relative; padding-left: 1.4rem; color: rgba(255, 255, 255, 0.82); font-size: 0.93rem; }
.offre-features li::before { content: "—"; position: absolute; left: 0; color: var(--blue-400); }
.offre-card .btn { margin-top: 2rem; justify-content: center; }
.offre-card .btn-outline { border-color: rgba(255, 255, 255, 0.2); color: var(--white); }
.offre-card .btn-outline:hover { border-color: var(--blue-400); color: var(--blue-400); }

/* FAQ */
.faq { padding-block: var(--space-section); background: linear-gradient(180deg, var(--paper-2) 0%, var(--paper) 45%, var(--paper-2) 100%); }
.faq-grid { display: grid; grid-template-columns: 0.8fr 1.6fr; gap: clamp(2rem, 6vw, 5rem); align-items: start; }
.accordion-item {
  border-bottom: 0;
  background: linear-gradient(90deg, transparent, var(--gray-200) 4%, var(--gray-200) 96%, transparent) bottom / 100% 1px no-repeat;
}
.accordion-trigger {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  text-align: left;
  padding-block: 1.4rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.02rem, 1.5vw, 1.2rem);
  letter-spacing: -0.02em;
  color: var(--gray-900);
  cursor: pointer;
  list-style: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.accordion-trigger:hover { color: var(--signature); }
.accordion-item[open] .accordion-trigger { color: var(--signature); }
.accordion-trigger::-webkit-details-marker { display: none; }
.accordion-icon { position: relative; flex-shrink: 0; width: 22px; height: 22px; }
.accordion-icon::before, .accordion-icon::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  background: var(--blue-600);
  transform: translate(-50%, -50%);
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast);
}
.accordion-icon::before { width: 14px; height: 1.5px; }
.accordion-icon::after { width: 1.5px; height: 14px; }
.accordion-item[open] .accordion-icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.accordion-panel { overflow: hidden; max-height: 0; transition: max-height var(--dur-med) var(--ease-in-out); }
/* Fallback (no JS): rely on the native [open] attribute to reveal the panel. */
.accordion-item[open] .accordion-panel { max-height: 1000px; }
/* With JS: precise height is set inline; force-collapse while closed either way. */
.accordion-item:not([open]) .accordion-panel { max-height: 0 !important; }
.accordion-panel p { padding-bottom: 1.5rem; color: var(--gray-600); max-width: 60ch; }

/* CONTACT */
.contact { padding-block: var(--space-section); background: linear-gradient(180deg, var(--paper-2) 0%, var(--paper-3) 100%); }
.contact-grid { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(2rem, 6vw, 5rem); }
.contact-info { margin-top: 2.4rem; display: flex; flex-direction: column; gap: 1.2rem; }
.contact-info li { display: flex; flex-direction: column; gap: 0.15rem; }
.contact-info span { font-size: 0.76rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--signature); font-weight: 600; }
.contact-info a, .contact-info p { font-size: 1.05rem; color: var(--gray-900); }
/* Souligné qui se dessine depuis la gauche, décalé du texte : un lien
   d'agence ne clignote pas, il se révèle. */
.contact-info a { position: relative; display: inline-block; }
.contact-info a::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
  background: var(--signature);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-med) var(--ease-out);
}
.contact-info a:hover { color: var(--signature); }
.contact-info a:hover::after { transform: scaleX(1); }

.contact-form {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-l);
  padding: clamp(1.6rem, 4vw, 2.6rem);
  box-shadow: var(--shadow-soft);
}
.form-note {
  font-size: 0.82rem; color: var(--gray-600);
  background: var(--paper-2);
  border: 0;
  border-left: 2px solid rgba(var(--signature-rgb), 0.35);
  border-radius: 0 var(--radius-s) var(--radius-s) 0;
  padding: 0.8rem 1rem; margin-bottom: 1.6rem;
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }
.field { position: relative; margin-bottom: 1.2rem; }
.field input, .field textarea, .field select {
  width: 100%;
  border: 1px solid var(--gray-200);
  border-radius: var(--radius-s);
  padding: 1.1rem 1rem 0.55rem;
  background: var(--paper);
  font-size: 0.98rem;
  transition: border-color var(--dur-fast), background var(--dur-fast), box-shadow var(--dur-fast);
}
.field select { padding-block: 0.85rem; }
.field textarea { resize: vertical; min-height: 110px; }
/* Au focus, le champ passe du papier au blanc : il s'éclaire au lieu de
   s'entourer. Le liseré de signature reste d'un pixel. */
.field input:focus, .field textarea:focus, .field select:focus {
  border-color: rgba(var(--signature-rgb), 0.5);
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(10, 12, 18, 0.04), 0 0 0 3px rgba(var(--signature-rgb), 0.07);
}
.field input:hover, .field textarea:hover, .field select:hover { border-color: var(--gray-300); }
.field label {
  position: absolute; left: 1rem; top: 1.1rem;
  font-size: 0.98rem; color: var(--gray-600);
  pointer-events: none;
  transition: transform var(--dur-fast) var(--ease-out), font-size var(--dur-fast) var(--ease-out), color var(--dur-fast);
  transform-origin: left top;
}
.field input:focus + label,
.field input:not(:placeholder-shown) + label,
.field textarea:focus + label,
.field textarea:not(:placeholder-shown) + label {
  transform: translateY(-0.65rem) scale(0.78);
  color: var(--blue-600);
}
/* Spécificité volontairement plus élevée que ".field label" (label flottant
   des champs texte) pour éviter que ce label statique ne se superpose au select. */
.field .select-label { position: static; display: block; font-size: 0.82rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--blue-600); margin-bottom: 0.5rem; }
.field-error { display: block; min-height: 1.1rem; font-size: 0.8rem; color: var(--red-error); margin-top: 0.3rem; }
.field.has-error input, .field.has-error textarea { border-color: var(--red-error); }
.form-success { margin-top: 1.2rem; text-align: center; color: var(--blue-700); font-size: 0.92rem; }
/* Strict pendant du message de succès : mêmes marge, alignement et corps.
   Seule la couleur change, et elle réutilise le rouge déjà employé par les
   erreurs de champ — aucune valeur nouvelle n'entre dans le système. */
.form-error { margin-top: 1.2rem; text-align: center; color: var(--red-error); font-size: 0.92rem; }
.form-error a { text-decoration: underline; text-underline-offset: 3px; }

/* FOOTER */
.site-footer {
  background:
    radial-gradient(ellipse 70% 50% at 22% 0%, #16191F 0%, transparent 58%),
    var(--ink);
  color: var(--white);
  padding-top: clamp(3.5rem, 7vw, 6rem);
}
.footer-top { display: grid; grid-template-columns: 0.9fr 2fr; gap: clamp(2.5rem, 6vw, 5rem); padding-bottom: clamp(3rem, 6vw, 4.5rem); border-bottom: 0; background: linear-gradient(90deg, rgba(255,255,255,.09), rgba(255,255,255,.09) 88%, transparent) bottom / 100% 1px no-repeat; }
.footer-brand p { margin-top: 1rem; color: rgba(255, 255, 255, 0.6); max-width: 30ch; }
.logo-footer .logo-text, .logo-footer .logo-mark { color: var(--white); }
.logo-footer .logo-mark { background: rgba(255, 255, 255, 0.08); }
.logo-footer .logo-text em { color: var(--blue-400); }
.footer-nav { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; }
.footer-col h3 { font-family: var(--font-display); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--signature-light); margin-bottom: 1.1rem; }
.footer-col ul { display: flex; flex-direction: column; gap: 0.7rem; }
/* Les liens du pied de page se déplacent d'un cheveu vers la droite au
   survol, comme si le doigt les poussait. Deux pixels, jamais plus. */
.footer-col a {
  display: inline-block;
  color: rgba(255, 255, 255, 0.68); font-size: 0.95rem;
  transition: color var(--dur-fast), transform var(--dur-fast) var(--ease-out);
}
.footer-col a:hover { color: var(--white); transform: translateX(2px); }

.footer-cta {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1.5rem;
  padding-block: clamp(2.5rem, 5vw, 3.5rem);
  border-bottom: 0;
  background: linear-gradient(90deg, rgba(255,255,255,.09), rgba(255,255,255,.09) 88%, transparent) bottom / 100% 1px no-repeat;
}
.footer-cta p { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.03em; font-size: clamp(1.3rem, 2.6vw, 1.9rem); max-width: 20ch; color: var(--white); }

.footer-bottom { display: flex; align-items: center; justify-content: space-between; padding-block: 1.6rem; font-size: 0.85rem; color: rgba(255, 255, 255, 0.58); }
.back-to-top {
  width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.15);
  display: grid; place-items: center;
  color: var(--white);
  transition: background var(--dur-fast), border-color var(--dur-fast), transform var(--dur-fast) var(--ease-out);
}
.back-to-top:hover { transform: translateY(-3px); }

/* CTA FLOTTANT (apparaît après le hero, masqué près du formulaire de contact) */
.floating-cta {
  position: fixed;
  right: clamp(1.2rem, 3vw, 2rem);
  bottom: clamp(1.2rem, 3vw, 2rem);
  z-index: 150;
  display: inline-flex; align-items: center;
  padding: 1rem 1.5rem;
  background: var(--ink);
  color: var(--white);
  font-family: var(--font-display);
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: -0.012em;
  border-radius: 999px;
  /* Le liseré intérieur clair n'est là que pour une raison : ce bouton est
     fixe et passe donc aussi bien sur le papier que sur l'encre. Sur le
     papier il ne se voit pas ; sur l'encre il redonne sa tranche à la
     pilule, qui sinon se fondrait dans la section « Méthode ». */
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.13),
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    0 2px 4px rgba(10, 12, 18, 0.14),
    0 16px 34px -14px rgba(10, 12, 18, 0.5);
  opacity: 0;
  transform: translateY(16px);
  pointer-events: none;
  /* Sans « visibility », ce lien reste dans l'ordre de tabulation alors qu'il
     est invisible : au clavier, le focus disparaissait sur un élément fantôme.
     La visibilité est transitionnée avec la même durée que l'opacité, donc
     l'apparition et la disparition restent strictement identiques à l'œil. */
  visibility: hidden;
  transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out), background var(--dur-fast), visibility 0s linear var(--dur-med);
}
/* Contrôlé en JS : apparaît après le hero, se masque au niveau des sections
   qui ont déjà leur propre CTA (pour ne jamais chevaucher de contenu). Sans
   JS, il reste caché : les CTA de chaque section restent l'accès principal. */
.floating-cta.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; visibility: visible; transition-delay: 0s; }
.floating-cta:hover { background: #171A23; transform: translateY(-2px); }

/* ==========================================================================
   MICRO-DÉTAILS
   Rien ici ne se voit isolément. C'est l'accumulation qui donne l'impression
   qu'une main est passée sur chaque état du site.
   ========================================================================== */

/* La barre de défilement participe de l'identité — la plupart des sites
   l'oublient, et c'est précisément pour ça qu'on la remarque quand elle est
   traitée. */
* { scrollbar-width: thin; scrollbar-color: var(--gray-300) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--gray-300);
  border: 3px solid var(--paper);
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: var(--gray-500); }

/* Le soulignement de la navigation part de la droite au repos et revient par
   la gauche : le trait ne clignote jamais, il circule. (Comportement déjà en
   place ; on lui donne ici l'épaisseur et la couleur de la signature.) */
.main-nav a span::after { height: 1.5px; background: var(--signature); border-radius: 2px; }
.main-nav a { transition: color var(--dur-fast) var(--ease-out); }
.main-nav a:hover, .main-nav a.is-active { color: var(--gray-900); }

/* Le bouton du menu mobile s'assombrit à la pression au lieu de sauter. */
.menu-toggle { transition: background var(--dur-fast); }
.menu-toggle:hover { background: rgba(10, 12, 18, 0.05); }

/* Le signe de l'accordéon respire au survol : il s'ouvre légèrement avant
   même le clic. */
.accordion-icon::before, .accordion-icon::after { border-radius: 2px; }
.accordion-trigger:hover .accordion-icon::before,
.accordion-trigger:hover .accordion-icon::after { background: var(--signature); }
.accordion-panel p { transition: none; }

/* Les pastilles du navigateur factice : la première capte un peu plus de
   lumière que les deux autres, comme un vrai reflet en haut à gauche. */
.browser-dots i:first-child { background: rgba(255, 255, 255, 0.3); }
.browser-url { font-family: var(--font-display); font-weight: 500; }

/* Retour en haut : la flèche monte d'un pixel avant le bouton. */
.back-to-top svg { transition: transform var(--dur-fast) var(--ease-out); }
.back-to-top:hover { background: rgba(255, 255, 255, 0.06); border-color: rgba(255, 255, 255, 0.28); }
.back-to-top:hover svg { transform: translateY(-2px); }

/* Le lien du menu mobile et celui du pied de page partagent le même souligné
   discret que les coordonnées de contact — un seul geste pour tous les liens
   de texte du site. */
.mobile-menu-footer a, .footer-bottom a {
  color: var(--signature-light);
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
}

/* Images et médias : jamais d'à-coup de rendu pendant le chargement. */
img { background: var(--paper-2); }

/* Les listes d'offres : le tiret de puce prend la signature, à l'échelle
   d'un caractère. */
.offre-features li::before { color: var(--signature-light); opacity: 0.8; }

/* Erreur de formulaire : le message glisse au lieu d'apparaître. */
.field-error { transition: color var(--dur-fast); }
.field.has-error input, .field.has-error textarea { box-shadow: 0 0 0 3px rgba(178, 58, 58, 0.08); }

/* Tout ce qui est cliquable adopte le même retour à la pression. */
a, button, summary { -webkit-tap-highlight-color: rgba(var(--signature-rgb), 0.12); }

/* ---------- 7. RESPONSIVE ---------- */

/* La surface se redresse à mesure que l'écran se resserre : moins d'espace,
   donc moins de perspective — l'objet se remet de face plutôt que de devenir
   illisible. Sa position (calée dans la respiration à droite du titre) ne
   change pas : c'est la composition du hero, elle tient à toutes les tailles. */
@media (max-width: 1180px) {
  .birth-plate {
    transform: perspective(1300px) rotateY(calc(-5deg + var(--ry, 0deg))) rotateX(calc(1.6deg + var(--rx, 0deg)));
  }
  .birth-index li { width: 16px; }
}

@media (max-width: 1024px) {
  .vision-grid, .faq-grid, .contact-grid { grid-template-columns: 1fr; }
  .vision-label { margin-bottom: 1rem; }
  .reason { grid-template-columns: 3rem 1fr; row-gap: 0.5rem; margin-inline: 0; }
  .reason-desc { grid-column: 2; }
  .offres-grid { grid-template-columns: 1fr; max-width: 480px; margin-inline: auto; }
  .footer-top { grid-template-columns: 1fr; }
  .footer-nav { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 860px) {
  .main-nav, .header-actions .btn { display: none; }
  .menu-toggle { display: flex; }
  /* Une carte par ligne : en dessous de cette largeur, deux maquettes côte à
     côte deviennent trop petites pour que les identités restent lisibles. */
  .cases-grid { grid-template-columns: minmax(0, 1fr); }
  .form-row { grid-template-columns: 1fr; }
}

@media (max-width: 700px) {
  /* Sur téléphone, le message et l'appel à l'action doivent occuper l'écran
     seuls : la scène s'efface plutôt que de rétrécir jusqu'à l'illisible, ou
     de venir buter contre le titre. */
  .hero-birth { display: none; }
}

@media (max-width: 560px) {
  .hero-bottom { flex-direction: column; align-items: flex-start; }
  .footer-nav { grid-template-columns: 1fr 1fr; }
  .footer-cta { flex-direction: column; align-items: flex-start; }
  .footer-bottom { flex-direction: column; gap: 1rem; align-items: flex-start; }
  .hero-scroll { display: none; }
  .cta-band-inner { flex-direction: column; align-items: flex-start; }
  .floating-cta span { display: none; }
  .floating-cta { width: 52px; height: 52px; padding: 0; justify-content: center; border-radius: 50%; }
  .floating-cta::before { content: "→"; font-size: 1.1rem; }
}

/* ---------- 8. ACCESSIBILITÉ / REDUCED MOTION ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .hero-title .reveal-line { transform: translateY(0) !important; opacity: 1 !important; }
  .reveal-up { opacity: 1 !important; transform: none !important; }

  /* Le hero reste composé, simplement sans mise en scène : tout est déjà là.
     La surface affiche une identité entièrement construite (voir le JS), le
     cycle ne se déclenche pas. */
  .hero, .hero *, .hero *::before, .hero *::after { transition-delay: 0s !important; animation-delay: 0s !important; }
  .hero-canvas, .hero-scroll, .hero-marquee, .birth-caption { opacity: 1 !important; }
  .eyebrow-line, .hero-slogan-line { transform: scaleX(1) !important; }
  .hero-title em { color: var(--blue-600) !important; }
  .birth-sweep { animation: none !important; opacity: 0 !important; }
  .birth-stage { transform: none !important; }
  /* Le curseur ne clignote pas, mais il reste posé sur la page : l'attente
     se dit aussi bien à l'arrêt. */
  .b-caret { animation: none !important; opacity: 1 !important; }
  /* Garde-fou : js/main.js n'essaie déjà pas de charger la couche 3D sous
     prefers-reduced-motion, mais si .has-3d se retrouvait posée pour
     n'importe quelle raison, cette règle force quand même le repli CSS. */
  .hero-webgl { opacity: 0 !important; }
  .hero.has-3d .hero-canvas,
  .hero.has-3d .hero-glow { opacity: 1 !important; }
}

@media (hover: none) {
  .cursor-dot { display: none; }
}

/* Print */
@media print {
  .site-header, .mobile-menu, .cursor-dot, .progress-bar, .grain, .back-to-top, .floating-cta { display: none !important; }
}
