/* ==========================================================================
   Variables — TOUTE la couleur du site vit ici. Le reste du CSS ne
   référence jamais une couleur en dur, uniquement ces variables.

   Le site a un thème unique, clair. Certaines sections sont malgré tout
   volontairement sur fond sombre (panneau "Mon profil", Compétences,
   Outils & projets IA) ou sur fond d'accent plein (Contact) : ce sont des
   respirations assumées de ce thème clair, d'où les variables --bg-dark
   et --text-on-dark* ci-dessous.
   ========================================================================== */
:root {
  /* Fond */
  --bg: #fafbfc;
  --bg-rgb: 250, 251, 252;
  --bg-alt: #f0f3f7; /* blocs alternés (ex: le panneau graphique "Mon profil") */
  --bg-dark: #12161f; /* blocs ponctuels en fond sombre (Compétences, Outils) — volontairement peu nombreux */
  --surface: #ffffff; /* cartes (cas client, sites, certifications) */
  --surface-tint: var(--bg-alt); /* tuiles/zones internes aux cartes */

  /* Texte */
  --text: #1a1f27;
  --text-rgb: 26, 31, 39;
  --text-muted: rgba(var(--text-rgb), 0.62);
  --text-faint: rgba(var(--text-rgb), 0.45);
  --border: rgba(var(--text-rgb), 0.12);
  --border-strong: rgba(var(--text-rgb), 0.25);

  /* Texte/traits sur les blocs en fond sombre (--bg-dark) */
  --text-on-dark: #eef2fb;
  --text-on-dark-rgb: 238, 242, 251;
  --text-on-dark-muted: rgba(var(--text-on-dark-rgb), 0.62);
  --text-on-dark-faint: rgba(var(--text-on-dark-rgb), 0.45);
  --border-on-dark: rgba(var(--text-on-dark-rgb), 0.14);
  --border-on-dark-strong: rgba(var(--text-on-dark-rgb), 0.22);

  /* Le panneau graphique "Mon profil" (bloc de la courbe) : bloc
     volontairement sombre — voir la règle .live plus bas, qui réaligne
     --text/--text-rgb en conséquence pour tout son contenu. */
  --live-panel-bg: #161d33;
  --live-panel-text: #eef2fb;

  /* Accent — bleu. Plusieurs paliers de luminosité pour rester lisible
     aussi bien sur le fond clair que sur les blocs sombres. */
  --accent: #2e6bff;
  --accent-rgb: 46, 107, 255;
  --accent-bright: #5c8cff;
  --accent-brighter: #8fb1ff;

  /* Pastille "en direct" + halo du hero */
  --live-dot-color: var(--accent-bright);
  --glow-color: var(--accent);

  /* Filet de jointure entre les deux blocs sombres consécutifs
     (Compétences puis Outils), qui sinon se fondraient l'un dans l'autre. */
  --divider-line: rgba(var(--accent-rgb), 0.55);
  --divider-line-fade: rgba(var(--accent-rgb), 0);

  /* Nappe diffuse du hero : bleu accent très doux sur le fond, avec
     un second ton violacé pour éviter l'aplat. Chaque nappe a sa version
     transparente, pour que le dégradé s'éteigne dans sa propre teinte
     (et non vers un gris). */
  --wash-1: rgba(var(--accent-rgb), 0.16);
  --wash-1-fade: rgba(var(--accent-rgb), 0);
  --wash-2: rgba(124, 92, 255, 0.10);
  --wash-2-fade: rgba(124, 92, 255, 0);

  /* Sélection de texte */
  --selection-bg: var(--accent);
  --selection-text: #ffffff;

  /* Contact — fond bleu accent plein dans les deux thèmes */
  --contact-bg: var(--accent);
  --contact-text: #f5f8ff;
  --contact-text-rgb: 245, 248, 255;
  --contact-button-bg: #ffffff;
  --contact-button-text: var(--accent);

  /* Typographie */
  --font-title: "Outfit", system-ui, -apple-system, sans-serif;
  --font-body: "Hanken Grotesk", system-ui, -apple-system, sans-serif;

  /* Mise en page */
  --max-width: 1180px;
  --header-height: 60px;
  --radius-sm: 8px;
  --radius-md: 11px;
  --radius-lg: 16px;
  --radius-pill: 999px;

  --transition-fast: 0.18s ease;
}

/* ==========================================================================
   Reset minimal
   ========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img,
svg {
  max-width: 100%;
  display: block;
}

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

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

p {
  margin: 0;
}

h1,
h2,
h3 {
  margin: 0;
  font-family: var(--font-title);
  font-weight: 700;
  letter-spacing: -0.02em;
}

::selection {
  background: var(--selection-bg);
  color: var(--selection-text);
}

@keyframes bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(6px);
  }
}

/* ==========================================================================
   Accessibilité : lien d'évitement + classe utilitaire sr-only
   ========================================================================== */
.skip-link {
  position: absolute;
  top: -100%;
  left: 0;
  background: var(--accent);
  color: var(--bg);
  padding: 0.75em 1.25em;
  z-index: 1000;
  font-weight: 600;
  transition: top var(--transition-fast);
}

.skip-link:focus {
  top: 0;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   En-tête / navigation à scroll-spy
   ========================================================================== */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
  background: rgba(var(--bg-rgb), 0.9);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}

.site-header__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 13px 20px;
  display: flex;
  align-items: center;
  gap: 18px;
}

.logo {
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.3px;
  white-space: nowrap;
}

.logo__tag {
  color: var(--accent);
  font-weight: 500;
}

.main-nav {
  flex: 1;
  display: flex;
  gap: 6px;
  /* "safe" évite le piège classique centre+overflow : sans lui, les premiers
     items deviennent inatteignables au scroll quand le menu ne tient pas
     (repli automatique sur un alignement à gauche si "safe" n'est pas supporté). */
  justify-content: safe center;
  overflow-x: auto;
  scrollbar-width: none;
  min-width: 0;
}

.main-nav::-webkit-scrollbar {
  display: none;
}

.main-nav a {
  font-family: var(--font-title);
  font-size: 12px;
  padding: 7px 12px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  color: var(--text-faint);
  transition: background var(--transition-fast), color var(--transition-fast);
}

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

.main-nav a[aria-current="true"] {
  background: var(--text);
  color: var(--bg);
}

.nav-cta {
  font-family: var(--font-title);
  font-size: 12px;
  font-weight: 600;
  padding: 9px 15px;
  background: var(--text);
  color: var(--bg) !important;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Lien Contact interne au menu : inutile en desktop, où le bouton
   .nav-cta est déjà visible en permanence. */
.main-nav__contact {
  display: none;
}

/* Bouton burger : absent du desktop, activé sous 900px. */
.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  margin-right: -10px;
  border: none;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  flex-shrink: 0;
}

/* Les trois barres : la barre centrale est l'élément, les deux autres
   ses pseudo-éléments. En position ouverte elles forment une croix. */
.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  display: block;
  width: 20px;
  height: 2px;
  background: currentColor;
  margin: 0 auto;
  transition: transform var(--transition-fast), opacity var(--transition-fast);
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: "";
  position: relative;
}

.nav-toggle__bars::before {
  top: -6px;
}

.nav-toggle__bars::after {
  top: 4px;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars {
  background: transparent;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before {
  transform: translateY(6px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after {
  transform: translateY(-6px) rotate(-45deg);
}

/* ==========================================================================
   Mise en page générale des sections
   ========================================================================== */
main {
  padding-top: var(--header-height);
}

/* La navigation saute vers l'id de section (ancre native) : sans ça, le
   header fixe recouvrirait le haut de la section ciblée. */
main > section {
  scroll-margin-top: var(--header-height);
}

.section-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 80px 20px;
}

.eyebrow {
  font-family: var(--font-title);
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--text-faint);
  margin: 0 0 10px;
  text-transform: uppercase;
}

.eyebrow--accent {
  color: var(--accent-bright);
}

.section-title {
  font-size: clamp(28px, 3.6vw, 44px);
  line-height: 1.05;
  margin-bottom: 16px;
}

.section-title--h2-only {
  font-family: var(--font-title);
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-faint);
  margin-bottom: 40px;
}

.dark-section .section-title--h2-only {
  color: var(--accent-bright);
}

/* ==========================================================================
   Hero / Profil
   ========================================================================== */
/* Le hero occupe exactement la hauteur de l'écran en desktop (titre +
   pitch + témoignages tiennent dans un seul écran, sans être coupés) ;
   la contrainte est relâchée en mobile (voir media query plus bas). Le
   header fixe réserve déjà var(--header-height) via le padding-top de
   <main> : on la retranche ici pour que header + hero remplissent
   exactement 100vh, sans déborder de la hauteur d'écran. */
/* La section occupe toute la largeur de l'écran : c'est ce qui permet à
   la courbe fantôme d'aller jusqu'au bord droit avec un simple right:0,
   sans calcul en 100vw (qui inclut la barre de défilement et provoque un
   scroll horizontal). Le contenu, lui, reste dans la colonne centrée
   .hero__inner. */
.hero {
  position: relative;
  overflow: hidden;
}

/* Le contenu se répartit sur toute la hauteur d'écran. Le padding haut
   redonne au groupe titre+pitch sa respiration d'origine, et deux cales
   souples (voir .hero__spacer) partagent l'espace libre restant 4/1
   entre le dessus et le dessous des témoignages. */
.hero__inner {
  min-height: calc(100vh - var(--header-height));
  max-width: var(--max-width);
  margin: 0 auto;
  padding: clamp(48px, 7vh, 80px) 20px 20px;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

/* Léger décalage vers le bas du groupe libellé + titre + pitch. */
.hero__intro {
  margin-top: 10px;
}

.hero__spacer {
  flex-shrink: 0;
}

.hero__spacer--top {
  flex-grow: 4;
}

.hero__spacer--bottom {
  flex-grow: 1;
}

/* Nappe de couleur diffuse dans la partie droite du hero : deux dégradés
   radiaux superposés, centrés vers le coin haut-droit et décalés l'un
   par rapport à l'autre pour un léger glissement de teinte. Aucun
   masque ni bord : chaque dégradé s'éteint dans sa propre teinte
   transparente, il n'y a donc ni limite nette ni halo marqué. Leur
   étendue les tient à l'écart de la colonne de texte et de la bande
   des témoignages. */
.hero__wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    radial-gradient(ellipse 58% 62% at 90% 12%, var(--wash-1) 0%, var(--wash-1-fade) 72%),
    radial-gradient(ellipse 40% 46% at 74% 34%, var(--wash-2) 0%, var(--wash-2-fade) 74%);
}

/* Le titre, le pitch et les témoignages restent au premier plan. */
.hero__intro,
.hero__testimonials,
.hero__hint {
  position: relative;
  z-index: 1;
}

.hero__eyebrow {
  font-family: var(--font-title);
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--accent);
  margin-bottom: 18px;
  text-transform: uppercase;
}

/* La taille dépend de la largeur ET de la hauteur (min de 2 unités) :
   sur un écran court (1280x720 typiquement), le titre se réduit tout
   seul pour que le hero tienne dans l'écran, sans point de rupture. */
.hero__title {
  font-size: clamp(34px, min(5.6vw, 7.8vh), 72px);
  line-height: 1;
  letter-spacing: -0.03em;
  max-width: 19ch;
}

.hero__pitch {
  font-size: clamp(16px, min(1.45vw, 2.28vh), 20px);
  line-height: 1.5;
  max-width: 60ch;
  margin-top: 20px;
  color: rgba(var(--text-rgb), 0.72);
}

.hero__hint {
  margin-top: 0;
  text-align: center;
}

.hero__hint-arrow {
  display: inline-block;
  animation: bob 1.8s ease-in-out infinite;
  font-size: 18px;
  color: var(--text-faint);
}

/* ==========================================================================
   "En direct" — scrollytelling
   ========================================================================== */
.live {
  position: relative;
  height: 380vh;
  /* Panneau volontairement toujours sombre (voir --live-panel-bg/text) :
     on réaligne --text/--text-rgb sur les valeurs "texte sur fond sombre"
     pour tout ce qui est à l'intérieur, quel que soit le thème actif. */
  --text: var(--text-on-dark);
  --text-rgb: var(--text-on-dark-rgb);
}

.live__panel {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  background: var(--live-panel-bg);
  color: var(--live-panel-text);
}

.live__glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 78% 40%, var(--glow-color) 0%, transparent 60%);
  opacity: 0.12;
  transition: opacity 0.2s linear;
  pointer-events: none;
}

.live__grid {
  position: relative;
  height: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 62px 20px 34px;
  display: grid;
  grid-template-columns: 0.82fr 1.18fr;
  gap: 44px;
  align-items: center;
}

/* Même traitement que les autres intitulés de section (RÉSULTATS,
   COMPÉTENCES) : 12px, interlettrage 1px, capitales. */
.live__tag {
  font-family: var(--font-title);
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--accent-bright);
  display: flex;
  align-items: center;
  gap: 9px;
}

.live__dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--live-dot-color);
  box-shadow: 0 0 12px var(--live-dot-color);
  flex-shrink: 0;
}

.live__intro {
  margin-top: 20px;
  font-size: clamp(19px, 2.2vw, 26px);
  line-height: 1.32;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: rgba(var(--text-rgb), 0.85);
}

.live__steps {
  margin-top: 26px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Les 4 points et leur texte sont TOUJOURS visibles (jamais perdus au
   scroll) : la progression ne fait que déplacer une mise en valeur
   (fond + opacité) le long de la liste, elle ne révèle pas de contenu. */
.live__step {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 10px 12px;
  border-radius: var(--radius-md);
  transition: background var(--transition-fast), opacity var(--transition-fast);
  opacity: 0.55;
}

.live__step.is-done {
  opacity: 0.85;
}

.live__step.is-active {
  opacity: 1;
  background: rgba(var(--text-rgb), 0.09);
}

.live__step-desc {
  font-size: 13px;
  line-height: 1.5;
  color: rgba(var(--text-rgb), 0.62);
  margin-top: 6px;
  max-width: 42ch;
}

.live__step-mark {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  margin-top: 2px;
  border-radius: var(--radius-pill);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-title);
  font-size: 12px;
  font-weight: 600;
  background: rgba(var(--text-rgb), 0.12);
  color: rgba(var(--text-rgb), 0.6);
}

.live__step.is-active .live__step-mark,
.live__step.is-done .live__step-mark {
  background: var(--accent-bright);
  color: var(--bg-dark);
}

.live__step-k {
  font-size: 15px;
  font-weight: 600;
}

.live__step-tools {
  font-family: var(--font-title);
  font-size: 11px;
  color: rgba(var(--text-rgb), 0.5);
  margin-top: 2px;
}

.live__stats {
  display: flex;
  gap: 44px;
  margin-bottom: 18px;
}

.live__stat-label {
  font-family: var(--font-title);
  font-size: 11px;
  color: rgba(var(--text-rgb), 0.5);
  letter-spacing: 0.5px;
}

.live__stat-value {
  font-family: var(--font-title);
  font-size: clamp(30px, 3.6vw, 46px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--accent-brighter);
  font-variant-numeric: tabular-nums;
}

.live__chart {
  width: 100%;
  height: auto;
}

.live__chart-line {
  fill: none;
  stroke: var(--accent-brighter);
  stroke-width: 3.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.live__chart-gridline {
  stroke: rgb(var(--text-rgb));
}

#fillg-start,
#fillg-end {
  stop-color: var(--accent);
}

#live-dot-halo,
#live-dot {
  fill: var(--accent-brighter);
}

/* ==========================================================================
   Résultats — onglets E-commerce / Lead gen
   ========================================================================== */
/* Un peu plus d'air sous les cartes avant la section suivante. */
#resultats .section-inner {
  padding-bottom: 128px;
}

.cases-tablist {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  margin-bottom: 28px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
}

.cases-tab {
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 600;
  padding: 9px 20px;
  border: none;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

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

.cases-tab[aria-selected="true"] {
  background: var(--text);
  color: var(--bg);
}

.cases-panel {
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.cases-panel.is-entering {
  opacity: 0;
  transform: translateY(8px);
}

.cases {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

.case-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 30px;
}

.case-card__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.case-card__title {
  font-size: 18px;
}

/* Note de période partagée par les 2 KPI (ex : "Sur 8 mois") : à côté du
   titre, jamais accrochée à un seul des deux chiffres qu'elle concerne. */
.case-card__period {
  font-family: var(--font-title);
  font-size: 11px;
  color: var(--text-faint);
  white-space: nowrap;
}

/* Les 2 KPI principaux : l'élément le plus visible de la carte. */
.case-card__kpis {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  margin-top: 18px;
}

.case-card__kpi-figure {
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.case-card__kpi-value {
  font-family: var(--font-title);
  font-size: clamp(32px, 3.6vw, 42px);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.case-card__kpi-label {
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  opacity: 0.75;
}

.case-card__kpi-note {
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 4px;
}

/* Constat / Mise en œuvre : deux temps clairement étiquetés, séparés
   d'une demi-ligne, pour distinguer la situation de départ du travail
   réellement effectué. */
.case-card__label {
  font-family: var(--font-title);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 4px;
}

/* Le travail effectué prime sur le constat : c'est lui qui est en
   couleur pleine, le constat reste en retrait. */
.case-card__constat {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-muted);
}

.case-card__actions {
  font-size: 14px;
  line-height: 1.6;
  font-weight: 500;
  color: var(--text);
}

.case-card__step {
  margin-top: 22px;
}

.case-card__step + .case-card__step {
  margin-top: 0.8em;
}

/* ==========================================================================
   Sections sombres génériques (Compétences, Outils)
   ========================================================================== */
.dark-section {
  background: var(--bg-dark);
  color: var(--text-on-dark);
}

/* ==========================================================================
   Compétences
   ========================================================================== */
.skill-groups {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 44px 60px;
}

.skill-group__name {
  font-family: var(--font-title);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--accent-bright);
  margin-bottom: 18px;
  text-transform: uppercase;
}

.skill {
  margin-bottom: 14px;
}

.skill__name {
  font-size: 15px;
  margin-bottom: 6px;
}

.skill-bar {
  max-width: 60%;
  height: 7px;
  background: rgba(var(--text-on-dark-rgb), 0.12);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.skill-bar__fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-bright));
  border-radius: var(--radius-pill);
  transition: width 0.15s linear;
}

.tech-tags {
  margin-top: 36px;
}

.tech-tags__label {
  font-family: var(--font-title);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--accent-bright);
  margin-bottom: 16px;
  text-transform: uppercase;
}

.tag-list {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.tag {
  font-family: var(--font-title);
  font-size: 12px;
  padding: 8px 15px;
  border: 1px solid var(--border-on-dark-strong);
  border-radius: var(--radius-pill);
}

/* Variante pour les tags posés sur une carte claire (Certifications &
   à-côtés) : le liseré par défaut est clair, donc invisible sur ce fond. */
.tag--light {
  border-color: var(--border-strong);
  color: var(--text);
}

/* ==========================================================================
   Outils & projets IA
   ========================================================================== */
.outils {
  position: relative;
  overflow: hidden;
}

/* Compétences et Outils sont deux blocs sombres consécutifs : sans
   marque, la jointure est invisible. Filet d'1px pleine largeur posé
   sur le haut de la section, estompé vers les deux bords. */
.outils::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    to right,
    var(--divider-line-fade) 0%,
    var(--divider-line) 50%,
    var(--divider-line-fade) 100%
  );
}

.outils__inner {
  position: relative;
  z-index: 1;
}

/* Constellation : un noyau de particules reliées entre elles au centre
   (canvas, voir js/main.js → initOutilsNetwork) et les 5 outils qui
   gravitent autour, chacun relié au noyau par un trait. Les outils
   dérivent lentement ; le canvas relit leur position à chaque frame,
   les traits suivent donc tout seuls. */
.outils__orbit {
  position: relative;
  min-height: 660px;
  margin-top: 44px;
}

.outils__network {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}

.tool-row {
  position: absolute;
  z-index: 1;
  width: 262px;
  will-change: transform;
}

/* Positions autour du noyau : haut, bas et côtés, la zone centrale
   restant libre pour l'amas de points. */
.outils__orbit .tool-row:nth-of-type(1) { top: 0; left: 0; }
.outils__orbit .tool-row:nth-of-type(2) { top: 20%; right: 0; }
.outils__orbit .tool-row:nth-of-type(3) { top: 43%; left: 0; }
.outils__orbit .tool-row:nth-of-type(4) { bottom: 0; right: 4%; }
.outils__orbit .tool-row:nth-of-type(5) { bottom: 4%; left: 3%; }

/* La pastille numérotée est le point d'ancrage du trait vers le noyau. */
.tool-row__n {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-bottom: 12px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--accent);
  font-family: var(--font-title);
  font-size: 11px;
  font-weight: 600;
  color: var(--accent-bright);
}

.tool-row__title {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.tool-row__desc {
  font-size: 13px;
  line-height: 1.55;
  color: rgba(var(--text-on-dark-rgb), 0.72);
  margin-top: 7px;
}

/* ==========================================================================
   Parcours
   ========================================================================== */
/* Titre au-dessus du contenu (et non plus en colonne latérale collante) :
   le contenu occupe ainsi toute la largeur et reste centré dans la page.

   La séparation entre sous-sections repose uniquement sur l'espace et la
   typographie, sans filet : l'écart AU-DESSUS du sous-titre est bien plus
   grand que celui qui le sépare de son contenu, si bien que chaque titre
   se rattache visuellement au bloc qu'il introduit. Les trois sous-titres
   partagent le même traitement, ce qui les tient ensemble comme
   sous-parties d'une seule section. */
.parcours-block {
  margin-top: clamp(76px, 8vw, 118px);
}

.parcours-block:first-of-type {
  margin-top: 0;
}

.parcours-block__title {
  font-size: 28px;
  margin-bottom: 30px;
}

/* Expériences (60%) et Formations (40%) côte à côte. Les deux blocs
   perdent leur marge haute puisqu'ils démarrent au même niveau, et
   align-items: start laisse Formations en haut de sa colonne au lieu de
   s'étirer sur la hauteur d'Expériences. */
.parcours-cols {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: clamp(48px, 5.5vw, 88px);
  align-items: start;
}

.parcours-cols .parcours-block {
  margin-top: 0;
}

/* La colonne Formations déborde de 16px hors de la colonne de contenu
   pour porter son espace utile à 440px. Ce débordement reste absorbé par
   le padding latéral de la section, il ne crée donc pas de scroll
   horizontal. */
.parcours-cols .parcours-block:last-child {
  margin-right: -16px;
}

/* ---- Expérience : même langage que les formations (liste à puce, pas
   de cadre), avec en plus l'entreprise, la description, et les missions
   annexes en retrait pour les subordonner sans les effacer. ---- */
.xp-list {
  display: grid;
  gap: 26px;
}

.xp-row {
  position: relative;
  padding: 0 0 0 16px;
}

.xp-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--accent);
}

.xp-row__title {
  font-family: var(--font-title);
  font-size: 18px;
  font-weight: 600;
  line-height: 1.3;
}

.xp-row__period {
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  margin-left: 8px;
  white-space: nowrap;
}

.xp-row__org {
  font-size: 14px;
  color: var(--text-muted);
  margin-top: 4px;
}

.xp-row__desc {
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-muted);
  margin-top: 10px;
  max-width: 92ch;
}

/* Missions annexes : mises en retrait derrière un filet neutre plutôt
   qu'atténuées davantage, pour rester lisibles tout en passant
   clairement au second plan. */
.xp-row__extra {
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
  margin-top: 12px;
  padding-left: 14px;
  border-left: 1px solid var(--border);
  max-width: 92ch;
}

.xp-row__extra-label {
  font-family: var(--font-title);
  font-weight: 600;
}

/* ---- Formations : liste à puce, l'année suit directement l'intitulé.
   Pas de filet de séparation. ---- */
.formation-list {
  display: grid;
  gap: 6px;
}

.formation-row {
  position: relative;
  padding: 8px 0 8px 16px;
}

.formation-row::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.05em;
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--accent);
}

.formation-row__year {
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  margin-left: 8px;
  white-space: nowrap;
}

.formation-row__title {
  font-size: 18px;
  font-weight: 600;
  line-height: 1.3;
}

.formation-row__org {
  font-size: 14px;
  color: var(--text-muted);
  margin-top: 4px;
}

/* ---- Sites web : grille 2x2, les 4 sites au même niveau. Aucun cadre
   arrondi ni ombre : seul le visuel reçoit un aplat neutre, qui sert de
   fond commun aux mockups (dont les fonds sont transparents). ---- */
.site-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px 26px;
}

.site-cell {
  text-align: center;
}

/* Ratio fixe + object-fit: contain = les 4 zones image ont exactement la
   même hauteur, et chaque mockup est cadré en entier, sans déformation
   ni recadrage, malgré des proportions sources différentes. */
/* Pas d'aplat derrière les mockups : leurs fonds sont transparents, ils
   se posent donc directement sur le fond de page.

   Le ratio de la zone est calé sur celui du mockup le plus large
   (peinture-domasky, 1400x781 ~ 1.79). Conséquence : c'est la HAUTEUR
   qui contraint tous les autres mockups, plus étroits, et les quatre
   images se rendent donc à hauteur identique. Avec un ratio plus haut,
   les mockups en 1400x908 dépassaient visuellement les autres. */
.site-cell__visual {
  aspect-ratio: 1400 / 781;
  margin-bottom: 16px;
}

.site-cell__visual img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
}

.site-cell__name {
  margin: 0;
  font-family: var(--font-title);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

.site-cell__name a {
  color: var(--accent);
}

.site-cell__name a:hover,
.site-cell__name a:focus-visible {
  text-decoration: underline;
}

.site-cell__meta {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 5px;
}

/* Année de création, mise en avant comme dans la liste des formations. */
.site-cell__year {
  font-family: var(--font-title);
  font-weight: 600;
  color: var(--accent);
}

/* ---- Certifications & à-côtés : cartes ---- */
.info-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  gap: 20px;
}

.info-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px;
}

.info-card__tag {
  font-family: var(--font-title);
  font-size: 11px;
  letter-spacing: 1px;
  color: var(--text-faint);
  margin-bottom: 14px;
  text-transform: uppercase;
}

.info-card__count {
  font-family: var(--font-title);
  font-size: 13px;
  color: var(--accent);
  margin-bottom: 16px;
}

/* Colonne de droite : plusieurs sous-parties dans une seule carte, avec
   les mêmes intitulés discrets que les autres cartes (.info-card__tag).
   L'écart entre sous-parties est bien plus grand que celui qui sépare un
   intitulé de son contenu, pour que chacun se rattache au sien. */
.aside-group + .aside-group {
  margin-top: 26px;
}

.aside-list {
  display: grid;
  gap: 6px;
}

.aside-list li {
  font-size: 14px;
}

.aside-list__level {
  color: var(--text-muted);
}

/* Deux colonnes en flux vertical : les 11 intitulés se répartissent et
   s'équilibrent d'eux-mêmes, sans les trous que laisserait une grille
   ligne par ligne (le premier intitulé, complet, tient sur 2 lignes). */
.cert-list {
  columns: 2;
  column-gap: 26px;
}

.cert-list li {
  position: relative;
  padding-left: 14px;
  margin-bottom: 9px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-muted);
  break-inside: avoid;
}

.cert-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 1px;
  background: var(--accent);
}

/* ---- Témoignages : dans le hero, sous le titre/pitch (voir .hero plus
   haut). Cartes basées sur --surface/--border comme le reste du site
   (cas clients, sites web) : claires en thème clair, sombres en thème
   sombre — jamais un bloc sombre fixe qui casserait l'équilibre du hero
   clair. Hauteur volontairement compacte (citation tronquée à 3 lignes)
   pour tenir dans le budget vertical du hero avec le titre et le pitch. ---- */
.testimonials-wrap {
  display: flex;
  align-items: stretch;
  gap: 14px;
}

.testimonials {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.testimonials::-webkit-scrollbar {
  display: none;
}

/* Traitement éditorial : aucune boîte (ni fond, ni bord, ni ombre, ni
   arrondi). Un simple filet vertical sépare les deux témoignages. */
.testimonial {
  scroll-snap-align: start;
  flex: 0 0 calc(50% - 10px);
  min-width: 240px;
}

.testimonial + .testimonial {
  border-left: 1px solid var(--border);
  padding-left: 20px;
}

.testimonial figure {
  margin: 0;
}

.testimonial__quote {
  margin: 0;
}

/* Guillemet d'ouverture en accent, posé au-dessus de la citation. */
.testimonial__quote::before {
  content: "\201C";
  display: block;
  font-family: var(--font-body);
  font-size: 34px;
  font-weight: 600;
  line-height: 0.7;
  color: var(--accent);
}

.testimonial__quote p {
  margin-top: 10px;
  font-size: 15px;
  line-height: 1.5;
  font-weight: 500;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.testimonial__author {
  margin-top: 14px;
}

.testimonial__name {
  display: block;
  font-family: var(--font-title);
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.testimonial__role {
  display: block;
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* Indicateurs de position : de simples traits, cible de clic 26x20 pour
   rester confortablement cliquables malgré leur finesse. */
.testimonials-dots {
  display: flex;
  gap: 6px;
  margin-top: 14px;
}

.testimonials-dot {
  position: relative;
  width: 26px;
  height: 20px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

.testimonials-dot::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  background: var(--border-strong);
  transition: background var(--transition-fast);
}

.testimonials-dot[aria-current="true"]::before {
  background: var(--accent);
}

.testimonials-next {
  flex-shrink: 0;
  align-self: center;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--text);
  font-size: 15px;
  font-family: var(--font-body);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.testimonials-next:hover,
.testimonials-next:focus-visible {
  background: var(--text);
  color: var(--bg);
}

.testimonials-next:disabled {
  opacity: 0.3;
  cursor: default;
}

/* ==========================================================================
   Contact
   ========================================================================== */
.contact {
  background: var(--contact-bg);
  color: var(--contact-text);
}

.contact .eyebrow {
  color: var(--contact-text);
  opacity: 0.7;
}

.contact__title {
  font-size: clamp(34px, 5.2vw, 64px);
  line-height: 1.02;
  max-width: 18ch;
}

.contact__actions {
  display: flex;
  gap: 14px;
  margin-top: 40px;
  flex-wrap: wrap;
}

.contact__action {
  font-family: var(--font-title);
  font-size: 14px;
  font-weight: 600;
  padding: 16px 28px;
  border-radius: var(--radius-md);
  transition: transform var(--transition-fast);
}

.contact__action:hover,
.contact__action:focus-visible {
  transform: translateY(-2px);
}

.contact__action--primary {
  background: var(--contact-button-bg);
  color: var(--contact-button-text);
}

.contact__action--secondary {
  background: rgba(var(--contact-text-rgb), 0.12);
  border: 1px solid rgba(var(--contact-text-rgb), 0.3);
}

/* ==========================================================================
   Placeholders — contenu à fournir plus tard
   ========================================================================== */
.placeholder {
  color: var(--text-faint);
}

/* .placeholder est pensé pour un fond clair (texte sombre semi-transparent) ;
   sur les fonds sombres/colorés, on hérite plutôt de la couleur ambiante en
   l'atténuant, pour rester lisible (ex : bouton email de la section Contact). */
.dark-section .placeholder,
.live .placeholder,
.contact .placeholder,
.testimonial .placeholder {
  color: inherit;
  opacity: 0.6;
}

/* Écran desktop court (1280x720, 1366x768…) : le hero doit tenir dans
   l'écran sans rogner le titre. On resserre l'interligne du hero et on
   raccourcit les citations d'une ligne — uniquement ici. Sur les écrans
   hauts (1440x900 et plus), la version généreuse est conservée telle
   quelle. */
@media (min-width: 901px) and (max-height: 820px) {
  .hero__inner {
    padding-top: clamp(28px, 4vh, 48px);
  }

  /* Écran court : l'espace libre est réduit, on garantit un minimum
     d'air autour des témoignages plutôt que de les coller au reste. */
  .hero__spacer {
    min-height: 18px;
  }

  .testimonial__quote p {
    -webkit-line-clamp: 2;
    line-clamp: 2;
  }
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 900px) {
  /* ---- Navigation : menu déroulant sous le bouton burger ---- */
  .nav-toggle {
    display: block;
    /* Le menu étant en position absolue, il ne pousse plus rien dans le
       flux : c'est cette marge auto qui renvoie le bouton à droite. */
    margin-left: auto;
  }

  .nav-cta {
    display: none;
  }

  .main-nav__contact {
    display: block;
  }

  .main-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    justify-content: flex-start;
    gap: 0;
    overflow: hidden;
    max-height: 0;
    background: var(--bg);
    border-bottom: 1px solid transparent;
    transition: max-height 0.25s ease, border-color 0.25s ease;
  }

  .main-nav.is-open {
    max-height: 70vh;
    overflow-y: auto;
    border-bottom-color: var(--border);
  }

  .main-nav a {
    font-size: 15px;
    padding: 14px 20px;
    border-radius: 0;
    border-top: 1px solid var(--border);
    color: var(--text);
  }

  .main-nav a[aria-current="true"] {
    background: transparent;
    color: var(--accent);
  }

  /* Sélecteur porté au même niveau que .main-nav a, qui sinon l'emporte
     et remettrait ce lien en couleur de texte normale. */
  .main-nav a.main-nav__contact {
    font-weight: 600;
    color: var(--accent);
  }

  /* ---- Mon profil : le panneau n'est plus épinglé. Sur un écran court,
     le contenu épinglé débordait et la courbe passait sous la ligne de
     flottaison. Il défile donc normalement, et l'animation est pilotée
     par la position de la section à l'écran (voir initLiveSection). ---- */
  .live {
    height: auto;
  }

  .live__panel {
    position: static;
    height: auto;
    overflow: visible;
  }

  .live__grid {
    grid-template-columns: 1fr;
    height: auto;
    padding: 64px 20px;
    gap: 30px;
  }

  .live__stats {
    gap: 30px;
    margin-bottom: 14px;
  }

  .skill-groups,
  .cases,
  .info-grid {
    grid-template-columns: 1fr;
  }

  /* Jauges de compétences en pleine largeur : à 60% elles devenaient
     trop courtes pour se lire. */
  .skill-bar {
    max-width: 100%;
  }

  /* Certifications : une seule colonne. */
  .cert-list {
    columns: 1;
  }

  /* La contrainte "hero = exactement 100vh" ne vaut que pour le desktop :
     en mobile, on laisse le contenu respirer normalement. */
  /* Espacements posés en marges explicites plutôt qu'en gap uniforme :
     l'écart au-dessus des témoignages est conservé tel quel, seul celui
     du dessous est resserré pour que les citations, désormais affichées
     en entier, s'étendent vers le bas sans repousser le titre. */
  .hero__inner {
    min-height: auto;
    padding-top: 90px;
    padding-bottom: 12px;
    gap: 0;
  }

  .hero__testimonials {
    margin-top: 36px;
  }

  .hero__hint {
    margin-top: 16px;
  }

  /* Citations affichées en entier : plus de troncature à 3 lignes. */
  .testimonial__quote p {
    display: block;
    -webkit-line-clamp: unset;
    line-clamp: unset;
    overflow: visible;
  }

  /* Un seul témoignage à la fois : le filet vertical n'a plus lieu d'être. */
  .testimonial {
    flex-basis: 100%;
    min-width: 220px;
  }

  .testimonial + .testimonial {
    border-left: none;
    padding-left: 0;
  }

  /* Courbe fantôme repoussée en bas du hero et fortement atténuée pour
     ne jamais passer derrière le titre ni le pitch. */
  /* Mobile : plus de répartition verticale, le contenu s'enchaîne. */
  .hero__spacer {
    display: none;
  }

  /* Expériences / Formations : les deux colonnes s'empilent. */
  .parcours-cols {
    grid-template-columns: 1fr;
  }

  .parcours-cols .parcours-block + .parcours-block {
    margin-top: 56px;
  }

  /* Colonnes empilées : plus de débordement à droite. */
  .parcours-cols .parcours-block:last-child {
    margin-right: 0;
  }

  /* Sites web : la grille 2x2 passe sur une seule colonne. */
  .site-grid {
    grid-template-columns: 1fr;
    gap: 28px;
  }

  /* Mobile : les outils redeviennent une simple liste, et la
     constellation reste en fond, allégée (voir js/main.js : moins de
     points, pas de traits vers les outils) et atténuée pour ne pas
     concurrencer le texte. */
  .outils__network {
    opacity: 0.5;
  }

  .outils__orbit {
    min-height: 0;
    margin-top: 32px;
  }

  .outils__orbit .tool-row,
  .outils__orbit .tool-row:nth-of-type(1),
  .outils__orbit .tool-row:nth-of-type(2),
  .outils__orbit .tool-row:nth-of-type(3),
  .outils__orbit .tool-row:nth-of-type(4),
  .outils__orbit .tool-row:nth-of-type(5) {
    position: static;
    width: auto;
    transform: none !important;
    margin-bottom: 30px;
  }

  .outils__orbit .tool-row:last-of-type {
    margin-bottom: 0;
  }

  /* ---- Cibles tactiles : au moins 44px sur les commandes ---- */
  .cases-tab {
    padding: 13px 22px;
    font-size: 14px;
  }

  .testimonials-next {
    width: 44px;
    height: 44px;
    font-size: 17px;
  }

  .testimonials-dot {
    width: 30px;
    height: 44px;
  }

  .contact__action {
    padding: 17px 26px;
  }

  /* Le texte des cas clients gagne en corps sur petit écran. */
  .case-card {
    padding: 24px 22px;
  }

  .case-card__constat,
  .case-card__actions {
    font-size: 15px;
  }

  .case-card__header {
    flex-wrap: wrap;
    gap: 4px 12px;
  }
}

@media (max-width: 640px) {
  .section-inner,
  .hero__inner {
    padding-left: 20px;
    padding-right: 20px;
  }

  .section-inner {
    padding-top: 60px;
    padding-bottom: 60px;
  }

  #resultats .section-inner {
    padding-bottom: 72px;
  }

  /* Titres : on redescend d'un cran pour éviter les coupures de mots. */
  .section-title {
    font-size: clamp(24px, 7vw, 30px);
  }

  .contact__title {
    font-size: clamp(28px, 9vw, 40px);
  }

  .parcours-block__title {
    font-size: 23px;
  }

  .parcours-block {
    margin-top: 64px;
  }

  /* Les deux KPI l'un sous l'autre plutôt que serrés côte à côte. */
  .case-card__kpis {
    gap: 18px;
  }

  .case-card__kpi {
    flex: 1 1 100%;
  }

  .live__intro {
    font-size: 19px;
  }

  .xp-row__desc,
  .xp-row__extra {
    max-width: none;
  }

  /* Le hero n'a plus besoin de la bascule de taille liée à la hauteur. */
  .hero__title {
    font-size: clamp(30px, 8.5vw, 40px);
  }

  .hero__pitch {
    font-size: 16px;
  }

  .contact__actions {
    gap: 12px;
  }

  .contact__action {
    width: 100%;
    text-align: center;
  }
}

/* ==========================================================================
   prefers-reduced-motion — l'état final est déjà atteint sans JS (voir
   js/main.js) ; ce filet CSS neutralise en plus les micro-transitions.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
