/* --- Polices IBM Plex, hébergées avec le site ----------------------------
   Engendré par scripts/fetch-fonts.mjs : ne pas modifier à la main.
   Les unicode-range viennent de Google et sont recopiés tels quels ; les
   changer modifierait quels caractères sont dessinés par IBM Plex et
   lesquels retombent sur une police système.
   -------------------------------------------------------------------- */

/* IBM Plex Mono 500 — latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-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;
}

/* IBM Plex Mono 500 — latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-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;
}

/* IBM Plex Mono 600 — latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-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;
}

/* IBM Plex Mono 600 — latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/ibm-plex-mono-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;
}

/* IBM Plex Sans 400 — latin-ext */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* IBM Plex Sans 400 — latin */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* IBM Plex Sans 500 — latin-ext */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* IBM Plex Sans 500 — latin */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* IBM Plex Sans 600 — latin-ext */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* IBM Plex Sans 600 — latin */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* IBM Plex Sans 700 — latin-ext */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* IBM Plex Sans 700 — latin */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/ibm-plex-sans-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;
}

/* ==========================================================================
   Infinitus IT — feuille de styles principale
   Palette, typographie et composants extraits de la maquette Design Canvas.
   ========================================================================== */

/* --- Jetons de design ---------------------------------------------------- */
:root {
  --ink:            #231f20;   /* fond sombre principal */
  --ink-card:       #2c2829;   /* carte sur fond sombre */
  --ink-card-hover: #353132;

  --accent:         oklch(0.74 0.16 121);  /* vert signature */
  --accent-bright:  oklch(0.82 0.17 121);  /* sur fond sombre */
  --accent-deep:    oklch(0.5 0.13 128);   /* sur fond clair */
  --accent-ink:     oklch(0.24 0.03 145);  /* texte sur pastille verte */
  --accent-wash:    oklch(0.95 0.035 120); /* fond d'icône clair */

  --fg-on-dark:     oklch(0.97 0.005 140);
  --muted-on-dark:  oklch(0.72 0.015 145);
  --fg:             oklch(0.24 0.012 152);
  --muted:          oklch(0.5 0.01 150);

  --surface:        oklch(1 0 0);
  --surface-alt:    oklch(0.965 0.004 150);
  --border:         oklch(0.9 0.006 150);
  --border-on-dark: rgba(255, 255, 255, 0.12);

  /* Superfamille IBM Plex : le sans et le mono partagent squelette et métriques,
     ils s'accordent donc sans réglage. La hiérarchie ne vient plus d'un contraste
     entre deux dessins, mais de trois voix : Sans régulier pour le texte, Sans
     gras pour les titres, Mono pour tout ce qui se mesure — chiffres, intitulés
     de section, numéros d'étape. C'est ce qui rend lisible la revendication de
     précision que le reste du système (filets de 1px, rayons de 3px) affirme. */
  --font-sans:    'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --font-display: 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Angles quasi droits : juste assez d'arrondi pour adoucir l'arête, jamais
     assez pour arrondir la forme. Trois valeurs suffisent — grands blocs,
     éléments courants, petits jetons. */
  --radius-lg: 4px;   /* panneaux, grilles bordées, formulaire */
  --radius:    3px;   /* cartes, boutons, champs de saisie */
  --radius-sm: 2px;   /* pastilles d'icône, bascules, liens sociaux */

  --shell:  1152px;
  --gutter: 32px;
  --ease:   cubic-bezier(0.22, 1, 0.36, 1);
}

/* --- Base ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 80px; }

body {
  margin: 0;
  background: var(--surface);
  color: var(--fg);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
a:hover { color: var(--accent-deep); }
::selection { background: var(--accent); color: var(--accent-ink); }
img { max-width: 100%; }
/* Les logos ont des ratios très différents (le logotype de navigation fait
   plus de 6:1) : on ne contraint jamais les deux dimensions à la fois. */

/* Lien d'évitement — accessibilité clavier */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: var(--accent-ink);
  padding: 12px 20px; font-weight: 600; border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; color: var(--accent-ink); }

/* --- Focus clavier ------------------------------------------------------- */
/* Un seul anneau pour tout le site. :focus-visible ne se déclenche qu'au
   clavier, la souris ne le voit jamais. La couleur change selon le fond pour
   rester au-dessus du ratio de 3:1 exigé d'un indicateur de focus. */
:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.section--light :focus-visible,
.section--wash  :focus-visible,
.legal :focus-visible { outline-color: var(--accent-deep); }

/* --- Utilitaires de mise en page ----------------------------------------- */
.shell {
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 var(--gutter);
  position: relative;
  z-index: 2;
}

.section        { padding: 128px 0; }
.section--dark  { background: var(--ink); color: var(--fg-on-dark); }
.section--light { background: var(--surface); border-bottom: 1px solid var(--border); }
.section--wash  { background: var(--surface-alt); color: var(--fg); }

.section__head        { max-width: 672px; }
.section__head--center { margin: 0 auto; text-align: center; }

/* Étiquette de section : « NOS SERVICES » précédé d'un trait */
.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 500;
  /* La chasse fixe espace déjà les lettres : l'interlettrage descend de 0.1em
     à 0.06em, sinon l'intitulé se disloque. */
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--accent-deep);
}
.eyebrow::before { content: ''; height: 1px; width: 24px; background: currentColor; }
.section--dark .eyebrow { color: var(--accent-bright); }

.section__title {
  margin: 16px 0 0;
  font-family: var(--font-display);
  font-size: clamp(30px, 3vw, 36px);
  font-weight: 700;
  text-wrap: balance;
  /* L'interlettrage se resserre au défilement, piloté par js/main.js */
  letter-spacing: var(--track, 0.008em);
}

.section__lead {
  margin: 16px 0 0;
  line-height: 1.65;
  color: var(--muted);
  text-wrap: pretty;
}
.section--dark .section__lead { color: var(--muted-on-dark); }

/* --- En-tête ------------------------------------------------------------- */
.site-header {
  position: fixed; left: 0; right: 0; top: 0; z-index: 50;
  background: transparent;
  border-bottom: 1px solid transparent;
  backdrop-filter: blur(20px);
  transition: background 0.3s, border-color 0.3s;
}
.site-header.is-scrolled {
  background: oklch(0.16 0.008 150 / 88%);
  border-bottom-color: var(--border-on-dark);
}

.site-nav {
  height: 80px;
  padding: 0 clamp(20px, 4.5vw, 80px);
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
}
.site-nav__logo {
  display: flex; align-items: center; flex-shrink: 0;
  margin-right: clamp(12px, 2vw, 24px);
}
.site-nav__logo img { height: clamp(24px, 2.6vw, 34px); width: auto; display: block; }

.site-nav__links {
  display: flex; align-items: center;
  gap: clamp(16px, 2.2vw, 28px);
  flex: 0 1 auto;
}
.site-nav__link {
  font-size: clamp(13.5px, 1.15vw, 15.5px);
  white-space: nowrap;
  padding-bottom: 4px;
  color: var(--muted-on-dark);
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: 0% 1.5px;
  transition: background-size 0.28s cubic-bezier(0.4, 0, 0.2, 1), color 0.2s;
}
.site-nav__link:hover,
.site-nav__link.is-active {
  background-size: 100% 1.5px;
  color: var(--fg-on-dark);
}

.site-nav__actions {
  display: flex; align-items: center; gap: 10px; flex-shrink: 0;
  margin-left: clamp(12px, 2vw, 24px);
}

/* Le CTA du panneau mobile n'existe que sous 480px (voir la requête média) :
   au-dessus, celui de l'en-tête fait le travail et le doubler serait redondant. */
.site-nav__link--cta { display: none; }

.lang-toggle {
  display: flex; align-items: center; justify-content: center;
  height: 34px; width: 34px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-sm);
  font: 600 13px var(--font-sans);
  letter-spacing: 0.06em;
  color: var(--muted-on-dark);
  cursor: pointer;
  transition: border-color 0.2s, color 0.2s;
}
.lang-toggle:hover { border-color: var(--accent); color: var(--accent); }

/* Bouton hamburger — masqué tant que la navigation tient en largeur */
.nav-toggle {
  display: none;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  height: 34px; width: 34px; padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.2s;
}
.nav-toggle:hover { border-color: var(--accent); }
.nav-toggle__bar {
  display: block; height: 1.5px; width: 16px; border-radius: 2px;
  background: var(--muted-on-dark);
  transition: transform 0.25s var(--ease), opacity 0.2s, background 0.2s;
}
.nav-toggle:hover .nav-toggle__bar { background: var(--accent); }
/* Ouvert : les deux barres extrêmes se croisent, celle du milieu s'efface. */
.site-header.is-nav-open .nav-toggle__bar:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.site-header.is-nav-open .nav-toggle__bar:nth-child(2) { opacity: 0; }
.site-header.is-nav-open .nav-toggle__bar:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

/* --- Boutons ------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  border-radius: var(--radius);
  padding: 12px 24px;
  font: 600 14px var(--font-sans);
  border: 1px solid transparent;
  cursor: pointer;
  transition: opacity 0.2s, background 0.2s;
}
.btn--primary { background: var(--accent); color: var(--accent-ink); }
.btn--primary:hover { opacity: 0.9; color: var(--accent-ink); }
.btn--ghost {
  border-color: var(--border-on-dark);
  background: rgba(255, 255, 255, 0.05);
  color: var(--fg-on-dark);
}
.btn--ghost:hover { background: rgba(255, 255, 255, 0.12); color: var(--fg-on-dark); }
.btn--sm { padding: 9px clamp(12px, 1.4vw, 18px); font-size: clamp(13.5px, 1.15vw, 15.5px); }
.btn--block { width: 100%; }

/* --- Hero ---------------------------------------------------------------- */
.hero {
  position: relative; overflow: hidden;
  background: var(--ink); color: var(--fg-on-dark);
  padding-top: 80px;
}
/* Atmosphère du hero : une lemniscate de Bernoulli — le symbole ∞, donc le nom
   de l'entreprise — tracée en filets, parcourue par trois points lumineux.
   Le dessin est peint par js/main.js ; l'opacité s'estompe au défilement.
   Remplace l'ancien couple grille 64×64 + halo radial : la grille était une
   signature d'interface générée, et le halo, un disque coloré sans décalage,
   relevait de la décoration pure. */
.hero__fx {
  pointer-events: none; position: absolute; inset: 0;
  width: 100%; height: 100%;
  transition: opacity 0.3s linear;
}
.hero__inner { position: relative; z-index: 2; padding: 128px var(--gutter); }
.hero__copy  { max-width: 768px; margin: 0 auto; text-align: center; }

.hero__badge {
  margin-bottom: 32px;
  display: inline-flex; align-items: center; gap: 8px;
  border-radius: var(--radius);
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.05);
  padding: 6px 16px;
  font-size: 12px; font-weight: 500;
  color: var(--muted-on-dark);
  animation: textIn 0.46s var(--ease) 0.05s both;
}
.pulse { position: relative; display: flex; height: 6px; width: 6px; }
.pulse::before,
.pulse::after {
  content: ''; border-radius: 999px; background: var(--accent);
}
.pulse::before {
  position: absolute; display: inline-flex; height: 100%; width: 100%;
  opacity: 0.75; animation: ping 1.2s cubic-bezier(0, 0, 0.2, 1) infinite;
}
.pulse::after { position: relative; display: inline-flex; height: 6px; width: 6px; }

.hero__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(38px, 4.6vw, 60px);
  /* Plex Sans est moins large que Space Grotesk : le -0.025em d'origine faisait
     se toucher les lettres. -0.01em garde la tension d'un titre d'affichage
     sans collision. */
  font-weight: 700; line-height: 1.05; letter-spacing: -0.01em;
  text-wrap: balance;
  animation: titleIn 0.67s var(--ease) 0.11s both;
}
/* Le mot accentué garde la couleur du titre ; c'est un filet qui porte
   l'emphase, tracé de gauche à droite une fois le titre posé. On reste ainsi
   dans le vocabulaire du site — gouttières de 1px, trait de l'eyebrow, filets
   des étapes — au lieu d'un dégradé sur le texte, qui délavait le mot et le
   rendait moins présent que le blanc qui l'entoure.
   Le décalage de -0.06em fait passer le filet sous la descendante du « q » :
   l'interligne du titre étant serré à 1.05, les glyphes débordent de la boîte
   et un filet calé à l'intérieur traverserait la lettre. */
.hero__title em {
  font-style: normal;
  position: relative; display: inline-block;
}
.hero__title em::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -0.06em;
  height: 3px; background: var(--accent-bright);
  transform-origin: left center;
  animation: ruleIn 0.62s var(--ease) 0.72s both;
}
.hero__lead {
  margin: 24px auto 0; max-width: 672px;
  font-size: 18px; line-height: 1.65;
  color: var(--muted-on-dark); text-wrap: pretty;
  animation: textIn 0.59s var(--ease) 0.23s both;
}
.hero__actions {
  margin-top: 36px;
  display: flex; align-items: center; justify-content: center;
  gap: 12px; flex-wrap: wrap;
  animation: textIn 0.55s var(--ease) 0.32s both;
}

/* Bandeau de chiffres clés */
.stats {
  margin: 64px 0 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px; overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-on-dark);
  background: var(--border-on-dark);
}
.stats__item {
  background: var(--ink-card);
  padding: 32px 24px; text-align: center;
  animation: statIn 0.59s var(--ease) both;
  /* Le HTML place <dt> (libellé) avant <dd> (valeur) comme l'exige la
     spécification ; l'ordre visuel est rétabli ici. */
  display: flex; flex-direction: column-reverse; justify-content: flex-end;
}
.stats__item dt, .stats__item dd { margin: 0; }
.stats__value {
  display: block;
  font-family: var(--font-mono);
  /* La chasse fixe est plus large : 33px compense les 36px du dessin précédent
     sans déborder de la cellule. */
  font-size: 33px; font-weight: 600; letter-spacing: -0.02em;
  /* Chiffres à chasse tabulaire : sans cela, le compteur animé change de
     largeur à chaque image et la bande entière tressaute pendant sa montée. */
  font-variant-numeric: tabular-nums;
  color: var(--fg-on-dark);
}
.stats__value--infinity { transform-origin: left center; }
.stats__label {
  margin-top: 4px; display: block;
  font-size: 14px; color: var(--muted-on-dark);
}

/* --- À propos ------------------------------------------------------------ */
.about__layout {
  display: grid; grid-template-columns: 1fr 1fr; gap: 80px;
}
.about__text p { margin: 24px 0 0; line-height: 1.7; color: var(--muted); }
.about__text p + p { margin-top: 16px; }

.about__quote {
  margin: 40px 0 0;
  border-left: 2px solid var(--accent);
  padding-left: 24px;
}
.about__quote blockquote {
  margin: 0;
  font-family: var(--font-display);
  font-size: 18px; font-style: italic; line-height: 1.65;
  color: var(--fg); text-wrap: pretty;
}
.about__quote figcaption {
  margin-top: 12px;
  font-size: 14px; font-weight: 500; color: var(--accent-deep);
}

/* Réponse d'Infinitus à la citation : même bloc, mais registre affirmatif —
   police d'affichage, pas d'italique, pour se distinguer du propos cité. */
.about__quote-reply {
  margin: 20px 0 0;
  font-family: var(--font-display);
  font-size: 17px; font-weight: 600; line-height: 1.5;
  color: var(--fg);
  text-wrap: pretty;
  /* Calée sur le bord droit de la colonne, en réponse à la citation */
  text-align: right;
}

/* La colonne de gauche s'ouvre sur l'eyebrow, une boîte inline centrée dans une
   ligne plus haute qu'elle : ~8px de demi-interligne repoussent son texte vers
   le bas. Le panneau de droite, lui, colle au haut de la rangée. On rattrape cet
   écart ici pour que les deux colonnes démarrent visuellement au même niveau.
   Le panneau étant en flex:1, il absorbe le décalage et les bas restent alignés. */
.about__aside {
  position: relative; z-index: 2;
  display: flex; flex-direction: column;
  padding-top: 8px;
}
.about__media {
  position: relative;
  display: flex; flex: 1; align-items: center; justify-content: center;
  overflow: hidden;
  border-radius: var(--radius-lg); border: 1px solid var(--border);
  background: #f3f3f3;
  padding: 40px; min-height: 280px;
}
.about__media-glow {
  pointer-events: none; position: absolute;
  height: 256px; width: 256px; border-radius: 999px;
  opacity: 0.2; filter: blur(80px);
  background: radial-gradient(circle, var(--accent), transparent 70%);
}
.about__media img { position: relative; width: 210px; height: auto; display: block; }

/* Les valeurs se lisent en lignes, pas en cartes : intitulé à gauche, propos à
   droite, séparés par un filet. La colonne d'énoncés reste alignée sous le
   visuel et laisse au texte la place de respirer. */
.values {
  margin-top: 32px;
  display: grid; grid-template-columns: 1fr;
  border-top: 1px solid var(--border);
}
.values__item {
  display: grid; grid-template-columns: 38% 1fr; gap: 32px;
  align-items: start;
  padding: 18px 4px;
  border-bottom: 1px solid var(--border);
}
.values__item h3 {
  margin: 0; font-family: var(--font-display);
  font-size: 15px; font-weight: 600; line-height: 1.45;
  text-wrap: balance;
}
.values__item p {
  margin: 0; font-size: 15px; line-height: 1.75; color: var(--muted);
  text-wrap: pretty;
}

/* --- Services ------------------------------------------------------------ */
.services {
  margin-top: 64px;
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1px; overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-on-dark);
  background: var(--border-on-dark);
}
.services__cell { display: flex; }
.services__card {
  display: flex; flex-direction: column; flex: 1;
  background: var(--ink-card); padding: 32px;
  transition: background 0.2s;
}
.services__card:hover { background: var(--ink-card-hover); }
.services__icon {
  margin-bottom: 24px;
  display: flex; height: 44px; width: 44px;
  align-items: center; justify-content: center;
  border-radius: var(--radius-sm); border: 1px solid var(--border-on-dark);
  background: oklch(0.3 0.02 145); color: var(--accent-bright);
}
.services__card h3 {
  margin: 0; font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
}
.services__card > p {
  margin: 12px 0 0; font-size: 14px; line-height: 1.65;
  color: var(--muted-on-dark);
}
.services__points {
  margin: 24px 0 0; padding: 24px 0 0;
  list-style: none;
  border-top: 1px solid var(--border-on-dark);
  display: flex; flex-direction: column; gap: 8px;
}
.services__points li {
  display: flex; align-items: center; gap: 10px;
  font-size: 14px; color: rgba(247, 247, 244, 0.85);
}
/* Les coches tirent leur vert du jeton, via currentColor : la couleur n'est
   plus recopiée dans 18 attributs stroke du HTML. */
.services__points svg { flex-shrink: 0; color: var(--accent-bright); }

/* --- Références ---------------------------------------------------------- */
.clients {
  margin: 64px auto 0;
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 1px; overflow: hidden;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--border);
}
.clients__cell {
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); padding: 30px 25px;
  filter: grayscale(1);
  transition: filter 0.3s;
}
.clients__cell:hover { filter: grayscale(0); }
.clients__logo {
  width: 100%; height: 60px;
  background-size: contain; background-repeat: no-repeat; background-position: center;
}

/* --- Approche ------------------------------------------------------------ */
.steps {
  margin-top: 64px;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px;
}
.steps__head { display: flex; align-items: center; gap: 16px; }
.steps__num {
  font-family: var(--font-mono);
  font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--accent-bright);
}
.steps__rule {
  height: 1px; flex: 1;
  background: linear-gradient(to right, color-mix(in oklch, var(--accent-bright) 40%, transparent), transparent);
}
.steps__item h3 {
  margin: 20px 0 0; font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
}
.steps__item p {
  margin: 10px 0 0; font-size: 14px; line-height: 1.65;
  color: var(--muted-on-dark);
}

/* --- Contact ------------------------------------------------------------- */
.contact__layout {
  display: grid; grid-template-columns: 1fr 1fr; gap: 80px;
}
.contact__cards {
  margin-top: 32px; display: flex; flex-direction: column; gap: 12px;
}
.contact__card {
  display: flex; align-items: center; gap: 16px;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface); padding: 16px 20px;
  transition: border-color 0.2s;
  color: inherit;
}
a.contact__card:hover { border-color: color-mix(in oklch, var(--accent) 50%, transparent); color: inherit; }
.contact__icon {
  display: flex; height: 40px; width: 40px; flex-shrink: 0;
  align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  background: var(--accent-wash); color: var(--accent-deep);
}
.contact__label { display: block; font-size: 12px; color: var(--muted); }
.contact__value { display: block; font-size: 14px; font-weight: 500; }

.form {
  border-radius: var(--radius-lg); border: 1px solid var(--border);
  background: var(--surface); padding: 32px;
  display: flex; flex-direction: column;
}
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form__field { margin-top: 16px; }
.form__row .form__field { margin-top: 0; }
.form__field--grow {
  display: flex; flex-direction: column; flex: 1; min-height: 120px;
}
.form label {
  margin-bottom: 6px; display: block;
  font-size: 12px; font-weight: 500; color: var(--muted);
}
.form input,
.form textarea {
  width: 100%;
  border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface);
  padding: 12px 16px;
  font: 400 14px var(--font-sans);
  color: var(--fg);
  transition: border-color 0.2s;
}
.form textarea { flex: 1; resize: none; }
.form input:focus,
.form textarea:focus { border-color: color-mix(in oklch, var(--accent) 60%, transparent); }
.form button { margin-top: 24px; }
.form button[disabled] { opacity: 0.6; cursor: progress; }

/* Astérisque des champs obligatoires et mention « (facultatif) » : la
   contrainte est annoncée avant la saisie, pas découverte à l'envoi. */
.form__req { margin-left: 3px; color: var(--accent-deep); }
.form__opt { font-weight: 400; text-transform: none; opacity: 0.75; }

/* Pot de miel anti-robot : hors écran plutôt que display:none, que certains
   robots savent détecter. aria-hidden et tabindex=-1 l'excluent du parcours. */
.form__trap {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden;
}

.form__hint {
  margin: 16px 0 0; font-size: 12px; line-height: 1.5; color: var(--muted);
}
.form__hint a { color: var(--accent-deep); text-decoration: underline; }

.form__status {
  margin: 12px 0 0; font-size: 13px; color: var(--muted); min-height: 1em;
}
/* L'état ne repose jamais sur la seule couleur : le texte du message porte
   déjà l'information, la couleur ne fait que la renforcer. */
.form__status--ok    { color: var(--accent-deep); font-weight: 500; }
.form__status--error { color: #b3261e; font-weight: 500; }

/* --- Pied de page -------------------------------------------------------- */
.site-footer {
  background: var(--ink); color: var(--fg-on-dark);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding: 56px 0;
}
.site-footer__layout {
  display: grid; grid-template-columns: 1.4fr 1fr 0.9fr 1.2fr; gap: 40px;
}
/* Alignée à gauche comme ses trois colonnes sœurs : centrée, elle cassait
   l'axe de lecture du pied de page. */
.site-footer__brand img { width: 190px; height: auto; display: block; }
.site-footer__tagline {
  margin: 22px 0 0; max-width: 300px;
  font-family: var(--font-display); font-size: 17px; line-height: 1.5;
  color: var(--fg-on-dark);
}
.site-footer h3 {
  margin: 0; font-size: 12px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.05em;
}
.site-footer ul {
  margin: 16px 0 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 10px;
}
.site-footer a { color: var(--muted-on-dark); font-size: 14px; }
.site-footer a:hover { color: var(--fg-on-dark); }
.site-footer address {
  margin: 16px 0 0; font-style: normal;
  display: flex; flex-direction: column; gap: 10px;
  font-size: 14px; line-height: 1.6; color: var(--muted-on-dark);
}
.site-footer address span { max-width: 250px; }
/* Téléphone et email étaient stylés comme le texte d'adresse voisin : rien ne
   les signalait comme cliquables, alors que ce sont les deux raccourcis les
   plus utiles du pied de page. */
.site-footer address a {
  text-decoration: underline;
  text-decoration-color: color-mix(in oklch, var(--accent) 55%, transparent);
  text-underline-offset: 3px;
  width: fit-content;
}
.site-footer address a:hover { color: var(--accent); text-decoration-color: var(--accent); }

.social { margin-top: 18px; display: flex; align-items: center; gap: 10px; }
.social a {
  display: flex; height: 34px; width: 34px;
  align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.14); border-radius: var(--radius-sm);
  color: var(--muted-on-dark);
  transition: border-color 0.2s, color 0.2s;
}
.social a:hover { border-color: var(--accent); color: var(--accent); }

.site-footer__legal {
  margin-top: 48px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  border-top: 1px solid var(--border-on-dark);
  padding-top: 24px;
  font-size: 12px; color: var(--muted-on-dark);
}
.site-footer__legal a:hover { color: var(--accent); }

/* --- Animations ---------------------------------------------------------- */
@keyframes ping   { 75%, 100% { transform: scale(2.2); opacity: 0; } }
@keyframes ruleIn { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes fadeUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
@keyframes lineIn { from { opacity: 0; transform: translateX(-26px); } to { opacity: 1; transform: none; } }
@keyframes titleIn { from { opacity: 0; transform: translateY(30px); filter: blur(5px); } to { opacity: 1; transform: none; filter: blur(0); } }
@keyframes textIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes cardIn { from { opacity: 0; transform: translateY(34px) scale(0.985); } to { opacity: 1; transform: none; } }
@keyframes logoIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: none; } }
@keyframes mediaIn { from { opacity: 0; transform: scale(1.05); } to { opacity: 1; transform: none; } }
@keyframes statIn { from { opacity: 0; transform: translateX(-38px); } to { opacity: 1; transform: none; } }
@keyframes panelIn { from { opacity: 0; transform: translateX(34px); } to { opacity: 1; transform: none; } }

/* Les éléments révélés au scroll sont masqués tant que .is-revealed est absent.
   Sans JavaScript, la règle .no-js les rend visibles d'emblée (voir <head>). */
[data-reveal] { opacity: 0; }
[data-reveal].is-revealed { opacity: 1; animation: var(--reveal-anim, fadeUp 0.5s var(--ease) both); }
.no-js [data-reveal] { opacity: 1; animation: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  [data-reveal] { opacity: 1; }
}

/* --- Adaptation aux petits écrans ---------------------------------------- */
@media (max-width: 1024px) {
  .services      { grid-template-columns: repeat(2, 1fr); }
  .clients       { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  /* 25 logos tombent juste sur 5 colonnes, jamais sur 4, 3 ou 2 : la place
     restante laisserait apparaître le fond de la grille en gris. Le dernier
     logo occupe donc toute la largeur de la ligne incomplète. */
  .clients__cell:last-child { grid-column: 1 / -1; }
  .steps         { grid-template-columns: repeat(2, 1fr); }
  .about__layout,
  .contact__layout { gap: 48px; }
  .site-footer__layout { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  :root { --gutter: 20px; }
  .section { padding: 88px 0; }
  .hero__inner { padding: 96px var(--gutter); }

  /* Navigation repliée derrière le bouton hamburger. Le conteneur des liens
     devient un panneau déroulant sous l'en-tête : même balisage, donc mêmes
     ancres et mêmes clés de traduction qu'en navigation large. */
  .nav-toggle { display: flex; }
  .site-nav__links {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 4px clamp(20px, 4.5vw, 80px) 12px;   /* aligné sur .site-nav */
    /* Fond pleinement opaque : l'en-tête porte déjà un backdrop-filter, et un
       second imbriqué laisse le contenu de la page transparaître sous les liens. */
    background: oklch(0.16 0.008 150);
    border-bottom: 1px solid var(--border-on-dark);
    opacity: 0; visibility: hidden; transform: translateY(-8px);
    transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s;
  }
  .site-header.is-nav-open .site-nav__links {
    opacity: 1; visibility: visible; transform: none;
  }
  .site-nav__link {
    padding: 15px 2px;
    font-size: 16px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
    background-image: none;   /* le soulignement animé n'a pas de sens ici */
  }
  .site-nav__links a:last-child { border-bottom: 0; }
  .site-nav__link.is-active { color: var(--accent); }
  /* iOS Safari zoome sur un champ dont le texte fait moins de 16px, ce qui
     décale la mise en page dès que le visiteur touche le formulaire. */
  .form input,
  .form textarea { font-size: 16px; }

  /* Au doigt, 34px est sous le minimum praticable. On passe à 44 les seuls
     contrôles carrés du site — les deux boutons de l'en-tête, qui sont les
     seules commandes disponibles sur téléphone, et les liens sociaux. */
  .lang-toggle,
  .nav-toggle,
  .social a { height: 44px; width: 44px; }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .about__layout,
  .contact__layout { grid-template-columns: 1fr; }
  /* Colonnes empilées : plus de niveau à rattraper entre elles. */
  .about__aside { padding-top: 0; }
  .services { grid-template-columns: 1fr; }
  .clients  { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .steps   { grid-template-columns: 1fr; }
  .clients { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Trop étroit pour deux colonnes : l'intitulé repasse au-dessus du propos. */
  .values__item { grid-template-columns: 1fr; gap: 8px; padding: 18px 4px; }
  .form__row { grid-template-columns: 1fr; gap: 0; }
  .form__row .form__field + .form__field { margin-top: 16px; }
  .site-footer__layout { grid-template-columns: 1fr; }
  .site-footer__legal { justify-content: center; text-align: center; }
}

@media (max-width: 480px) {
  /* Le logotype et le bouton « Démarrer un projet » saturent la barre et
     repoussent le sélecteur de langue hors de l'écran. Le CTA est retiré ici :
     le hero en propose un dès le premier écran et le pied de page reprend les
     coordonnées, alors que la bascule FR/EN n'existe qu'à cet endroit. */
  .site-nav__actions .btn { display: none; }
  .site-nav__actions { margin-left: 12px; }

  /* … et réapparaît en dernière ligne du panneau, en pastille accentuée, pour
     que l'appel à l'action reste atteignable sur téléphone. */
  .site-nav__link--cta {
    display: block;
    margin-top: 10px;
    border-bottom: 0;
    border-radius: var(--radius);
    background: var(--accent);
    color: var(--accent-ink);
    font-weight: 600;
    text-align: center;
  }
  .site-nav__link--cta:hover,
  .site-nav__link--cta.is-active { color: var(--accent-ink); }
}

/* --- Pages légales ------------------------------------------------------- */
/* Sur une page claire, l'en-tête ne peut pas rester transparent : son texte est
   pensé pour le hero sombre. On le fige donc en fond plein. */
.site-header--solid {
  background: var(--ink);
  border-bottom-color: var(--border-on-dark);
}

.legal {
  max-width: 760px;
  margin: 0 auto;
  /* 80px pour dégager l'en-tête fixe, puis la respiration propre à la page */
  padding: calc(80px + 72px) var(--gutter) 96px;
}
.legal__eyebrow {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--accent-deep);
}
.legal h1 {
  margin: 12px 0 0;
  font-family: var(--font-display);
  font-size: clamp(30px, 4vw, 40px); font-weight: 700;
  letter-spacing: -0.02em;
}
.legal__date { margin: 8px 0 0; font-size: 14px; color: var(--muted); }
.legal h2 {
  margin: 44px 0 0;
  font-family: var(--font-display);
  font-size: 19px; font-weight: 600;
}
.legal p  { margin: 14px 0 0; line-height: 1.75; color: var(--muted); }
.legal ul { margin: 14px 0 0; padding-left: 22px; line-height: 1.75; color: var(--muted); }
.legal li + li { margin-top: 8px; }
.legal a { color: var(--accent-deep); }
.legal a:hover { color: oklch(0.42 0.11 128); }


/* --- Bandeau de consentement ---------------------------------------------
   Une ligne fine posée au bas de l'écran, sur le fond encre du site. Emprise
   minimale : le hero est l'argument du site, le bandeau ne doit pas le couvrir.

   Les deux boutons ont la même taille, la même hauteur de texte et le même
   nombre de clics. Refuser n'est jamais plus difficile qu'accepter — un bouton
   de refus effacé serait un motif trompeur, et le consentement ne serait plus
   libre.

   Le bandeau est livré avec l'attribut `hidden` : c'est js/consent.js qui
   décide de l'afficher, selon la réponse déjà donnée. */
.consent {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 60;                       /* au-dessus de l'en-tête, sous le lien d'évitement */
  background: var(--ink);
  border-top: 1px solid var(--border-on-dark);
  color: var(--fg-on-dark);
  opacity: 0;
  transform: translateY(100%);
  transition: opacity 0.32s var(--ease), transform 0.32s var(--ease);
}
.consent.is-visible { opacity: 1; transform: none; }

.consent__panel {
  display: flex;
  align-items: center;
  gap: 20px;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 12px var(--gutter);
}

.consent__copy { flex: 1 1 auto; min-width: 0; }

/* L'intitulé n'est pas dessiné : sur une seule ligne, la phrase se suffit. Il
   reste dans le balisage pour les lecteurs d'écran, qui annoncent ainsi ce
   qu'est ce bandeau avant d'en lire le contenu. */
.consent__title {
  position: absolute;
  width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.consent__body {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--muted-on-dark);
}

.consent__link {
  color: var(--accent-bright);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.consent__actions {
  display: flex;
  flex: 0 0 auto;
  gap: 10px;
}

.consent__btn {
  flex: 1 1 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius);
  padding: 7px 16px;
  font: 600 13px var(--font-sans);
  white-space: nowrap;
  border: 1px solid transparent;
  cursor: pointer;
  transition: opacity 0.2s, background 0.2s, border-color 0.2s;
}
.consent__btn--primary { background: var(--accent); color: var(--accent-ink); }
.consent__btn--primary:hover { opacity: 0.9; }
.consent__btn--ghost {
  border-color: var(--border-on-dark);
  background: rgba(255, 255, 255, 0.05);
  color: var(--fg-on-dark);
}
.consent__btn--ghost:hover { background: rgba(255, 255, 255, 0.12); }

/* Au doigt, deux boutons côte à côte sous 720px deviennent trop étroits pour
   être visés sans erreur : la ligne se déplie et les boutons s'élargissent. */
@media (max-width: 720px) {
  .consent__panel {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
    padding: 16px var(--gutter);
  }
  .consent__body { font-size: 14px; }
  .consent__btn { padding: 11px 22px; font-size: 14px; }
  .consent__actions > * { flex: 1 1 0; }
}

/* Le bandeau apparaît, sans glisser. */
@media (prefers-reduced-motion: reduce) {
  .consent { transition: none; transform: none; }
}

/* --- Page 404 --------------------------------------------------------------
   Une section sombre pleine hauteur, comme le hero, avec la lemniscate rompue
   peinte derrière par js/notfound.js. Le pied de page, déjà sombre, prend la
   suite : la page est d'un seul tenant.

   Rien de neuf n'est introduit ici — mêmes jetons, même échelle typographique
   et même bouton que le reste du site. */
.notfound {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  /* 80px pour dégager l'en-tête fixe. La hauteur laisse le pied de page
     affleurer sous la ligne de flottaison, sans forcer à défiler pour
     comprendre. */
  min-height: min(720px, 82vh);
  padding: calc(80px + 40px) var(--gutter) 88px;
  background: var(--ink);
  color: var(--fg-on-dark);
  text-align: center;
}

/* Le tracé tient sa propre bande dans la colonne, entre l'intitulé et le
   titre. En fond de section, il passait derrière le texte : on ne le voyait
   pas. Le rapport de la lemniscate est d'environ 2,3 pour 1 ; la bande est un
   peu plus large que haute pour lui laisser de l'air autour. */
.notfound__fx {
  pointer-events: none;
  display: block;
  width: min(520px, 100%);
  height: clamp(160px, 34vw, 250px);
  margin: 0 auto;
}

.notfound__inner {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center;
  gap: 20px;
  max-width: 640px;
}

.notfound__eyebrow {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--accent-bright);
}

.notfound__title {
  margin: 0;
  font-size: clamp(34px, 5.6vw, 60px);
  font-weight: 700; line-height: 1.05; letter-spacing: -0.02em;
  text-wrap: balance;
}

.notfound__lead {
  margin: 0;
  max-width: 46ch;
  font-size: clamp(15px, 1.5vw, 17px);
  line-height: 1.65;
  color: var(--muted-on-dark);
}

.notfound .btn { margin-top: 8px; }
