/* =========================================================================
   Paul Charpentier — système visuel « Plateau »
   Base encre profonde + craie, accents flare / cobalt / ambre / menthe.
   Typographie : grotesque système (Arial et équivalents), aucune fonte chargée.
   ========================================================================= */

/* ---------- Jetons ---------- */
:root {
  /* Encres — base sombre, légèrement verte */
  --ink: #0f1a16;
  --ink-2: #16241f;
  --ink-3: #1e302a;

  /* Surfaces claires */
  --paper: #e8e9e1;
  --paper-2: #dcded2;

  /* Gris de texte */
  --muted: #9aa8a1;
  --muted-dark: #4d5b55;
  --dim: #7b8a83;

  /* Accents */
  --signal: #f0451e;
  --signal-on-paper: #c9330f;
  --cobalt: #4a63f0;
  --cobalt-on-paper: #1e36d6;
  --amber: #f2b01e;
  --mint: #4fd6ae;

  --accent: var(--signal);
  --rule: rgba(232, 233, 225, 0.15);
  --rule-strong: rgba(232, 233, 225, 0.3);
  --rule-dark: rgba(15, 26, 22, 0.18);

  /* Typographie — pile système, aucune fonte téléchargée */
  --sans: Arial, 'Helvetica Neue', Helvetica, 'Liberation Sans', system-ui, sans-serif;
  --display: var(--sans);
  --mono: var(--sans);

  --max: 1320px;
  --gut: clamp(20px, 4.5vw, 56px);
  --section-y: clamp(84px, 12vh, 168px);
  --hdr-h: 68px;

  /* ---- Mouvement ----
     Deux courbes et trois durées, appliquées partout. « cut » pour tout ce
     qui entre, sort ou réagit ; « loop » pour ce qui tourne en continu.
     Les boucles gardent leur propre durée : elles ne racontent pas une
     entrée, elles tournent. Le décalage entre éléments d'une même série
     est un multiple de --stagger, cinq éléments au maximum. */
  --ease-cut: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-loop: linear;
  --dur-micro: 180ms;
  --dur-elem: 420ms;
  --dur-seq: 900ms;
  --stagger: 60ms;

  --radius: 4px;
  color-scheme: dark;
}

/* Accents par catégorie */
[data-cat='evenements'] { --accent: var(--signal); }
[data-cat='crm-rp'] { --accent: var(--amber); }
[data-cat='vibe-coding'] { --accent: var(--mint); }
[data-cat='terrain'] { --accent: var(--cobalt); }

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: clamp(1rem, 0.97rem + 0.18vw, 1.08rem);
  font-weight: 400;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; padding: 0; }

/* Les ancres ne passent ni sous l'en-tête ni sous le sommaire */
[id] { scroll-margin-top: calc(var(--hdr-h) + 72px); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--signal); color: #fff; }

/* ---------- Utilitaires ---------- */
.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gut); }
.vh {
  position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--signal); color: #fff; padding: 12px 18px;
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; text-decoration: none;
  transition: top var(--dur-micro) var(--ease-cut);
}
.skip:focus { top: 12px; }

/* Sur-titre : filet + libellé en capitales */
.eyebrow {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  display: flex;
  align-items: center;
  gap: 12px;
}
.eyebrow::before {
  content: '';
  width: 26px; height: 2px;
  background: currentColor;
  flex: none;
}
.eyebrow--plain::before { display: none; }
.eyebrow--center { justify-content: center; }

.mono {
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.muted { color: var(--muted); }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.022em;
  text-wrap: balance;
}
h2 { font-size: clamp(1.8rem, 3.8vw, 2.9rem); }
h3 { font-size: clamp(1.12rem, 1.7vw, 1.42rem); line-height: 1.2; }
p { text-wrap: pretty; }

.lede {
  font-size: clamp(1.05rem, 1rem + 0.42vw, 1.3rem);
  line-height: 1.62;
  color: var(--paper);
  max-width: 60ch;
}

/* Titre de page */
.pagetitle {
  font-size: clamp(2.3rem, 7vw, 5rem);
  text-transform: uppercase;
  letter-spacing: -0.03em;
  line-height: 0.98;
  margin: 22px 0 0;
}

/* ---------- En-tête ---------- */
.hdr {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--ink);
  border-bottom: 1px solid var(--rule);
  view-transition-name: hdr;
}
.hdr__in {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.4vw, 34px);
  height: var(--hdr-h);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  flex: none;
  margin-right: auto;
}
.brand__mark { width: 34px; height: 34px; flex: none; }
.brand__txt {
  font-weight: 700;
  letter-spacing: -0.015em;
  font-size: 1rem;
  line-height: 1.1;
}
.brand__txt small {
  display: block;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 3px;
}

.nav { display: flex; align-items: center; gap: clamp(12px, 1.8vw, 26px); }
.nav a {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--muted);
  padding: 6px 0;
  position: relative;
  transition: color var(--dur-micro) var(--ease-cut);
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--signal);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-micro) var(--ease-cut);
}
.nav a:hover { color: var(--paper); }
.nav a:hover::after { transform: scaleX(1); }
.nav a[aria-current='page'] { color: var(--paper); }
.nav a[aria-current='page']::after { transform: scaleX(1); }

.navtoggle { display: none; }

/* Bascule de langue : les deux codes côte à côte, la langue lue en clair. */
.lang {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: none;
  padding: 9px 12px;
  border: 1px solid var(--rule-strong);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-decoration: none;
  color: var(--muted);
  transition: border-color var(--dur-micro) var(--ease-cut), color var(--dur-micro) var(--ease-cut);
}
.lang i { width: 1px; height: 11px; background: var(--rule-strong); }
.lang .is-cur { color: var(--paper); box-shadow: inset 0 -2px 0 var(--signal); }
.lang:hover { border-color: var(--signal); color: var(--paper); }
.lang:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
/* Sur téléphone, la place manque : seule la langue de destination reste. */
@media (max-width: 560px) {
  .lang i, .lang .is-cur { display: none; }
  .lang { padding: 9px 11px; color: var(--paper); }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 12px 22px;
  border: 1px solid var(--rule-strong);
  background: transparent;
  color: var(--paper);
  transition: background var(--dur-micro) var(--ease-cut), color var(--dur-micro) var(--ease-cut), border-color var(--dur-micro) var(--ease-cut), transform var(--dur-micro) var(--ease-cut);
  white-space: nowrap;
}
.btn:hover { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.btn--signal {
  background: var(--signal);
  border-color: var(--signal);
  color: #fff;
}
.btn--signal:hover { background: var(--paper); border-color: var(--paper); color: var(--ink); }
.btn--ghost:hover { transform: translateY(-2px); }
.btn > svg { width: 15px; height: 15px; flex: none; }
.btn__arrow { transition: transform var(--dur-micro) var(--ease-cut); }
.btn:hover .btn__arrow { transform: translateX(4px); }

/* ---------- Sommaire de page ---------- */
.pagenav {
  position: sticky;
  top: var(--hdr-h);
  z-index: 80;
  background: color-mix(in srgb, var(--ink) 92%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}
.pagenav__in {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-block: 11px;
  overflow-x: auto;
  scrollbar-width: none;
}
.pagenav__in::-webkit-scrollbar { display: none; }
.pagenav__lbl {
  flex: none;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--dim);
  margin-right: 6px;
}
.pagenav a {
  flex: none;
  text-decoration: none;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--rule-strong);
  padding: 8px 15px;
  transition: color var(--dur-micro) var(--ease-cut), border-color var(--dur-micro) var(--ease-cut), background var(--dur-micro) var(--ease-cut);
}
.pagenav a:hover { color: var(--paper); border-color: var(--paper); }
.pagenav a.is-cur { background: var(--paper); color: var(--ink); border-color: var(--paper); }
@media (max-width: 560px) { .pagenav__lbl { display: none; } }

/* ---------- Pied de page ---------- */
.foot { border-top: 1px solid var(--rule); margin-top: auto; }
.foot__cta {
  padding: clamp(66px, 10vw, 128px) 0;
  border-bottom: 1px solid var(--rule);
  position: relative;
  overflow: hidden;
}
.foot__cta h2 { font-size: clamp(1.9rem, 5.6vw, 4rem); line-height: 1.04; }
.foot__cta .lede { margin-top: 20px; }
.foot__acts { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 38px; }
.foot__grid {
  display: grid;
  gap: 34px 44px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  padding: 52px 0 36px;
}
.foot__grid h3 {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 16px;
}
.foot__grid li { margin-bottom: 10px; }
.foot__grid a,
.foot__mail { text-decoration: none; font-size: 0.95rem; transition: color var(--dur-micro) var(--ease-cut); }
.foot__mail {
  font-family: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  overflow-wrap: anywhere;
}
.foot__grid a:hover,
.foot__mail:hover { color: var(--signal); }
.foot__base {
  border-top: 1px solid var(--rule);
  padding: 22px 0 32px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  justify-content: space-between;
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--dim);
}

/* ---------- Parallaxe ---------- */
[data-px] {
  transform: translate3d(0, calc(var(--p, 0) * var(--depth, 0px)), 0);
}
@media (max-width: 720px) {
  [data-px] { transform: translate3d(0, calc(var(--p, 0) * var(--depth, 0px) * 0.45), 0); }
}
@media (prefers-reduced-motion: reduce) {
  [data-px] { transform: none !important; }
}

/* ---------- Apparition ---------- */
.rv { opacity: 0; transform: translateY(20px); transition: opacity var(--dur-elem) var(--ease-cut), transform var(--dur-elem) var(--ease-cut); }
.rv.is-in { opacity: 1; transform: none; }
.rv:nth-child(2) { transition-delay: calc(var(--stagger) * 1); }
.rv:nth-child(3) { transition-delay: calc(var(--stagger) * 2); }
.rv:nth-child(4) { transition-delay: calc(var(--stagger) * 3); }
@media (prefers-reduced-motion: reduce) {
  .rv { opacity: 1; transform: none; transition: none; animation: none; }
}

/* Là où le navigateur sait rattacher une animation à la progression d'un
   élément dans l'écran, le défilement pilote lui-même l'apparition : plus
   d'observateur, plus de classe posée par le script, et le mouvement suit
   le geste du lecteur au lieu de se déclencher à heure fixe. Le décalage
   entre éléments d'une série ne s'exprime plus en millisecondes mais en
   fractions de course — un délai n'a pas de sens sur une piste de
   défilement. Le script se retire de lui-même quand cette règle s'applique. */
@supports (animation-timeline: view()) {
  .rv {
    opacity: 1;
    transform: none;
    transition: none;
    animation: rvIn auto var(--ease-cut) both;
    animation-timeline: view();
    animation-range: entry 8% entry 58%;
  }
  .rv:nth-child(2) { animation-range: entry 14% entry 64%; }
  .rv:nth-child(3) { animation-range: entry 20% entry 70%; }
  .rv:nth-child(4) { animation-range: entry 26% entry 76%; }
  @keyframes rvIn { from { opacity: 0; transform: translateY(20px); } }
}

/* =========================================================================
   ACCUEIL — héros
   ========================================================================= */
.hero {
  position: relative;
  padding: clamp(56px, 8vw, 108px) 0 clamp(48px, 7vw, 88px);
  overflow: hidden;
  isolation: isolate;
}
.hero__bg {
  position: absolute;
  inset: -12% -6% -18%;
  z-index: -3;
  background-image:
    linear-gradient(var(--rule) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: radial-gradient(120% 90% at 50% 20%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(120% 90% at 50% 20%, #000 20%, transparent 78%);
  opacity: 0.6;
}
.hero__glow {
  position: absolute;
  z-index: -2;
  width: min(1100px, 130vw);
  aspect-ratio: 1;
  left: 50%;
  top: -46%;
  translate: -50% 0;
  background: radial-gradient(circle, rgba(240, 69, 30, 0.24) 0%, rgba(74, 99, 240, 0.1) 40%, transparent 68%);
  pointer-events: none;
}
.hero__ghost {
  position: absolute;
  z-index: -1;
  left: 50%;
  translate: -50% 0;
  top: clamp(90px, 16vw, 210px);
  font-size: clamp(3.5rem, 13vw, 12rem);
  font-weight: 700;
  letter-spacing: 0.02em;
  color: transparent;
  -webkit-text-stroke: 1px rgba(232, 233, 225, 0.12);
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
}

.hero__status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper);
  border: 1px solid var(--rule-strong);
  padding: 8px 15px 8px 12px;
  border-radius: 999px;
  margin-bottom: clamp(30px, 4.5vw, 52px);
}
.dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--signal);
  flex: none;
  box-shadow: 0 0 0 0 rgba(240, 69, 30, 0.7);
  animation: pulse 2.4s var(--ease-loop) infinite;
}
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(240, 69, 30, 0.6); }
  70% { box-shadow: 0 0 0 9px rgba(240, 69, 30, 0); }
  100% { box-shadow: 0 0 0 0 rgba(240, 69, 30, 0); }
}
@media (prefers-reduced-motion: reduce) { .dot { animation: none; } }

/* Le titre passe en SVG : seul le tracé d'un contour peut se dessiner,
   -webkit-text-stroke ne sait pas s'animer. La taille suit la largeur du
   conteneur, plafonnée — ce qui reproduit l'ancien clamp(). */
.hero h1 { margin: 0; }
.hn { display: block; width: 100%; max-width: 940px; height: auto; }
.hn text {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 126px;
  letter-spacing: -0.04em;
}
.hn__fill { fill: var(--paper); animation: hnRise var(--dur-seq) var(--ease-cut) both; }
.hn__draw {
  fill: none;
  stroke: var(--paper);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}
/* L'état de départ est porté par la keyframe, jamais par la règle de base :
   si l'animation ne tourne pas, le titre s'affiche entier plutôt qu'absent. */
.hn__draw tspan {
  stroke-dasharray: 560;
  animation: hnDraw var(--dur-elem) var(--ease-cut) both;
  animation-delay: calc(var(--stagger) * 2 + var(--i) * var(--stagger) / 2);
}
@keyframes hnRise { from { transform: translateY(118px); } }
@keyframes hnDraw { from { stroke-dashoffset: 560; } }

.hero__body {
  display: grid;
  gap: clamp(30px, 4.4vw, 62px);
  grid-template-columns: minmax(0, 1fr);
  margin-top: clamp(32px, 4.2vw, 54px);
  align-items: end;
}
@media (min-width: 900px) {
  .hero__body { grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr); align-items: center; }
}
.hero__tagline {
  font-size: clamp(1.12rem, 1rem + 0.72vw, 1.52rem);
  line-height: 1.5;
  max-width: 32ch;
  text-wrap: balance;
}
.hero__tagline em { font-style: normal; color: var(--signal); font-weight: 700; }
.hero__side { display: flex; flex-direction: column; gap: 22px; }
.hero__stage { display: flex; justify-content: center; }
.hero__meta {
  display: grid;
  gap: 8px 20px;
  grid-template-columns: auto 1fr;
  font-size: 0.86rem;
  color: var(--muted);
  border-top: 1px solid var(--rule);
  padding-top: 20px;
  line-height: 1.5;
}
.hero__meta dt {
  color: var(--dim); text-transform: uppercase; letter-spacing: 0.14em;
  font-size: 0.66rem; font-weight: 700; padding-top: 4px;
}
.hero__meta dd { margin: 0; color: var(--paper); }
.hero__acts { display: flex; flex-wrap: wrap; gap: 12px; }


/* ---------- Socle tournant ----------
   Le plateau tourne en continu ; à chaque quart de tour un balayage vertical
   échange le support. Les quatre groupes partagent la même animation,
   décalée d'un quart de cycle par un délai négatif. */
.sc { display: block; width: 100%; max-width: 272px; height: auto; }
/* Sans cette règle, le display de la classe l'emporte sur l'attribut hidden
   et le socle vectoriel reste affiché à côté du rendu 3D. */
.sc[hidden] { display: none; }

.sc__spin {
  transform-box: fill-box;
  transform-origin: center;
  animation: scSpin 16s var(--ease-loop) infinite;
}
@keyframes scSpin { to { transform: rotate(360deg); } }

.sc__rim { animation: scRim 16s step-end infinite; }
@keyframes scRim {
  0% { stroke: var(--amber); }
  26% { stroke: var(--signal); }
  51% { stroke: var(--cobalt); }
  76% { stroke: var(--mint); }
}

/* Le délai est positif : un délai négatif ferait défiler les quatre
   supports à rebours et la couleur du plateau ne suivrait plus. */
.sc__sup {
  animation: scSup 16s var(--ease-cut) infinite both;
  animation-delay: calc(var(--i) * 4s);
}
/* La sortie déborde de 2,6 % sur le quart suivant : l'ancien support se
   retire pendant que le nouveau se pose, sans plateau vide entre les deux. */
@keyframes scSup {
  0% { opacity: 0; clip-path: inset(0 0 100% 0); }
  2.6% { opacity: 1; clip-path: inset(0 0 0 0); }
  25% { opacity: 1; clip-path: inset(0 0 0 0); }
  27.6% { opacity: 0; clip-path: inset(100% 0 0 0); }
  100% { opacity: 0; clip-path: inset(100% 0 0 0); }
}

/* Le filet qui accompagne l'échange — le même geste qu'une coupe en régie. */
.sc__scan {
  transform-box: view-box;
  animation: scScan 4s var(--ease-cut) infinite;
}
@keyframes scScan {
  0% { transform: translateY(0); opacity: 0; }
  3% { opacity: 1; }
  10% { transform: translateY(252px); opacity: 1; }
  13% { transform: translateY(252px); opacity: 0; }
  100% { transform: translateY(252px); opacity: 0; }
}

.sc__sup a { cursor: pointer; }
.sc__hit { pointer-events: all; }
.sc__lbl, .sc__cat { text-anchor: middle; font-family: var(--sans); }
.sc__lbl { fill: var(--paper); font-size: 19px; font-weight: 700; }
.sc__cat { fill: var(--dim); font-size: 12px; font-weight: 700; letter-spacing: 0.14em; }
.sc__sup a:hover .sc__lbl { fill: var(--accent); }
.sc__sup a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 899px) { .sc { max-width: 264px; } }

/* Sans mouvement, le plateau garde un seul support et cesse de tourner : la
   mise à l'arrêt générique les laisserait tous les quatre invisibles. */
@media (prefers-reduced-motion: reduce) {
  .sc__spin, .sc__rim { animation: none; }
  .sc__scan { animation: none; opacity: 0; }
  .sc__sup { animation: none; opacity: 0; clip-path: none; }
  .sc__sup[data-cat='crm-rp'] { opacity: 1; }
}


/* ---------- Socle en volume ----------
   Même emprise que le rendu vectoriel, pour que le remplacement de l'un par
   l'autre ne déplace rien dans la page. */
.stage3d { position: relative; width: 100%; max-width: 272px; }
.stage3d[hidden] { display: none; }
.stage3d canvas { display: block; width: 100%; aspect-ratio: 360 / 372; }
.stage3d__lien {
  display: block;
  text-align: center;
  text-decoration: none;
  margin-top: 2px;
  transition: color var(--dur-micro) var(--ease-cut);
}
.stage3d__sub {
  display: block;
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--paper);
  transition: color var(--dur-micro) var(--ease-cut);
}
.stage3d__cat {
  display: block;
  margin-top: 5px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--dim);
}
.stage3d__lien:hover .stage3d__sub { color: var(--accent); }
@media (max-width: 899px) { .stage3d { max-width: 264px; margin-inline: auto; } }

/* ---------- Indicateurs ---------- */
.metrics { border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.metrics__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 900px) { .metrics__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.metric {
  padding: clamp(28px, 3.4vw, 46px) clamp(18px, 2.4vw, 34px);
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  display: block;
  position: relative;
  transition: background var(--dur-micro) var(--ease-cut);
}
.metric:nth-child(2n) { border-right: 0; }
@media (min-width: 900px) {
  .metric { border-bottom: 0; }
  .metric:nth-child(2n) { border-right: 1px solid var(--rule); }
  .metric:last-child { border-right: 0; }
}
.metric:hover { background: var(--ink-2); }
.metric::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--signal);
  transform: scaleY(0); transform-origin: top;
  transition: transform var(--dur-micro) var(--ease-cut);
}
.metric:hover::before { transform: scaleY(1); }
.metric__v {
  font-size: clamp(1.8rem, 3.2vw, 2.7rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
  margin-bottom: 12px;
}
/* Le chiffre atterrit, un filet se trace sous lui : c'est le moment de
   calage. Il n'apparaît qu'une fois le décompte terminé, donc jamais quand
   le mouvement est réduit — le décompte ne tourne pas dans ce cas. */
.metric__v::after {
  content: '';
  position: absolute;
  left: 0;
  width: 2.2em;
  height: 2px;
  margin-top: 6px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  display: block;
}
.metric__v.is-set::after { animation: mLock var(--dur-elem) var(--ease-cut) both; }
@keyframes mLock { to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) { .metric__v::after { display: none; } }
.metric__l { font-size: 0.95rem; line-height: 1.45; }
.metric__n {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dim);
  margin-top: 12px;
  line-height: 1.5;
}

/* ---------- Sections ---------- */
.sec { padding: var(--section-y) 0; position: relative; }
.sec--tight { padding: clamp(52px, 7vw, 96px) 0; }
.sec--paper { background: var(--paper); color: var(--ink); }
.sec--paper .muted { color: var(--muted-dark); }
.sec--paper .eyebrow { color: var(--signal-on-paper); }
.sec--paper .btn { border-color: var(--rule-dark); color: var(--ink); }
.sec--paper .btn:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.sec--paper .btn--signal { background: var(--signal-on-paper); border-color: var(--signal-on-paper); color: #fff; }
.sec--paper .btn--signal:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* Aplat de couleur pleine — rythme visuel entre deux sections sombres */
.sec--cobalt { background: var(--cobalt-on-paper); color: var(--paper); }
.sec--cobalt .eyebrow { color: var(--paper); }
.sec--cobalt .muted { color: rgba(232, 233, 225, 0.78); }
.sec--cobalt .btn { border-color: rgba(232, 233, 225, 0.5); color: var(--paper); }
.sec--cobalt .btn:hover { background: var(--paper); color: var(--cobalt-on-paper); border-color: var(--paper); }
.sec--cobalt .pressband li { border-color: rgba(232, 233, 225, 0.42); color: var(--paper); }
.sec--cobalt .note { border-left-color: var(--paper); color: rgba(232, 233, 225, 0.86); }
.sec--cobalt .note a { color: var(--paper); }

.sec__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px 36px;
  margin-bottom: clamp(38px, 5vw, 72px);
}
.sec__head > div { max-width: 54ch; }
.sec__head h2 { margin-top: 18px; }
.sec__head--center { justify-content: center; text-align: center; }
.sec__head--center > div { margin-inline: auto; }
.sec__head--center .eyebrow { justify-content: center; }

/* ---------- Cartes réalisations ---------- */
.works { display: grid; gap: clamp(16px, 2vw, 28px); grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); }
.works--feat { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 940px) {
  .works--feat { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .works--feat > .card:nth-child(1) { grid-column: span 6; }
  .works--feat > .card:nth-child(2),
  .works--feat > .card:nth-child(3) { grid-column: span 3; }
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  text-decoration: none;
  background: var(--ink-2);
  border: 1px solid var(--rule);
  overflow: hidden;
  isolation: isolate;
  transition: border-color var(--dur-micro) var(--ease-cut), transform var(--dur-micro) var(--ease-cut), background var(--dur-micro) var(--ease-cut);
}
.card:hover { border-color: color-mix(in srgb, var(--accent) 55%, transparent); transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) { .card:hover { transform: none; } }

.card__art { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: var(--ink-3); }
.card:nth-child(1).card--big .card__art { aspect-ratio: 21 / 9; }
.card__art svg { width: 100%; height: 100%; }
.card__art::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 54%, rgba(15, 26, 22, 0.62) 100%);
}
.card__tag {
  position: absolute;
  z-index: 2;
  left: 16px; top: 16px;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--accent);
  padding: 6px 11px;
}
/* Pastille logo du partenaire, posée sur le visuel */
.card__logo {
  position: absolute;
  z-index: 2;
  right: 16px; bottom: 16px;
  width: clamp(76px, 9vw, 108px);
  height: clamp(42px, 5vw, 58px);
  background: var(--paper);
  border-radius: 10px;
  padding: 8px 11px;
  display: grid;
  place-items: center;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.38);
}
.card__logo img { width: 100%; height: 100%; object-fit: contain; }

.card__body { padding: clamp(20px, 2.4vw, 34px); display: flex; flex-direction: column; gap: 14px; flex: 1; }
.card__kicker {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.card h3 { font-size: clamp(1.22rem, 2vw, 1.75rem); }
.card--big h3 { font-size: clamp(1.6rem, 3.4vw, 2.7rem); }
.card__teaser { color: var(--muted); font-size: 0.97rem; line-height: 1.62; max-width: 62ch; }
.card--big .card__teaser { font-size: clamp(1rem, 1.2vw, 1.14rem); color: var(--paper); }
.card__more {
  margin-top: auto;
  padding-top: 10px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.card__more span { transition: transform var(--dur-micro) var(--ease-cut); }
.card:hover .card__more span { transform: translateX(5px); }
.card__stats { display: flex; flex-wrap: wrap; gap: 10px 26px; padding-top: 6px; }
.card__stat b {
  display: block;
  font-size: clamp(1.15rem, 1.8vw, 1.5rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.2;
  color: var(--accent);
}
.card__stat span {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted);
}

/* ---------- Bandeau presse ---------- */
.pressband { display: flex; flex-wrap: wrap; gap: 12px; }
.pressband li {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: 1px solid var(--rule);
  padding: 10px 16px;
  color: var(--paper);
}
.sec--paper .pressband li { border-color: var(--rule-dark); color: var(--ink); }

/* =========================================================================
   PORTFOLIO
   ========================================================================= */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  padding-bottom: clamp(26px, 3.2vw, 44px);
  border-bottom: 1px solid var(--rule);
  margin-bottom: clamp(26px, 3.2vw, 46px);
}
.filter {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 10px 17px;
  border: 1px solid var(--rule-strong);
  color: var(--muted);
  transition: color var(--dur-micro) var(--ease-cut), border-color var(--dur-micro) var(--ease-cut), background var(--dur-micro) var(--ease-cut);
}
.filter:hover { color: var(--paper); border-color: var(--paper); }
.filter[aria-pressed='true'] { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.filter__n { opacity: 0.55; margin-left: 8px; }

.card.is-hidden { display: none; }
.works--all .card { animation: cardIn var(--dur-elem) var(--ease-cut) both; }
@keyframes cardIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
/* Au chargement, les sept cartes sous la ligne de flottaison jouaient leur
   entrée sans témoin. Rattachée au défilement, chacune joue la sienne à son tour. */
@supports (animation-timeline: view()) {
  .works--all .card {
    animation: cardIn auto var(--ease-cut) both;
    animation-timeline: view();
    animation-range: entry 6% entry 52%;
  }
}
@media (prefers-reduced-motion: reduce) { .works--all .card { animation: none; } }

.filtercount {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 24px;
}

/* =========================================================================
   PAGE RÉALISATION
   ========================================================================= */
.casehead { position: relative; padding: clamp(46px, 7vw, 96px) 0 clamp(36px, 4.6vw, 64px); overflow: hidden; }
.casehead__art { position: absolute; inset: 0; z-index: -1; opacity: 0.45; }
.casehead__art svg { width: 100%; height: 100%; object-fit: cover; }
.casehead__art::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(15, 26, 22, 0.5) 0%, rgba(15, 26, 22, 0.94) 82%, var(--ink) 100%);
}
.casehead h1 {
  font-size: clamp(2.1rem, 6.4vw, 4.8rem);
  text-transform: uppercase;
  letter-spacing: -0.03em;
  line-height: 1;
  margin: 20px 0 0;
}
.casehead__sub { font-size: clamp(1.05rem, 1.6vw, 1.38rem); color: var(--muted); margin-top: 20px; max-width: 54ch; line-height: 1.5; }
.casehead__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 40px;
  margin-top: 36px;
  padding-top: 24px;
  border-top: 1px solid var(--rule);
  font-size: 0.86rem;
}
.casehead__meta b {
  display: block; color: var(--dim); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.14em; font-size: 0.64rem; margin-bottom: 6px;
}

/* Plaque partenaire : logo fourni, posé sur un aplat clair */
.partner {
  display: inline-flex;
  align-items: center;
  gap: 20px;
  margin-top: 30px;
  border: 1px solid var(--rule);
  background: var(--ink-2);
  padding: 14px 24px 14px 14px;
}
.partner__logo {
  flex: none;
  width: clamp(116px, 15vw, 168px);
  height: clamp(60px, 7vw, 84px);
  background: var(--paper);
  border-radius: 14px;
  padding: 10px 14px;
  display: grid;
  place-items: center;
}
.partner__logo img { width: 100%; height: 100%; object-fit: contain; }
.partner b { display: block; font-size: 1.02rem; line-height: 1.35; }
.partner span {
  display: block;
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--dim); margin-bottom: 8px;
}
.aside .partner {
  margin-top: 0; width: 100%; border: 0; padding: 0; background: none;
  flex-direction: column; align-items: stretch; gap: 14px;
}
.aside .partner__logo { width: 100%; height: clamp(76px, 12vw, 104px); }

.caseblocks { display: grid; gap: clamp(44px, 6vw, 84px); padding-bottom: var(--section-y); }
@media (min-width: 960px) { .caseblocks { grid-template-columns: minmax(0, 1fr) minmax(0, 330px); align-items: start; } }

.block + .block { margin-top: clamp(44px, 5.5vw, 74px); }
.block h2 {
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 22px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule);
  line-height: 1.4;
}
.block p + p { margin-top: 18px; }
.block p { max-width: 66ch; }
.ticks li { position: relative; padding-left: 28px; margin-bottom: 16px; max-width: 66ch; }
.ticks li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.78em;
  width: 14px; height: 2px;
  background: var(--accent);
}
.numlist { counter-reset: n; }
.numlist li { position: relative; padding-left: 44px; margin-bottom: 18px; counter-increment: n; max-width: 66ch; }
.numlist li::before {
  content: counter(n, decimal-leading-zero);
  position: absolute; left: 0; top: 0.1em;
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.06em; color: var(--accent);
}

.resgrid { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.resgrid > div { background: var(--ink); padding: clamp(22px, 2.8vw, 34px); }
.resgrid b {
  display: block;
  font-size: clamp(1.55rem, 3vw, 2.4rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.1;
  color: var(--accent);
  margin-bottom: 12px;
}
.resgrid span { font-size: 0.9rem; line-height: 1.5; color: var(--muted); display: block; }

.note {
  border-left: 2px solid var(--accent);
  padding: 6px 0 6px 22px;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.68;
  max-width: 64ch;
  margin-top: 26px;
}
.takeaway {
  background: var(--ink-2);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--accent);
  padding: clamp(24px, 3vw, 36px);
  font-size: clamp(1.02rem, 1.3vw, 1.16rem);
  line-height: 1.6;
  margin-top: 32px;
}

.aside { position: sticky; top: calc(var(--hdr-h) + 24px); display: flex; flex-direction: column; gap: 24px; }
@media (max-width: 959px) { .aside { position: static; } }
.aside__box { border: 1px solid var(--rule); padding: 26px; }
.aside__box h3 {
  font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); margin-bottom: 18px;
}
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chips li {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em;
  border: 1px solid var(--rule); padding: 7px 12px; color: var(--paper);
}
.aside .btn { width: 100%; }

.casenav {
  display: flex; flex-wrap: wrap; gap: 20px; justify-content: space-between;
  border-top: 1px solid var(--rule); padding: 30px 0 var(--section-y);
}
.casenav a {
  text-decoration: none; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted); transition: color var(--dur-micro) var(--ease-cut);
}
.casenav a:hover { color: var(--paper); }
.casenav b {
  display: block; font-size: 1.15rem; font-weight: 700; text-transform: none;
  letter-spacing: -0.02em; color: var(--paper); margin-top: 8px;
}

/* =========================================================================
   COMPÉTENCES
   ========================================================================= */
.skillgroup { border-top: 1px solid var(--rule); padding: clamp(40px, 5.2vw, 76px) 0; }
.skillgroup__in { display: grid; gap: 28px clamp(32px, 4.5vw, 76px); }
@media (min-width: 900px) { .skillgroup__in { grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr); } }
.skillgroup__num {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--signal);
  margin-bottom: 18px;
}
.skillgroup h2 { font-size: clamp(1.45rem, 2.7vw, 2.15rem); line-height: 1.1; }
.skillgroup__lede { color: var(--muted); margin-top: 18px; font-size: 1rem; line-height: 1.68; max-width: 42ch; }
.skillgroup__sticky { position: sticky; top: calc(var(--hdr-h) + 86px); }
@media (max-width: 899px) { .skillgroup__sticky { position: static; } }
.skillgroup__items li {
  border-bottom: 1px solid var(--rule);
  padding: 16px 0 16px 28px;
  position: relative;
  font-size: 0.99rem;
  line-height: 1.6;
}
.skillgroup__items li::before {
  content: '';
  position: absolute; left: 0; top: 1.5em;
  width: 14px; height: 2px; background: var(--signal);
}
.skillgroup__items li:first-child { border-top: 1px solid var(--rule); }

.levels { display: grid; gap: clamp(18px, 2.2vw, 30px); grid-template-columns: repeat(auto-fit, minmax(min(100%, 270px), 1fr)); }
.level { border: 1px solid var(--rule-dark); padding: clamp(24px, 3vw, 36px); position: relative; }
.level__bar { display: flex; gap: 5px; margin-bottom: 22px; }
.level__bar i { display: block; height: 5px; flex: 1; background: var(--rule-dark); }
.level__bar i.on { background: var(--signal-on-paper); }
.level h3 { font-size: 1.14rem; line-height: 1.3; }
.level__note { color: var(--muted-dark); font-size: 0.9rem; margin-top: 12px; line-height: 1.6; }
.level ul { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }
.level li {
  font-size: 0.74rem; font-weight: 700; letter-spacing: 0.04em;
  border: 1px solid var(--rule-dark); padding: 7px 12px;
}

/* =========================================================================
   PARCOURS
   ========================================================================= */
.timeline { border-top: 1px solid var(--rule); }
.tl {
  display: grid;
  gap: 12px clamp(28px, 4.5vw, 66px);
  padding: clamp(32px, 4vw, 52px) 0;
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 820px) { .tl { grid-template-columns: 210px minmax(0, 1fr); } }
.tl__when { font-size: 0.82rem; color: var(--muted); line-height: 1.5; }
.tl__when b {
  display: block; color: var(--paper); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; font-size: 0.76rem; margin-bottom: 8px;
}
.tl h3 { font-size: clamp(1.14rem, 1.9vw, 1.5rem); line-height: 1.25; }
.tl h3 em { font-style: normal; color: var(--signal); }
.tl__detail { color: var(--muted); margin-top: 14px; font-size: 0.96rem; line-height: 1.68; }
.tl .ticks { margin-top: 20px; }
.tl .ticks li { font-size: 0.96rem; color: var(--muted); margin-bottom: 13px; }
.tl .ticks li::before { background: var(--signal); }

.factgrid { display: grid; gap: clamp(24px, 3.4vw, 46px); grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); }
.factgrid h3 {
  font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); margin-bottom: 18px;
}
.factgrid li { padding: 11px 0; border-bottom: 1px solid var(--rule); font-size: 0.96rem; line-height: 1.5; }
.factgrid li span { color: var(--muted); }

/* =========================================================================
   CONTACT
   ========================================================================= */
.contactgrid { display: grid; gap: clamp(28px, 3.4vw, 50px); }
@media (min-width: 900px) { .contactgrid { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); } }
.bigcontact { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); align-content: start; align-self: start; }
.bigcontact a,
.bigcontact button {
  font: inherit;
  color: inherit;
  width: 100%;
  text-align: left;
  border: 0;
  cursor: pointer;
  background: var(--ink);
  padding: clamp(24px, 3vw, 36px);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 20px;
  transition: background var(--dur-micro) var(--ease-cut);
}
.bigcontact a:hover,
.bigcontact button:hover { background: var(--ink-2); }
.bigcontact svg { width: 22px; height: 22px; flex: none; color: var(--signal); }
.bigcontact div { min-width: 0; }
.bigcontact b { display: block; overflow-wrap: anywhere; font-size: clamp(0.98rem, 2vw, 1.4rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.25; }
.bigcontact span { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--dim); display: block; margin-bottom: 8px; }
.bigcontact .btn__arrow { margin-left: auto; color: var(--muted); }

/* ---------- CV consultable, non téléchargeable ---------- */
.cvframe { border: 1px solid var(--rule); background: var(--ink); padding: 16px; }
.cvframe img { display: block; width: 100%; height: auto; }
.cvframe figcaption { font-size: 0.78rem; line-height: 1.6; color: var(--dim); margin-top: 14px; }

/* ---------- Transitions de page ----------
   Une coupe, pas un fondu : la nouvelle page recouvre l'ancienne par un
   balayage dont le sens suit celui de la navigation. Et un objet traverse —
   le visuel d'une carte devient la bannière de sa fiche. Le nom `art` est
   posé au vol par le script sur les deux seuls éléments concernés : dix
   cartes nommées d'un côté contre une seule de l'autre feraient sortir les
   neuf autres chacune dans son coin. */
@view-transition { navigation: auto; }

/* Les éléments fixes sont extraits de l'instantané de la page : sans ça, ils
   participeraient au balayage et glisseraient avec le reste. */
.pagenav { view-transition-name: pagenav; }
.progress { view-transition-name: progress; }
.floatcta { view-transition-name: floatcta; }

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: vtHold var(--dur-elem) var(--ease-loop) both; }
  ::view-transition-new(root) { animation: vtWipe var(--dur-elem) var(--ease-cut) both; }

  /* L'objet qui voyage. Les deux instantanés n'ont pas le même format — une
     carte est plus ramassée qu'une bannière — d'où le recadrage. */
  ::view-transition-group(art) {
    animation-duration: var(--dur-seq);
    animation-timing-function: var(--ease-cut);
  }
  ::view-transition-old(art),
  ::view-transition-new(art) {
    height: 100%;
    object-fit: cover;
    overflow: clip;
  }

  /* On remonte vers la liste : le balayage repart dans l'autre sens. */
  :root:active-view-transition-type(remontee) ::view-transition-new(root) { animation-name: vtWipeUp; }

  /* D'une fiche à l'autre, on avance dans le conducteur : mouvement latéral. */
  :root:active-view-transition-type(laterale) ::view-transition-new(root) { animation-name: vtSlideIn; }
  :root:active-view-transition-type(laterale) ::view-transition-old(root) { animation-name: vtSlideOut; }
}
/* Changement de langue : la page se retourne comme une carte. L'ancienne
   version pivote jusqu'à la tranche, la nouvelle en revient de l'autre côté.
   Les éléments nommés rejoignent l'instantané de la page (classe is-flip,
   posée par le script d'en-tête) pour tourner avec elle. */
:root.is-flip .hdr,
:root.is-flip .pagenav,
:root.is-flip .progress,
:root.is-flip .floatcta { view-transition-name: none; }
@media (prefers-reduced-motion: no-preference) {
  :root:active-view-transition-type(flip)::view-transition { background: #070d0b; }
  :root:active-view-transition-type(flip) ::view-transition-old(root) {
    animation: vtFlipOut 340ms cubic-bezier(0.55, 0, 0.9, 0.4) both;
    backface-visibility: hidden;
  }
  :root:active-view-transition-type(flip) ::view-transition-new(root) {
    animation: vtFlipIn 520ms var(--ease-cut) 320ms both;
    backface-visibility: hidden;
  }
}
@keyframes vtFlipOut {
  from { transform: perspective(1600px) rotateY(0); filter: brightness(1); }
  to { transform: perspective(1600px) rotateY(-90deg) scale(0.92); filter: brightness(0.45); }
}
@keyframes vtFlipIn {
  from { transform: perspective(1600px) rotateY(90deg) scale(0.92); filter: brightness(0.45); }
  to { transform: perspective(1600px) rotateY(0); filter: brightness(1); }
}

/* Repli sans transitions entre documents : le même retournement, joué sur
   le corps de page par site.js. */
@media (prefers-reduced-motion: no-preference) {
  html.flip-out, html.flip-in { background: #070d0b; overflow-x: clip; }
  html.flip-out body { animation: vtFlipOut 340ms cubic-bezier(0.55, 0, 0.9, 0.4) both; }
  html.flip-in body { animation: vtFlipIn 520ms var(--ease-cut) both; }
}

@keyframes vtHold { to { opacity: 0.5; } }
/* Les deux bornes sont écrites : une interpolation entre inset() et la
   valeur none n'existe pas, elle bascule d'un coup à mi-parcours. Le
   balayage ne se voyait donc pas — la page restait invisible, puis
   apparaissait. */
@keyframes vtWipe { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes vtWipeUp { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes vtSlideIn { from { transform: translateX(5%); opacity: 0; } }
@keyframes vtSlideOut { to { transform: translateX(-4%); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}


/* =========================================================================
   VISUELS DE RÉALISATION — mise en mouvement
   Deux régimes et deux seulement. Une entrée jouée une fois quand le visuel
   arrive à l'écran ; une boucle qui ne tourne qu'au survol de la carte, ou
   en continu sur la bannière d'une fiche, jamais sur dix cartes à la fois.
   Toutes les animations sont déclarées à l'arrêt : l'état de départ est
   celui de la première image, donc rien ne clignote avant son tour, et sans
   JavaScript rien n'est jamais mis en pause — le visuel reste entier.
   ========================================================================= */
.card__art, .casehead__art { --art-stagger: calc(var(--stagger) / 2); }
.a-in, .a-open, .a-rise, .a-wave { transform-box: fill-box; }
.a-in, .a-open, .a-wave { transform-origin: center; }
.a-rise { transform-origin: bottom; }
.a-ring { transform-box: fill-box; transform-origin: center; }

/* ---- Entrées, jouées une fois, armées par le script ---- */
.is-armed .a-draw {
  stroke-dasharray: 1;
  animation: aDraw calc(var(--dur-seq) * 1.4) var(--ease-cut) both paused;
}
.is-armed .a-in {
  animation: aIn var(--dur-elem) var(--ease-cut) both paused;
  animation-delay: calc(var(--i, 0) * var(--art-stagger));
}
.is-armed .a-open {
  animation: aOpen var(--dur-elem) var(--ease-cut) both paused;
  animation-delay: calc(var(--i, 0) * var(--art-stagger));
}
.is-armed .a-rise {
  animation: aRise var(--dur-elem) var(--ease-cut) both paused;
  animation-delay: calc(var(--i, 0) * var(--art-stagger));
}
.is-armed .a-wipe {
  animation: aWipe var(--dur-elem) var(--ease-cut) both paused;
  animation-delay: calc(var(--i, 0) * var(--art-stagger));
}
.is-on .a-draw, .is-on .a-in, .is-on .a-open, .is-on .a-rise, .is-on .a-wipe {
  animation-play-state: running;
}
@keyframes aDraw { from { stroke-dashoffset: 1; } }
@keyframes aIn { from { opacity: 0; transform: scale(0.4); } }
@keyframes aOpen { from { transform: scaleY(0); } }
@keyframes aRise { from { transform: scaleY(0); } }
/* Même piège que pour les transitions de page : sans borne d'arrivée
   explicite, le dévoilement bascule au lieu de balayer. */
@keyframes aWipe { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }

/* ---- Boucles, à l'arrêt tant que la carte n'est pas survolée ---- */
.a-ring { animation: aRing 3.2s var(--ease-cut) infinite both paused; animation-delay: calc(var(--i, 0) * 0.26s); }
.a-blink { animation: aBlink 1.8s step-end infinite both paused; animation-delay: calc(var(--i, 0) * 0.22s); }
.a-march { animation: aMarch 1.6s var(--ease-loop) infinite both paused; }
.a-spin { animation: aSpin 26s var(--ease-loop) infinite both paused; animation-delay: calc(var(--i, 0) * -6s); }
.a-wave { animation: aWave 1.5s var(--ease-cut) infinite both paused; animation-delay: calc(var(--i, 0) * -0.07s); }
.a-scanline { animation: aScan 3.6s var(--ease-cut) infinite both paused; }
.a-spin { transform-box: view-box; transform-origin: 600px 338px; }
.a-scanline { transform-box: view-box; }

@keyframes aRing { from { transform: scale(0.82); opacity: 0.9; } to { transform: scale(1.06); opacity: 0; } }
@keyframes aBlink { 0%, 62% { opacity: 1; } 63%, 100% { opacity: 0.18; } }
@keyframes aMarch { to { stroke-dashoffset: -28; } }
@keyframes aSpin { to { transform: rotate(360deg); } }
@keyframes aWave { 50% { transform: scaleY(0.34); } }
@keyframes aScan { 0% { transform: translateX(0); opacity: 0; } 6% { opacity: 0.55; } 88% { opacity: 0.55; } 100% { transform: translateX(1200px); opacity: 0; } }

.card:hover .a-loop,
.card:focus-visible .a-loop,
.casehead__art .a-loop { animation-play-state: running; }

/* Sans mouvement, les visuels restent ce qu'ils sont : des dessins fixes.
   La mise à l'arrêt générique ne suffirait pas, elle laisserait les pièces
   figées sur leur première image, c'est-à-dire repliées. */
@media (prefers-reduced-motion: reduce) {
  .card__art [class*='a-'],
  .casehead__art [class*='a-'] { animation: none !important; clip-path: none !important; }
}

/* =========================================================================
   MOBILE
   ========================================================================= */
@media (max-width: 980px) {
  .navtoggle {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-size: 0.74rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    border: 1px solid var(--rule-strong);
    padding: 10px 15px;
  }
  .navtoggle i { display: block; width: 15px; height: 9px; position: relative; flex: none; }
  .navtoggle i::before, .navtoggle i::after {
    content: ''; position: absolute; left: 0; right: 0; height: 1.5px; background: currentColor;
    transition: transform var(--dur-micro) var(--ease-cut), opacity var(--dur-micro) var(--ease-cut);
  }
  .navtoggle i::before { top: 0; }
  .navtoggle i::after { bottom: 0; }
  .navtoggle[aria-expanded='true'] i::before { transform: translateY(3.75px) rotate(45deg); }
  .navtoggle[aria-expanded='true'] i::after { transform: translateY(-3.75px) rotate(-45deg); }

  .nav {
    position: fixed;
    inset: var(--hdr-h) 0 auto;
    background: var(--ink);
    border-bottom: 1px solid var(--rule);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 8px var(--gut) 28px;
    transform: translateY(-14px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-micro) var(--ease-cut), transform var(--dur-micro) var(--ease-cut);
    max-height: calc(100dvh - var(--hdr-h));
    overflow-y: auto;
  }
  .nav.is-open { transform: none; opacity: 1; pointer-events: auto; }
  .nav a {
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    text-transform: none;
    padding: 18px 0;
    border-bottom: 1px solid var(--rule);
    color: var(--paper);
  }
  .nav a::after { display: none; }
  .nav a[aria-current='page'] { color: var(--signal); }
  .hdr__cta { display: none; }
  .nav .btn { margin-top: 22px; display: flex; text-transform: uppercase; font-size: 0.78rem; }
}
@media (min-width: 981px) { .nav .btn--mob { display: none; } }

@media (max-width: 1000px) { .hero__ghost { display: none; } }

@media (max-width: 560px) {
  .hero__meta { grid-template-columns: 1fr; gap: 4px; }
  .hero__meta dt { margin-top: 14px; }
  .foot__base { flex-direction: column; }
  .partner { flex-direction: column; align-items: flex-start; gap: 16px; width: 100%; }
}

/* ---------- Impression ---------- */
@media print {
  .hdr, .pagenav, .foot__cta, .navtoggle, .hero__glow, .hero__bg, .hero__ghost, .floatcta { display: none !important; }
  body { background: #fff; color: #000; }
}

/* =========================================================================
   MOUVEMENT — ouverture, progression, CTA flottant, compteurs
   ========================================================================= */
[data-rise] { animation: riseIn var(--dur-elem) var(--ease-cut) both; }
[data-rise='1'] { animation-delay: calc(var(--stagger) * 6); }
[data-rise='2'] { animation-delay: calc(var(--stagger) * 8); }
@keyframes riseIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

.progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 120;
  pointer-events: none;
  background: transparent;
}
.progress i {
  display: block;
  height: 100%;
  background: var(--signal);
  transform: scaleX(var(--sp, 0));
  transform-origin: left;
}

.floatcta {
  position: fixed;
  z-index: 55;
  right: clamp(14px, 2.5vw, 28px);
  bottom: clamp(14px, 2.5vw, 28px);
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 13px 22px;
  border-radius: 999px;
  background: var(--signal);
  color: #fff;
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  opacity: 0;
  transform: translateY(14px) scale(0.96);
  pointer-events: none;
  transition: opacity var(--dur-elem) var(--ease-cut), transform var(--dur-elem) var(--ease-cut);
}
.floatcta.is-on { opacity: 1; transform: none; pointer-events: auto; }
.floatcta:hover { transform: translateY(-2px); }
.floatcta:focus-visible { opacity: 1; transform: none; pointer-events: auto; }
@media (max-width: 560px) { .floatcta { padding: 11px 17px; font-size: 0.72rem; } }

.metric__v, .card__stat b, .resgrid b { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  [data-rise] { animation: none !important; transform: none !important; opacity: 1 !important; }
  .progress { display: none; }
  .floatcta { transition: none; }
  .floatcta:hover { transform: none; }
}

/* =========================================================================
   BANDEAU DE MARQUES — défilement continu, bords fondus
   Même principe que le carrousel de référence : une piste dupliquée qui
   glisse d'une demi-longueur, et un masque dégradé sur les deux bords.
   ========================================================================= */
.brandband {
  --bb-gap: clamp(30px, 4.5vw, 64px);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: clamp(28px, 3.4vw, 46px) 0;
  overflow: hidden;
}
.brandband__lbl {
  text-align: center;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--dim);
  margin-bottom: clamp(22px, 2.6vw, 34px);
}
.brandband__mask {
  overflow: hidden;
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.brandband__track {
  display: flex;
  width: max-content;
  animation: bbSlide 34s var(--ease-loop) infinite;
  will-change: transform;
}
/* L'écart est porté par le jeu lui-même : les quatre jeux ont la même
   largeur, donc une translation de -50 % retombe exactement sur deux jeux
   et la boucle est invisible. */
.brandband__set {
  display: flex;
  align-items: center;
  gap: var(--bb-gap);
  padding-right: var(--bb-gap);
  flex: none;
}
.brandband:hover .brandband__track,
.brandband:focus-within .brandband__track { animation-play-state: paused; }
@keyframes bbSlide {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
/* Plaques carrées, sans marge interne : la marge est portée par le fichier,
   normalisé par src/logos.js pour que tous les logos aient la même surface. */
.brandband__set li {
  flex: none;
  width: clamp(80px, 8.6vw, 106px);
  aspect-ratio: 1;
  background: var(--paper);
  border-radius: 20px;
  display: grid;
  place-items: center;
  overflow: hidden;
  filter: saturate(0.25);
  opacity: 0.78;
  transition: filter var(--dur-micro) var(--ease-cut), opacity var(--dur-micro) var(--ease-cut);
}
.brandband__set li:hover { filter: none; opacity: 1; }
.brandband__set img { width: 100%; height: 100%; object-fit: contain; }
@media (prefers-reduced-motion: reduce) {
  .brandband__mask { -webkit-mask-image: none; mask-image: none; }
  .brandband__track {
    animation: none;
    width: 100%;
    max-width: var(--max);
    margin-inline: auto;
    padding-inline: var(--gut);
  }
  .brandband__track .brandband__set + .brandband__set { display: none; }
  .brandband__set { width: 100%; flex-wrap: wrap; justify-content: center; padding-right: 0; }
}

/* =========================================================================
   BANNIÈRE « QUI SUIS-JE »
   ========================================================================= */
.about { padding: var(--section-y) 0; }
.about__in {
  display: grid;
  gap: clamp(32px, 5vw, 76px);
  align-items: center;
}
@media (min-width: 900px) {
  .about__in { grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr); }
}
/* Le portrait est détouré et composé sur l'aplat flare dans le fichier
   lui-même (voir src/portrait.js), comme sur le site de référence : aucun
   filtre ni fusion en CSS, seulement le rayon d'angle. */
.about__shot {
  position: relative;
  aspect-ratio: 1;
  max-width: 420px;
  width: 100%;
}
.about__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 32px;
}
/* Repli tant qu'aucun portrait n'est déposé : l'aplat occupe le cadre */
.about__shot--mark {
  background: var(--signal);
  border-radius: 32px;
  display: grid;
  place-items: center;
}
.about__mark {
  font-size: clamp(4rem, 12vw, 8rem);
  font-weight: 700;
  letter-spacing: -0.06em;
  line-height: 1;
  color: var(--ink);
}
.pill {
  display: inline-flex;
  align-items: center;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--signal);
  border: 1px solid var(--signal);
  border-radius: 999px;
  padding: 9px 18px;
}
.about h2 {
  font-size: clamp(1.9rem, 4vw, 3.1rem);
  line-height: 1.1;
  margin-top: clamp(22px, 2.6vw, 34px);
  max-width: 20ch;
}
.about h2 em { font-style: normal; color: var(--signal); }
.about__cols {
  display: grid;
  gap: clamp(22px, 3vw, 44px);
  margin-top: clamp(30px, 3.6vw, 50px);
}
@media (min-width: 720px) { .about__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.about__cols p { color: var(--muted); font-size: 0.97rem; line-height: 1.8; }
.about__acts { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(28px, 3.2vw, 44px); }

/* =========================================================================
   CE QUI ME DISTINGUE
   ========================================================================= */
.edge {
  background: var(--ink-2);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: var(--section-y) 0;
}
.edge h2 { max-width: 22ch; }
.edge h2 em { font-style: normal; color: var(--signal); }
.edge__grid {
  display: grid;
  gap: clamp(18px, 2.4vw, 32px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
}
.edge__card {
  border: 1px solid var(--rule);
  background: var(--ink);
  padding: clamp(26px, 3vw, 38px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  transition: border-color var(--dur-micro) var(--ease-cut);
}
.edge__card:hover { border-color: var(--rule-strong); }
.edge__num {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--signal);
}
.edge__card h3 { font-size: clamp(1.14rem, 1.7vw, 1.4rem); line-height: 1.25; }
.edge__txt { color: var(--muted); font-size: 0.96rem; line-height: 1.75; }

/* =========================================================================
   MOUVEMENT RÉDUIT — filet de sécurité
   Les blocs plus haut traitent les cas qui demandent davantage qu'une mise à
   l'arrêt : le bandeau de marques se recompose en grille, la parallaxe reprend
   sa position neutre, la barre de progression disparaît. Celui-ci couvre tout
   le reste, y compris les animations ajoutées par la suite et les transitions
   de page nommées, que le sélecteur universel n'atteint pas.
   Les durées sont ramenées à 1 ms plutôt que supprimées : l'élément atteint
   son état final au lieu de rester bloqué sur son état de départ.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
  }
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}
