:root {
  /* ===== Brand accents — constant across themes ===== */
  --accent: #ff004f;          /* portfolio */
  --accent-ms: #f7c948;       /* Microsoft (fills/borders) */
  --accent-ms-2: #ffd861;     /* Microsoft hover gold */
  --accent-ms-text: var(--accent-ms); /* Microsoft text — darkens in light theme for AA */
  --on-accent: #fff;          /* text/icons sitting on a filled accent surface */

  /* ===== Theme tokens (dark = default; light overrides in [data-theme="light"]) ===== */
  --bg: #080808;
  --text: #fff;
  --text-muted: #ababab;
  --surface: #262626;                       /* solid cards / inputs */
  --surface-raised: rgba(255, 255, 255, 0.04); /* elevated panels/tints */
  --surface-sunken: rgba(0, 0, 0, 0.3);     /* sunken inset backgrounds */
  --border: rgba(255, 255, 255, 0.12);
  --border-soft: rgba(255, 255, 255, 0.06);
  --border-line: #130f0f;                   /* footer / pagination */
  --grid-line: rgba(255, 255, 255, 0.05);   /* report-canvas grid */
  --img-outline: #fff;                      /* about photo outline */
  --shadow-card: none;                      /* dark = pas d'ombre (bord + lueur) ; light = ombre douce */

  /* ===== Spacing scale (4 / 8px grid) ===== */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 80px;
  --space-10: 100px;

  /* ===== Radius scale ===== */
  --radius-xs: 6px;
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 16px;
  --radius-2xl: 18px;
  --radius-3xl: 20px;
  --radius-pill: 999px;

  /* ===== Type scale (ratio ~1.18) ===== */
  --fs-300: 0.8rem;    /* ~13px — captions / meta */
  --fs-400: 1rem;      /* 16px — body */
  --fs-500: 1.125rem;  /* 18px */
  --fs-600: 1.375rem;  /* 22px */
  --fs-700: 1.625rem;  /* 26px */
  --fs-800: 3rem;      /* 48px — h2 / section titles */
  --fs-900: 3.5rem;    /* 56px — h1 */
  --lh-tight: 1.15;
  --lh-base: 1.6;
}

/* ===== Light theme — overrides only the theme tokens (accents stay constant) ===== */
[data-theme="light"] {
  /* Light = SA PROPRE palette chaude (blanc cassé + rose profond + ambre), pas le dark
     inversé. Profondeur par surfaces contrastées + ombres douces — pas de lueurs. */
  --bg: #faf9f7;              /* blanc cassé chaud, premium */
  --text: #1a1613;           /* presque-noir chaud */
  --text-muted: #605850;     /* gris chaud, ~6:1 sur --bg (AA) */
  --surface: #ffffff;        /* cartes/inputs pleins (blanc → flottent sur le fond) */
  --surface-raised: #ffffff; /* panneaux élevés = blanc + ombre (profondeur) */
  --surface-sunken: #efece8; /* creux : un cran plus chaud/sombre que le fond */
  --border: rgba(26, 22, 19, 0.14);
  --border-soft: rgba(26, 22, 19, 0.08);
  --border-line: rgba(26, 22, 19, 0.12);
  --grid-line: rgba(26, 22, 19, 0.06);
  --img-outline: rgba(26, 22, 19, 0.16);
  --accent: #d11346;         /* ROSE profond : vif mais AA-lisible sur clair (fini le fluo qui vibre) */
  --accent-ms: #c6912e;      /* OR → ambre riche : le dégradé rose→or ne s'efface plus sur clair */
  --accent-ms-text: #7a5e00; /* ambre assombri pour l'or en TEXTE pur */
  --shadow-card: 0 1px 2px rgba(26, 22, 19, 0.05), 0 16px 34px -16px rgba(26, 22, 19, 0.17);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Visually hidden but available to screen readers */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: "Poppins", sans-serif;
  overflow-x: hidden;
}

/*HEADER*/

.container {
  max-width: 1520px; /* cappe + centre sur grand écran (≤1520 : inchangé, gouttière 10%) */
  margin: 0 auto;
  padding: 10px 10%;
}

.header-sticky {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  position: fixed;
  width: 100%;
  height: 72px;
  padding: 0 clamp(20px, 5vw, 64px);
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  top: 0;
  left: 0;
  z-index: 200;
  transition: height 0.3s ease, background 0.3s ease, border-color 0.3s ease;
}
/* Subtle scroll state: shorter, a touch more opaque, hairline border */
.header-sticky.scrolled {
  height: 58px;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  border-bottom-color: var(--border);
}

/* Hero glow — a single, discreet rose touch that slowly breathes. Kept low so
   the dark background stays clean and contrasted; readability comes first. */
:root {
  --hero-glow: rgba(255, 0, 79, 0.11);
}
[data-theme="light"] {
  --hero-glow: transparent; /* light : pas de lueur colorée (fait délavé/sale) → profondeur par ombres */
}

.header {
  position: relative;
  overflow: hidden; /* clip the soft glow to the hero band */
  width: 100%;
  min-height: 100vh;
  background: var(--bg);
  margin-bottom: 100px;
  display: flex;
  align-items: center;
  padding-top: 69px; /* clear the fixed nav bar */
}

/* One soft, low-opacity glow that drifts and breathes very slowly — alive but
   never busy, and it doesn't muddy the clean surface. GPU transforms only. */
.header::before {
  content: "";
  position: absolute;
  z-index: 0;
  aspect-ratio: 1;
  width: min(56vw, 700px);
  right: -6vw;
  top: -8vw;
  border-radius: 50%;
  filter: blur(64px);
  pointer-events: none;
  background: radial-gradient(circle, var(--hero-glow), transparent 68%);
  animation: hero-glow-drift 24s ease-in-out infinite alternate;
}
@keyframes hero-glow-drift {
  from {
    transform: translate3d(0, 0, 0) scale(1);
    opacity: 0.6;
  }
  to {
    transform: translate3d(-5%, 6%, 0) scale(1.14);
    opacity: 1;
  }
}

/* ===================================================================
   FONDS — « souffle » unifié. Une nappe unique derrière tout le contenu
   sous le hero (#about enveloppe about/parcours/projets/contact/footer) :
   des lueurs rose→or DÉCALÉES verticalement créent un rythme lumineux au
   scroll. Très subtil (opacité 6-9%), feutré (transitions douces), GPU
   (opacité), jamais sur le texte (::before, z-index négatif, pointer-events
   none). reduced-motion → la respiration se calme.
   =================================================================== */
#about {
  position: relative;
  isolation: isolate; /* la lueur reste derrière le contenu de #about, au-dessus du noir */
}
#about::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  will-change: opacity;
  background:
    radial-gradient(50% 28% at 84% 5%, color-mix(in srgb, var(--accent) 4%, transparent), transparent 54%),
    radial-gradient(54% 28% at 10% 27%, color-mix(in srgb, var(--accent-ms) 3%, transparent), transparent 56%),
    radial-gradient(54% 30% at 90% 54%, color-mix(in srgb, var(--accent) 4%, transparent), transparent 54%),
    radial-gradient(50% 28% at 12% 80%, color-mix(in srgb, var(--accent-ms) 3%, transparent), transparent 56%);
  animation: page-breathe 16s ease-in-out infinite alternate;
}
@keyframes page-breathe {
  from { opacity: 0.45; }
  to { opacity: 0.8; }
}
/* Light : les radiales colorées (rose/or à 3-4%) font délavé/sale sur clair — coupées.
   La profondeur vient des surfaces contrastées + ombres douces. */
[data-theme="light"] #about::before {
  display: none;
}
@media (prefers-reduced-motion: reduce) {
  #about::before { animation: none; opacity: 0.65; }
}

.nom {
  font-size: 25px;
}

.nom a {
  text-decoration: none;
  color: inherit;
}

/* Logo wordmark — Archivo, tight; the P/S initials carry the brand rose */
.nom-text {
  font-family: "Archivo", var(--body, sans-serif);
  font-size: 1.2em;
  font-weight: 800;
  letter-spacing: -0.01em;
  margin: 0;
  transition: opacity 0.2s ease;
}
.nom a:hover .nom-text {
  opacity: 0.82;
}

span {
  color: var(--accent);
}

nav {
  font-size: 19px;
  display: flex;
  align-items: center;
}

nav ul {
  display: flex;
  align-items: center;
  gap: 8px;
}

nav ul li {
  list-style: none;
  display: inline-block;
  margin: 0;
}

nav a {
  text-decoration: none;
  color: var(--text-muted);
  position: relative;
  padding: 7px 14px;
  letter-spacing: 0.01em;
  transition: color 0.2s ease;
}

nav a:hover {
  color: var(--text);
}

/* Rose->gold underline that grows from the left; also shown on the active link */
nav ul li a::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}

nav ul li a:hover::after,
nav ul li a.active-link::after {
  transform: scaleX(1);
}

nav ul li a.active-link {
  color: var(--text);
}

.header-text {
  position: relative;
  z-index: 1; /* above the animated glow */
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 6vh clamp(24px, 6vw, 80px) 8vh;
  color: var(--text);
}

/* Subtle scroll effect: the hero copy gently rises and fades as you scroll
   down — a clean, discreet take on the old header feel. Scroll-driven (runs
   on the compositor, 60fps) and progressive: browsers without scroll timelines
   simply skip it. Disabled under reduced-motion. */
@media (prefers-reduced-motion: no-preference) and (min-width: 769px) {
  @supports (animation-timeline: scroll()) {
    .header-text {
      animation: hero-dissolve linear both;
      animation-timeline: scroll(root);
      animation-range: 0 82vh;
      will-change: transform, opacity, filter;
    }
    @keyframes hero-dissolve {
      to {
        opacity: 0.05;
        transform: scale(0.93) translateY(26px);
        filter: blur(6px);
      }
    }
  }
}

/* Mono eyebrow with a bichromy accent bar (fil rouge rose -> or) */
.hero-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 30px;
}
.hero-eyebrow::before {
  content: "";
  width: 40px;
  height: 2px;
  background: linear-gradient(
    90deg,
    var(--accent),
    var(--accent-ms),
    var(--accent)
  );
  background-size: 300% 100%;
  animation: hero-bar 4.5s ease-in-out infinite alternate;
}
@keyframes hero-bar {
  to {
    background-position: 100% 0;
  }
}

.hero-cue {
  margin-top: 54px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 12px;
}
.hero-cue::before {
  content: "";
  width: 1px;
  height: 32px;
  background: linear-gradient(var(--accent), transparent);
}

/* Progressive reveal (motion.js adds .in when the element scrolls in) */
.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s cubic-bezier(0.2, 0.8, 0.2, 1),
    transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.reveal.in {
  opacity: 1;
  transform: none;
}
/* Title rises from behind a mask on load — CSS-only, so it ALWAYS ends visible.
   The default state (and reduced-motion / no-JS) is fully shown; the hidden
   offset exists ONLY during the keyframe (fill: both starts low, ends at 0).
   Not tied to JS/IntersectionObserver (which mis-fires under overflow clip). */
.hero-title-mask {
  display: block;
  overflow: hidden;
  padding-bottom: 0.12em; /* room so the gradient/descenders aren't clipped */
}
@media (prefers-reduced-motion: no-preference) {
  .header-text h1 {
    animation: hero-title-rise 0.9s 0.25s cubic-bezier(0.19, 1, 0.22, 1) both;
  }
  @keyframes hero-title-rise {
    from {
      transform: translateY(112%);
    }
    to {
      transform: translateY(0);
    }
  }
}

/* Load cascade timing for the fading elements (eyebrow / sub / cue) */
.hero-eyebrow.reveal {
  transition-delay: 0.1s;
}
.header-sub.reveal {
  transition-delay: 0.46s;
}
.hero-cue.reveal {
  transition-delay: 0.58s;
}
@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .header-text h1 span,
  .hero-eyebrow::before,
  .header::before {
    animation: none;
  }
}

/*ABOUT*/

#about {
  padding: 0px 0;
  color: var(--text-muted);
}

.row {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  margin-top: 80px;
}

/* ===== About — editorial story: text left · portrait right =====
   (visual details for .about-headline etc. live after .sub-title so the
   headline overrides the generic .sub-title font/colour in the cascade.) */
.about-story {
  flex-basis: 100%;
  width: 100%;
  display: grid;
  grid-template-columns: 1.12fr 0.88fr; /* balanced — photo has presence, text leads */
  grid-template-areas: "intro photo" "copy photo"; /* DOM order = ordre mobile (titre→photo→récit) */
  column-gap: clamp(36px, 5vw, 72px);
  row-gap: 0;
  align-items: start; /* photo top lines up with the "À propos" eyebrow */
}
.about-intro { grid-area: intro; }
.about-photo { grid-area: photo; }
.about-copy { grid-area: copy; }

/* ===== PARCOURS — its own section after About (eyebrow + title + the 4 tabs). ===== */
#parcours {
  flex-basis: 100%;
  width: 100%;
  margin-top: clamp(96px, 14vw, 170px); /* generous inter-section breathing */
  margin-bottom: clamp(64px, 9vw, 120px); /* breathing before Projects */
  scroll-margin-top: 90px; /* clears the sticky header on nav-jump */
}
/* Section marker — a mono eyebrow, coherent with the site's other eyebrows. */
.prc-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: var(--fs-300);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 26px;
}
.prc-eyebrow::before {
  content: "";
  width: 38px;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
}
/* One-shot arrival cascade: eyebrow → selector (→ the content cascades on its own). */
#parcours .prc-eyebrow.reveal {
  transition-delay: 0.03s;
}
#parcours .tab-title.reveal {
  transition-delay: 0.16s;
}
.about-panels {
  width: 100%;
}

/* Discrete availability line — light touch, never a headline (see DECISIONS). */
.about-availability {
  margin-top: 16px;
  font-size: var(--fs-300);
  color: var(--text-muted);
  font-style: italic;
}

.sub-title {
  font-size: var(--fs-800);
  font-weight: 600;
  color: var(--text);
  margin-bottom: 30px;
  line-height: var(--lh-tight);
}

/* ===== About story — visual layer (defined after .sub-title on purpose) ===== */

/* Eyebrow — mono kicker; its gradient rule DRAWS ITSELF when it reveals in. */
.about-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: var(--fs-300);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 22px;
}
.about-eyebrow::before {
  content: "";
  width: 0;
  height: 2px;
  flex: 0 0 auto;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  transition: width 0.6s 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.about-eyebrow.rv-in::before {
  width: 38px;
}

/* Narrative headline — Archivo poster weight (overrides .sub-title) */
.about-headline {
  font-family: "Archivo", var(--body, sans-serif);
  font-weight: 900;
  font-size: clamp(30px, 3.8vw, 50px);
  line-height: 1.02;
  letter-spacing: -0.02em;
  margin-bottom: 26px;
}

.about-body {
  max-width: 60ch;
  color: var(--text-muted);
  font-size: var(--fs-500);
  line-height: 1.8;
  font-weight: 300;
}
/* Highlighted terms — rose = products · gold = Microsoft · strong = throughline.
   Gold uses --accent-ms-text so it stays AA-legible in the light theme. */
.about-body .hl-rose {
  color: var(--accent);
  font-weight: 500;
}
.about-body .hl-gold {
  color: var(--accent-ms-text);
  font-weight: 500;
}
.about-body .hl-strong {
  color: var(--text);
  font-weight: 500;
}
@media (hover: hover) {
  .about-body .hl-rose,
  .about-body .hl-gold {
    transition: text-shadow 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
  }
  /* Quiet, tight halo — a subtle lift rather than a glow bloom. */
  .about-body .hl-rose:hover {
    text-shadow: 0 0 9px color-mix(in srgb, var(--accent) 45%, transparent);
  }
  .about-body .hl-gold:hover {
    text-shadow: 0 0 9px color-mix(in srgb, var(--accent-ms) 45%, transparent);
  }
}

/* ---- Portrait column ---- */
.about-photo {
  position: relative;
  max-width: 440px; /* keep the portrait + accent balanced against the text */
  justify-self: end; /* push right: airs out the left text, fills the right space */
}

/* Registration-mark accent: the colour plate peeks out to the RIGHT (generous)
   and a generous band at the BOTTOM — a printer's mis-registration. The frame
   (and its plate) carry the continuous parallax drift; --parallax is inherited
   from .about-photo. The caption tracks the same drift so spacing stays fixed. */
.about-frame {
  position: relative;
  z-index: 0;
  transform: translateY(var(--parallax, 0));
  will-change: transform;
}
/* The colour plate GROWS on hover (see below) — its transform-origin sits at the
   photo centre so it expands outward evenly past the right/bottom edges. */
.about-frame::before {
  content: "";
  position: absolute;
  inset: 14px -20px -18px 14px; /* top · right(overflow) · bottom(generous) · left */
  background: linear-gradient(135deg, var(--accent), var(--accent-ms));
  border-radius: var(--radius-xl); /* soft radius — matches the project cards */
  opacity: 0.85;
  transform-origin: top left; /* grows toward the bottom-right → offset stays visible */
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.5s ease;
}
/* Mask = the photo + its border (the "cadre"). It carries the hover zoom, so the
   frame zooms WITH the photo; overflow:hidden clips the image, never the plate. */
.about-mask {
  position: relative;
  z-index: 1;
  overflow: hidden;
  border-radius: var(--radius-xl); /* soft, elegant — coherent with cards */
  border: 1px solid var(--img-outline);
  transform-origin: top left; /* same anchor as the plate → décalage held while zooming */
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1); /* in sync with the halo */
}
/* Natural framing — no scroll transform on the image itself. */
.about-portrait {
  display: block;
  width: 100%;
}
/* Hover — mirrors the design-sample intent: the photo (with its frame) zooms in
   while the offset colour plate GROWS behind it, so the décalage stays clearly
   visible the whole time. */
@media (hover: hover) {
  /* Both move together (same timing, no delay); the halo just zooms a touch more
     than the photo and, anchored top-left, keeps growing offset bottom-right. */
  .about-photo:hover .about-mask {
    transform: scale(1.05);
  }
  .about-photo:hover .about-frame::before {
    transform: scale(1.09); /* slightly larger zoom than the photo, stays offset */
    opacity: 1;
  }
}
/* Caption — mono, OFF the gradient band, given real air below the photo, and it
   rides the same parallax so the gap to the plate never collapses. */
.about-cap {
  position: relative;
  z-index: 1;
  margin-top: 34px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  transform: translateY(var(--parallax, 0));
}

/* ---- CV — ghost button: thin rose outline; on hover a rose fill WIPES in from
   the left (behind the label) and a download arrow nudges down. ---- */
.btn-cv {
  position: relative;
  isolation: isolate; /* own stacking context so the fill sits behind the label */
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 32px;
  padding: 13px 30px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-xs); /* same radius as the site's other buttons */
  background: transparent;
  color: var(--text);
  font-weight: 500;
  text-decoration: none;
  transition: color 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.btn-cv::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--accent);
  transform: translateX(-101%);
  transition: transform 0.45s cubic-bezier(0.65, 0, 0.35, 1);
}
.btn-cv::after {
  content: "↓";
  font-size: 0.95em;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.btn-cv:hover,
.btn-cv:focus-visible {
  color: var(--on-accent);
}
.btn-cv:hover::before,
.btn-cv:focus-visible::before {
  transform: translateX(0);
}
.btn-cv:hover::after,
.btn-cv:focus-visible::after {
  transform: translateY(3px);
}
@media (prefers-reduced-motion: reduce) {
  .btn-cv::before {
    transition: none;
  }
}

/* ---- Reveal — ONE-SHOT entrance. .rv starts hidden; the observer adds .rv-in
   once (then unobserves), so the story eases in on first arrival and stays put.
   Slow, soft ease-out for a posed, fluid cascade. ---- */
.rv {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 1.05s cubic-bezier(0.22, 1, 0.36, 1),
    transform 1.05s cubic-bezier(0.22, 1, 0.36, 1);
}
.rv.rv-in {
  opacity: 1;
  transform: none;
}
/* Stagger — eyebrow → titre → récit → dispo → CV (photo rides alongside). */
.about-eyebrow.rv {
  transition-delay: 0.05s;
}
.about-photo.rv {
  transition-delay: 0.14s;
}
.about-headline.rv {
  transition-delay: 0.2s;
}
.about-body.rv {
  transition-delay: 0.38s;
}
.about-availability.rv {
  transition-delay: 0.56s;
}
.btn-cv.rv {
  transition-delay: 0.7s;
}
@media (prefers-reduced-motion: reduce) {
  .rv {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .about-eyebrow::before {
    width: 38px;
    transition: none;
  }
}

/* ---- Scroll-EXIT — variant B: directional lateral "peel / slide" (validated).
   As the story leaves the top: the text slides LEFT + fades, the photo PEELS to
   the RIGHT (slide + micro-rotation), and the halo drifts a touch further right —
   the composition opens in two. Same family as the hero (fade + fluid movement),
   tuned to this dense layout instead of a global zoom-back.
   Driven by a view-timeline SHARED on .about-story so text/photo/halo stay in
   sync. animation-fill-mode:forwards is the key: the animations do NOT fill BEFORE
   the exit range, so the one-shot entrance (transitions on the same elements) and
   the photo hover both play untouched — the exit only takes over as it leaves.
   Progressive + reduced-motion safe: no scroll-timeline → nothing moves. ---- */
@media (prefers-reduced-motion: no-preference) and (min-width: 769px) {
  @supports (animation-timeline: view()) {
    .about-story {
      view-timeline-name: --about-story;
      view-timeline-axis: block;
    }
    .about-copy,
    .about-photo,
    .about-frame::before {
      animation-timeline: --about-story;
      animation-range: exit 0% exit 100%;
      animation-fill-mode: forwards; /* no fill before exit → entrance + hover intact */
      animation-timing-function: linear;
      will-change: opacity, transform, filter;
    }
    .about-copy {
      animation-name: about-exit-copy;
    }
    .about-photo {
      animation-name: about-exit-photo;
    }
    .about-frame::before {
      animation-name: about-exit-halo;
    }
    /* text glides left */
    @keyframes about-exit-copy {
      to {
        opacity: 0;
        transform: translate(-54px, -14px);
        filter: blur(3px);
      }
    }
    /* photo peels right + micro-rotation */
    @keyframes about-exit-photo {
      to {
        opacity: 0;
        transform: translate(52px, -8px) rotate(1.4deg);
        filter: blur(2px);
      }
    }
    /* halo drifts a touch further right — separates from the photo */
    @keyframes about-exit-halo {
      to {
        opacity: 0.2;
        transform: translate(34px, 6px) scale(1.03);
      }
    }
  }
}

/* ---- ABOUT — tablette/mobile : empilé titre → photo → récit (grid-areas). ---- */
@media (max-width: 768px) {
  .about-story {
    grid-template-columns: 1fr;
    grid-template-areas: "intro" "photo" "copy"; /* titre → photo → récit+CV */
    row-gap: clamp(22px, 6vw, 36px);
  }
  .about-headline {
    font-size: clamp(28px, 6.5vw, 44px);
  }
  .about-photo {
    max-width: min(320px, 78%);
    justify-self: center;
    margin: 2px auto 0;
  }
  .about-frame::before {
    inset: 12px -12px -12px 12px; /* halo moins débordant → pas de scroll horizontal */
  }
  .about-frame,
  .about-cap {
    transform: none; /* parallax coupé sur mobile (perf + n'a pas de sens en empilé) */
    will-change: auto;
  }
  .about-body {
    max-width: none;
    font-size: 16px;
  }
  .about-cap {
    margin-top: 26px;
    text-align: center;
  }
  .btn-cv {
    min-height: 44px; /* cible tactile */
  }
}

/* Poster headline — Archivo, affirmed, brand gradient on the accent word */
.header-text h1 {
  font-family: "Archivo", var(--body, sans-serif);
  font-weight: 900;
  font-size: clamp(44px, 7vw, 92px);
  line-height: 0.98;
  letter-spacing: -0.03em;
  max-width: 15ch;
}
/* Living rose->gold gradient with a slow light band sweeping across it */
.header-text h1 span {
  background: linear-gradient(
    110deg,
    var(--accent) 0%,
    var(--accent-ms) 38%,
    #fff2cf 50%,
    var(--accent-ms) 62%,
    var(--accent) 100%
  );
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: hero-idees 8s ease-in-out infinite alternate;
}
@keyframes hero-idees {
  from {
    background-position: 160% 0;
  }
  to {
    background-position: -60% 0;
  }
}

/* h1 always outranks h2 on the Microsoft detail heroes (h1.sub-title) */
h1.sub-title {
  font-size: var(--fs-900);
  line-height: var(--lh-tight);
}

.header-sub {
  font-size: var(--fs-500);
  line-height: 1.65;
  max-width: 52ch;
  margin-top: 34px;
  color: var(--text-muted);
  font-weight: 300;
}


/* Editorial "Filet" selector — variante A. Typo only (no pill/fill): uppercase
   JetBrains Mono labels sitting on a full-width hairline; the active tab is marked
   by a thin rose→gold underline that GLIDES to it (width = the label's), like the
   header's scroll-spy. Inactive muted → white on hover. JS positions .tab-ind. */
.tab-title {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(20px, 4vw, 44px);
  margin: 0 0 34px;
  /* TEST — no full-width rule under the tabs; the gliding rose→gold filet
     (.tab-ind) is the only active marker. */
}

/* The gliding rose→gold filet — width/position set by positionTabIndicator(). */
.tab-ind {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 2px;
  opacity: 0;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  pointer-events: none;
  transition: transform 0.42s cubic-bezier(0.2, 0.8, 0.2, 1),
    width 0.42s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.3s ease;
}

.tab-links {
  margin: 0;
  white-space: nowrap;
  cursor: pointer;
  font-family: "JetBrains Mono", monospace;
  font-weight: 600;
  font-size: 15.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 2px 2px 18px;
  transition: color 0.3s ease;
}

.tab-links:hover {
  color: var(--text);
}

.tab-links.active-link {
  color: var(--text);
}

.tab-content {
  display: none;
  /* Visible so the skills line-drift + section-exit peel aren't clipped. The mobile
     tab-slider does its clipping on .tab-panels (which keeps overflow:hidden), so
     this doesn't affect the mobile panel switching. */
  overflow: visible;
}

.tab-content.active-tab {
  display: block;
}

.tab-panels {
  position: relative;
  width: 100%;
  transition: height 0.35s ease;
}

.tab-panels-track {
  width: 100%;
}

/* ===================================================================
   SKILLS — direction ③ « Sur la Ligne » : bandes typo + révélation « Seuil ».
   CONTENU du 1er onglet (Compétences), rendu par displaySkills dans .tab-content.skills.
   Composant uniforme (les 5 groupes rendus à l'identique) ; fil rouge rose→or pour
   tous, Microsoft en OR (--c bascule) ; TEXTE ONLY.
   =================================================================== */
.skl-bands {
  /* No top rule — the selector's hairline (its border-bottom) already separates,
     otherwise the two lines would double up. */
  margin-top: 4px;
}
/* One uniform band per group. --c = rose by default; Microsoft flips to gold. */
.skl-band {
  --c: var(--accent);
  position: relative;
  padding: 34px 0 34px; /* more air around the separators */
  view-timeline-name: --sklband;
  view-timeline-axis: block;
  outline: none;
  /* one-shot entrance (a local observer adds .in — see displaySkills) */
  opacity: 0;
  transform: translateY(16px); /* subtle arrival */
  transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
/* Separator: full-width hairline between bands. */
.skl-band:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--border);
}
.skl-band[data-hat="ms"] {
  --c: var(--accent-ms);
}
.skl-band[tabindex] {
  cursor: pointer;
}
.skl-band.in {
  opacity: 1;
  transform: none;
}
.skl-band:focus-visible {
  outline: 2px solid var(--c);
  outline-offset: 6px;
  border-radius: 6px;
}
.skl-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-weight: 600;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.skl-eyebrow::before {
  content: "";
  width: 26px;
  height: 2px;
  background: linear-gradient(90deg, var(--c), var(--accent-ms));
}
/* Flagships — the interface IS the type. */
.skl-line {
  font-family: "Archivo", var(--body, sans-serif);
  font-weight: 900;
  font-size: clamp(26px, 5.2vw, 58px);
  line-height: 1.02;
  letter-spacing: -0.02em;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35em;
  align-items: baseline;
  will-change: transform;
}
.skl-anchor {
  background: linear-gradient(110deg, var(--c), var(--accent-ms) 42%, #fff2cf 50%, var(--accent-ms) 58%, var(--c));
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.skl-sep {
  color: var(--text-muted);
  font-weight: 700;
  font-size: 0.5em;
  align-self: center;
}

/* Resting invitation — the secondaries are HIDDEN; this signals there's more. */
.skl-invite {
  margin-top: 16px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: 22px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.skl-invite-rule {
  width: 26px;
  height: 2px;
  background: linear-gradient(90deg, var(--c), var(--accent-ms));
  transition: width 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.skl-invite-n {
  font-weight: 600;
  background: linear-gradient(90deg, var(--c), var(--accent-ms));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.skl-invite-txt {
  text-transform: uppercase;
}
.skl-invite-arw {
  color: var(--c);
}
.skl-band:hover .skl-invite,
.skl-band:focus-visible .skl-invite,
.skl-band.lit .skl-invite {
  opacity: 0;
  transform: translateY(-4px);
}
.skl-band:hover .skl-invite-rule {
  width: 44px;
}

/* Hidden → revealed detail (grid-rows, no height jump). */
.skl-detail {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.55s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.skl-band:hover .skl-detail,
.skl-band:focus-visible .skl-detail,
.skl-band.lit .skl-detail {
  grid-template-rows: 1fr;
}
.skl-inner {
  min-height: 0;
  overflow: hidden;
}
/* One clean colour cue: a single rose→or vertical rule (no per-word underline). */
.skl-row {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 13px 26px;
  padding: 8px 0 4px 18px;
}
.skl-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 6px;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--c), var(--accent-ms));
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.skl-band:hover .skl-row::before,
.skl-band:focus-visible .skl-row::before,
.skl-band.lit .skl-row::before {
  transform: scaleY(1);
}
/* Each secondary: a slow, wide rose→or ignition sweeps through, then the word
   settles on --text (legible in both themes — colour only PASSES through). */
.skl-g {
  font-family: "JetBrains Mono", monospace;
  font-weight: 500;
  font-size: 13.5px;
  letter-spacing: 0.06em;
  background: linear-gradient(100deg, var(--text) 0 38%, var(--c) 44%, #fff2cf 50%, var(--accent-ms) 56%, var(--text) 62% 100%);
  background-size: 300% 100%;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: var(--text);
  -webkit-text-fill-color: transparent;
  transform: translateY(8px);
  transition: background-position 1.5s cubic-bezier(0.33, 0, 0.2, 1),
    transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.skl-band:hover .skl-g,
.skl-band:focus-visible .skl-g,
.skl-band.lit .skl-g {
  background-position: 0 0;
  transform: none;
}
.skl-g:nth-child(1) { transition-delay: 0.05s; }
.skl-g:nth-child(2) { transition-delay: 0.18s; }
.skl-g:nth-child(3) { transition-delay: 0.31s; }
.skl-g:nth-child(4) { transition-delay: 0.44s; }
.skl-g:nth-child(5) { transition-delay: 0.57s; }
.skl-g:nth-child(6) { transition-delay: 0.70s; }
.skl-g:nth-child(7) { transition-delay: 0.83s; }
.skl-g:nth-child(8) { transition-delay: 0.96s; }

/* Focus-pull — hovering one band eases the others' type back (depth of field).
   Only opacity of the line/eyebrow (never the band opacity, which entrance/exit own). */
@media (hover: hover) {
  .skl-bands:hover .skl-band:not(:hover) .skl-line,
  .skl-bands:hover .skl-band:not(:hover) .skl-eyebrow {
    opacity: 0.42;
    transition: opacity 0.4s ease;
  }
}

/* Signature scroll motion (same family as hero/about, a notch richer):
   featured lines DRIFT like tickets on a pass rail, the anchor sweeps rose→or, and
   each band PEELS off the top on exit (fade + lift + lateral drift + soft blur).
   The panel is overflow:visible on desktop so none of this is clipped; fill:forwards
   keeps the exit from fighting the one-shot entrance. */
@media (prefers-reduced-motion: no-preference) and (min-width: 769px) {
  @supports (animation-timeline: view()) {
    .skl-line {
      animation: skl-drift linear both;
      animation-timeline: --sklband;
      animation-range: cover 0% cover 100%;
    }
    .skl-band:nth-child(even) .skl-line {
      animation-name: skl-drift-r;
    }
    @keyframes skl-drift { from { transform: translateX(-1.2vw); } to { transform: translateX(1.2vw); } }
    @keyframes skl-drift-r { from { transform: translateX(1.2vw); } to { transform: translateX(-1.2vw); } }
    .skl-anchor {
      animation: skl-sweep linear both;
      animation-timeline: --sklband;
      animation-range: entry 20% cover 60%;
    }
    @keyframes skl-sweep { from { background-position: 160% 0; } to { background-position: -60% 0; } }
    .skl-band {
      animation: skl-exit linear both;
      animation-timeline: view();
      animation-range: cover 55% cover 100%;
      animation-fill-mode: forwards;
      will-change: opacity, transform, filter;
    }
    .skl-band:nth-child(even) {
      animation-name: skl-exit-r;
    }
    @keyframes skl-exit { to { opacity: 0; transform: translate(-2.4vw, -22px); filter: blur(4px); } }
    @keyframes skl-exit-r { to { opacity: 0; transform: translate(2.4vw, -22px); filter: blur(4px); } }
  }
}

/* Fail-safe / reduced-motion — everything visible & legible, secondaries open. */
@media (prefers-reduced-motion: reduce) {
  .skl-band {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .skl-detail {
    grid-template-rows: 1fr;
  }
  .skl-invite {
    display: none;
  }
  .skl-row::before {
    transform: scaleY(1);
  }
  .skl-g {
    background-position: 0 0;
    transform: none;
    transition: none;
  }
}

@media (max-width: 600px) {
  .skl-line {
    font-size: clamp(22px, 7vw, 30px);
  }
  .skl-row {
    gap: 12px 18px;
  }
}

/* ===================================================================
   REGISTRE — one "record row" component (Experience / Studies / Certifs),
   rendered by renderRegistre. Archivo title + org·place mono, a right-aligned
   mono date-spine, detail revealed on hover/focus/tap (rose→gold ignition →
   legible --text + a vertical filet). Same family as skills ③, text-only.
   =================================================================== */
.reg {
  margin-top: 4px;
}
.reg-item {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 24px;
  padding: 28px 2px;
  text-decoration: none;
  color: inherit;
  view-timeline-name: --reg;
  view-timeline-axis: block;
  outline: none;
  opacity: 0;
  transform: translateY(18px); /* subtle arrival */
  transition: opacity 0.85s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.85s cubic-bezier(0.22, 1, 0.36, 1);
}
.reg-item.in {
  opacity: 1;
  transform: none;
}
.reg-item:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--border);
}
.reg-item[tabindex] {
  cursor: pointer;
}
.reg-item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: 6px;
}
.reg-head {
  flex: 1 1 auto;
  min-width: 0;
}
.reg-titleline {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
}
.reg-tag {
  font-family: "JetBrains Mono", monospace;
  font-weight: 600;
  font-size: 11.5px;
  letter-spacing: 0.1em;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.reg-title {
  font-family: "Archivo", var(--body, sans-serif);
  font-weight: 700;
  font-size: clamp(19px, 2.5vw, 28px);
  line-height: 1.08;
  letter-spacing: -0.01em;
  color: var(--text);
  will-change: transform;
}
.reg-meta {
  margin-top: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.reg-cue {
  margin-left: 10px;
  color: var(--accent);
  opacity: 0.7;
  display: inline-block;
  transition: opacity 0.3s ease, transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.reg-item:hover .reg-cue,
.reg-item:focus-visible .reg-cue,
.reg-item.open .reg-cue {
  opacity: 0;
  transform: translateY(-3px);
}
/* Date-spine — mono tabular, right-aligned (aligns into a vertical column). */
.reg-side {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding-top: 6px;
}
.reg-dates {
  font-family: "JetBrains Mono", monospace;
  font-size: 13px;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* Revealed detail — grid-rows; rose→gold ignition settles to --text + vertical filet. */
.reg-detail {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.reg-item:hover .reg-detail,
.reg-item:focus-visible .reg-detail,
.reg-item.open .reg-detail {
  grid-template-rows: 1fr;
}
.reg-detail-in {
  min-height: 0;
  overflow: hidden;
}
.reg-drow {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  padding: 14px 0 2px 18px;
  max-width: 72ch;
}
.reg-drow::before {
  content: "";
  position: absolute;
  left: 0;
  top: 14px;
  bottom: 2px;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--accent), var(--accent-ms));
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.6s 0.06s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.reg-item:hover .reg-drow::before,
.reg-item:focus-visible .reg-drow::before,
.reg-item.open .reg-drow::before {
  transform: scaleY(1);
}
.reg-ignite {
  font-family: "JetBrains Mono", monospace;
  font-size: 13px;
  letter-spacing: 0.03em;
  line-height: 1.7;
  background: linear-gradient(100deg, var(--text) 0 36%, var(--accent) 43%, #fff2cf 50%, var(--accent-ms) 57%, var(--text) 64% 100%);
  background-size: 300% 100%;
  background-position: 100% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: var(--text);
  -webkit-text-fill-color: transparent;
  transform: translateY(8px);
  transition: background-position 1.5s cubic-bezier(0.33, 0, 0.2, 1),
    transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.reg-item:hover .reg-ignite,
.reg-item:focus-visible .reg-ignite,
.reg-item.open .reg-ignite {
  background-position: 0 0;
  transform: none;
}
.reg-ignite:nth-child(1) { transition-delay: 0.06s; }
.reg-ignite:nth-child(2) { transition-delay: 0.18s; }
.reg-ignite:nth-child(3) { transition-delay: 0.30s; }
.reg-ignite:nth-child(4) { transition-delay: 0.42s; }
.reg-ignite:nth-child(5) { transition-delay: 0.54s; }
.reg-ignite:nth-child(6) { transition-delay: 0.66s; }

/* Liste à puces optionnelle (ex. réalisations Avanade) — verticale, sous l'intro,
   marqueur carré rose→or, dans la DA du registre. Suit le thème (dark/light). */
.reg-bullets {
  flex-basis: 100%; /* pleine largeur dans le .reg-drow (flex) → passe sous l'intro */
  display: grid;
  gap: 10px;
  margin-top: 12px;
}
.reg-bullet {
  position: relative;
  padding-left: 20px;
  font-family: "Poppins", sans-serif;
  font-size: 14px;
  line-height: 1.55;
  font-weight: 300;
  color: var(--text-muted);
}
.reg-bullet::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 8px;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: linear-gradient(135deg, var(--accent), var(--accent-ms));
}

/* Lien de vérification ↗ (certifications) — DISTINCT du toggle : le survol/tap déploie
   le détail, le clic sur ↗ ouvre la vérif (nouvel onglet, stopPropagation en JS). */
.reg-verify {
  font-family: "JetBrains Mono", monospace;
  font-size: 15px;
  line-height: 1;
  color: var(--accent);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  border-radius: 6px;
  transition: color 0.25s, transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.reg-verify:hover,
.reg-verify:focus-visible {
  color: var(--accent-ms);
  transform: translate(2px, -2px);
}
@media (hover: none) {
  .reg-verify {
    min-width: 44px;
    min-height: 44px;
    padding: 11px;
  }
  .reg-side {
    align-items: center;
  }
}

/* Microsoft (data-hat="ms") → OR au lieu de rose→or, cohérent avec les compétences.
   Suit le thème (en light : --accent-ms = ambre, --accent-ms-text = or foncé). */
.reg-item[data-hat="ms"] .reg-cue {
  color: var(--accent-ms-text);
}
.reg-item[data-hat="ms"] .reg-drow::before {
  background: linear-gradient(180deg, var(--accent-ms), var(--accent-ms-text));
}
/* background-IMAGE (pas le shorthand) → garde le background-clip:text du base, sinon le
   dégradé remplit la boîte (rectangle) et le texte devient transparent/invisible. */
.reg-item[data-hat="ms"] .reg-ignite {
  background-image: linear-gradient(100deg, var(--text) 0 36%, var(--accent-ms) 44%, #fff2cf 50%, var(--accent-ms) 56%, var(--text) 64% 100%);
}
.reg-item[data-hat="ms"] .reg-verify {
  color: var(--accent-ms-text);
}
.reg-item[data-hat="ms"] .reg-verify:hover {
  color: var(--accent-ms);
}

/* Certifications — les titres sont plus longs (ex. "PL-900 — Power Platform
   Fundamentals") → un cran plus petits + interligne aéré → passe à la ligne
   proprement, pas de débordement. Détail (tags) un peu plus aéré. */
.tab-content.certifications .reg-title {
  font-size: clamp(17px, 2vw, 23px);
  line-height: 1.16;
}
.tab-content.certifications .reg-drow {
  gap: 12px 24px;
}

/* Scroll motion — subtle registre title drift + a per-ROW section-exit that mirrors
   the skills bands' peel (skl-exit), so BOTH tab contents leave the same way: each
   row files away as it scrolls off the top (lift + lateral drift + fade + soft blur),
   alternating direction. Viewport-sized rows → actually visible (unlike a whole-tall-
   section dissolve). fill:forwards so it never fights the one-shot entrance. */
@media (prefers-reduced-motion: no-preference) and (min-width: 769px) {
  @supports (animation-timeline: view()) {
    .reg-title {
      animation: reg-drift linear both;
      animation-timeline: --reg;
      animation-range: cover 0% cover 100%;
    }
    .reg-item:nth-child(even) .reg-title {
      animation-name: reg-drift-r;
    }
    @keyframes reg-drift { from { transform: translateX(-1vw); } to { transform: translateX(1vw); } }
    @keyframes reg-drift-r { from { transform: translateX(1vw); } to { transform: translateX(-1vw); } }
    .reg-item {
      animation: reg-exit linear both;
      animation-timeline: view();
      animation-range: cover 55% cover 100%;
      animation-fill-mode: forwards;
      will-change: opacity, transform, filter;
    }
    .reg-item:nth-child(even) {
      animation-name: reg-exit-r;
    }
    @keyframes reg-exit { to { opacity: 0; transform: translate(-2.4vw, -22px); filter: blur(4px); } }
    @keyframes reg-exit-r { to { opacity: 0; transform: translate(2.4vw, -22px); filter: blur(4px); } }
  }
}

@media (prefers-reduced-motion: reduce) {
  .reg-item { opacity: 1; transform: none; transition: none; }
  .reg-detail { grid-template-rows: 1fr; }
  .reg-drow::before { transform: scaleY(1); }
  .reg-ignite { background-position: 0 0; transform: none; transition: none; }
  .reg-cue { display: none; }
}
@media (max-width: 600px) {
  .reg-item { gap: 14px; padding: 22px 2px; }
  .reg-title { font-size: clamp(18px, 6vw, 24px); }
  .reg-dates { font-size: 12px; }
}

/* Projects  */

#projects {
  flex-basis: 100%; /* enfant flex de .row — sinon rétrécit à son contenu (grille filtrée = cartes minuscules) */
  width: 100%;
  margin: 50px 0;
}

#projects h2 {
  text-align: center;
  margin-top: 85px;
}

/* ===================================================================
   PROJECTS — direction G2 (validée) : grille 2 colonnes, cartes éditoriales,
   thumb duotone (couleur-projet pour les vedettes, graphite neutre pour le web),
   hover CALMÉ = wash discret + sweep rose→or qui traverse le thumb + liseré (texte
   blanc, fini le flood criant). Rendu par buildProjectCard (createElement).
   =================================================================== */

/* Filters — editorial mono chips (active = rose→gold gradient). */
.project-filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 36px auto 0;
  max-width: 760px;
}
.filter-chip {
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 8px 16px;
  cursor: pointer;
  transition: color 0.25s, border-color 0.25s, background 0.25s;
}
.filter-chip:hover {
  color: var(--text);
}
.filter-chip.is-active {
  color: #0a0708;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  border-color: transparent;
  font-weight: 500; /* poids chargé (600 = faux-gras → décalait la rangée centrée) */
}

/* Grid — 2 columns (1 on mobile), ample editorial cards. */
.project-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
  align-items: start; /* each card sizes itself → one can grow on hover */
  margin: 44px auto 0;
  width: 100%;
}

.proj-card {
  --c: var(--accent);
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  text-decoration: none;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
  box-shadow: var(--shadow-card); /* none en dark ; ombre douce en light (profondeur) */
  /* one-shot reveal (display.js revealCards adds .in; fail-safe never leaves hidden) */
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
    transform 0.7s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.5s ease,
    background 0.5s ease;
}
.proj-card.in {
  opacity: 1;
  transform: none;
}
.proj-card.is-web {
  --c: #5a5560; /* neutral graphite — breaks the monotone-rose of the web block */
}

/* Duotone thumb (project colour) + rose→gold sweep on hover + title cap. */
.proj-thumb {
  position: relative;
  aspect-ratio: 16 / 9; /* uniform for every card = equal heights */
  overflow: hidden;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0; /* keep top rounded when card overflow becomes visible on hover */
  background: linear-gradient(135deg, color-mix(in srgb, var(--c) 55%, #0a0708), #0a0708 78%);
}
.proj-mesh {
  position: absolute;
  inset: 0;
  opacity: 0.5;
  background: repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 22px);
}
/* Carte de marque : logo (app/techno) centré sur le champ charte du thumb (façon cas
   Microsoft). Le thumb porte déjà le fond --c ; le logo est en contain (jamais recadré).
   border-radius arrondit les icônes d'app carrées ; sans effet sur les logos transparents. */
.proj-logo {
  position: absolute;
  inset: 0;
  margin: auto;
  max-width: 54%;
  max-height: 58%;
  object-fit: contain;
  border-radius: 20%;
  z-index: 1;
  filter: drop-shadow(0 12px 30px rgba(0, 0, 0, 0.42));
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.proj-card:hover .proj-logo {
  transform: scale(1.04);
}
[data-theme="light"] .proj-logo {
  filter: drop-shadow(0 10px 24px rgba(26, 22, 19, 0.18));
}
.proj-sweep {
  position: absolute;
  inset: 0;
  z-index: 2; /* sweep sits above the image/wash */
  background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--accent-ms) 45%, transparent) 48%, color-mix(in srgb, var(--accent) 45%, transparent) 54%, transparent 72%);
  background-size: 250% 100%;
  background-position: 130% 0;
  transition: background-position 1.1s cubic-bezier(0.2, 0.8, 0.2, 1);
}
/* Real capture — muted/tinted at rest so raw shots don't jar; full colour on hover. */
.proj-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.65) brightness(0.8) contrast(1.02);
  transition: filter 0.55s ease, transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
}
/* DA wash/duotone over the capture — lifts (fades) on hover to reveal it. */
.proj-wash {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(155deg, color-mix(in srgb, var(--c) 42%, transparent), transparent 55%),
    linear-gradient(0deg, rgba(10, 7, 8, 0.5), rgba(10, 7, 8, 0.06));
  transition: opacity 0.5s ease;
}
.proj-cap {
  position: absolute;
  left: 16px;
  bottom: 12px;
  font-family: "Archivo", var(--body, sans-serif);
  font-weight: 900;
  font-size: clamp(22px, 3vw, 34px);
  letter-spacing: -0.02em;
  color: #fff;
  opacity: 0.92;
}

.proj-body {
  padding: 16px 18px 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}
.proj-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.proj-card.is-feat .proj-eyebrow {
  color: color-mix(in srgb, var(--c) 75%, var(--text-muted)); /* brand-tinted eyebrow */
}
.proj-title {
  font-family: "Archivo", var(--body, sans-serif);
  font-weight: 700;
  font-size: clamp(19px, 2.1vw, 25px);
  letter-spacing: -0.01em;
  line-height: 1.05;
}
/* Under the thumb — a 2-line teaser at rest (min-height reserves the space so all
   cards start equal); on hover the card GROWS in place to reveal the full text
   (max-height transitions; the grid follows smoothly). */
.proj-sum {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-muted);
  font-weight: 300;
  min-height: 3.1em; /* reserve 2 lines → equal heights at rest */
  max-height: 3.2em; /* clamp to 2 lines at rest */
  overflow: hidden;
  transition: max-height 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.proj-foot {
  margin-top: auto;
  padding-top: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: "JetBrains Mono", monospace;
  font-size: 11.5px;
  color: var(--text-muted);
}
.proj-arrow {
  color: var(--accent);
  transition: transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.proj-card::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  z-index: 4;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* "Voir plus" conditionnel (mobile) — repère fin : petit filet + mono + chevron.
   Masqué par défaut ; affiché seulement si le résumé est tronqué (.has-more, mesuré)
   ET au tactile (règle @media hover:none). Distinct du lien de la carte. */
.proj-more {
  display: none;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
  min-height: 44px; /* cible tactile (le repère visuel reste fin, la zone de tap fait 44px) */
  padding: 8px 0;
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.proj-more-rule {
  width: 22px;
  height: 2px;
  background: linear-gradient(90deg, var(--c), var(--accent-ms));
}
.proj-more-arw {
  color: var(--c);
  transition: transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.proj-card.sum-open .proj-more-arw {
  transform: rotate(180deg); /* ↓ → ↑ (voir moins) */
}

/* HOVER calmé (validé) : wash discret + sweep dégradé + liseré ; texte reste blanc.
   Plus : la carte GRANDIT en place — le texte de présentation se déroule en entier
   à son emplacement (max-height), la grille suit en douceur. */
@media (hover: hover) {
  .proj-card:hover {
    transform: translateY(-5px);
    border-color: color-mix(in srgb, var(--c) 45%, var(--border));
    background: color-mix(in srgb, var(--c) 10%, var(--surface-raised));
  }
  .proj-card:hover .proj-sweep {
    background-position: -30% 0;
  }
  /* the wash lifts to reveal the real capture in full colour */
  .proj-card:hover .proj-img {
    filter: saturate(1) brightness(1);
    transform: scale(1.04);
  }
  .proj-card:hover .proj-wash {
    opacity: 0.15;
  }
  /* the card grows in place: full presentation text unfolds where it already is */
  .proj-card:hover .proj-sum {
    max-height: 12em;
  }
  .proj-card:hover::after {
    transform: scaleX(1);
  }
  .proj-card:hover .proj-arrow {
    transform: translate(3px, -3px);
  }
}

/* Per-card scroll-exit (section peel, same family as skills/registre). */
@media (prefers-reduced-motion: no-preference) and (min-width: 769px) {
  @supports (animation-timeline: view()) {
    .proj-card {
      animation: proj-exit linear both;
      animation-timeline: view();
      animation-range: cover 60% cover 100%;
      animation-fill-mode: forwards;
      will-change: opacity, transform, filter;
    }
    @keyframes proj-exit {
      to { opacity: 0; transform: translateY(-20px) scale(0.985); filter: blur(3px); }
    }
  }
}
@media (prefers-reduced-motion: reduce) {
  .proj-card {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .proj-sweep {
    display: none;
  }
}
/* ===================================================================
   PROJETS — tablette/mobile (≤768) : 1 colonne (2 col trop serré à 768),
   texte de présentation COMPLET d'emblée, filtres tappables.
   =================================================================== */
@media (max-width: 768px) {
  .project-grid {
    grid-template-columns: 1fr;
    gap: 20px;
    margin-top: 36px;
  }
  /* Hiérarchie en 1 colonne : vedettes en 4/3 (plus de présence),
     web en 16/9 (secondaire, plus court). */
  .proj-card.is-feat .proj-thumb {
    aspect-ratio: 4 / 3;
  }
  /* Cartes COMPACTES qui respirent : résumé tronqué (~3 lignes). Un "voir plus"
     conditionnel (plus bas) étend le texte sur place, distinct du tap-carte. */
  .proj-sum {
    min-height: 0;
    max-height: 4.7em; /* ~3 lignes */
    overflow: hidden;
  }
  .proj-card.sum-open .proj-sum {
    max-height: 40em; /* étendu au tap (transition douce via max-height) */
  }
  /* Filtres : chips qui wrappent, centrés, cibles ≥44px. */
  .project-filters {
    gap: 10px;
    margin-top: 28px;
  }
  .filter-chip {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 11px 16px;
  }
}
/* Tactile : le hover (sweep/wash/liseré) dégrade proprement ; on ajoute un léger
   état au TAP (teinte marque), sans transform pour ne pas gêner reveal/sortie. */
@media (hover: none) {
  /* Le "voir plus" n'apparaît qu'au tactile ET si le résumé est tronqué. */
  .proj-card.has-more .proj-more {
    display: inline-flex;
  }
  .proj-card:active {
    border-color: color-mix(in srgb, var(--c) 45%, var(--border));
    background: color-mix(in srgb, var(--c) 12%, var(--surface-raised));
  }
  .filter-chip:active {
    color: var(--text);
    border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
  }
}

/* "Voir plus" — pill mono ghost qui se remplit rose→or au survol (→ GitHub) */
.btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  align-items: center;
  gap: 9px;
  width: fit-content;
  margin: 50px auto 0;
  font-family: "JetBrains Mono", monospace;
  font-size: 12.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm); /* moins arrondi (plus pill) */
  padding: 13px 28px;
  text-decoration: none;
  transition: color 0.35s, border-color 0.35s,
    transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  transform: translateX(-101%);
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.btn:hover {
  color: #160d02;
  border-color: transparent;
  transform: translateY(-2px);
}
.btn:hover::before {
  transform: translateX(0);
}

.btn:hover {
  background: var(--accent);
  color: var(--on-accent);
}


/* --------Contact----------- */

/* ===== CONTACT — C1 (split invitation + formulaire éditorial) ===== */
#contact {
  flex-basis: 100%; /* enfant flex de .row — occupe toute la largeur */
  width: 100%;
  padding: clamp(80px, 12vh, 150px) 0 clamp(70px, 10vh, 120px);
}
.contact-split {
  display: grid;
  grid-template-columns: 0.92fr 1.08fr;
  gap: clamp(40px, 5vw, 66px);
  align-items: start;
}
.c-eyebrow {
  font-family: "JetBrains Mono", monospace;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 22px;
}
.c-eyebrow::before {
  content: "";
  width: 40px;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
}
.c-title {
  font-family: "Archivo", sans-serif;
  font-weight: 900;
  font-size: clamp(32px, 5vw, 58px);
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: 20px;
}
.c-title em {
  font-style: normal;
  background: linear-gradient(115deg, var(--accent), var(--accent-ms));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.c-lead {
  font-size: clamp(15px, 1.6vw, 18px);
  line-height: 1.72;
  color: var(--text-muted);
  font-weight: 300;
  max-width: 42ch;
}
.c-avail {
  margin-top: 24px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #d7d2da;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  padding: 8px 16px;
}
.c-avail .c-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
}
.c-channels {
  margin-top: 42px;
}
.c-channel {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 16px 2px;
  border-top: 1px solid var(--border);
  text-decoration: none;
  color: inherit;
  transition: padding-left 0.32s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.c-channel:last-child {
  border-bottom: 1px solid var(--border);
}
.c-channel .c-lab {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  flex: 0 0 78px;
}
.c-channel .c-val {
  font-size: 15.5px;
  color: #e6e1e9;
  transition: color 0.25s;
  word-break: break-word;
}
.c-channel .c-arw {
  margin-left: auto;
  font-family: "JetBrains Mono", monospace;
  color: var(--accent);
  opacity: 0;
  transform: translateX(-5px);
  transition: opacity 0.3s, transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.c-channel::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: -1px;
  width: 2px;
  background: linear-gradient(180deg, var(--accent), var(--accent-ms));
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1);
}
@media (hover: hover) {
  .c-channel:hover {
    padding-left: 16px;
  }
  .c-channel:hover::before {
    transform: scaleY(1);
  }
  .c-channel:hover .c-val {
    color: #fff;
  }
  .c-channel:hover .c-arw {
    opacity: 1;
    transform: none;
  }
}

/* --- Formulaire éditorial (labels mono visibles, filet rose→or au focus) --- */
.c-form {
  border: 1px solid var(--border);
  border-radius: var(--radius-2xl);
  background: var(--surface-raised);
  padding: clamp(24px, 3vw, 36px) clamp(22px, 3vw, 34px);
}
.c-row2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}
.c-field {
  position: relative;
  margin-bottom: 26px;
}
.c-field label {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 9px;
  transition: color 0.25s;
}
.c-field input,
.c-field textarea {
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border);
  padding: 9px 2px;
  color: var(--text);
  font-family: "Poppins", sans-serif;
  font-size: 15.5px;
  outline: none;
  resize: vertical;
}
.c-field textarea {
  min-height: 120px;
  line-height: 1.6;
}
.c-field input::placeholder,
.c-field textarea::placeholder {
  color: #6a6570;
}
.c-field::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.c-field:focus-within::after {
  transform: scaleX(1);
}
.c-field:focus-within label {
  color: var(--text);
}
.c-field.invalid input,
.c-field.invalid textarea {
  border-bottom-color: var(--accent);
}
.c-field.invalid label {
  color: var(--accent);
}
.c-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.c-form-foot {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 4px;
}
.c-submit {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 15px 32px;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, var(--border));
  border-radius: var(--radius-sm);
  font-family: "Poppins", sans-serif;
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  background: transparent;
  cursor: pointer;
  transition: color 0.35s, border-color 0.35s,
    transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 0.35s;
}
/* le dégradé rose→or glisse depuis la gauche au survol (ignition) */
.c-submit::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  transform: translateX(-101%);
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.c-submit:hover {
  color: #fff; /* texte blanc sur le remplissage (mieux lisible) */
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.32);
  border-color: transparent;
  transform: translateY(-2px);
  box-shadow: 0 14px 34px -12px color-mix(in srgb, var(--accent) 45%, transparent);
}
.c-submit:hover::before {
  transform: translateX(0);
}
.c-submit:disabled {
  opacity: 0.7;
  cursor: default;
  transform: none;
  box-shadow: none;
}
.c-submit .c-spin {
  width: 15px;
  height: 15px;
  display: none;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: var(--text);
  border-radius: 50%;
  animation: c-spin 0.7s linear infinite;
}
.c-submit.loading .c-spin {
  display: inline-block;
}
@keyframes c-spin {
  to {
    transform: rotate(360deg);
  }
}
.c-status {
  font-family: "JetBrains Mono", monospace;
  font-size: 13px;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 1.3em;
}
.c-status.ok {
  color: #e6e1e9;
}
.c-status.ok .c-ic {
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 700;
}
.c-status.err {
  color: #ff5b7f;
}
@media (max-width: 860px) {
  .contact-split {
    grid-template-columns: 1fr;
  }
  .c-row2 {
    grid-template-columns: 1fr;
  }
}

/* --- Header toggles: a small, coherent, DA-integrated pair --- */

/* Toggles langue/thème — regroupés dans #sidemenu (dans le menu sur mobile). */
.nav-toggles {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: 14px;
}
.nav-toggles > button {
  margin-left: 0; /* espacement géré par le gap */
}

/* Language: a compact segmented control with a sliding rose highlight */
.lang-toggle {
  flex: 0 0 auto;
  position: relative;
  display: inline-flex;
  align-items: center;
  margin-left: 22px;
  padding: 3px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.lang-opt {
  position: relative;
  z-index: 1;
  width: 28px;
  text-align: center;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  padding: 3px 0;
  transition: color 0.25s ease;
}
.lang-slider {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 28px;
  height: calc(100% - 6px);
  background: var(--accent);
  border-radius: var(--radius-pill);
  transition: transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1);
  z-index: 0;
}
html[lang="en"] .lang-slider {
  transform: translateX(28px);
}
html[lang="fr"] .lang-opt[data-lang="fr"],
html[lang="en"] .lang-opt[data-lang="en"] {
  color: var(--on-accent);
}

/* Theme: bare morphing sun/moon (no button chrome) */
.theme-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 16px;
  padding: 4px;
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  transition: color 0.2s ease;
}
.theme-toggle:hover {
  color: var(--accent);
}
.theme-icon {
  display: block;
  overflow: visible;
  width: 23px;
  height: 23px;
}
.theme-orb,
.theme-cut,
.theme-rays {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.4s ease;
}
/* Dark (default): crescent moon, rays hidden */
.theme-rays {
  opacity: 0;
  transform: rotate(-50deg) scale(0.5);
}
/* Light: full sun (orb shrinks) + rays fan out */
[data-theme="light"] .theme-cut {
  transform: translate(9px, -9px);
}
[data-theme="light"] .theme-orb {
  transform: scale(0.68);
}
[data-theme="light"] .theme-rays {
  opacity: 1;
  transform: rotate(0) scale(1);
}

.lang-toggle:focus-visible,
.theme-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-pill);
}

/* Reduced motion: toggles switch instantly but stay fully functional */
@media (prefers-reduced-motion: reduce) {
  .lang-slider,
  .theme-orb,
  .theme-cut,
  .theme-rays,
  .lang-opt {
    transition: none;
  }
}

/* ===== FOOTER — 3 zones éditorial ===== */
.site-footer {
  flex-basis: 100%; /* enfant flex de .row */
  width: 100%;
  position: relative;
  border-top: 1px solid var(--border);
  margin-top: clamp(40px, 6vw, 90px);
}
.site-footer::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  width: min(220px, 40%);
  height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
}
.foot-main {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: clamp(32px, 4vw, 48px);
  padding: clamp(48px, 7vw, 70px) 0 44px;
}
.foot-wm {
  font-family: "Archivo", sans-serif;
  font-weight: 800;
  font-size: 20px;
  letter-spacing: -0.01em;
}
.foot-wm span {
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.foot-brand p {
  margin-top: 12px;
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  max-width: 34ch;
  line-height: 1.7;
}
/* force block layout — override the global `nav { display:flex }` on <nav class="foot-col"> */
.foot-col {
  display: block;
  font-size: 14px;
}
.foot-col h4 {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 16px;
}
.foot-col a {
  display: block;
  text-decoration: none;
  color: #cfc9d3;
  font-size: 14px;
  padding: 6px 0;
  transition: color 0.25s, padding-left 0.25s;
}
.foot-col a:hover {
  color: #fff;
  padding-left: 5px;
}
.foot-col a .m {
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  color: var(--text-muted);
  margin-right: 8px;
}
.foot-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
  padding: 22px 0 40px;
  border-top: 1px solid var(--border);
  font-family: "JetBrains Mono", monospace;
  font-size: 12px;
  color: var(--text-muted);
}
.foot-cr .foot-c {
  background: linear-gradient(90deg, var(--accent), var(--accent-ms));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.foot-totop {
  text-decoration: none;
  color: var(--text-muted);
  display: inline-flex;
  gap: 8px;
  align-items: center;
  transition: color 0.25s;
}
.foot-totop:hover {
  color: #fff;
}
.foot-totop i {
  color: var(--accent);
  font-style: normal;
}
@media (max-width: 860px) {
  .foot-main {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

/* --------------small Screen ------------ */

nav .fa-solid {
  display: none;
}

/* ===================================================================
   NAV MOBILE (≤768px) — menu burger : panneau qui glisse, fond bloqué,
   toggles dans le menu, cibles ≥44px. Breakpoint unifié.
   =================================================================== */
@media (max-width: 768px) {
  nav .fa-bars {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin-right: -8px; /* garde l'alignement visuel, zone de tap 44px */
    font-size: 22px;
    color: var(--text);
    cursor: pointer;
  }
  #sidemenu {
    position: fixed;
    top: 0;
    right: 0;
    height: 100vh;
    height: 100dvh; /* pleine hauteur — échappe au containing-block de la barre (backdrop-filter) */
    width: min(84vw, 320px);
    flex-direction: column;
    justify-content: flex-start;
    align-items: stretch;
    gap: 2px;
    text-align: left;
    padding: 88px 26px 40px;
    background: color-mix(in srgb, var(--text) 5%, var(--bg)); /* PLEIN opaque — masque la page */
    border-left: 1px solid var(--border);
    box-shadow: -24px 0 70px -24px rgba(0, 0, 0, 0.7);
    transform: translateX(100%);
    transition: transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1),
      display 0.4s allow-discrete;
    z-index: 210;
    overflow-y: auto;
    /* FERMÉ = display:none → le panneau (hors-champ à droite) ne compte PLUS dans la
       largeur de layout → aucun overflow horizontal (un simple translateX le laissait
       étendre la page). allow-discrete + @starting-style gardent le slide fluide. */
    display: none;
  }
  body.menu-open #sidemenu {
    display: flex; /* colonne : flex-direction déjà défini plus haut */
    transform: translateX(0);
  }
  @starting-style {
    body.menu-open #sidemenu {
      transform: translateX(100%);
    }
  }
  body.menu-open nav .fa-bars {
    display: none; /* le × du panneau ferme */
  }
  body.menu-open {
    overflow: hidden; /* le fond ne scrolle plus */
  }
  body.menu-open::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 199; /* sous la barre + le menu (contexte 200), au-dessus de la page */
    background: rgba(4, 3, 4, 0.55);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    animation: nav-backdrop 0.3s ease;
  }
  @keyframes nav-backdrop {
    from { opacity: 0; }
  }
  #sidemenu li {
    display: block;
    margin: 0;
    width: 100%;
  }
  #sidemenu li a {
    display: flex;
    align-items: center;
    min-height: 48px; /* cible tactile */
    width: 100%;
    color: var(--text);
    font-size: 18px;
    padding: 6px 4px;
  }
  #sidemenu li a::after {
    display: none;
  }
  #sidemenu .fa-xmark {
    position: absolute;
    top: 22px;
    right: 22px;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    font-size: 24px;
    color: var(--text-muted);
    cursor: pointer;
    transition: color 0.25s;
  }
  #sidemenu .fa-xmark:hover {
    color: var(--text);
  }
  /* toggles dans le menu : séparés par un filet, cibles larges */
  .nav-toggles {
    margin: 22px 0 0;
    padding-top: 22px;
    border-top: 1px solid var(--border);
    gap: 18px;
  }
  .lang-toggle {
    padding: 6px; /* cible plus grande au doigt */
  }
}

/* ===================================================================
   HERO — tablette (≤768) + mobile (≤480).
   =================================================================== */
@media (max-width: 768px) {
  .header {
    display: block; /* le nav (.container) ne pousse plus le hero vers la droite */
    min-height: auto; /* pas de 100vh forcé → ne pousse pas le contenu trop bas */
    padding-top: 92px; /* dégage la barre fixe (72px) */
    padding-bottom: 48px;
    margin-bottom: clamp(48px, 10vw, 80px);
  }
  .header > .container {
    padding: 0; /* wrapper du nav (fixe) : ne prend plus de hauteur/place ici */
  }
  .header-text {
    max-width: none;
    margin: 0;
    padding: 0 10% 8px; /* gouttière standard (comme .container) → aligné à gauche comme le about */
  }
  .header-text h1 {
    font-size: clamp(40px, 6vw, 62px);
    letter-spacing: -0.015em; /* moins serré qu'en desktop */
  }
  .hero-cue {
    margin-top: clamp(30px, 6vw, 48px);
  }
}
/* ===================================================================
   HERO MOBILE-FIRST (≤480) — DIRECTION 02 « le mot-force centré » :
   plein écran (le hero possède le fold, About ne dépasse pas), contenu
   optiquement centré, « idées » GÉANT en dégradé + lueur rose = événement
   visuel qui remplit l'écran. Le vide devient un halo, pas un manque.
   Desktop INCHANGÉ (tout est dans ce media ≤480).
   =================================================================== */
@media (max-width: 480px) {
  .header {
    min-height: 100vh;
    min-height: 100dvh; /* possède l'écran → on ne voit pas la section suivante à l'ouverture */
    display: flex;
    flex-direction: column;
    justify-content: center; /* composition centrée : le mot-force est l'événement */
    padding: 84px 18px 96px; /* bas > haut → léger biais vers le centre optique (le contenu monte un peu) */
    margin-bottom: 0;
  }
  .header-text {
    padding: 0;
    max-width: 340px;
    margin-inline: auto;
    width: 100%;
    text-align: center;
  }
  .hero-copy {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  /* Kicker : filet rose→or de part et d'autre, centré */
  .hero-eyebrow {
    justify-content: center;
    align-items: center;
    font-size: 10px;
    letter-spacing: 0.14em;
    line-height: 1.6;
    gap: 9px;
    margin-bottom: clamp(40px, 9.5vw, 54px); /* remonte l'eyebrow (plus d'air vers le titre) */
    max-width: 290px;
    text-wrap: balance;
    color: var(--text-muted);
  }
  .hero-eyebrow::before,
  .hero-eyebrow::after {
    content: "";
    flex: none;
    width: 16px;
    height: 2px;
    background: linear-gradient(90deg, var(--accent), var(--accent-ms), var(--accent));
    background-size: 300% 100%;
    animation: hero-bar 4.5s ease-in-out infinite alternate;
  }

  /* Amorce (setup) : subordonnée — pose le contexte au-dessus du mot-force */
  .header-text h1 {
    font-size: clamp(27px, 7.6vw, 33px);
    line-height: 1.1;
    letter-spacing: -0.018em;
    font-weight: 700;
    color: color-mix(in srgb, var(--text) 88%, transparent);
    width: 100%;
    max-width: 300px;
    margin-inline: auto;
    text-align: center; /* amorce recentrée */
  }
  .header-text h1 br { display: none; }

  /* LE MOT-FORCE : « idées » ÉNORME, dégradé rose→or, l'événement de l'écran */
  .header-text h1 span {
    display: block;
    font-weight: 900;
    font-size: clamp(64px, 22vw, 100px);
    line-height: 0.84;
    letter-spacing: -0.035em;
    margin-top: clamp(16px, 4.5vw, 24px);
    text-align: center; /* …mais « idées » reste centré */
  }

  /* Sous-titre : discret, blotti sous le mot */
  .header-sub {
    margin-top: clamp(42px, 10.5vw, 56px); /* descend le sous-titre (plus d'air sous le titre) */
    font-size: 14px;
    line-height: 1.5;
    max-width: 30ch;
    margin-inline: auto;
  }

  /* Lueur : halo rose (teinté or au cœur) derrière le mot-force = l'événement
     visuel qui « remplit » le centre de l'écran */
  .header::before {
    width: min(92vw, 440px);
    top: 24%;
    left: 0;
    right: 0;
    margin-inline: auto;
    background: radial-gradient(circle, var(--hero-glow) 0%, rgba(247, 201, 72, 0.05) 46%, transparent 70%);
  }
  [data-theme="dark"] .header {
    --hero-glow: rgba(255, 0, 79, 0.24);
  }

  /* Appel au scroll : filet animé ancré en bas (le hero possède l'écran, donc
     rien ne dépasse pour signaler le scroll → ce filet le fait) */
  .header::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 22px;
    width: 2px;
    height: 28px;
    transform: translateX(-50%);
    transform-origin: center bottom;
    border-radius: 2px;
    background: linear-gradient(180deg, var(--accent) 0%, transparent 100%);
    animation: hero-thread 2.4s ease-in-out infinite;
  }
  @keyframes hero-thread {
    0%, 100% { opacity: 0.2; transform: translateX(-50%) scaleY(0.6); }
    50% { opacity: 0.75; transform: translateX(-50%) scaleY(1); }
  }
}
@media (prefers-reduced-motion: reduce) and (max-width: 480px) {
  .header::after,
  .hero-eyebrow::before,
  .hero-eyebrow::after { animation: none; }
  .header::after { opacity: 0.5; }
}

@media only screen and (max-width: 600px) {
  .row {
    margin-top: 30px;
  }

  /* hero + nav mobile → gérés par les blocs unifiés @media 768/480 plus haut */

  .sub-title {
    font-size: 40px;
    margin-top: 20px;
  }

  /* about → géré par le bloc unifié @media (max-width: 768px) */

  .tab-title {
    gap: clamp(14px, 4vw, 24px);
  }

  .tab-links {
    font-size: 13px;
    letter-spacing: 0.08em;
    padding: 2px 2px 13px;
  }

  .contact-left,
  .contact-right {
    flex-basis: 100%;
  }

  .project-grid {
    gap: 20px;
    margin-top: 30px;
  }
  #projects h2 {
    margin-bottom: 45px;
  }
  .nom {
    font-size: 15px;
    margin: 20px;
  }

  .social-icons {
    margin-bottom: 30px;
  }
  .tab-content.active-tab {
    margin-right: 0px;
  }

  .tab-content.certifications {
    margin-right: 0;
  }

  .tab-panels {
    overflow: hidden;
    margin-right: 0;
  }

  .tab-panels-track {
    display: flex;
    flex-direction: column;
    transition: transform 0.35s ease;
    will-change: transform;
  }

  .tab-panels-track .tab-content {
    display: block;
    margin-right: 0;
    width: 100%;
  }
}



/* ============================================================
   HAT TINT — accent color driven by a project's casquette.
   --hat / --hat-text default to the pink accent; a [data-hat]
   value (on <body> for detail pages, on a card/chip for the
   grid) switches the tint. Applied to tags/filters/highlights
   only, never to structural surfaces.
   ============================================================ */
:root {
  --hat: var(--accent);
  --hat-text: var(--accent);
}
[data-hat="Microsoft"] {
  --hat: var(--accent-ms);
  --hat-text: var(--accent-ms-text);
}
[data-hat="Web"] {
  --hat: var(--accent);
  --hat-text: var(--accent);
}

/* ===================================================================
   GRANDS ÉCRANS (≥1680px) — les grands moments profitent de l'espace.
   13" et écrans normaux inchangés (l'échelle typo de base reste en dessous).
   =================================================================== */
@media (min-width: 1680px) {
  /* le contenu gagne un poil de largeur (gouttière un peu resserrée) */
  .container {
    padding-left: 8%;
    padding-right: 8%;
  }
  /* hero — le titre grandit un peu */
  .header-text {
    max-width: 1320px;
  }
  .header-text h1 {
    font-size: clamp(92px, 6.4vw, 118px);
  }
  /* titres de section — un cran plus grands */
  .sub-title {
    font-size: clamp(48px, 3.4vw, 60px);
  }
  /* contact — l'accroche profite de la place */
  .c-title {
    font-size: clamp(58px, 4.4vw, 72px);
  }
}

/* ===================================================================
   MOBILE (≤768) — sorties de section ALLÉGÉES. On remet un dissolve simple
   (fondu + léger translate vers le haut) quand une section quitte l'écran,
   MAIS sans le peel latéral / blur / drift / parallax du desktop → GPU
   (opacity + transform seulement), fluide au scroll tactile. Le desktop garde
   ses sorties riches (blocs min-width:769). reduced-motion : rien.
   =================================================================== */
@media (max-width: 768px) and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* view() se mesure contre le scrollport le plus proche : un ancêtre
       overflow:hidden le "capture" et l'anim ne progresse jamais. overflow:clip
       clippe pareil SANS créer de scrollport → l'anim retrouve la racine (comme
       l'about). Pour parcours, les bands sont piégés dans le slider d'onglets
       (.tab-content/.tab-panels) → on anime la SECTION #parcours, hors du slider. */
    .header {
      overflow: clip;
    }
    .header-text,
    .about-story,
    #parcours,
    .proj-card {
      animation: mob-exit linear both;
      animation-timeline: view();
      animation-range: cover 62% cover 100%;
      animation-fill-mode: forwards;
      will-change: opacity, transform, filter;
    }
    /* SIGNATURE UNIQUE — le dissolve du hero desktop, version mobile simple :
       fondu + zoom arrière subtil + touche de flou. Seule la section en cours de
       sortie anime (view-timeline) → le flou léger reste fluide. */
    @keyframes mob-exit {
      to {
        opacity: 0.05;
        transform: scale(0.94) translateY(16px);
        filter: blur(2px);
      }
    }
  }
}

/* ===================================================================
   PARCOURS — tablette/mobile (≤768) : sélecteur d'onglets scrollable,
   registre lisible, cibles ≥44px.
   =================================================================== */
@media (max-width: 768px) {
  /* Onglets : une seule ligne, scroll horizontal (swipe) — plus de wrap qui
     casserait le filet. Le filet (.tab-ind, absolute) scrolle avec le contenu. */
  .tab-title {
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: 4px;
    margin-bottom: 26px;
    padding-bottom: 3px; /* garde le filet dans le clip */
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    /* Indice de scroll : fondu sur le(s) bord(s) où il reste des onglets. Par
       défaut (au milieu) les deux bords fondent ; JS ajoute .at-start / .at-end /
       .no-scroll selon la position. Le fondu reste fixe aux bords visibles
       (mask-image = repère sur la box, pas sur le contenu défilé). */
    --tab-fade: 30px;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--tab-fade), #000 calc(100% - var(--tab-fade)), transparent 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 var(--tab-fade), #000 calc(100% - var(--tab-fade)), transparent 100%);
  }
  .tab-title.at-start {
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - var(--tab-fade)), transparent 100%);
    mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - var(--tab-fade)), transparent 100%);
  }
  .tab-title.at-end {
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--tab-fade), #000 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 var(--tab-fade), #000 100%);
  }
  .tab-title.no-scroll {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .tab-title::-webkit-scrollbar {
    display: none;
  }
  .tab-links {
    flex: 0 0 auto;
    scroll-snap-align: start;
    font-size: 13px;
    letter-spacing: 0.08em;
    padding: 13px 8px 15px; /* cible tactile ≥44px */
  }

  /* Registre : titre et dates-épine ne se collent pas ; tailles adaptées. */
  .reg-item {
    gap: 14px;
    padding: 22px 2px;
  }
  .reg-title {
    font-size: clamp(18px, 5.4vw, 24px);
  }
  .reg-side {
    padding-top: 3px;
  }
  .reg-dates {
    font-size: 12px;
  }
}

/* ===================================================================
   PARCOURS — affordance TACTILE (hover:none). Skills/registre = TAP.
   =================================================================== */
@media (hover: none) {
  /* Pas de survol réel → seul le TAP (.lit/.open) déploie. On force l'état FERMÉ
     tant que non déployé, pour neutraliser le :hover "collant" du tactile (sinon
     impossible de refermer au re-tap). */
  .skl-band:not(.lit) .skl-detail {
    grid-template-rows: 0fr;
  }
  .skl-band:not(.lit) .skl-invite {
    opacity: 1;
    transform: none;
  }
  .reg-item:not(.open) .reg-detail {
    grid-template-rows: 0fr;
  }

  /* Skills — "+N · voir plus ↓" : traitement fin & éditorial (filet + mono +
     chevron vers le bas), SANS encadré. La band entière est la cible de tap
     (≥44px) ; le padding vertical donne une zone confortable sur le repère. */
  .skl-invite {
    height: auto;
    padding: 11px 0;
    font-size: 12px;
    gap: 12px;
  }
  .skl-invite-arw {
    transform: rotate(90deg); /* → devient ↓ : indique le déploiement */
  }
  /* Déployée : le repère se replie (pas de trou sous le détail ouvert). */
  .skl-band.lit .skl-invite {
    height: 0;
    padding-top: 0;
    padding-bottom: 0;
    margin-top: 0;
    overflow: hidden;
  }

  /* Registre — le "＋" reste visible (affordance) et pivote en "×" à l'ouverture. */
  .reg-cue {
    opacity: 1;
    font-size: 18px;
    margin-left: 8px;
  }
  .reg-item:not(.open) .reg-cue {
    opacity: 1;
    transform: none;
  }
  .reg-item.open .reg-cue {
    opacity: 1;
    transform: rotate(45deg);
    color: var(--accent-ms);
  }
}

/* ===================================================================
   CONTACT / FOOTER — tablette/mobile (≤768 + ≤480).
   =================================================================== */
@media (max-width: 768px) {
  /* Contact : split → empilé (accroche + canaux directs, puis formulaire). */
  .contact-split {
    grid-template-columns: 1fr;
    gap: clamp(40px, 8vw, 56px);
  }
  /* Inputs : ≥16px = PAS de zoom auto iOS au focus ; hauteur tactile confortable. */
  .c-field input,
  .c-field textarea {
    font-size: 16px;
    padding: 13px 2px;
  }
  .c-field textarea {
    min-height: 130px;
  }
  /* Footer : marque pleine largeur, puis Navigation | Ailleurs en 2 colonnes. */
  .foot-main {
    grid-template-columns: 1fr 1fr;
    gap: clamp(26px, 6vw, 40px);
    padding: clamp(40px, 8vw, 56px) 0 36px;
  }
  .foot-brand {
    grid-column: 1 / -1;
  }
  /* Liens footer : cibles tactiles ≥44px. */
  .foot-col a {
    min-height: 44px;
    display: flex;
    align-items: center;
  }
  .foot-totop {
    padding: 11px 0;
  }
}
@media (max-width: 480px) {
  /* Nom / Email empilés (fini les 2 colonnes serrées). */
  .c-row2 {
    grid-template-columns: 1fr;
    gap: 0;
  }
  /* Bouton Envoyer pleine largeur = CTA clair au doigt (status en dessous). */
  .c-form-foot {
    flex-direction: column;
    align-items: stretch;
  }
  .c-submit {
    width: 100%;
    justify-content: center;
  }
  /* Footer : tout empilé sur 1 colonne. */
  .foot-main {
    grid-template-columns: 1fr;
  }
  .foot-bottom {
    padding: 20px 0 32px;
  }
}
/* Canaux directs : la flèche ↗ reste visible au tactile (repère de lien externe). */
@media (hover: none) {
  .c-channel .c-arw {
    opacity: 1;
    transform: none;
  }
}

/* ===================================================================
   COHÉRENCE GOUTTIÈRE (mobile ≤768) — #projects/#contact/footer ont un .container
   IMBRIQUÉ dans celui de #about (double 10% → ~18%), alors que about/parcours sont
   à 10%. On neutralise la gouttière du .container imbriqué sur mobile → toutes les
   sections partent de la MÊME gouttière (10%, celle de #about). Desktop inchangé.
   =================================================================== */
@media (max-width: 768px) {
  #projects > .container,
  #contact > .container,
  .site-footer > .container {
    padding-left: 0;
    padding-right: 0;
  }
}

/* ===================================================================
   GRILLE PROJETS — LIGHT. Thumbs duotone de marque → pastel clair, cap assombri,
   image/wash éclaircis. La carte (blanc + ombre) et le liseré rose→ambre suivent
   déjà les tokens. Additif : dark intact.
   =================================================================== */
[data-theme="light"] .proj-thumb {
  background: linear-gradient(135deg, color-mix(in srgb, var(--c) 24%, #fff), #f1eee9 82%);
}
[data-theme="light"] .proj-mesh {
  background: repeating-linear-gradient(135deg, rgba(26, 22, 19, 0.045) 0 1px, transparent 1px 22px);
}
[data-theme="light"] .proj-cap {
  color: color-mix(in srgb, var(--c) 58%, #1c1712); /* nom de projet : marque assombrie, lisible sur pastel */
}
[data-theme="light"] .proj-card.is-feat .proj-eyebrow {
  color: color-mix(in srgb, var(--c) 48%, #2a2622);
}
/* vraie capture : moins assombrie sur clair ; wash de marque léger (pas un voile sombre) */
[data-theme="light"] .proj-img {
  filter: saturate(0.92) brightness(0.99) contrast(1.02);
}
[data-theme="light"] .proj-wash {
  background: linear-gradient(155deg, color-mix(in srgb, var(--c) 20%, transparent), transparent 55%),
    linear-gradient(0deg, rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0.04));
}
