/* ============================================================
   MEHDI BOUKLACHI — PORTFOLIO
   Design System v5 — "Éditorial Papier & Studio"
   ============================================================ */

/* ── GOOGLE FONTS ──
   Chargées via <link rel="preconnect"> + <link href="...css2..."> dans le
   <head> de chaque page (pattern non bloquant). Ne pas dupliquer ici avec
   @import : cela chargeait deux fois les mêmes fichiers de police. */

/* ── DESIGN TOKENS (PALETTE A TERRACOTTA) ── */
:root {
  /* Colors — ivoire lumineux, noir, accent chaud très ponctuel */
  --bg:          #F5F1EA; /* Ivoire chaud lumineux */
  --bg-alt:      #ECE5D8; /* Beige doux */
  --bg-card:     #FFFFFF; /* Blanc papier */
  --bg-dark:     #16130F; /* Noir brun très sombre — identité de l'étude de cas */
  --bg-dark-2:   #201C16; /* Surface sombre secondaire */

  --text:        #151515; /* Primary body & headers */
  --text-sec:    #767066; /* Secondary warm gray */
  --text-inv:    #F7F2E9; /* Blanc cassé — textes importants sur fond sombre */
  --text-inv-sec:#C9BBA0; /* Beige chaud — textes secondaires sur fond sombre */

  /* Valeurs fixes, jamais réécrites en cascade — utilisées pour restaurer
     le texte clair-sur-sombre dans les zones volontairement sombres du
     track (hero, slides techniques), même quand --text-inv a été
     localement redéfini pour signifier "sombre-sur-clair" ailleurs. */
  --ink-strong:  #F7F2E9;
  --ink-soft:    #C9BBA0;

  /* Accent chaud — un mot, un repère, une note. Jamais une surface entière. */
  --accent:      #C98267; /* Terre cuite lumineuse */
  --accent-hover:#A66A50; /* Plus sombre au hover */
  --accent-light:#F0E4DA; /* Teinte neutre beige */
  --accent-border:#E3CBB9;/* Bordure discrète */

  /* Accent secondaire — vert sauge, encore plus rare */
  --accent-2:    #8B9275;

  /* Cyan vif — réservé au Hero uniquement, mots-clés sélectionnés (jamais un paragraphe entier) */
  --accent-cyan: #00A7AD;

  /* Signification stricte : jaune = test/expérimentation, vert = résultat/validation */
  --color-test:   #E7B740;
  --color-result: #83A66E;

  /* Teintes froides — réservées EXCLUSIVEMENT aux phénomènes de verre/lumière
     (glass-capsule, open-book). Jamais utilisées comme fond ou texte ailleurs. */
  --glass-tint-cyan: rgba(170, 210, 218, 0.14);
  --glass-tint-mint: rgba(185, 212, 190, 0.10);

  --border:      #E2DCCF; /* Bordure claire chaude */
  --border-dark: #35322C; /* Bordure sombre */

  /* Tag colors — neutres, plus d'orange plein */
  --tag-real-bg: #EFE9DF;
  --tag-real-tx: #6B5D48;
  --tag-concept-bg: #EFE9DF;
  --tag-concept-tx: #6B6155;

  /* Typography */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-serif: 'Lora', Georgia, serif;
  /* Georgia Pro Condensed n'est pas une police web-safe/hébergeable (police
     commerciale) : on utilise la vraie Georgia système en priorité (présente
     nativement sur la quasi-totalité des OS), Lora en repli. */
  --font-editorial: Georgia, 'Lora', serif;

  /* Spacing scale */
  --sp-1:  0.25rem;
  --sp-2:  0.5rem;
  --sp-3:  0.75rem;
  --sp-4:  1rem;
  --sp-5:  1.25rem;
  --sp-6:  1.5rem;
  --sp-8:  2rem;
  --sp-10: 2.5rem;
  --sp-12: 3rem;
  --sp-16: 4rem;
  --sp-20: 5rem;
  --sp-24: 6rem;
  --sp-32: 8rem;

  /* Layout */
  --max-w:    1200px;
  --max-w-md: 800px;
  --max-w-sm: 600px;

  /* Radius */
  --r-sm:  6px;
  --r-md:  12px;
  --r-lg:  20px;

  /* Shadows */
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.02);
  --shadow-md: 0 4px 20px rgba(0,0,0,0.06), 0 2px 6px rgba(0,0,0,0.03);
  --shadow-lg: 0 12px 40px rgba(0,0,0,0.08), 0 4px 12px rgba(0,0,0,0.04);
  --shadow-hover: 0 24px 60px rgba(200,109,81,0.12), 0 6px 20px rgba(0,0,0,0.06);

  /* Transitions */
  --t-fast:  150ms ease;
  --t-base:  200ms ease;
  --t-slow:  400ms ease;
}

/* ── RESET ── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.7;
  color: var(--text);
  background: var(--bg);
  overflow-x: hidden;
}

img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
button { cursor: pointer; border: none; background: none; font: inherit; }

/* ── FOCUS — feedback clavier visible et cohérent ── */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.track a:focus-visible,
.track button:focus-visible {
  outline-color: var(--text-inv);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  html { scroll-behavior: auto; }
}

/* ── LAYOUT UTILITIES ── */
.container {
  width: 100%;
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 0 var(--sp-8);
}

.container--md {
  max-width: var(--max-w-md);
}

.section {
  padding: var(--sp-24) 0;
}

.section--alt {
  background: var(--bg-alt);
}

.section--dark {
  background: var(--bg-dark);
  color: var(--text-inv);
}

/* ── REVEAL ANIMATION ── */
.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 400ms ease, transform 400ms ease;
}

.reveal.revealed {
  opacity: 1;
  transform: translateY(0);
}

.reveal-delay-1 { transition-delay: 80ms; }
.reveal-delay-2 { transition-delay: 160ms; }
.reveal-delay-3 { transition-delay: 240ms; }

/* ── TYPOGRAPHY ── */
.t-label {
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-sec);
  margin-bottom: var(--sp-2);
}

.t-label--accent {
  color: var(--accent);
}

.t-serif {
  font-family: var(--font-serif);
  font-style: italic;
}

.t-body {
  font-size: 16px;
  color: var(--text-sec);
  line-height: 1.7;
}

.t-h1 {
  font-family: var(--font-serif);
  font-size: clamp(34px, 4vw, 54px);
  font-weight: 400;
  font-style: italic;
  line-height: 1.2;
}

.t-h2 {
  font-family: var(--font-sans);
  font-size: clamp(26px, 3.2vw, 40px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.2;
}

.t-lead {
  font-size: 19px;
  font-weight: 400;
  line-height: 1.7;
  color: var(--text-sec);
}

/* ── NAVIGATION ── */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  padding: var(--sp-5) 0;
  transition: background var(--t-slow), box-shadow var(--t-slow), padding var(--t-slow);
}

.nav.scrolled {
  background: rgba(249, 248, 246, 0.94);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 1px 0 var(--border);
  padding: var(--sp-4) 0;
}

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
}

.nav__logo {
  font-size: 21px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.02em;
  transition: color var(--t-base);
}

.nav__logo:hover {
  color: var(--accent-cyan);
}

/* Non scrollé = toujours sur le hero sombre (le tout premier écran) :
   texte clair pour rester lisible sur le papier noir. Dès que .scrolled
   pose son fond opaque clair, le texte sombre par défaut redevient correct. */
.nav:not(.scrolled) .nav__logo {
  color: #F5F3EE;
}

/* :not(.scrolled) a plus de classes que :hover seul et gagnait la
   cascade — le survol restait figé en blanc sur le hero. Rétablit le
   cyan au survol dans ce contexte précis. */
.nav:not(.scrolled) .nav__logo:hover {
  color: var(--accent-cyan);
}

/* Le point du "i" devient le seul accent cyan — pas de caractère
   supplémentaire : glyphe "ı" (sans point) + point réel repositionné,
   mesuré sur les métriques réelles d'Inter Bold. */
.nav__logo-i {
  position: relative;
  display: inline-block;
  /* line-height:1 est indispensable : sans ça, la boîte de ce span hérite
     du line-height du logo (~1.7×), ce qui place son bord bas très loin
     sous la vraie ligne de base — le point cyan positionné en "bottom"
     se retrouvait décalé de plus de 10px (le bug "point flottant"). */
  line-height: 1;
}

/* Valeurs en px fixes (pas em) : le logo a une taille fixe (21px, pas de
   clamp/vw), donc pas besoin d'unité relative — ça évite surtout les
   dimensions fractionnaires (ex. 4.41px) qui rendent le cercle flou par
   anti-aliasing à cette taille. 5×5 tombe pile sur des pixels entiers. */
.nav__logo-i::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 11px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent-cyan);
  transform: translateX(-50%);
}

.nav__right {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
}

.nav__link {
  font-size: 16px;
  font-weight: 500;
  color: var(--text-sec);
  transition: color var(--t-base);
  position: relative;
}

.nav__link:hover {
  color: var(--accent-cyan);
}

/* Même logique de contraste que le logo : clair sur le hero non scrollé,
   sombre par défaut une fois le fond opaque du nav posé. */
.nav:not(.scrolled) .nav__link {
  color: rgba(245, 243, 238, 0.78);
}

.nav:not(.scrolled) .nav__link:hover {
  color: var(--accent-cyan);
}

.nav__cta {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-sec);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--border);
  background: transparent;
  border-radius: var(--r-sm);
  transition: all var(--t-base);
}

.nav__cta:hover {
  background: var(--text);
  color: var(--bg-card);
  border-color: var(--text);
}

.nav__burger {
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: var(--sp-2);
  cursor: pointer;
}

.nav__burger span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--text);
}

.nav__mobile {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 99;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-8);
}

.nav__mobile.open {
  display: flex;
}

.nav__mobile-link {
  font-size: 28px;
  font-weight: 600;
  color: var(--text);
}

.nav__mobile-close {
  position: absolute;
  top: var(--sp-5);
  right: var(--sp-8);
  font-size: 28px;
  color: var(--text-sec);
}

/* ── HERO — Split Editorial (premium) ── */
.hero {
  min-height: 92svh;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  padding: calc(var(--sp-24) + 60px) 0 var(--sp-16);
  border-bottom: 1px solid var(--border);
}

.hero__inner {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: var(--sp-16);
  align-items: center;
}

.hero__content {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

.hero__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.hero__eyebrow-line {
  width: 32px;
  height: 2px;
  background: var(--accent);
}

.hero__positioning {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-sec);
}

.hero__name {
  font-family: var(--font-sans);
  font-size: clamp(40px, 5vw, 62px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--text);
}

.hero__role {
  font-size: clamp(15px, 1.4vw, 18px);
  font-weight: 600;
  color: var(--text-sec);
  letter-spacing: 0.01em;
}

.hero__role strong {
  color: var(--text);
}

.hero__statement {
  font-family: var(--font-serif);
  font-size: clamp(22px, 2.6vw, 30px);
  font-style: italic;
  color: var(--text);
  line-height: 1.4;
  max-width: 560px;
}

.hero__statement em {
  color: var(--accent);
  font-style: italic;
}

.hero__ctas {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding-top: var(--sp-3);
  flex-wrap: wrap;
}

.hero__proof-hint {
  font-size: 13px;
  color: var(--text-sec);
}

.hero__proof-hint strong {
  color: var(--text);
  font-weight: 700;
}

/* Photo — intégration éditoriale, pas une carte générique */
.hero__photo-col {
  position: relative;
  display: flex;
  justify-content: center;
  padding-right: var(--sp-6);
}

.hero__photo-col::before {
  content: '';
  position: absolute;
  top: var(--sp-6);
  left: calc(var(--sp-6) * -1 + var(--sp-3));
  right: 0;
  bottom: calc(var(--sp-6) * -1);
  background: var(--accent);
  border-radius: var(--r-md);
  z-index: 0;
}

.hero__photo-frame {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 360px;
  aspect-ratio: 4/5;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}

.hero__photo-caption {
  position: absolute;
  z-index: 2;
  top: 50%;
  right: calc(-1 * var(--sp-5));
  transform: translateY(-50%) rotate(90deg);
  transform-origin: right center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-sec);
  white-space: nowrap;
}

.hero__scroll {
  position: absolute;
  bottom: var(--sp-4);
  left: 50%;
  transform: translateX(-50%);
  color: var(--text-sec);
  opacity: 0.4;
}

/* ── BUTTONS ── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-6);
  border-radius: var(--r-sm);
  font-size: 14px;
  font-weight: 600;
  transition: all var(--t-base);
  white-space: nowrap;
}

.btn--primary {
  background: var(--text);
  color: var(--bg-card);
  border: 1px solid var(--text);
}

.btn--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  transform: translateY(-1px);
  box-shadow: var(--shadow-hover);
}

.btn--ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}

.btn--ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-light);
}

.btn--ghost-dark {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}

.btn--ghost-dark:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.btn--sm {
  padding: var(--sp-2) var(--sp-4);
  font-size: 13px;
}

/* ── SECTION HEADERS ── */
.section-header {
  margin-bottom: var(--sp-12);
}

.section-header__num {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-2);
}

.section-header__title {
  font-family: var(--font-sans);
  font-size: clamp(28px, 3.5vw, 42px);
  font-weight: 700;
  letter-spacing: -0.03em;
}

.section-header__subtitle {
  margin-top: var(--sp-3);
  font-size: 16px;
  color: var(--text-sec);
  max-width: 600px;
}

/* ── TAGS ── */
.tag {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 100px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.tag--real {
  background: var(--tag-real-bg);
  color: var(--tag-real-tx);
}

.tag--concept {
  background: var(--tag-concept-bg);
  color: var(--tag-concept-tx);
}

.tag--category {
  background: var(--bg-alt);
  color: var(--text-sec);
  border: 1px solid var(--border);
}

.tag--category-dark {
  background: rgba(255,255,255,0.08);
  color: var(--text-inv-sec);
  border: 1px solid var(--border-dark);
}

/* ── DISABLED CTA (ex: CV en attente du fichier réel) ── */
.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* ── PROOF PLACEHOLDER (aucune fausse preuve : état "à venir" explicite) ── */
.proof-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 140px;
  padding: var(--sp-6);
  background: var(--bg-alt);
  border: 1px dashed var(--border);
  text-align: center;
  font-size: 13px;
  color: var(--text-sec);
}

/* ── DARK METRIC BOX (résultat clé sur fond sombre, pages projets) ── */
.metric-box--dark {
  padding: var(--sp-5);
  background: var(--bg-dark);
  border-radius: var(--r-md);
  color: var(--text-inv);
}

.metric-box--dark .metric-box__value {
  font-size: 22px;
  font-weight: 700;
  color: var(--accent);
  line-height: 1.2;
}

.metric-box--dark .metric-box__label {
  font-size: 13px;
  color: var(--text-inv-sec);
  margin-top: var(--sp-2);
}

/* ============================================================
   PROJECT CARDS — HOMEPAGE (WITH STAGE COMPOSITION)
   ============================================================ */

.projects-grid {
  display: flex;
  flex-direction: column;
  gap: var(--sp-12);
}

.project-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: box-shadow var(--t-slow), border-color var(--t-slow);
}

.project-card:hover {
  box-shadow: var(--shadow-hover);
  border-color: var(--accent-border);
}

.project-card__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 480px;
}

.project-card--reverse .project-card__inner {
  direction: rtl;
}

.project-card--reverse .project-card__content,
.project-card--reverse .project-card__visual {
  direction: ltr;
}

.project-card__content {
  padding: var(--sp-10);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--sp-6);
}

.project-card__meta {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

.project-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}

.project-card__title {
  font-size: clamp(22px, 2.5vw, 30px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.2;
}

.project-card__problem {
  font-size: 15px;
  color: var(--text-sec);
  line-height: 1.6;
}

.project-card__problem strong {
  color: var(--text);
}

.project-card__index {
  font-size: 12px;
  color: var(--accent);
  font-weight: 700;
  letter-spacing: 0.1em;
  margin-bottom: var(--sp-1);
}

.project-card__results-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
  margin-top: var(--sp-2);
}

.project-card__result {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--sp-3) var(--sp-4);
  background: var(--bg-alt);
  border-radius: var(--r-sm);
  border-left: 3px solid var(--accent);
}

.project-card__result-value {
  font-size: 26px;
  font-weight: 700;
  color: var(--accent);
  line-height: 1;
}

.project-card__result-label {
  font-size: 12px;
  color: var(--text-sec);
}

/* ── MECHANISM VISUAL (schéma abstrait, pas de screenshot brut) ── */
.project-card__visual {
  background: var(--bg-alt);
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-10);
}

.mechanism {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  width: 100%;
}

.mechanism__flow {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.mechanism__step {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  transition: transform var(--t-slow), border-color var(--t-slow);
}

.mechanism__step-num {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent);
  flex-shrink: 0;
}

.mechanism__arrow {
  align-self: center;
  color: var(--border-dark);
  opacity: 0.5;
}

.project-card:hover .mechanism__step {
  transform: translateX(4px);
  border-color: var(--accent-border);
}

.project-card:hover .mechanism__step:nth-child(3) {
  transform: translateX(8px);
}

.mechanism__caption {
  font-size: 12px;
  color: var(--text-sec);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--border);
}

.mechanism__caption strong {
  color: var(--text);
}

/* ── FLOW RIBBON (bandeau d'étapes — comment le système fonctionne) ── */
.flow-ribbon {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
  padding: var(--sp-4) var(--sp-5);
  background: var(--bg-dark);
  border-radius: var(--r-md);
  color: var(--text-inv);
  font-size: 13px;
  font-weight: 600;
  margin: var(--sp-6) 0;
}

.flow-ribbon--light {
  background: var(--bg-alt);
  color: var(--text);
  border: 1px solid var(--border);
}

.flow-ribbon__step {
  padding: 4px 10px;
  background: rgba(255,255,255,0.08);
  border-radius: var(--r-sm);
}

.flow-ribbon--light .flow-ribbon__step {
  background: var(--bg-card);
  border: 1px solid var(--border);
}

.flow-ribbon__arrow {
  color: var(--accent);
}

.flow-ribbon__label {
  font-weight: 700;
}

/* ── NEEDS LIST (chips de besoins — scannable, pas un paragraphe) ── */
.needs-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.needs-list__item {
  padding: var(--sp-2) var(--sp-4);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: 100px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.needs-list--dark .needs-list__item {
  background: rgba(255,255,255,0.06);
  border-color: var(--border-dark);
  color: var(--text-inv-sec);
}

/* ── CAPABILITY GRID (Copilot — comment) ── */
.capability-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-4);
}

.capability-card {
  padding: var(--sp-5);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color var(--t-base), transform var(--t-base);
}

.capability-card:hover {
  border-color: var(--accent-border);
  transform: translateY(-2px);
}

.capability-card__title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: var(--sp-1);
}

.capability-card__desc {
  font-size: 12px;
  color: var(--text-sec);
  line-height: 1.5;
}

/* ── PROOF SPLIT (Copilot — preuves par client) ── */
.proof-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-5);
}

.proof-split__col {
  padding: var(--sp-6);
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.proof-split__client {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-3);
}

.proof-split__list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.proof-split__list li {
  font-size: 14px;
  color: var(--text-sec);
  line-height: 1.5;
  padding-left: var(--sp-4);
  position: relative;
}

.proof-split__list li::before {
  content: '→';
  position: absolute;
  left: 0;
  color: var(--accent);
}

/* ── PROOF CAPTION (une preuve n'est jamais posée sans légende) ── */
.proof {
  margin-top: var(--sp-4);
}

.proof__caption {
  margin-top: var(--sp-3);
  padding-left: var(--sp-3);
  border-left: 2px solid var(--accent);
  font-size: 13px;
  color: var(--text-sec);
  line-height: 1.5;
}

.proof__caption strong {
  color: var(--text);
}

.proof-placeholder__type {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-sec);
  margin-bottom: var(--sp-2);
}

/* ── BROWSER MOCKUP FRAME ── */
.browser-frame {
  background: #fff;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.browser-frame__header {
  height: 28px;
  background: #F0EEE9;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  padding: 0 var(--sp-3);
  gap: 6px;
}

.browser-frame__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #D5D2CA;
}

.browser-frame__dot--red { background: #E56A54; }
.browser-frame__dot--yellow { background: #F1B743; }
.browser-frame__dot--green { background: #57B677; }

.browser-frame__body {
  overflow: hidden;
}

.browser-frame__body img {
  width: 100%;
  height: auto;
  display: block;
}

/* ============================================================
   SKILLS & TIMELINE
   ============================================================ */

.skills-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-6);
}

.skill-domain {
  padding: var(--sp-6);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg-card);
}

.skill-domain__name {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border);
}

.skill-domain__list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.skill-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-2);
}

.skill-item__name {
  font-size: 14px;
  color: var(--text);
}

.skill-item__link {
  font-size: 11px;
  color: var(--accent);
  white-space: nowrap;
}

.timeline {
  display: flex;
  flex-direction: column;
  position: relative;
  padding-left: var(--sp-8);
}

.timeline::before {
  content: '';
  position: absolute;
  left: var(--sp-3);
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: var(--border);
}

.timeline-item {
  position: relative;
  padding-bottom: var(--sp-8);
}

.timeline-item::before {
  content: '';
  position: absolute;
  left: calc(-1 * var(--sp-8) + var(--sp-3) - 3px);
  top: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}

.timeline-item__company {
  font-size: 17px;
  font-weight: 700;
}

.timeline-item__role {
  font-size: 14px;
  color: var(--text-sec);
  margin-top: 2px;
}

.timeline-item__period {
  font-size: 12px;
  color: var(--text-sec);
  margin-top: 2px;
  opacity: 0.8;
}

.timeline-item__contribution {
  font-size: 14px;
  color: var(--text-sec);
  margin-top: var(--sp-3);
  line-height: 1.6;
  padding: var(--sp-3) var(--sp-4);
  background: var(--bg-alt);
  border-radius: var(--r-sm);
  border-left: 2px solid var(--accent);
}

/* ============================================================
   CONTACT & FOOTER
   ============================================================ */

.contact-section {
  padding: var(--sp-24) 0;
  background: var(--bg-dark);
  color: var(--text-inv);
}

.contact__title {
  font-family: var(--font-serif);
  font-size: clamp(32px, 4vw, 50px);
  font-weight: 400;
  font-style: italic;
  color: var(--text-inv);
  margin-bottom: var(--sp-4);
}

.contact__subtitle {
  font-size: 17px;
  color: var(--text-inv-sec);
  line-height: 1.7;
  max-width: 520px;
  margin-bottom: var(--sp-8);
}

.contact__links {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.contact__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-inv-sec);
  padding: var(--sp-3) var(--sp-5);
  border: 1px solid var(--border-dark);
  border-radius: var(--r-sm);
  transition: all var(--t-base);
}

.contact__link:hover {
  color: var(--text-inv);
  border-color: rgba(255,255,255,0.3);
  background: rgba(255,255,255,0.05);
}

.contact__link--primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.contact__link--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.footer {
  background: var(--bg-dark);
  border-top: 1px solid var(--border-dark);
  padding: var(--sp-8) 0;
}

.footer__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.footer__copy {
  font-size: 13px;
  color: var(--text-inv-sec);
}

.footer__links {
  display: flex;
  gap: var(--sp-6);
}

.footer__link {
  font-size: 13px;
  color: var(--text-inv-sec);
}

.footer__link:hover {
  color: var(--text-inv);
}

/* ============================================================
   PROJECT CASE STUDY PAGE (LEVEL 2)
   ============================================================ */

.project-hero {
  padding: calc(var(--sp-20) + 70px) 0 var(--sp-16);
  background: var(--bg-dark);
  color: var(--text-inv);
}

.project-hero__breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-6);
  font-size: 13px;
  color: var(--text-inv-sec);
}

.project-hero__breadcrumb a {
  color: var(--text-inv-sec);
}

.project-hero__breadcrumb a:hover {
  color: var(--text-inv);
}

.project-hero__meta {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
  flex-wrap: wrap;
}

.project-hero__title {
  font-size: clamp(36px, 5vw, 64px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.0;
  color: var(--text-inv);
  margin-bottom: var(--sp-4);
}

.project-hero__summary {
  font-size: 18px;
  color: var(--text-inv-sec);
  line-height: 1.7;
  max-width: 640px;
}

.hero-stats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}

.hero-proof-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-3);
}

/* Project nav footer */
.project-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-10) 0;
  border-top: 1px solid var(--border);
  margin-top: var(--sp-12);
  gap: var(--sp-4);
}

.project-nav__back {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-sec);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

.project-nav__back:hover {
  color: var(--accent);
}

/* ============================================================
   STORY TRACK — l'expérience horizontale unique (Ecofina)
   ============================================================ */

/* ── IMMERSIVE MEDIA (utilisé hors track, ex. sur pages héritées) ── */
.immersive-media {
  position: relative;
  width: 100%;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #000;
  box-shadow: var(--shadow-lg);
}

.immersive-media video,
.immersive-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.immersive-media__tag {
  position: absolute;
  top: var(--sp-4);
  left: var(--sp-4);
  z-index: 2;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(0,0,0,0.55);
  padding: 6px 12px;
  border-radius: 100px;
}

/* ── PANEL CAPTION (courte, sans "ce que ça prouve") ── */
.panel-caption {
  margin-top: var(--sp-3);
  font-size: 14px;
  color: var(--text-inv-sec);
  max-width: 520px;
  line-height: 1.5;
}

.panel-caption--light {
  color: var(--text-sec);
}

/* ── STICKY NOTE ("Ce que j'en retiens" — 2 à 4 fois max) — papier
   teinté cyan, cohérent avec l'accent du reste du portfolio plutôt
   qu'un jaune post-it générique. ── */
.sticky-note {
  position: absolute;
  z-index: 4;
  background: #CDEFF1;
  padding: var(--sp-5) var(--sp-6);
  max-width: 260px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.18), 0 2px 6px rgba(0,0,0,0.1);
  transform: rotate(-3deg);
  font-family: var(--font-serif);
}

.sticky-note::before {
  content: '';
  position: absolute;
  top: -8px;
  left: 28px;
  width: 36px;
  height: 12px;
  background: rgba(0,167,173,0.3);
  transform: rotate(-4deg);
}

.sticky-note__label {
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-cyan);
  margin-bottom: var(--sp-2);
}

.sticky-note__text {
  font-style: italic;
  font-size: 15px;
  line-height: 1.45;
  color: #0C2E30;
}

.sticky-note__sign {
  font-family: var(--font-sans);
  font-style: normal;
  font-size: 11px;
  color: var(--text-sec);
  margin-top: var(--sp-3);
}

/* ── MEDIA MASK (anonymisation ciblée — pas de flou global) ── */
.media-mask {
  position: absolute;
  z-index: 2;
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  background: rgba(22,20,15,0.12);
  pointer-events: none;
}

.media-mask__label {
  position: absolute;
  bottom: var(--sp-2);
  left: var(--sp-2);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.7);
}

/* ── MIND MAP (organique, lignes qui se dessinent) ── */
.mindmap {
  position: relative;
  width: min(88vw, 66vh, 640px);
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  flex-shrink: 0;
}

.mindmap__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.mindmap__svg path {
  fill: none;
  stroke: var(--accent-2);
  stroke-width: 0.6;
  opacity: 0.7;
  stroke-dasharray: 140;
  stroke-dashoffset: 140;
  transition: stroke-dashoffset 1000ms ease;
  vector-effect: non-scaling-stroke;
}

.mindmap.is-active .mindmap__svg path {
  stroke-dashoffset: 0;
}

.mindmap__center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  color: var(--text-inv);
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(20px, 2.6vw, 28px);
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.mindmap__node {
  position: absolute;
  z-index: 2;
  transform: translate(-50%, -50%);
  width: 128px;
  text-align: center;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--text-inv-sec);
  opacity: 0;
  transition: opacity 600ms ease, color 300ms ease;
}

.mindmap.is-active .mindmap__node {
  opacity: 1;
}

.mindmap__node::before {
  content: '';
  display: block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  margin: 0 auto 5px;
}

/* ── STORY TRACK (sticky horizontal — toute l'expérience) ── */
.track {
  position: relative;
}

.track__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  display: flex;
  align-items: center;
  background: var(--bg);
}

.track__strip {
  display: flex;
  height: 100%;
  will-change: transform;
}

/* Grille commune : même point de départ vertical, mêmes marges, sur
   TOUTES les slides — plus de position "centrée" variable selon la
   hauteur du contenu (source des désalignements et des débordements).

   Thème : la plupart des composants du track référencent --text-inv /
   --text-inv-sec (pensés à l'origine pour un fond sombre unique). Plutôt
   que réécrire chaque composant, on redéfinit localement ce que ces deux
   variables SIGNIFIENT : clair par défaut (--text-inv devient le texte
   sombre-sur-clair), et on les restaure à leur valeur blanc cassé
   d'origine (--ink-strong/--ink-soft, fixes, jamais réécrites) sur le
   hero et les 2-3 slides volontairement sombres. */
.track__panel {
  flex-shrink: 0;
  width: 100vw;
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  padding: calc(var(--sp-16) + 56px) var(--sp-16) var(--sp-12);
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  --text-inv: var(--text);
  --text-inv-sec: var(--text-sec);
  --bg-dark-2: var(--bg-alt);
}

/* ══════════════════════════════════════════════════════════════
   SYSTÈME DE LUMIÈRE DE FENÊTRE — vraies photos, pas de gradient CSS
   ══════════════════════════════════════════════════════════════
   Trois vraies textures photographiques (ombres de fenêtre réelles,
   diffuses, irrégulières) servent d'overlay sur .track__panel::before.
   Un seul pseudo-élément, piloté par variables : image, taille,
   position, opacité, mode de fusion, transformation (rotation/flip)
   pour qu'un même fichier serve plusieurs fois sans se répéter à
   l'identique. Fond neutre par défaut (aucune texture) tant qu'une
   slide n'a pas explicitement une classe --wl-*. */
.track__panel::before {
  content: '';
  position: absolute;
  /* --wl-inset permet de surdimensionner le calque avant une éventuelle
     rotation (--wl-transform) : sans marge, une boîte pile calée sur le
     panneau (inset:0) tournée révèle ses propres coins/bords aux angles
     du panneau — visible comme une "diagonale de fichier PNG" trahissant
     l'asset. Par défaut 0 (comportement inchangé pour les slides sans
     rotation). */
  inset: var(--wl-inset, 0);
  z-index: 0;
  pointer-events: none;
  background-image: var(--wl-img, none);
  background-size: var(--wl-size, 160%);
  background-position: var(--wl-pos, 0% 0%);
  background-repeat: no-repeat;
  opacity: var(--wl-opacity, 0);
  mix-blend-mode: var(--wl-blend, multiply);
  transform: var(--wl-transform, none);
}

.track__panel--dark::before {
  --wl-blend: screen;
}

/* Prototype A — Ciblage : ombre de fenêtre réelle, lumière latérale
   gauche, cadrée large sur la partie la plus diffuse du fichier. */
.track__panel--wl-a {
  --wl-img: url('../assets/images/light/window-shadow-01.png');
  --wl-size: 130%;
  --wl-pos: -10% 20%;
  --wl-opacity: 0.5;
}

/* Prototype B (réservé) — variation diagonale, même famille de
   fichiers, cadrage différent pour éviter la répétition visible. */
.track__panel--wl-b {
  --wl-img: url('../assets/images/light/window-shadow-02.png');
  --wl-size: 95%;
  --wl-pos: 60% -10%;
  --wl-opacity: 0.32;
  --wl-transform: scaleX(-1);
}

/* Prototype C — Problème : troisième fichier de la même famille, cadrage
   haut-droit, pour ne jamais répéter à l'identique wl-a/wl-b.
   Même correction de fond que la slide Ciblage : mix-blend + opacity sur
   une image opaque ne laisse jamais de vraie zone transparente. Remplacé
   par un vrai PNG alpha dérivé de window-shadow-03.png (blanc→alpha 0
   réel, RGB anthracite fixe), composité en mode normal.
   Deuxième réglage : la première version (70%, très localisée) protégeait
   bien le titre mais laissait toute la moitié gauche du panneau à 0% —
   perçue comme "la moitié de la page sans ombre" plutôt qu'une lumière
   qui vit sur toute la slide. Régénéré avec une courbe alpha plus douce
   (seuil blanc relevé, alpha max réduit) et une taille qui couvre tout le
   panneau : chaque zone reçoit désormais une valeur mesurable (titre
   217/239, cartes 184/239, marge gauche 202/239, photo 229/239) — plus
   aucune zone à 0% strict, mais aucune non plus assez sombre pour gêner
   la lecture du texte. */
.track__panel--wl-c {
  --wl-img: url('../assets/images/light/window-shadow-03-alpha.png');
  --wl-size: 200%;
  --wl-pos: 100% 50%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide CRM — même méthode (vrai PNG alpha, composité normal), asset
   différent (window-shadow-02.png, plus doux nativement) pour ne pas
   répéter le cadrage des autres slides claires. Position calée par
   échantillonnage : chaque zone du panneau touchée (184-229/255 mesuré),
   la zone du gros chiffre "2 806" la plus préservée (229). */
.track__panel--wl-crm {
  --wl-img: url('../assets/images/light/window-shadow-02-alpha.png');
  --wl-size: 220%;
  --wl-pos: 90% 50%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide Personnalisation — même asset alpha que la slide Problème
   (window-shadow-03), cadrage différent pour ne pas répéter la même
   projection lumineuse. */
/* Repassée en panneau sombre (alternance noir/blanc du portfolio) : même
   asset et même logique que le hero/Ciblage (RGB anthracite quasi-noir,
   alpha réel), cadrage différent des deux pour ne pas répéter la même
   projection. Vérifié : la zone de texte centrale reste à 24-25/255,
   identique au papier noir seul — la lumière ne touche jamais le texte. */
.track__panel--wl-personnalisation {
  --wl-img: url('../assets/images/light/window-shadow-alpha.png');
  --wl-size: 95%;
  --wl-pos: 20% 70%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide Conversion — même asset alpha que la slide CRM (window-shadow-02),
   cadrage différent : les deux slides 05/06 restent dans le même système
   sans jamais avoir la même ombre. */
.track__panel--wl-conversion {
  --wl-img: url('../assets/images/light/window-shadow-02-alpha.png');
  --wl-size: 200%;
  --wl-pos: 25% 20%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide Test→Scale — repassée en panneau sombre (alternance) : même asset
   que le hero/Ciblage/Personnalisation, cadrage encore différent. */
.track__panel--wl-test-scale {
  --wl-img: url('../assets/images/light/window-shadow-alpha.png');
  --wl-size: 100%;
  --wl-pos: 80% 15%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide Automatisation — repassée en panneau clair (alternance) : même
   asset que la slide Problème (window-shadow-03), cadrage différent. */
.track__panel--wl-automatisation {
  --wl-img: url('../assets/images/light/window-shadow-03-alpha.png');
  --wl-size: 175%;
  --wl-pos: 65% 85%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide conclusion (outro) — même famille que hero/Ciblage/Site (vrai
   papier noir + vrai PNG alpha, composité normal), cadrage encore
   différent pour ne jamais répéter la même projection. */
.track__panel--wl-outro {
  --wl-img: url('../assets/images/light/window-shadow-02-alpha.png');
  --wl-size: 130%;
  --wl-pos: 75% 75%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide Simulateur — repassée en panneau clair (alternance noir/blanc) :
   même asset que CRM/Conversion (window-shadow-02), cadrage différent
   pour ne jamais répéter la même projection. */
.track__panel--wl-simulateur {
  --wl-img: url('../assets/images/light/window-shadow-02-alpha.png');
  --wl-size: 180%;
  --wl-pos: 15% 85%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide Contenu — repassée en panneau clair (alternance noir/blanc) :
   même asset que Problème/Automatisation (window-shadow-03), cadrage
   différent pour ne jamais répéter la même projection. */
.track__panel--wl-contenu {
  --wl-img: url('../assets/images/light/window-shadow-03-alpha.png');
  --wl-size: 190%;
  --wl-pos: 85% 10%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* Slide Site — même famille que hero/Ciblage/Personnalisation/Test-Scale
   (vrai papier noir + vrai PNG alpha, composité normal), cadrage encore
   différent pour ne jamais répéter la même projection. */
.track__panel--wl-site {
  --wl-img: url('../assets/images/light/window-shadow-alpha.png');
  --wl-size: 100%;
  --wl-pos: 40% 90%;
  --wl-blend: normal;
  --wl-opacity: 1;
}

/* ── PAPIER ÉDITORIAL — texture réelle en fond des sections claires
   (remplace les grands aplats crème plats). Discrète : la matière se
   perçoit, jamais sale ni contrastée. ── */
.track__panel--paper {
  /* Ancien réglage : tuile de 900px en background-repeat:repeat. La photo
     n'est pas parfaitement raccordable (mesuré : léger saut de ton net
     entre son bord haut et son bord bas), donc chaque raccord de tuile
     produisait une ligne horizontale visible dans le panneau — la
     "démarcation" signalée. Passé en image unique, cover, sans répétition
     (même principe que le papier noir du hero) : plus aucun raccord. */
  background-image: url('../assets/images/light/paper-texture.png');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-blend-mode: multiply;
}

/* ── Ombre de contact réutilisable — l'objet semble posé sur une
   surface éclairée, pas collé à plat sur la page. ── */
.contact-shadow {
  position: relative;
}
.contact-shadow::after {
  content: '';
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: -14px;
  height: 28px;
  background: radial-gradient(ellipse 60% 100% at 50% 0%, rgba(20,17,14,0.16), transparent 75%);
  z-index: -1;
  pointer-events: none;
}
.track__panel--dark .contact-shadow::after {
  background: radial-gradient(ellipse 60% 100% at 50% 0%, rgba(0,0,0,0.5), transparent 75%);
}

.track__panel > * {
  position: relative;
  z-index: 1;
}

/* ── PANEL SOMBRE — exception volontaire, pour le rythme et les preuves
   techniques (utilisée sur 2-3 slides maximum, jamais par défaut) ── */
.track__panel--dark {
  background: var(--bg-dark);
  color: var(--ink-strong);
  --text-inv: var(--ink-strong);
  --text-inv-sec: var(--ink-soft);
  --bg-dark-2: #201C16;
}

/* ── Slide "Ciblage" — même famille de fond que le Hero (vrai papier
   noir photographié, pas un aplat), accents cyan scopés à ce panneau. ── */
.track__panel--ciblage {
  background: #0A0806 url('../assets/images/hero/paper-black.png') center / cover no-repeat;
  /* Centrage vertical propre à cette slide : .track__panel est en
     justify-content:flex-start partout ailleurs (règle globale, ne pas
     y toucher — elle évite des débordements sur les slides plus chargées).
     Cette slide a peu de contenu et flex-start le laissait tassé en haut,
     avec beaucoup de vide en dessous. */
  justify-content: center;
  /* Troisième correction, à la racine cette fois : mix-blend-mode + opacity
     sur une image opaque ne produit JAMAIS une vraie zone transparente,
     même quand la moyenne mesurée est basse — chaque pixel du calque
     participe un peu au rendu final, d'où le "filtre" perçu malgré des
     réglages qui semblaient corrects sur le papier. Remplacé par un vrai
     PNG alpha dérivé de window-shadow-01.png (blanc→alpha 0 réel, gris
     foncé→alpha jusqu'à 190/255 ; RGB anthracite fixe). Composité en
     mode normal (pas de blend, pas d'opacity de calque) : les zones
     réellement transparentes du PNG rendent le papier noir strictement
     inchangé, pixel pour pixel — vérifié en superposant l'asset sur un
     fond rouge puis cyan uni : 6 des 9 points échantillonnés (coins,
     centre, quadrants) tombent EXACTEMENT sur la couleur de test (0 de
     déviation RGB), seule la vraie forme d'ombre diffuse (~32% de la
     surface) diffère. */
  --wl-img: url('../assets/images/light/window-shadow-alpha.png');
  --wl-size: 105%;
  --wl-pos: 55% 45%;
  --wl-opacity: 1;
}

/* --wl-blend est fixé directement sur le pseudo-élément par
   .track__panel--dark::before (screen, pour les cartes de lumière) — une
   valeur posée sur le parent est héritée mais une valeur posée sur
   l'élément lui-même gagne toujours. Cette slide utilise un vrai PNG
   alpha, pas un blend : il faut donc réécrire --wl-blend ici, sur le
   pseudo-élément, pour qu'il l'emporte sur cette valeur héritée. */
.track__panel--ciblage::before {
  --wl-blend: normal;
}

/* Le fichier .mp4 lui-même contient une fine bande noire figée à gauche
   et à droite de l'image captée (mesuré directement sur une frame réelle :
   ~1.5% de la largeur de chaque côté, uniquement gauche/droite) — ce n'est
   pas un problème d'object-fit (déjà en cover, le ratio du conteneur colle
   presque exactement à celui de la vidéo). Léger zoom pour sortir ces
   bords du cadre visible ; le conteneur reste en overflow:hidden. */
.track__panel--ciblage .floating-window video {
  transform: scale(1.07);
}

.track__panel--ciblage .editorial-split__label,
.track__panel--ciblage .keyword-row__word--accent {
  color: var(--accent-cyan);
}

.track__panel--ciblage .editorial-split__label,
.track__panel--ciblage .track__panel-sub {
  font-family: var(--font-editorial);
}

.track__panel--ciblage .editorial-split__label {
  font-style: italic;
  letter-spacing: 0.18em;
}

/* ── LIGHT WINDOW — surface claire posée sur fond sombre (plus de blanc) ── */
.light-window {
  background: var(--bg-alt);
  border-radius: var(--r-lg);
  box-shadow: 0 20px 50px rgba(0,0,0,0.28), 0 4px 14px rgba(0,0,0,0.16);
  padding: var(--sp-6);
  transition: transform 300ms ease, box-shadow 300ms ease;
}

.light-window:hover {
  transform: translateY(-4px) scale(1.01);
  box-shadow: 0 26px 60px rgba(0,0,0,0.32), 0 6px 16px rgba(0,0,0,0.18);
}

.light-window img,
.light-window video {
  /* width:100% forçait l'image à occuper toute la largeur du panneau quel
     que soit son ratio réel, donc sa hauteur suivait sans limite — sur un
     schéma haut (n8n-workflow-enrichment.png, 1024×505), ça poussait le
     titre au-dessus hors du cadre visible. max-height borne la taille
     réelle sans recadrer ; les attributs width/height du <img> donnent le
     ratio dès le premier rendu (pas de saut de mise en page au chargement
     d'une image lazy). */
  width: 100%;
  height: auto;
  max-height: 46vh;
  display: block;
  margin: 0 auto;
  object-fit: contain;
  border-radius: var(--r-md);
}

/* ── FLOATING WINDOW — la preuve ne touche plus la page, elle flotte ── */
.floating-window {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #000;
  border: 1px solid rgba(255,255,255,0.08);
  box-shadow: 0 30px 70px -12px rgba(20,17,14,0.35), 0 10px 24px -8px rgba(20,17,14,0.2);
  transition: transform 400ms cubic-bezier(.2,.7,.3,1), box-shadow 400ms cubic-bezier(.2,.7,.3,1);
  max-height: 54vh;
}

.floating-window:hover {
  transform: translateY(-6px) scale(1.012);
  box-shadow: 0 40px 90px -12px rgba(20,17,14,0.42), 0 14px 30px -8px rgba(20,17,14,0.24);
}

.floating-window--offset {
  position: absolute;
  z-index: 3;
}

.floating-window__bar {
  height: 30px;
  background: rgba(0,0,0,0.35);
  border-bottom: 1px solid rgba(255,255,255,0.06);
  display: flex;
  align-items: center;
  padding: 0 var(--sp-3);
  gap: 6px;
  position: relative;
  z-index: 2;
}

.floating-window__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255,255,255,0.18);
}

.floating-window img,
.floating-window video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.floating-window--contain { background: var(--bg-alt); }
.floating-window--contain img,
.floating-window--contain video { object-fit: contain; background: var(--bg-alt); }

.floating-window--tilt-l { transform: rotate(-1.1deg) translateY(-4px); }
.floating-window--tilt-r { transform: rotate(1.1deg) translateY(4px); }

/* Duo : grande fenêtre + petite fenêtre légèrement superposée, une seule composition */
.duo-window {
  position: relative;
  width: 100%;
}

.duo-window__main { width: 100%; }

.duo-window__minor {
  position: absolute;
  width: 44%;
  bottom: -8%;
  left: -6%;
  z-index: 3;
  border: 3px solid var(--bg);
}

.track__panel--dark .duo-window__minor { border-color: var(--bg-dark); }

/* ── EDITORIAL LEDE — tension serif/italic vs sans-serif, formalisée
   (remplace les styles inline dupliqués sur plusieurs chapitres) ── */
.editorial-lede {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--text-inv-sec);
  line-height: 1.3;
}

.editorial-lede--sm { font-size: 0.55em; }
.editorial-lede--md { font-size: 0.62em; }

/* ── EDITORIAL CARD — grille de magazine, jamais flottante.
   Contraste volontaire avec floating-window/paper-card : pas de rotation,
   pas d'élévation au survol, marge généreuse, numéro + légende. ── */
.editorial-card {
  padding: var(--sp-6);
  border: 1px solid var(--border-dark);
  border-radius: var(--r-md);
  transition: border-color 300ms ease;
}

.track__panel:not(.track__panel--dark) .editorial-card { border-color: var(--border); }

.editorial-card:hover { border-color: var(--accent-border); }

.editorial-card__num {
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.08em;
  margin-bottom: var(--sp-3);
}

.editorial-card__title {
  font-size: 16px;
  font-weight: 700;
  color: var(--text-inv);
  letter-spacing: -0.01em;
}

.editorial-card__caption {
  margin-top: var(--sp-2);
  font-size: 12px;
  color: var(--text-inv-sec);
}

/* ── Slide "Problème" — accents cyan scopés à ce panneau uniquement
   (les labels/numéros partagent des classes utilisées ailleurs en
   orange ; on ne change jamais leur couleur par défaut). ── */
.track__panel--problem .editorial-split__label,
.track__panel--problem .editorial-card__num,
.track__panel--problem .glass-capsule {
  color: var(--accent-cyan);
}

.track__panel--problem .glass-capsule {
  border-color: rgba(0,167,173,0.35);
  box-shadow: 0 1px 1px rgba(255,255,255,0.5) inset, 0 10px 22px -12px rgba(20,17,14,0.2);
}

.track__panel--problem .editorial-split__label,
.track__panel--problem .track__panel-sub,
.track__panel--problem .diagnostic-photo__caption {
  font-family: var(--font-editorial);
}

.track__panel--problem .editorial-split__label {
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--problem .track__panel-sub {
  font-style: italic;
}

.track__panel--problem .diagnostic-photo__caption {
  font-style: italic;
  letter-spacing: 0.01em;
}

/* Un mot-clé glass à l'intérieur d'un grand titre hérite toujours la
   typographie du titre (pas le serif italique par défaut du glass-capsule)
   — il doit se lire comme un mot du titre, pas comme un élément étranger. */
.track__panel--problem .editorial-split__title .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

/* Cartes et photo : relief très léger façon papier posé, jamais un
   drop-shadow de carte SaaS ni un hover flottant. */
.track__panel--problem .editorial-card {
  background: rgba(255,255,255,0.6);
  border-color: rgba(20,17,14,0.08);
  padding: var(--sp-8);
  box-shadow: 0 3px 10px -6px rgba(20,17,14,0.14);
  transition: border-color 300ms ease, padding 300ms ease;
}

/* Grille 2×3 de cartes : à largeur réduite (tablette), le padding
   généreux pensé pour le desktop pousse la grille sous la hauteur du
   viewport (mesuré : ~11px coupés à 1024×768). Un padding légèrement
   plus compact suffit à tout faire rentrer, sans toucher au texte. */
@media (max-width: 1200px) and (min-width: 769px) {
  .track__panel--problem .editorial-card {
    padding: var(--sp-6);
  }
}

.track__panel--problem .editorial-card:hover {
  border-color: rgba(0,167,173,0.38);
}

.track__panel--problem .diagnostic-photo {
  box-shadow: 0 6px 16px -8px rgba(20,17,14,0.2), 0 0 0 1px rgba(255,255,255,0.5) inset;
}

/* ── Slide "CRM" — accents cyan scopés à ce panneau uniquement (mêmes
   classes partagées utilisées en orange ailleurs, ex. Test→Scale). ── */
.track__panel--crm {
  justify-content: center;
}

.track__panel--crm .editorial-split__label,
.track__panel--crm .keyword-row__word--accent,
.track__panel--crm .glass-capsule,
.track__panel--crm .stat-big__value {
  color: var(--accent-cyan);
}

.track__panel--crm .glass-capsule {
  border-color: rgba(0,167,173,0.4);
}

.track__panel--crm .editorial-split__title .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

.track__panel--crm .editorial-split__label,
.track__panel--crm .track__panel-sub {
  font-family: var(--font-editorial);
}

.track__panel--crm .editorial-split__label {
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--crm .track__panel-sub {
  font-style: italic;
}

/* ── Slide "Personnalisation" — accents cyan scopés à ce panneau uniquement. ── */
.track__panel--personnalisation {
  justify-content: center;
  /* Repassée en fond papier noir réel pour respecter l'alternance
     noir/blanc du portfolio (même asset que le hero/Ciblage). */
  background: #0A0806 url('../assets/images/hero/paper-black.png') center / cover no-repeat;
}

/* --wl-blend est fixé directement sur le pseudo-élément par
   .track__panel--dark::before (screen) — une valeur héritée du parent ne
   suffit pas à le surclasser (même bug déjà corrigé sur Ciblage). */
.track__panel--personnalisation::before {
  --wl-blend: normal;
}

.track__panel--personnalisation .editorial-split__label,
.track__panel--personnalisation .kw,
.track__panel--personnalisation .glass-capsule,
.track__panel--personnalisation .step-flow__item--accent {
  color: var(--accent-cyan);
}

.track__panel--personnalisation .glass-capsule {
  border-color: rgba(0,167,173,0.4);
}

.track__panel--personnalisation .punchline .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

.track__panel--personnalisation .editorial-split__label,
.track__panel--personnalisation .track__panel-sub {
  font-family: var(--font-editorial);
}

.track__panel--personnalisation .editorial-split__label {
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--personnalisation .track__panel-sub {
  font-style: italic;
}

.track__panel--personnalisation .step-flow__arrow {
  /* --text-inv-sec (pas --text-sec) : ce panneau redevient sombre, il faut
     donc la variable qui suit le thème clair-sur-sombre du panel, pas le
     token fixe pensé pour les panneaux clairs. */
  color: var(--text-inv-sec);
  opacity: 0.6;
}

/* ── Slide "Conversion" — accents cyan scopés à ce panneau uniquement. ── */
.track__panel--conversion {
  justify-content: center;
}

.track__panel--conversion .editorial-split__label,
.track__panel--conversion .kw,
.track__panel--conversion .glass-capsule,
.track__panel--conversion .step-flow__item--accent {
  color: var(--accent-cyan);
}

.track__panel--conversion .glass-capsule {
  border-color: rgba(0,167,173,0.4);
}

.track__panel--conversion .track__panel-title .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

.track__panel--conversion .editorial-split__label,
.track__panel--conversion .track__panel-sub {
  font-family: var(--font-editorial);
}

.track__panel--conversion .editorial-split__label {
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--conversion .track__panel-sub {
  font-style: italic;
}

.track__panel--conversion .step-flow__arrow {
  color: var(--text-sec);
  opacity: 0.5;
}

.track__panel--conversion .contact-shadow {
  width: 100%;
  display: flex;
  justify-content: center;
}

/* ── Slide "Test → Scale" — repassée sombre : accents cyan scopés,
   centrage vertical, papier noir réel. ── */
/* justify-content passe en flex-start + padding-top explicite : le
   contenu (assez court par rapport à la hauteur du panneau) descend
   d'une quantité fixe et contrôlée, plutôt que de dépendre du calcul
   de centrage qui recule dès que le contenu grossit. */
.track__panel--test-scale {
  justify-content: flex-start;
  padding-top: calc(var(--sp-16) + 246px);
  background: #0A0806 url('../assets/images/hero/paper-black.png') center / cover no-repeat;
}

.track__panel--test-scale::before {
  --wl-blend: normal;
}

.track__panel--test-scale .editorial-split__label,
.track__panel--test-scale .kw,
.track__panel--test-scale .step-flow__item--accent {
  color: var(--accent-cyan);
}

.track__panel--test-scale .editorial-split__label {
  font-family: var(--font-editorial);
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--test-scale .track__panel-sub {
  font-family: var(--font-editorial);
  font-style: italic;
}

.track__panel--test-scale h3 .glass-capsule,
.track__panel--test-scale .punchline .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

/* ── Slide "Automatisation" — repassée claire : accents cyan scopés,
   centrage vertical, papier blanc réel (héritée de --paper). ── */
.track__panel--automatisation {
  justify-content: center;
}

.track__panel--automatisation .editorial-split__label,
.track__panel--automatisation .keyword-row__word--accent,
.track__panel--automatisation .glass-capsule {
  color: var(--accent-cyan);
}

.track__panel--automatisation .glass-capsule {
  border-color: rgba(0,167,173,0.4);
}

.track__panel--automatisation .editorial-split__title .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

.track__panel--automatisation .editorial-split__label {
  font-family: var(--font-editorial);
  font-style: italic;
  letter-spacing: 0.18em;
}

/* ── Slide "Site" — fond papier noir réel (même famille que le hero),
   accents cyan scopés. justify-content reste flex-start (comportement
   par défaut de .track__panel) : le titre part toujours du haut du
   cadre, jamais poussé au-dessus par un centrage vertical si la
   composition dessous devient plus haute que l'espace disponible. ── */
.track__panel--site {
  padding-top: calc(var(--sp-16) + 20px);
  padding-bottom: var(--sp-2);
  background: #0A0806 url('../assets/images/hero/paper-black.png') center / cover no-repeat;
}

/* .panel-frame est un simple bloc partout ailleurs sur le site — ici on
   le rend flex-column et haut de 100% pour que .site-compose (flex:1)
   puisse remplir tout l'espace vertical restant sous le titre, quelle
   que soit la hauteur du panneau. Scopé à cette slide uniquement. */
.track__panel--site .panel-frame {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.track__panel--site::before {
  --wl-blend: normal;
}

.track__panel--site .editorial-split__label {
  color: var(--accent-cyan);
  font-family: var(--font-editorial);
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--site .punchline .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

/* Titre compacté pour laisser le maximum de hauteur à la composition
   ci-dessous — la preuve visuelle prime sur la taille du titre ici. */
.track__panel--site .punchline {
  font-size: clamp(22px, 2.6vw, 32px);
  white-space: nowrap;
}

.track__panel--site .editorial-split__label {
  margin-bottom: 0;
}

/* ── SITE COMPOSE — vrai canvas en couches (pas une grille, pas un
   wrapper centré étroit) : hauteur et largeur explicites via
   clamp()/vw pour que le site final, le code et le montage soient
   tous les trois position:absolute à l'intérieur, indépendamment de
   la hauteur de leur propre contenu. overflow:visible assumé — le
   montage doit pouvoir déborder du canvas nominal, c'est le principe
   même de la superposition. ── */
.site-compose {
  position: relative;
  width: min(92vw, 1500px);
  flex: 1 1 auto;
  min-height: 0;
  margin: 0 auto;
  overflow: visible;
}

.site-compose__label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-inv-sec);
  margin-bottom: var(--sp-3);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid rgba(255,255,255,0.14);
  display: inline-block;
}

/* Barre d'adresse réelle (vrai domaine ecofina.ch) sur la fenêtre du
   site final — même logique que les points de trafic : un indice
   visuel de "navigateur", pas une donnée inventée. */
.floating-window__bar--browser {
  gap: var(--sp-3);
}

.floating-window__url {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 9.5px;
  color: rgba(255,255,255,0.55);
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 20px;
  padding: 3px 10px;
  flex: 1;
  max-width: 160px;
}

.floating-window__url svg {
  flex-shrink: 0;
  opacity: 0.7;
}

/* Numéros de ligne — repère visuel d'éditeur de code réel, purement
   décoratif (aucune donnée), aligné sur le même line-height que le code.
   Scopé à cette slide : .code-window__body est réutilisé ailleurs
   (Simulateur) avec du texte brut, pas la structure à deux colonnes. */
.site-compose__code .code-window__body {
  display: flex;
  gap: var(--sp-3);
}

.code-window__lines {
  flex-shrink: 0;
  color: rgba(255,255,255,0.22);
  text-align: right;
  white-space: pre;
  user-select: none;
}

.code-window__code {
  flex: 1;
  min-width: 0;
  white-space: pre;
}

.site-compose__site {
  position: absolute;
  left: 23%;
  top: calc(4% - 30px);
  width: 54%;
  z-index: 2;
}

.site-compose__site .floating-window,
.site-compose__montage .floating-window {
  max-height: none;
}

.site-compose__site .floating-window video,
.site-compose__montage .floating-window video {
  height: auto;
  object-fit: contain;
}

.site-compose__code {
  position: absolute;
  right: -0.3%;
  top: 2%;
  width: 25%;
  z-index: 4;
}

.site-compose__code .code-window {
  box-shadow: 0 24px 50px -14px rgba(0,0,0,0.5);
}

/* Montage : coin BAS-GAUCHE de la composition, chevauche légèrement le
   coin bas-gauche du site (diagonale montage↗site↗code demandée). */
.site-compose__montage {
  position: absolute;
  left: -0.3%;
  bottom: calc(4% + 40px);
  width: 25%;
  z-index: 4;
}

.site-compose__montage .floating-window {
  border: 3px solid var(--bg-dark);
  box-shadow: 0 30px 60px -12px rgba(0,0,0,0.6), 0 10px 24px -8px rgba(0,0,0,0.4);
}

.site-compose__tag {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 4;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #f4f1ea;
  background: rgba(10,8,6,0.55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  padding: 3px 9px;
  border-radius: 20px;
}

/* ── Annotations manuscrites — élément de design permanent (voulu par
   le client), pas des notes de développement. Police Caveat, cyan,
   légère rotation pour l'effet "croquis", flèches SVG courbes assorties.
   Masquées sur mobile où la composition empilée n'a plus de cible
   précise à désigner. ── */
.site-annotation {
  position: absolute;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--accent-cyan);
  pointer-events: none;
}

.site-annotation__text {
  font-family: 'Caveat', 'Segoe Script', 'Bradley Hand', cursive;
  font-style: italic;
  font-weight: 700;
  font-size: 22px;
  line-height: 1.15;
  white-space: nowrap;
  transform: rotate(-2deg);
  text-shadow: 0 2px 10px rgba(0,0,0,0.6);
}

.site-annotation__arrow {
  flex-shrink: 0;
  opacity: 0.85;
}

/* Ancrées directement sur leur bloc cible (.site-compose__site / __code
   / __montage sont chacun position:absolute, donc un point d'ancrage
   valide) plutôt que sur .site-compose — la flèche vise toujours la
   même zone du bloc, quelle que soit la hauteur du canvas (flex:1) ou
   la largeur du viewport, puisque tout est relatif à la taille RÉELLE
   du bloc au lieu d'un pourcentage d'un canvas qui varie séparément. */

/* Code (annotation C) : AU-DESSUS du bloc, centrée dans l'espace noir
   libre sous le titre — flèche courte qui s'arrête au bord extérieur
   de la fenêtre de code, sans jamais entrer dans le contenu. */
.site-annotation--code {
  left: 50%;
  top: -51px;
  transform: translateX(-50%);
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
}

/* Montage (annotation A) : juste au-dessus du bloc, dans la zone noire
   libre — flèche courte qui s'arrête au bord extérieur de la vidéo,
   sans jamais entrer dans le contenu. */
.site-annotation--montage {
  left: 50%;
  top: -119px;
  transform: translateX(-50%);
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
}

@media (max-width: 768px), (max-height: 500px) {
  .site-annotation {
    display: none;
  }
  .track__panel--site .punchline {
    white-space: normal;
  }
}

/* ── Slide "Simulateur" — repassée en panneau clair (alternance
   noir/blanc), accents cyan scopés, même système visuel que les autres
   slides claires (papier réel, ombre de fenêtre, glass-capsule). ── */
.track__panel--simulateur {
  justify-content: center;
  padding-top: calc(var(--sp-16) + 8px);
  padding-bottom: var(--sp-6);
}

.track__panel--simulateur .editorial-split__label,
.track__panel--simulateur .kw,
.track__panel--simulateur .glass-capsule,
.track__panel--simulateur .step-flow__item--accent {
  color: var(--accent-cyan);
}

.track__panel--simulateur .glass-capsule {
  border-color: rgba(0,167,173,0.4);
}

.track__panel--simulateur .punchline .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

/* Titre sur une seule ligne pour laisser le maximum de hauteur aux deux
   preuves — même logique que la slide Site. */
.track__panel--simulateur .punchline {
  font-size: clamp(22px, 2.6vw, 32px);
  white-space: nowrap;
}

.track__panel--simulateur .editorial-split__label,
.track__panel--simulateur .track__panel-sub {
  font-family: var(--font-editorial);
}

.track__panel--simulateur .editorial-split__label {
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--simulateur .track__panel-sub {
  font-style: italic;
}

.track__panel--simulateur .step-flow__arrow {
  color: var(--text-sec);
  opacity: 0.5;
}

/* Fenêtre de code cohérente avec celle de la slide Site : numéros de
   ligne à gauche, code à droite, mots-clés en cyan plutôt qu'orange. */
.track__panel--simulateur .code-window__body {
  display: flex;
  gap: var(--sp-4);
}

.track__panel--simulateur .code-window--major .code-window__body {
  font-size: 12.5px;
  line-height: 1.6;
}

.track__panel--simulateur .code-window__body .c-kw {
  color: var(--accent-cyan);
}

@media (max-width: 768px), (max-height: 500px) {
  .track__panel--simulateur .punchline {
    white-space: normal;
  }
}

/* ── Slide "Contenu" — repassée en panneau clair (alternance
   noir/blanc), accents cyan scopés, même système visuel que les autres
   slides claires (papier réel, ombre de fenêtre, glass-capsule). Le
   magazine est la preuve principale, les posts réels sont des cartes
   physiques (.paper-card) qui gravitent légèrement autour, pas une
   grille régulière. ── */
.track__panel--contenu {
  justify-content: center;
  padding-top: calc(var(--sp-16) + 8px);
  padding-bottom: var(--sp-6);
}

.track__panel--contenu .editorial-split__label,
.track__panel--contenu .kw,
.track__panel--contenu .glass-capsule {
  color: var(--accent-cyan);
}

.track__panel--contenu .glass-capsule {
  border-color: rgba(0,167,173,0.4);
}

.track__panel--contenu .punchline .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

.track__panel--contenu .punchline {
  font-size: clamp(22px, 2.6vw, 32px);
  white-space: nowrap;
}

.track__panel--contenu .editorial-split__label,
.track__panel--contenu .track__panel-sub {
  font-family: var(--font-editorial);
}

.track__panel--contenu .editorial-split__label {
  font-style: italic;
  letter-spacing: 0.18em;
}

.track__panel--contenu .track__panel-sub {
  font-style: italic;
}

@media (max-width: 768px), (max-height: 500px) {
  .track__panel--contenu .punchline {
    white-space: normal;
  }
}

/* Composition : les vraies publications posées comme des cartes
   physiques sur la table — pas de pièce centrale, pas de grille rigide.
   Réparties en ligne (flex), chaque carte décalée verticalement via
   position:relative (top) pour un effet "posé naturellement", sans
   affecter la largeur/hauteur du conteneur (donc jamais de risque de
   coupure en bas). */
.content-cards {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: nowrap;
  gap: var(--sp-5);
  width: 100%;
  /* Compense le décalage vertical (top) des cartes : sans cette marge
     réelle, leur position:relative peint hors de la boîte du conteneur
     sans agrandir sa hauteur réelle, ce qui fausse le centrage vertical
     du panneau (justify-content:center centrerait une boîte plus petite
     que ce qui est réellement peint à l'écran). Padding-top uniquement
     (pas bottom) : équilibre l'air au-dessus/en-dessous des cartes. */
  padding: 63px 0 0;
}

.content-card {
  position: relative;
  flex-shrink: 0;
}

.track__panel--contenu .paper-card {
  border-radius: var(--r-sm);
}

@media (max-width: 768px), (max-height: 500px) {
  .content-cards {
    flex-wrap: wrap;
    gap: var(--sp-4);
  }
  .content-card {
    top: 0 !important;
  }
}

/* Écrans courts (ex. 1366×768, 1600×900) : .site-compose se
   redimensionne tout seul via clamp(380px, 50vh, 610px). Sous ~820px
   .site-compose est maintenant en flex:1 (occupe tout l'espace vertical
   restant du panneau, quelle que soit sa hauteur) plutôt qu'une
   hauteur fixée en dur — la géométrie diagonale (montage bas-gauche /
   site centre / code haut-droite) reste donc identique à toutes les
   hauteurs, sans média-requête qui la casse. */
@media (max-height: 960px) and (min-width: 769px) {
  /* Test → Scale et Automatisation ont un padding-top fixe généreux
     (pensé pour de grands écrans) qui déborde sur un écran court — on
     le réduit fortement ici, avec le reste de la composition. */
  .track__panel--test-scale {
    padding-top: calc(var(--sp-16) + 16px) !important;
    padding-bottom: var(--sp-5) !important;
  }
  .track__panel--test-scale .panel-frame {
    max-width: 1080px !important;
  }
  .track__panel--test-scale .track__panel-sub {
    margin-bottom: var(--sp-5) !important;
  }
  .track__panel--test-scale .test-scale-row {
    margin-bottom: var(--sp-6) !important;
    transform: none !important;
  }
  .track__panel--test-scale .step-flow {
    margin-top: var(--sp-6) !important;
  }
}

@media (max-width: 768px), (max-height: 500px) {
  .site-compose {
    width: 100%;
    max-width: 340px;
    height: auto;
  }
  .site-compose__site {
    position: static;
    width: 100%;
    margin-left: 0;
  }
  .site-compose__code {
    position: static;
    width: 100%;
    margin-top: var(--sp-4);
  }
  .site-compose__montage {
    position: static;
    width: 62%;
    margin: var(--sp-4) 0 0 auto;
  }
}

/* ── OPEN BOOK — un vrai livre/magazine ouvert, pas deux rectangles
   arrondis côte à côte. Réservé aux moments éditoriaux majeurs (jamais
   pour des données/statistiques — voir §Data legibility ailleurs).
   Construction : perspective partagée + légère bascule vers l'arrière
   (vue de dessus), reliure centrale visible (::before), gouttière /
   courbure du papier vers la reliure, tranche de pages (empilement de
   fines ombres sur les bords extérieurs), ombre de contact au sol
   (::after) séparée de l'ombre portée globale. Aucun backdrop-filter. */
.open-book {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 0;
  width: 100%;
  perspective: 2600px;
  filter: drop-shadow(0 36px 60px rgba(20,17,14,0.3)) drop-shadow(0 10px 18px rgba(20,17,14,0.16));
}

/* Reliure centrale — ombre de gouttière + fin filet de lumière */
.open-book::before {
  content: '';
  position: absolute;
  top: 2%;
  bottom: 2%;
  left: 45.5%;
  width: 9%;
  z-index: 3;
  pointer-events: none;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(20,17,14,0.16) 38%,
    rgba(20,17,14,0.24) 50%,
    rgba(20,17,14,0.16) 62%,
    transparent 100%);
}

.open-book--dark::before {
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(0,0,0,0.5) 38%,
    rgba(0,0,0,0.65) 50%,
    rgba(0,0,0,0.5) 62%,
    transparent 100%);
}

/* Ombre de contact au sol — le livre est posé, pas plaqué sur la page */
.open-book::after {
  content: '';
  position: absolute;
  left: 8%;
  right: 8%;
  bottom: -22px;
  height: 34px;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 100% at 50% 0%, rgba(20,17,14,0.22), transparent 78%);
}

.open-book--dark::after {
  background: radial-gradient(ellipse 60% 100% at 50% 0%, rgba(0,0,0,0.55), transparent 78%);
}

.book-page {
  padding: var(--sp-8);
  position: relative;
  transform-style: preserve-3d;
}

.book-page--left {
  background: var(--bg-card);
  border-radius: var(--r-lg) 2px 2px var(--r-lg);
  box-shadow:
    inset -22px 0 30px -20px rgba(20,17,14,0.32),
    inset 3px 0 0 0 rgba(255,255,255,0.5),
    -1px 0 0 rgba(20,17,14,0.06), -3px 0 0 rgba(20,17,14,0.04), -5px 0 0 rgba(20,17,14,0.02);
  transform: rotateX(6deg) rotateY(3deg);
  transform-origin: right center;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.book-page--right {
  background: var(--bg-card);
  border-radius: 2px var(--r-lg) var(--r-lg) 2px;
  box-shadow:
    inset 22px 0 30px -20px rgba(20,17,14,0.32),
    inset -3px 0 0 0 rgba(255,255,255,0.5),
    1px 0 0 rgba(20,17,14,0.06), 3px 0 0 rgba(20,17,14,0.04), 5px 0 0 rgba(20,17,14,0.02);
  transform: rotateX(6deg) rotateY(-3deg);
  transform-origin: left center;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.open-book--dark .book-page--left,
.open-book--dark .book-page--right {
  background: var(--bg-dark-2);
}

.open-book--dark .book-page--left {
  --text-inv: var(--ink-strong); --text-inv-sec: var(--ink-soft);
  box-shadow:
    inset -22px 0 30px -20px rgba(0,0,0,0.6),
    inset 3px 0 0 0 rgba(255,255,255,0.06),
    -1px 0 0 rgba(0,0,0,0.5), -3px 0 0 rgba(0,0,0,0.35), -5px 0 0 rgba(0,0,0,0.2);
}

.open-book--dark .book-page--right {
  --text-inv: var(--ink-strong); --text-inv-sec: var(--ink-soft);
  box-shadow:
    inset 22px 0 30px -20px rgba(0,0,0,0.6),
    inset -3px 0 0 0 rgba(255,255,255,0.06),
    1px 0 0 rgba(0,0,0,0.5), 3px 0 0 rgba(0,0,0,0.35), 5px 0 0 rgba(0,0,0,0.2);
}

.book-page__label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-3);
}

.book-page__media {
  border-radius: var(--r-md);
  overflow: hidden;
}

.book-page__media img,
.book-page__media video {
  width: 100%;
  max-height: 38vh;
  display: block;
  object-fit: contain;
}

.book-page-caption {
  margin-top: var(--sp-3);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-align: center;
  color: var(--text-inv-sec);
}

/* ── GLASS CAPSULE — mot-clé traité comme un objet physique éclairé.
   Signature element : max 2-3 occurrences sur tout le site, jamais un
   titre entier. Utilise directement l'asset réel (verre/loupe traversé
   par la lumière, source Canva) comme matière du panneau — pas de
   gradient recréé en CSS. Le mot reste toujours au-dessus, net. ── */
.glass-capsule {
  display: inline-block;
  position: relative;
  padding: 0.02em 0.34em;
  border-radius: 0.34em;
  font-family: var(--font-serif);
  font-style: italic;
  background: transparent;
  -webkit-backdrop-filter: blur(4px) saturate(1.15);
  backdrop-filter: blur(4px) saturate(1.15);
  border: 1px solid rgba(255,255,255,0.4);
  box-shadow: 0 1px 1px rgba(255,255,255,0.35) inset, 0 10px 22px -10px rgba(20,17,14,0.28);
  color: var(--accent-hover);
}

/* Pas d'overflow:hidden sur l'élément inline-block lui-même : ça force les
   navigateurs à aligner sa BOX (bord bas) plutôt que la vraie ligne de
   base du texte interne sur la ligne environnante — décalage vertical
   perceptible. Le clip se fait plutôt sur chaque pseudo-élément via son
   propre border-radius, ce qui laisse le texte s'aligner normalement. */

/* Texture du verre réel — blend "screen" : seuls les reflets clairs de
   l'asset se peignent, le centre reste transparent (jamais un fill plat). */
.glass-capsule::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: url('../assets/images/light/glass-capsule-wide.png');
  background-size: cover;
  background-position: center;
  mix-blend-mode: screen;
  opacity: 0.3;
  pointer-events: none;
}

/* Reflet spéculaire diagonal, très discret */
.glass-capsule::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(115deg, transparent 42%, rgba(255,255,255,0.4) 49%, transparent 56%);
  opacity: 0.35;
  pointer-events: none;
}

.track__panel--dark .glass-capsule {
  border-color: rgba(255,255,255,0.16);
  box-shadow: 0 1px 1px rgba(255,255,255,0.12) inset, 0 10px 24px -8px rgba(0,0,0,0.5);
  color: var(--accent);
}

.track__panel--dark .glass-capsule::before {
  opacity: 0.18;
}

/* Slide "Ciblage" : cyan plutôt que l'orange par défaut des panneaux
   sombres — doit venir après .track__panel--dark .glass-capsule pour
   gagner la cascade (même spécificité, 2 classes). */
.track__panel--ciblage .glass-capsule {
  color: var(--accent-cyan);
  border-color: rgba(0,167,173,0.4);
}

/* Même correctif pour la slide "Personnalisation", repassée en panneau
   sombre pour respecter l'alternance noir/blanc du portfolio. */
.track__panel--personnalisation .glass-capsule {
  color: var(--accent-cyan);
  border-color: rgba(0,167,173,0.4);
}

/* Même correctif pour la slide "Test → Scale", repassée en panneau
   sombre pour respecter l'alternance noir/blanc du portfolio. */
.track__panel--test-scale .glass-capsule {
  color: var(--accent-cyan);
  border-color: rgba(0,167,173,0.4);
}

/* Même correctif pour la slide "Site". */
.track__panel--site .glass-capsule {
  color: var(--accent-cyan);
  border-color: rgba(0,167,173,0.4);
}

/* ── PAPER CARD — preuve secondaire posée comme un document physique ── */
.paper-card {
  background: var(--bg-card);
  border-radius: var(--r-md);
  box-shadow: 0 18px 40px -10px rgba(20,17,14,0.22), 0 4px 10px -4px rgba(20,17,14,0.12);
  padding: var(--sp-2);
  transition: transform 350ms cubic-bezier(.2,.7,.3,1), box-shadow 350ms cubic-bezier(.2,.7,.3,1);
}

.paper-card:hover {
  transform: translateY(-4px) rotate(0deg) scale(1.012);
  box-shadow: 0 26px 54px -10px rgba(20,17,14,0.28), 0 8px 16px -4px rgba(20,17,14,0.16);
}

.paper-card img { width: 100%; display: block; border-radius: calc(var(--r-md) - 4px); }

/* ── MEDIA FRAME — composant unique pour toutes les preuves visuelles ──
   object-fit:contain (jamais de crop), fond clair adapté, ombre douce,
   légère élévation au survol. Remplace les crops destructeurs. ── */
.media-frame {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-alt);
  border: 1px solid rgba(255,255,255,0.08);
  box-shadow: 0 10px 28px rgba(0,0,0,0.22), 0 2px 8px rgba(0,0,0,0.12);
  transition: transform 300ms ease, box-shadow 300ms ease;
}

.media-frame:hover {
  transform: translateY(-4px) scale(1.012);
  box-shadow: 0 18px 38px rgba(0,0,0,0.28), 0 4px 12px rgba(0,0,0,0.16);
}

.media-frame img,
.media-frame video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.media-frame__bar {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 28px;
  background: rgba(0,0,0,0.06);
  border-bottom: 1px solid rgba(255,255,255,0.06);
  display: flex;
  align-items: center;
  padding: 0 var(--sp-3);
  gap: 6px;
  z-index: 2;
}

.media-frame__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(0,0,0,0.15);
}

.media-frame--padtop img,
.media-frame--padtop video { padding-top: 28px; box-sizing: border-box; }

/* ── GRILLE COMMUNE — même largeur, mêmes marges sur toutes les slides ── */
.panel-frame {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
}

/* ── HIÉRARCHIE TYPOGRAPHIQUE — niveau 1 : la grande idée ── */
.punchline {
  font-size: clamp(26px, 3.4vw, 44px);
  font-weight: 800;
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: var(--text-inv);
  max-width: 760px;
}

.punchline--tight { margin-bottom: var(--sp-3); }

/* Mots-clés colorés — la couleur porte un sens précis, jamais une phrase entière */
.kw { color: var(--accent); }
.kw--test { color: var(--color-test); }
.kw--result { color: var(--color-result); }

.keyword-row__word--test { color: var(--color-test); }
.keyword-row__word--result { color: var(--color-result); }

.flow-ribbon__step--test { color: var(--color-test); font-weight: 700; }
.flow-ribbon__step--result { color: var(--color-result); font-weight: 700; }

/* ── STEP FLOW — respiration éditoriale (remplace les barres beige pleines) ── */
.step-flow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-5) var(--sp-6);
}

.step-flow__item {
  font-size: 14.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-inv-sec);
}

.step-flow__item--accent { color: var(--accent); }
.step-flow__item--test { color: var(--color-test); }
.step-flow__item--result { color: var(--color-result); }

.step-flow__arrow {
  color: var(--accent);
  opacity: 0.55;
  font-size: 13px;
}

/* ── PLACEHOLDER SOMBRE (preuve manquante — jamais inventée) ── */
.proof-placeholder--dark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-3) var(--sp-5);
  background: var(--bg-dark-2);
  border: 1px dashed var(--border-dark);
  color: var(--text-inv-sec);
  font-size: 11.5px;
  letter-spacing: 0.03em;
  border-radius: var(--r-sm);
}

.track__panel-num {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-2);
}

.track__panel-title {
  font-size: clamp(22px, 2.6vw, 32px);
  font-weight: 700;
  color: var(--text-inv);
  margin-bottom: var(--sp-4);
  max-width: 620px;
  letter-spacing: -0.02em;
}

.track__panel-sub {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 16px;
  color: var(--text-inv-sec);
  margin-bottom: var(--sp-5);
}

.track__panel-media {
  flex: 1;
  min-height: 0;
  max-height: 70vh;
  border-radius: var(--r-lg);
  overflow: hidden;
  position: relative;
  background: #000;
  box-shadow: var(--shadow-lg);
}

.track__panel-media video,
.track__panel-media img,
.track__panel-media .proof-placeholder {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.track__panel--hero {
  position: relative;
  flex-direction: row;
  align-items: stretch;
  justify-content: flex-start;
  text-align: left;
  overflow: hidden;
  padding: 0 !important;
  background: #0A0806 url('../assets/images/hero/paper-black.png') center / cover no-repeat;
  --text-inv: #F5F3EE;
  --text-inv-sec: #C7C2B6;
}

@keyframes heroFadeUp {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Dédiée au portrait : le scale(1.12) doit survivre à l'animation
   d'entrée (heroFadeUp seul écraserait le transform au dernier keyframe
   et annulerait l'agrandissement une fois l'animation terminée). */
@keyframes heroPortraitFadeUp {
  from { opacity: 0; transform: translateY(14px) scale(1.12); }
  to   { opacity: 1; transform: translateY(0) scale(1.12); }
}

/* Lumière naturelle réelle (photo, pas un gradient recréé) — une fenêtre
   hors-champ qui éclaire le papier noir. mix-blend-mode:screen : les zones
   sombres de l'asset n'altèrent jamais le noir du papier, seules les zones
   claires l'éclaircissent — le noir reste noir. */
.track__panel--hero::before {
  content: '';
  position: absolute;
  inset: -8% -6%;
  z-index: 1;
  background-image: url('../assets/images/hero/window-light.png');
  background-size: 135% auto;
  background-position: 18% 32%;
  background-repeat: no-repeat;
  mix-blend-mode: screen;
  opacity: 0.5;
  transform: rotate(-1.5deg);
  pointer-events: none;
}

.track__hero-portrait {
  position: relative;
  z-index: 2;
  flex: 0 0 45%;
  height: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  min-width: 0;
}

.track__hero-portrait img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  display: block;
  object-fit: contain;
  /* +~12% : le haut de la tête reste fixé au bord supérieur du panneau
     (transform-origin:top + align-items:flex-start), l'agrandissement se
     fait vers le bas — seul le bas de l'image (pieds) peut être rogné par
     l'overflow:hidden du panneau, jamais la tête. Keyframe dédiée (pas
     heroFadeUp) pour que le scale survive à la fin de l'animation. */
  transform-origin: top center;
  filter: drop-shadow(0 26px 50px rgba(0,0,0,0.55));
  animation: heroPortraitFadeUp 1000ms ease 100ms both;
}

.track__hero-text {
  position: relative;
  z-index: 3;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--sp-16);
  min-width: 0;
}

.track__hero-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-cyan);
  margin-bottom: var(--sp-5);
  animation: heroFadeUp 800ms ease 80ms both;
}

.track__hero-name {
  font-size: clamp(52px, 7.2vw, 108px);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.035em;
  color: var(--text-inv);
  margin-bottom: var(--sp-5);
  animation: heroFadeUp 800ms ease 150ms both;
}

.track__hero-role {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-inv-sec);
  margin-bottom: var(--sp-8);
  animation: heroFadeUp 800ms ease 300ms both;
}

.track__hero-statement {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(19px, 2vw, 25px);
  line-height: 1.5;
  color: var(--text-inv-sec);
  max-width: 530px;
  margin-bottom: var(--sp-12);
  animation: heroFadeUp 800ms ease 450ms both;
}

.track__hero-statement .kw {
  font-weight: 700;
  color: var(--accent-cyan);
  font-style: italic;
}

.track__panel--hero .glass-capsule {
  color: var(--accent-cyan);
  border-color: rgba(0,167,173,0.4);
  box-shadow: 0 1px 1px rgba(255,255,255,0.10) inset, 0 10px 24px -8px rgba(0,0,0,0.55);
}

.track__panel--hero .glass-capsule::before {
  opacity: 0.2;
}

.track__progress {
  position: absolute;
  bottom: var(--sp-6);
  left: var(--sp-16);
  display: flex;
  gap: 6px;
  z-index: 5;
}

.track__progress-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255,255,255,0.22);
  transition: background var(--t-base), transform var(--t-base);
}

.track__progress-dot.is-active {
  background: var(--accent-cyan);
  transform: scale(1.4);
}

/* Les dots sont des sœurs des panels (pas des descendants) : leur
   contraste doit s'adapter au panel actif, clair ou sombre. */
.track__sticky:has(.track__panel.is-active:not(.track__panel--dark):not(.track__panel--hero)) .track__progress-dot {
  background: rgba(23, 19, 15, 0.18);
}

.track__sticky:has(.track__panel.is-active:not(.track__panel--dark):not(.track__panel--hero)) .track__progress-dot.is-active {
  background: var(--accent-cyan);
}

/* ── SPLIT PANEL (problème + photo réunion) ── */
.split-panel {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: var(--sp-10);
  align-items: center;
  width: 100%;
  max-width: 1180px;
}

.split-panel__photo {
  position: relative;
  height: min(60vh, 460px);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}

.split-panel__photo img,
.split-panel__photo video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ── DUO MEDIA (2 vidéos, composition asymétrique) ── */
.duo-media {
  position: relative;
  width: 100%;
  max-width: 980px;
  height: min(64vh, 480px);
}

.duo-media__a {
  position: absolute;
  top: 0;
  right: 0;
  width: 62%;
  height: 68%;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  z-index: 2;
}

.duo-media__b {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 56%;
  height: 62%;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  z-index: 1;
  border: 4px solid var(--bg-dark);
}

.duo-media__a video,
.duo-media__b video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.duo-media__label {
  position: absolute;
  z-index: 3;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(0,0,0,0.5);
  padding: 5px 10px;
  border-radius: 100px;
}

/* ── EDITORIAL SPLIT (label + titre fort + mots clés + preuve contenue) ── */
.editorial-split {
  display: grid;
  gap: var(--sp-10);
  align-items: center;
  width: 100%;
  max-width: 1240px;
}

.editorial-split--45-55 { grid-template-columns: 0.82fr 1fr; }
.editorial-split--42-58 { grid-template-columns: 0.75fr 1fr; }

.editorial-split__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-3);
}

.editorial-split__title {
  font-size: clamp(28px, 3vw, 40px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--text-inv);
  margin-bottom: var(--sp-4);
}

.editorial-split__lead {
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-inv-sec);
  max-width: 420px;
  margin-bottom: var(--sp-6);
}

/* Mots-clés en ligne, avec flèches, accent sur les mots importants */
.keyword-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

.keyword-row__word {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-inv);
}

.keyword-row__word--accent {
  color: var(--accent);
}

.keyword-row__arrow {
  color: var(--text-inv-sec);
  opacity: 0.5;
  font-size: 13px;
}

/* Fenêtre produit — vidéo/capture contenue, jamais plein écran */
.product-window {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #000;
  box-shadow: var(--shadow-lg);
  border: 1px solid rgba(255,255,255,0.08);
  max-height: 56vh;
  transition: transform 300ms ease, box-shadow 300ms ease;
}

.product-window:hover {
  transform: translateY(-4px) scale(1.012);
  box-shadow: 0 20px 44px rgba(0,0,0,0.32), 0 4px 14px rgba(0,0,0,0.18);
}

.product-window__bar {
  height: 30px;
  background: #232019;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  display: flex;
  align-items: center;
  padding: 0 var(--sp-3);
  gap: 6px;
}

.product-window__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255,255,255,0.18);
}

.product-window video,
.product-window img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  max-height: calc(56vh - 30px);
}

/* ── DIAGNOSTIC (slide problèmes — liste séquentielle) ── */
.diagnostic-photo {
  position: relative;
  width: 100%;
  max-width: 320px;
  aspect-ratio: 4/5;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  margin: 0 auto;
}

.diagnostic-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.diagnostic-photo__caption {
  margin-top: var(--sp-3);
  font-size: 12.5px;
  color: var(--text-inv-sec);
  max-width: 320px;
  margin: var(--sp-3) auto 0;
  text-align: center;
  line-height: 1.4;
}

.diagnostic-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  margin-top: var(--sp-8);
}

.diagnostic-list__item {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 500ms ease, transform 500ms ease;
}

.is-active .diagnostic-list__item {
  opacity: 1;
  transform: translateY(0);
}

.diagnostic-list__item:nth-child(1) { transition-delay: 60ms; }
.diagnostic-list__item:nth-child(2) { transition-delay: 160ms; }
.diagnostic-list__item:nth-child(3) { transition-delay: 260ms; }
.diagnostic-list__item:nth-child(4) { transition-delay: 360ms; }
.diagnostic-list__item:nth-child(5) { transition-delay: 460ms; }
.diagnostic-list__item:nth-child(6) { transition-delay: 560ms; }

.diagnostic-list__num {
  font-size: 18px;
  font-weight: 800;
  color: var(--accent);
  flex-shrink: 0;
  width: 34px;
}

.diagnostic-list__word {
  font-size: clamp(19px, 1.7vw, 25px);
  font-weight: 700;
  color: var(--text-inv);
  letter-spacing: -0.01em;
  line-height: 1.2;
}

/* ── CRM FLOW (liste verticale, mots clés en surbrillance) ── */
.crm-flow {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin: var(--sp-5) 0;
}

.crm-flow__step {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-inv-sec);
}

.crm-flow__step--accent {
  color: var(--text-inv);
  font-weight: 800;
}

.crm-flow__step--accent .crm-flow__hl {
  color: var(--accent);
}

.crm-flow__arrow {
  color: var(--text-inv-sec);
  opacity: 0.4;
  font-size: 12px;
  line-height: 1;
}

.stat-big {
  display: inline-flex;
  flex-direction: column;
  margin-top: var(--sp-2);
}

.stat-big__value {
  font-size: clamp(44px, 4.5vw, 64px);
  font-weight: 800;
  color: var(--accent);
  line-height: 1;
  letter-spacing: -0.02em;
}

.stat-big__label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-inv-sec);
  margin-top: var(--sp-2);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ── PRODUCT WINDOW — variante "compact" (garde de l'air autour de la vidéo) ── */
.product-window--compact {
  max-width: 760px;
  max-height: 46vh;
  margin: 0 auto;
}

.product-window--compact video,
.product-window--compact img {
  max-height: calc(46vh - 30px);
}

/* ── PRODUCT WINDOW — variante "contain" (proportions respectées) ── */
.product-window--contain {
  background: var(--bg-dark-2);
}

.product-window--contain video,
.product-window--contain img {
  object-fit: contain;
  background: var(--bg-dark-2);
}

/* ── VISIBILITÉ — deux axes ── */
.visibility-axes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-10);
  width: 100%;
  max-width: 1100px;
  margin-bottom: var(--sp-8);
}

.visibility-axis__label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-4);
}

.visibility-axis__lead {
  font-size: 13.5px;
  color: var(--text-inv-sec);
  line-height: 1.5;
  margin-bottom: var(--sp-4);
  max-width: 380px;
}

.visibility-flow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-8);
  margin: var(--sp-8) 0 var(--sp-4);
  font-size: 13px;
  font-weight: 700;
  color: var(--text-inv-sec);
  letter-spacing: 0.02em;
}

.visibility-flow__col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  text-align: center;
}

.visibility-flow__col span { color: var(--text-inv); }

.visibility-flow__plus {
  font-size: 20px;
  color: var(--accent);
}

.visibility-flow__down {
  display: block;
  text-align: center;
  color: var(--accent);
  font-size: 18px;
  margin: var(--sp-2) 0;
}

.visibility-outcome {
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  color: var(--text-inv);
}

.visibility-outcome .kw { color: var(--accent); }

/* ── REASONING FLOW (slide simulateur — gauche) ── */
.reasoning-flow {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin: var(--sp-5) 0;
}

.reasoning-flow__step {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-inv-sec);
}

.reasoning-flow__step--accent {
  color: var(--accent);
  font-weight: 800;
}

.reasoning-flow__arrow {
  color: var(--text-inv-sec);
  opacity: 0.4;
  font-size: 12px;
  line-height: 1;
}

/* ── CODE WINDOW (preuve technique réelle) ── */
.code-window {
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #1a1712;
  box-shadow: var(--shadow-lg);
  border: 1px solid rgba(255,255,255,0.08);
  max-width: 480px;
  transition: transform 300ms ease, box-shadow 300ms ease;
}

.code-window:hover {
  transform: translateY(-4px) scale(1.012);
  box-shadow: 0 20px 44px rgba(0,0,0,0.32), 0 4px 14px rgba(0,0,0,0.18);
}

.code-window__bar {
  height: 30px;
  background: #232019;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  display: flex;
  align-items: center;
  padding: 0 var(--sp-3);
  gap: 6px;
}

.code-window__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255,255,255,0.18);
}

.code-window__body {
  padding: var(--sp-4) var(--sp-5);
  font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace;
  font-size: 12px;
  line-height: 1.6;
  color: #d8d0c0;
  white-space: pre;
  overflow-x: auto;
}

.code-window__body .c-kw { color: var(--accent); }
.code-window__body .c-num { color: #9cc9a1; }
.code-window__body .c-com { color: #7a7468; font-style: italic; }

.simulator-proof-shot {
  position: absolute;
  bottom: -28px;
  right: -36px;
  width: 46%;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: 0 16px 40px rgba(0,0,0,0.4);
  border: 1px solid rgba(255,255,255,0.1);
}

.simulator-proof-shot img { width: 100%; display: block; }

.simulator-visual-wrap {
  position: relative;
  padding-bottom: var(--sp-10);
}

/* ── BIG PHRASE (affirmation forte, réutilisée entre slides) ── */
.big-phrase {
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 800;
  color: var(--text-inv);
  line-height: 1.25;
  margin: var(--sp-3) 0 var(--sp-5);
  max-width: 640px;
}

.big-phrase .kw { color: var(--accent); }

/* ── VIDEO PAIR (deux vraies vidéos, côte à côte, sans chevauchement) ── */
.video-pair {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: var(--sp-4);
  align-items: start;
  width: 100%;
}

.video-pair__item { display: flex; flex-direction: column; gap: var(--sp-2); }

.video-pair__caption {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-inv-sec);
  text-align: center;
}

.video-pair .product-window { max-width: none; }

/* ── SIMULATOR HERO SHOT (preuve visuelle dominante, non superposée) ── */
.simulator-hero-shot {
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  border: 1px solid rgba(255,255,255,0.1);
  background: var(--bg-alt);
  transition: transform 300ms ease, box-shadow 300ms ease;
}

.simulator-hero-shot:hover {
  transform: translateY(-4px) scale(1.012);
  box-shadow: 0 20px 44px rgba(0,0,0,0.32), 0 4px 14px rgba(0,0,0,0.18);
}

.simulator-hero-shot img { width: 100%; display: block; aspect-ratio: 1024 / 415; object-fit: contain; }

.simulator-hero-caption {
  font-size: 11px;
  color: var(--text-inv-sec);
  text-align: center;
  margin-top: var(--sp-3);
  letter-spacing: 0.03em;
}

.code-window--minor {
  max-width: 100%;
  transform: scale(1);
}

.code-window--minor .code-window__body {
  font-size: 10.5px;
  padding: var(--sp-3) var(--sp-4);
  line-height: 1.5;
  max-height: 150px;
}

.code-window-caption {
  font-size: 10.5px;
  color: var(--text-inv-sec);
  margin-top: var(--sp-2);
  font-style: italic;
}

/* ── CODE WINDOW — variante "major" (le code devient la preuve principale) ── */
.code-window--major {
  max-width: 100%;
}

.code-window--major .code-window__body {
  font-size: 13.5px;
  line-height: 1.7;
  padding: var(--sp-5) var(--sp-6);
}

/* ── MINI PROOF STACK (2 petites preuves secondaires groupées) ── */
.mini-proof-stack {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.mini-proof-stack .code-window__body {
  font-size: 10px;
  padding: var(--sp-2) var(--sp-3);
  line-height: 1.5;
  max-height: 110px;
}

/* ── SITE GRID (composition asymétrique — 1 grande preuve + 2 secondaires) ── */
.site-grid {
  display: grid;
  grid-template-columns: 0.85fr 1.3fr;
  grid-template-rows: auto auto;
  gap: var(--sp-5) var(--sp-6);
  width: 100%;
}

.site-grid__text { display: flex; flex-direction: column; justify-content: center; }

/* ── CARD STACK (posts LinkedIn empilés comme sur une table) ── */
.card-stack {
  position: relative;
  width: 100%;
  max-width: 320px;
  aspect-ratio: 3/4;
  margin: 0 auto;
}

.card-stack__item {
  position: absolute;
  inset: 0;
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: 0 18px 40px rgba(0,0,0,0.35), 0 4px 10px rgba(0,0,0,0.2);
  border: 1px solid rgba(255,255,255,0.08);
  transition: transform 400ms ease, box-shadow 400ms ease;
}

.card-stack__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.card-stack:hover .card-stack__item {
  transform: translateY(-4px) scale(1.012) !important;
  box-shadow: 0 20px 44px rgba(0,0,0,0.32), 0 4px 14px rgba(0,0,0,0.18);
}

.card-stack__item:nth-child(1) { transform: rotate(-8deg) translate(-26%, 6%); z-index: 1; }
.card-stack__item:nth-child(2) { transform: rotate(6deg) translate(24%, 10%); z-index: 2; }
.card-stack__item:nth-child(3) { transform: rotate(-3deg) translate(-10%, -10%); z-index: 3; }
.card-stack__item:nth-child(4) { transform: rotate(5deg) translate(6px, -2px); z-index: 4; }
.card-stack__item:last-child { z-index: 5; }

.card-stack-group {
  display: flex;
  gap: var(--sp-10);
  flex-wrap: wrap;
  justify-content: center;
}

.card-stack-caption {
  text-align: center;
  font-size: 12px;
  color: var(--text-inv-sec);
  margin-top: var(--sp-4);
  letter-spacing: 0.02em;
}

/* ── STICKY NOTE — variante finale (grande, décalée, point focal de clôture) ── */
.sticky-note--outro {
  position: relative;
  z-index: 3;
  background: var(--bg-card);
  padding: var(--sp-8) var(--sp-8) var(--sp-6);
  width: min(90vw, 480px);
  box-shadow: 0 30px 70px rgba(0,0,0,0.35), 0 6px 16px rgba(0,0,0,0.15);
  transform: rotate(-2.4deg) translateX(-4%);
  font-family: var(--font-serif);
  margin: 0 auto;
}

.sticky-note--outro::before {
  content: '';
  position: absolute;
  top: -10px;
  left: 36px;
  width: 44px;
  height: 14px;
  background: rgba(176,107,69,0.28);
  transform: rotate(-4deg);
}

.sticky-note--outro .sticky-note__label {
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-3);
}

.sticky-note--outro .sticky-note__text {
  font-style: italic;
  font-size: clamp(17px, 1.9vw, 21px);
  line-height: 1.5;
  color: var(--text);
}

.sticky-note--outro .sticky-note__sign {
  font-family: var(--font-sans);
  font-style: normal;
  font-size: 12px;
  color: var(--text-sec);
  margin-top: var(--sp-4);
}

/* ── KEYWORD CLOUD (mots-clés dispersés, discrets, jamais une liste) ── */
.keyword-cloud {
  position: relative;
  width: 100%;
  max-width: 900px;
  height: 100%;
  pointer-events: none;
}

.keyword-cloud__item {
  position: absolute;
  font-weight: 700;
  color: var(--text-inv-sec);
  white-space: nowrap;
  letter-spacing: 0.02em;
}

/* ── OUTRO — dernière slide Ecofina, fond clair (vraie respiration) ── */
/* Repassée en panneau sombre (vrai papier noir texturé, même famille que
   Site/Personnalisation/Test-Scale) pour la conclusion — contraste et
   accent cuivre/beige chaud (--accent-hover) plutôt que le cyan des
   autres slides sombres : la conclusion referme la boucle sur le ton
   chaleureux du hero, pas sur l'identité technique du cyan. */
.track__panel--outro {
  padding-top: calc(var(--sp-16) + 16px);
  padding-bottom: var(--sp-8);
  background: #0A0806 url('../assets/images/hero/paper-black.png') center / cover no-repeat;
}

.track__panel--outro::before {
  --wl-blend: normal;
}

.track__panel--outro .track__panel-num {
  color: var(--accent-cyan);
}

.outro-grid {
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  gap: var(--sp-16);
  align-items: start;
  width: 100%;
}

.outro-punchline {
  font-size: clamp(28px, 3.6vw, 46px);
  font-weight: 800;
  line-height: 1.14;
  letter-spacing: -0.02em;
  color: var(--text-inv);
  margin-bottom: var(--sp-6);
}

.track__panel--outro .glass-capsule {
  color: var(--accent-cyan);
  border-color: rgba(0,167,173,0.4);
}

.track__panel--outro .outro-punchline .glass-capsule {
  font-family: inherit;
  font-style: normal;
  font-weight: inherit;
}

/* ── Composition de conclusion — magazine + post-it, ancrée en bas de
   la colonne gauche (align-items:end sur .outro-grid) pendant que la
   colonne de droite se déploie depuis le haut. Le magazine reste
   l'objet principal (posé, légèrement incliné, ombre douce) ; le
   post-it est un second objet physique distinct, "scotché" en haut à
   droite, sans jamais cacher la couverture. ── */
.outro-composition {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* fit-content (pas 100%) : la boîte se cale exactement sur la largeur
     du magazine (son plus large enfant) au lieu de rester étirée à
     320px — c'est ce qui permet au bouton CV de se centrer par rapport
     au magazine réel, pas par rapport à une colonne plus large que lui.
     Le magazine (déjà width:280px) ne bouge donc pas : il occupait déjà
     tout cet espace, aligné à gauche de la colonne. */
  width: fit-content;
  max-width: 320px;
}

/* Vrai visuel (rendu 3D du livre, perspective + ombre déjà intégrées
   dans le PNG) : pas de box-shadow/rotate/rayon ajoutés par-dessus, ça
   doublerait un effet déjà présent dans l'image elle-même. */
.outro-magazine {
  width: 280px;
}

.outro-magazine img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 300ms ease;
}

.outro-magazine:hover img {
  transform: translateY(-4px);
}

/* ── Colonne de droite enrichie : synthèse → à propos → compétences →
   CV → contact. Empilement compact (gap réduit) pour que l'ensemble
   tienne à 1600×760 sans que rien ne paraisse petit ou tassé. ── */
.outro-info {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.outro-steps {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3) var(--sp-4);
}

.outro-steps__item {
  font-size: 15px;
  font-weight: 800;
  color: var(--text-inv);
  letter-spacing: -0.01em;
}

.outro-steps__arrow {
  color: var(--accent-hover);
  opacity: 0.7;
  font-size: 14px;
}

.outro-about {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-inv-sec);
  max-width: 580px;
}

.outro-skills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 8px;
  max-width: 100%;
}

.outro-skill {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-strong);
  border: 1px solid rgba(201,130,103,0.4);
  background: rgba(201,130,103,0.1);
  border-radius: 999px;
  padding: 5px 13px;
  white-space: nowrap;
}

.outro-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

/* Sous le magazine, dans la colonne gauche : vraie respiration au-dessus
   pour ne pas coller au bord de l'objet posé. */
.outro-composition .outro-actions {
  margin-top: 40px;
}

/* ── CV — même famille visuelle que .glass-capsule (verre teinté cyan)
   mais à l'échelle d'un vrai bouton : c'est l'action principale de la
   colonne, elle doit se repérer immédiatement, cliquable et
   téléchargeable (voir attribut download dans le HTML). ── */
.outro-cv-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  background: rgba(0,167,173,0.14);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(0,167,173,0.5);
  color: var(--accent-cyan);
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 18px 44px;
  border-radius: 999px;
  box-shadow: 0 14px 30px rgba(0,167,173,0.2), 0 1px 1px rgba(255,255,255,0.14) inset;
  transition: transform 200ms ease, box-shadow 200ms ease, background 200ms ease;
}

.outro-cv-btn:hover {
  background: rgba(0,167,173,0.24);
  transform: translateY(-2px);
  box-shadow: 0 18px 38px rgba(0,167,173,0.3), 0 1px 1px rgba(255,255,255,0.16) inset;
}

/* ── Contact — Email + LinkedIn uniquement, en grand et bien contrasté :
   c'est la dernière chose que le visiteur lit, elle doit se lire sans
   effort (blanc cassé plein, jamais le gris secondaire de la colonne). ── */
.outro-contact {
  padding: 14px var(--sp-4);
  background: rgba(247,242,233,0.04);
  border: 1px solid rgba(247,242,233,0.12);
  border-radius: var(--r-md);
}

.outro-contact__grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.outro-contact__label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-hover);
  margin-bottom: 6px;
}

.outro-contact__item {
  display: inline-block;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink-strong);
  transition: color 200ms ease;
}

a.outro-contact__item:hover {
  color: var(--accent-cyan);
}

/* ── Apparition discrète du bloc CV + contact à l'arrivée sur la slide
   (arrivée normale ou via le défilement animé du lien Contact du
   header) — .is-active est déjà posé par setActivePanel() dans
   main.js, aucune logique supplémentaire nécessaire ici. ── */
.outro-reveal {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 280ms ease, transform 280ms ease;
}

.track__panel--outro.is-active .outro-reveal {
  opacity: 1;
  transform: translateY(0);
}

/* ── SYNTHESIS (dernier panneau du track) ── */
.synthesis-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-5);
  max-width: 620px;
}

.synthesis-item__label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--sp-1);
}

.synthesis-item__text {
  font-size: 13px;
  color: var(--text-inv-sec);
  line-height: 1.5;
}

/* ── FINAL NOTE (papier posé, pas une section contact) ── */
.final-note {
  padding: var(--sp-32) 0 var(--sp-24);
  background: var(--bg);
}

.final-note__paper {
  max-width: 420px;
  margin: 0 auto;
  background: var(--bg-card);
  padding: var(--sp-8) var(--sp-8);
  box-shadow: 0 20px 50px rgba(0,0,0,0.1), 0 4px 12px rgba(0,0,0,0.05);
  transform: rotate(-1.2deg);
  text-align: center;
}

.final-note__text {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(20px, 2.4vw, 26px);
  line-height: 1.5;
  color: var(--text);
}

.final-note__sign {
  color: var(--accent);
}

.final-note__cta {
  display: block;
  margin-top: var(--sp-8);
  text-align: center;
  font-size: 13px;
  color: var(--text-sec);
}

.final-note__cta a {
  color: var(--text);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}

.final-note__cta a:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* ============================================================
   RESPONSIVE
   ============================================================ */

@media (max-width: 1024px) {
  .skills-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .hero__inner {
    grid-template-columns: 1fr;
  }
  .hero__photo-col {
    order: -1;
    padding-right: 0;
    margin-bottom: var(--sp-4);
  }
  .hero__photo-col::before {
    display: none;
  }
  .hero__photo-caption {
    display: none;
  }
  .hero__photo-frame {
    max-width: 220px;
    aspect-ratio: 1/1;
    border-radius: 50%;
    box-shadow: var(--shadow-md);
  }
  .capability-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 768px), (max-height: 500px) {
  .container {
    padding: 0 var(--sp-5);
  }
  .nav__links, .nav__cta {
    display: none;
  }
  .nav__burger {
    display: flex;
  }
  .project-card__inner {
    grid-template-columns: 1fr;
    min-height: auto;
  }
  .project-card--reverse .project-card__inner {
    direction: ltr;
  }
  .project-card__visual {
    min-height: 240px;
    order: -1;
  }
  .skills-grid {
    grid-template-columns: 1fr;
  }
  .capability-grid {
    grid-template-columns: 1fr;
  }
  .proof-split {
    grid-template-columns: 1fr;
  }
  .hero-stats-grid {
    grid-template-columns: 1fr;
  }
  .hero-proof-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  /* Story track : pas de sticky horizontal sur mobile — fallback vertical fluide */
  .track__sticky {
    position: relative;
    height: auto;
    padding: var(--sp-10) 0;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .track__panel--hero {
    flex-direction: column;
    padding: 0 !important;
    background-position: center;
  }
  .track__panel--hero::before {
    background-size: 220% auto;
    background-position: 30% 15%;
  }
  .track__hero-portrait {
    flex: 0 0 auto;
    height: auto;
    padding-top: var(--sp-8);
  }
  .track__hero-portrait img {
    max-height: 46vh;
    max-width: 82%;
    /* Le scale(1.12) du desktop est repris par la version mobile empilée :
       pas d'overflow:hidden de hauteur fixe ici pour l'absorber proprement,
       donc on revient à l'animation d'entrée simple sans agrandissement. */
    animation: heroFadeUp 1000ms ease 100ms both;
  }
  .track__hero-text {
    padding: var(--sp-8) var(--sp-6) var(--sp-10);
    text-align: center;
    align-items: center;
  }
  .track__hero-statement {
    margin-left: auto;
    margin-right: auto;
  }
  .track__strip {
    flex-direction: column;
    height: auto;
    transform: none !important;
  }
  .track__panel {
    width: 100%;
    height: auto;
    padding: var(--sp-10) var(--sp-5);
    align-items: stretch;
  }
  .track__panel-media {
    max-height: 42vh;
  }
  .track__progress,
  .track__scroll-hint {
    display: none;
  }
  .split-panel {
    grid-template-columns: 1fr !important;
    gap: var(--sp-6);
  }
  .split-panel > * {
    min-width: 0;
  }
  .split-panel__photo {
    height: 34vh;
  }
  .duo-media {
    height: auto;
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
  }
  .duo-media__a,
  .duo-media__b {
    position: static;
    width: 100%;
    height: 30vh;
    border: none;
  }
  .editorial-split {
    grid-template-columns: 1fr !important;
    gap: var(--sp-6);
  }
  .editorial-split > * {
    min-width: 0;
  }
  .product-window {
    max-height: 34vh;
  }
  .product-window video,
  .product-window img {
    max-height: calc(34vh - 30px);
  }
  .diagnostic-photo {
    max-width: 160px;
    margin: 0 auto;
  }
  .diagnostic-photo__caption {
    text-align: center;
    margin: var(--sp-2) auto 0;
  }
  .card-stack-group {
    gap: var(--sp-16);
  }
  .card-stack {
    max-width: 220px;
  }
  .visibility-axes {
    grid-template-columns: 1fr;
    gap: var(--sp-8);
  }
  .visibility-flow {
    flex-direction: column;
    gap: var(--sp-2);
  }
  .simulator-proof-shot {
    display: none;
  }
  .code-window {
    max-width: 100%;
  }
  .video-pair {
    grid-template-columns: 1fr;
    gap: var(--sp-5);
  }
  .site-grid {
    grid-template-columns: 1fr;
  }
  .keyword-cloud {
    display: none;
  }
  .sticky-note--outro {
    transform: rotate(-1.5deg);
    width: 100%;
  }
  .outro-grid {
    grid-template-columns: 1fr;
    gap: var(--sp-8);
  }
  .grid-2col {
    grid-template-columns: 1fr !important;
  }
  .grid-2col > * {
    min-width: 0;
  }
  .test-scale-grid {
    grid-template-columns: 1fr !important;
    gap: var(--sp-6) !important;
  }
  .test-scale-grid > * {
    min-width: 0;
  }
  .test-scale-row {
    flex-direction: column !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    transform: none !important;
    gap: var(--sp-4) !important;
    margin: 0 0 var(--sp-8) 0 !important;
    text-align: center !important;
  }
  .test-scale-row > div {
    max-width: 100% !important;
    text-align: center !important;
    flex: none !important;
  }
  .test-scale-row .track__panel-sub {
    text-align: center !important;
  }
  .test-scale-row > div > div[style*="justify-content:flex-end"] {
    justify-content: center !important;
  }
  .site-grid {
    grid-template-columns: 1fr !important;
  }
  .site-grid > * {
    min-width: 0;
  }
  .site-montage-row {
    justify-content: center !important;
  }
  .site-montage-col {
    width: 80% !important;
    min-width: 0 !important;
    max-width: 320px !important;
  }
  .duo-window__minor,
  .floating-window--offset {
    position: static;
    width: 100%;
    margin-top: var(--sp-4);
    border: none;
  }
  .glass-capsule {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .open-book {
    grid-template-columns: 1fr;
    filter: none;
  }
  .open-book::before,
  .open-book::after {
    display: none;
  }
  .book-page--left,
  .book-page--right {
    transform: none;
    border-radius: var(--r-lg);
    box-shadow: 0 12px 30px rgba(20,17,14,0.18);
    margin-bottom: var(--sp-4);
    min-width: 0;
    padding: var(--sp-5);
  }
  .duo-window,
  .code-window,
  .floating-window {
    min-width: 0;
  }
  .editorial-card-grid {
    grid-template-columns: 1fr 1fr !important;
  }
  .outro-composition {
    max-width: 100%;
    margin: 0 auto;
  }
  .outro-magazine {
    margin: 0 auto;
  }
  .sticky-note {
    position: static;
    transform: rotate(-1.5deg);
    margin: var(--sp-5) auto 0;
  }
  .mindmap {
    width: 100%;
    aspect-ratio: auto;
  }
  .mindmap__svg {
    display: none;
  }
  .mindmap__node {
    position: static;
    display: block;
    width: 100%;
    margin: var(--sp-2) 0;
    opacity: 1;
    transform: none;
  }
  .mindmap__node::before {
    display: none;
  }
  .mindmap__center {
    position: static;
    transform: none;
    display: block;
    width: fit-content;
    margin: 0 auto var(--sp-6);
  }
  .synthesis-grid {
    grid-template-columns: 1fr;
  }

  /* ── Vidéos — jamais croppées sur mobile (object-fit:cover donnait un
     cadrage serré pensé pour le format desktop de chaque fenêtre) : on
     repasse en contain, la hauteur suit alors le ratio réel de la vidéo
     au lieu d'être forcée à 100% du conteneur. ── */
  .floating-window video {
    height: auto;
    object-fit: contain;
  }

  /* ── Logo "Mehdi" — sur le hero (nav transparent, texte blanc), le
     fond réel derrière peut être clair par endroits selon la photo :
     un petit fond stable évite tout texte blanc sur zone claire. Padding
     + margin négative égale : aucun décalage visuel de position, juste
     une zone de contraste garantie. Uniquement en dehors de .scrolled :
     une fois le nav opaque, le contraste est déjà assuré autrement. ── */
  .nav:not(.scrolled) .nav__logo {
    background: rgba(10, 8, 6, 0.5);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    padding: 4px 10px;
    margin: -4px -10px;
    border-radius: var(--r-md);
  }

  /* ── Ombres de fenêtre décoratives — sur mobile, chaque panneau passe
     en hauteur "auto" (empilement vertical) au lieu de 100vh : la photo
     de fond, positionnée en % pour un cadre desktop, ne tombe plus au
     même endroit et peut créer une bordure nette ou assombrir une zone
     de lecture. Masquée sur mobile plutôt que mal repositionnée slide
     par slide (l'ombre est purement décorative, jamais du contenu). Le
     hero garde son propre effet de lumière (::before dédié, déjà réglé
     pour mobile plus haut) : non concerné par cette liste. ── */
  .track__panel--wl-c,
  .track__panel--wl-crm,
  .track__panel--wl-personnalisation,
  .track__panel--wl-conversion,
  .track__panel--wl-test-scale,
  .track__panel--wl-automatisation,
  .track__panel--wl-outro,
  .track__panel--wl-simulateur,
  .track__panel--wl-contenu {
    --wl-opacity: 0;
  }

  /* ── Contact (dernière slide) — .outro-reveal reste à opacity:0 tant
     que .is-active n'est pas posé sur le panneau, or setActivePanel()
     (seul code qui pose .is-active) n'est jamais appelé sur mobile :
     initTrack() s'arrête avant, faute de scroll-jack. Résultat : email/
     téléphone/LinkedIn restaient invisibles en permanence. Rendu visible
     directement sur mobile, sans attendre un événement qui n'arrive
     jamais ici. ── */
  .outro-reveal {
    opacity: 1;
    transform: none;
  }

  /* Zone tactile confortable (~44px) sur les liens de contact, sans
     changer leur taille de texte ni leur apparence. */
  .outro-contact__item {
    padding: 11px 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .track__sticky {
    position: relative;
    height: auto;
  }
  .track__strip {
    flex-direction: column;
    height: auto;
    transform: none !important;
  }
  .track__panel {
    width: 100%;
    height: auto;
    padding: var(--sp-10) var(--sp-8);
  }
  .mindmap.is-active .mindmap__node,
  .mindmap__node {
    opacity: 1;
  }
  .mindmap.is-active .mindmap__svg path,
  .mindmap__svg path {
    stroke-dashoffset: 0;
  }
}
