/* ---------- 0. Polices auto-hébergées ----------
   Geist et Sarina sont sous licence SIL Open Font, l'auto-hébergement est permis.
   Servies depuis le domaine plutôt que depuis fonts.gstatic.com : l'adresse IP du
   visiteur ne part plus chez un tiers, et on économise deux résolutions DNS.
   Geist est variable (axe wght 100-900), d'où une seule déclaration pour 400 et 500.
   unicode-range limite le téléchargement au sous-ensemble réellement utilisé :
   latin seul dans la plupart des cas, latin-ext uniquement si la page contient un
   caractère qui l'exige. Les jeux cyrillique et vietnamien ne sont pas embarqués. */

@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('assets/fonts/geist-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Geist';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('assets/fonts/geist-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Sarina';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/sarina-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Sarina';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/sarina-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* =========================================================
   Portfolio — valeurs relevées sur le site de référence
   Breakpoints mesurés : 500px (mobile) → 1703px (desktop)
   ========================================================= */

/* ---------- 1. Jetons ---------- */
:root {
  /* couleurs (palette Tailwind gray, comme la référence) */
  --ink:   #030712;   /* gray-950 : titres et texte courant */
  --dim:   #9ca3af;   /* gray-400 : lignes grisées du hero  */
  --muted: #6b7280;   /* gray-500 : labels, dates, méta     */
  --rule:  #e5e7eb;   /* gray-200 : filets de séparation    */
  --bg:    #ffffff;

  /* gouttière : 20px à 500px → 120px à 1703px */
  --gut: clamp(1.25rem, 8.31vw - 1.35rem, 7.5rem);
  /* gap de la grille : 32px → 80px */
  --gap: clamp(2rem, 0.75rem + 3.99vw, 5rem);
  /* Rythme vertical des sections. Valeur FIXE, pas fluide : c'est ce qui
     garantit un espace identique de part et d'autre du filet gris.
     contenu → --rule-gap → filet → --rule-gap → contenu */
  --rule-gap: 7.5rem;   /* 120px */
  --mod-gap:  7.5rem;   /* écart entre deux modules de la page projet */

  --f: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Substitution de lettre : les M sont dessinés en Sarina, en contour bleu.
     Valeurs MESURÉES sur les glyphes (voir NOTES.md), au même corps que le
     texte : rapporté au cadratin, le « m » de Sarina fait 0,514 de haut contre
     0,544 pour Geist — 94 %, donc pas d'agrandissement nécessaire.
     Sa largeur, elle, fait 1,311 contre 0,734 : c'est elle qui produit le
     chevauchement, sans truquage. */
  --alt:        "Sarina", cursive;
  --alt-size:   1em;         /* même corps que le texte qui l'entoure */
  --alt-shift:  0.038em;     /* centre la lettre sur la bande d'x */
  --alt-inset:  -0.138em;    /* lui rend l'avance d'un m normal */
  --alt-stroke: #1a2bff;     /* contour de la lettre substituée */
  --alt-fill:   #ffffff;     /* son intérieur ; `transparent` pour l'évider */
}

/* ---------- 2. Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
/* l'en-tête est fixe : les ancres doivent s'arrêter en dessous */
:target, .sect, .hero { scroll-margin-top: 68px; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 1rem/1.5 var(--f);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  margin: 0;
  font-weight: 500;
  letter-spacing: -0.045em;   /* constante sur tout le site */
}

/* le min() par la hauteur garantit que le hero tient dans l'écran,
   même sur un portable 13" où la fenêtre fait ~760px de haut */
h1 {
  font-size: min(clamp(2.5rem, 0.94rem + 4.99vw, 6.25rem), 11.5vh);
  line-height: 0.95;
}
h2 { font-size: clamp(1.75rem, 0.71rem + 3.32vw, 4.25rem); line-height: 1;    }
h3 { font-size: clamp(1.25rem, 0.85rem + 1.26vw, 2.2rem);  line-height: 1.1;  }

p { margin: 0; }
ul, ol, dl { margin: 0; padding: 0; list-style: none; }
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

/* Lien d'évitement (RGAA 12.7) : premier élément focusable de la page, il permet
   de sauter l'en-tête pour atteindre directement le contenu. Hors écran tant
   qu'il n'a pas le focus — pas display:none, qui le retirerait de l'ordre de
   tabulation et le rendrait inatteignable. */
.skip {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 100;
  transform: translate(-50%, -100%);
  padding: 0.75rem 1.5rem;
  background: var(--ink);
  color: var(--bg);
  font-size: 0.9375rem;
  border-radius: 0 0 0.5rem 0.5rem;
}
.skip:focus { transform: translate(-50%, 0); }
/* <main> porte tabindex="-1" pour que le focus s'y pose vraiment. Il n'est pas
   dans l'ordre de tabulation : pas de contour à afficher sur tout le bloc. */
main:focus { outline: none; }

/* Liens en plein texte (page 404, corps des modules) : soulignés en permanence
   et non au seul survol. Un lien qui ne se distingue que par sa couleur ne
   satisfait pas le RGAA 10.6 ; le trait s'épaissit au survol pour le retour. */
.notfound__links a,
.mod__body p > a {
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0 100%;
  background-repeat: no-repeat;
  background-size: 100% 1px;
  transition: background-size 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.notfound__links a:hover,
.mod__body p > a:hover { background-size: 100% 2px; }
.notfound__links { display: flex; flex-direction: column; gap: 0.5rem; }

/* Soulignement au survol, commun à tous les liens de navigation et de contact.
   Le dégradé de 1px animé en background-size remplace le « + » qui les préfixait :
   text-decoration ne s'anime pas, un dégradé si. Même mécanique que les titres
   de projets, mais deux fois plus rapide — sur un lien de 15px, une transition
   d'une demi-seconde donne une impression de latence. */
.head__nav a,
.head__contact,
.menu a,
.foot__mail,
.foot__social a {
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0 100%;
  background-repeat: no-repeat;
  background-size: 0 1px;
  /* Le trait se positionne sur la boîte de CONTENU et non sur celle de padding.
     Sans ça, les liens de réseaux — qui ont 4px de padding vertical pour leur
     zone cliquable — voient leur soulignement descendre de 4px et déborder de
     8px de chaque côté, alors que « Écris-moi », sans padding, reste collé au
     texte. Les deux traits sont maintenant au même endroit. */
  background-origin: content-box;
  transition: background-size 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.head__nav a:hover,
.head__contact:hover,
.menu a:hover,
.foot__mail:hover,
.foot__social a:hover { background-size: 100% 1px; }

/* placeholders : à supprimer quand les vraies images arrivent */
.ph {
  display: grid;
  place-items: center;
  font: 400 0.8125rem/1 var(--f);
  letter-spacing: normal;
  background:
    repeating-linear-gradient(135deg, var(--rule) 0 1px, transparent 1px 12px),
    #f8f9fa;
  color: var(--muted);
  font-size: 0.8125rem;
}
.ph::after { content: attr(data-ph); }

/* ---------- 3. Grille maîtresse : 1fr 2fr ---------- */
.grid {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: var(--gap);
  align-items: start;
}

.inner { max-width: 100%; }

.sect { padding-inline: var(--gut); }
.sect > .inner {
  border-top: 1px solid var(--rule);
  padding-block: var(--rule-gap);
}

/* étiquette de section : « 01 » dans la colonne 1, intitulé dans la colonne 2 */
.label {
  margin-bottom: 2rem;
  font-size: 0.9375rem;   /* 15px */
  font-weight: 500;
}
.label--solo { margin-bottom: 3.5rem; }

/* ---------- 4. Hero ---------- */
.hero {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 7.25rem var(--gut) 3rem;   /* 116px / 48px */
}

/* texte centré sur toute la largeur du conteneur.
   Le corps est fluide : 28px en mobile, 70px au-delà de 1700px.
   Le retrait latéral n'est plus décoratif : il raccourcit la ligne, ce qui évite
   des lignes trop longues sur un bloc centré. */
.hero__title {
  padding-inline: clamp(0rem, 6.5vw - 1rem, 7rem);
  text-align: center;
  text-wrap: balance;                 /* équilibre la dernière ligne */
  font-size: clamp(1.75rem, 4.2vw, 4.375rem);
  line-height: 1.02;
  font-weight: 500;
  letter-spacing: -0.045em;           /* la constante du site */
}

/* La lettre substituée. line-height: 0 est indispensable : sans lui, un corps
   plus grand agrandit la boîte de ligne et décale tout l'interlignage du bloc. */
.alt {
  font-family: var(--alt, cursive);
  font-size: var(--alt-size, 1em);
  line-height: 0;                    /* sinon la boîte de ligne grandit */
  letter-spacing: normal;
  vertical-align: var(--alt-shift, 0);
  margin-inline: var(--alt-inset, 0);   /* négatif : la lettre reprend l'avance d'un
                                        m normal et son encre passe par-dessus */
  position: relative;                /* la fait peindre au-dessus des voisines */

  /* Intérieur blanc, contour bleu. Le fond masque les lettres noires que la
     scripte recouvre — c'est lui qui la fait lire comme posée par-dessus le mot
     plutôt que mêlée à lui. L'ordre de peinture du texte étant fond puis
     contour, le trait reste visible sur toute son épaisseur. */
  color: var(--alt-fill, #ffffff);
  -webkit-text-stroke: 0.04em var(--alt-stroke, #1a2bff);
}

/* Emplacement d'icône inséré dans le texte. Dimensionné en em : il suit donc
   le corps du titre à toutes les tailles d'écran, sans réglage supplémentaire.
   vertical-align le pose par rapport à la ligne de base plutôt qu'au milieu
   de la ligne, sinon la pastille flotte trop haut. */
.slot {
  display: inline-block;
  width: 0.92em;
  height: 0.92em;
  margin-inline: 0.08em;
  vertical-align: -0.14em;
  overflow: hidden;   /* recadre le SVG ou l'image au carré */
  font-style: normal;
}
.slot > * {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* emplacement encore vide : même repère que les autres placeholders du site */
.slot:empty {
  background:
    repeating-linear-gradient(135deg, var(--rule) 0 1px, transparent 1px 7px),
    #eceded;
}

.facts {
  display: flex;
  justify-content: center;   /* centré sous le titre, comme la maquette */
  gap: 57px;
  margin-top: 2.5rem;
}
.facts dt,
.facts dd {
  font-size: 0.9375rem;  /* 15px pour le label ET pour la valeur */
  line-height: 1.5;
}
.facts dt { color: var(--muted); }
.facts dd { margin: 0; }

/* ---------- 5. Logos clients ---------- */
.logos {
  display: flex;
  flex-wrap: wrap;
}
.logos li {
  flex: 0 0 25%;          /* 4 par ligne */
  height: 120px;
  display: grid;
  place-items: center;
}
.logos .ph { width: min(70%, 12rem); height: 80px; }
.marquee .ph { width: 100%; height: 100%; }

.logos img,
.marquee img {
  width: auto;
  max-width: 85%;
  max-height: 80px;
  object-fit: contain;   /* jamais de déformation, quel que soit le format */
  filter: grayscale(1);
}
.logos img { height: 80px; }
.marquee img { max-height: 3.25rem; }

.marquee { display: none; overflow: hidden; }
.marquee__row {
  display: flex;
  align-items: center;
  gap: 2.5rem;
  padding-right: 2.5rem;
  flex: 0 0 auto;
}
/* boîte fixe et généreuse : le logo ne peut jamais être comprimé */
.marquee__row li {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 9.5rem;
  height: 5rem;
}
.marquee__track { display: flex; width: max-content; animation: slide 32s linear infinite; }
@keyframes slide { to { transform: translateX(-50%); } }

/* ---------- 6. À propos ---------- */
/* la photo occupe ~53 % de la colonne 1, en ratio 2:3 */
.about__photo {
  width: 53%;
  aspect-ratio: 2 / 3;
  object-fit: cover;   /* le ratio 2:3 est imposé : on recadre, on ne déforme pas */
}

/* la colonne de texte est un flex vertical à gap 24px : c'est lui qui gère
   tous les espacements internes, aucun margin sur le h2 ni sur le paragraphe */
.about__text {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.lede {
  max-width: 46.25rem;   /* 740px : bridé, pas toute la colonne */
  font-size: 0.9375rem;  /* 15px */
  line-height: 1.5;
  color: var(--ink);
}

.tags {
  display: flex;
  gap: 1.5rem;          /* 24px, pas la gouttière de la grille */
  margin-top: 1rem;
}
.tags ul {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.tags li {
  font-weight: 400;
  font-size: 1.125rem;    /* 18px en desktop, 16px en mobile */
  line-height: 1.5;
  letter-spacing: -0.014em;
}

/* ---------- 7. Projets : une ligne par projet ---------- */
.row {
  padding-block: 2rem;              /* 32px */
  transition: opacity 0.4s;
}
/* sinon la dernière ligne ajoute 32px sous le contenu que le haut n'a pas */
.row:last-child { padding-bottom: 0; }
.label + .row { padding-top: 0; }

/* colonne de gauche : même module de 24px que la section 01, aucun margin */
.row__text {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.row__text > p {
  font-size: 0.9375rem;   /* 15px */
  line-height: 1.5;
  color: var(--ink);      /* et non du gris : c'est bien l'encre */
}

/* soulignement animé du titre : un dégradé de 1px dont la largeur passe de 0 à 100 %.
   box-decoration-break garde le trait correct sur un titre qui passe à la ligne. */
.row__underline {
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  background-image: linear-gradient(var(--ink), var(--ink));
  background-position: 0 90%;
  background-repeat: no-repeat;
  background-size: 0 1px;
  transition: background-size 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.row:hover .row__underline { background-size: 100% 1px; }

.row__shot {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 2;    /* ratio mesuré : 920 × 613 */
  width: 100%;
}
.row__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}
.row:hover .row__shot img { transform: scale(1.04); }

/* les autres projets s'effacent quand on en survole un */
#work:has(.row:hover) .row:not(:hover) { opacity: 0.4; }

/* --- pastilles --- */
.pill {
  padding: 0.45em 0.9em;
  border-radius: 999px;
  background: #eeedf3;
  color: var(--ink);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  line-height: 1.5;
  white-space: nowrap;
}

/* version mobile : dans la colonne de texte */
.tags-left {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.tags-overlay { display: none; }

/* CTA de carte projet. C'est un <span> et non un <a> : la carte entière est déjà
   un lien, et un lien imbriqué dans un lien est invalide. Le clic passe par le
   grand lien, et le libellé s'ajoute à son nom accessible.
   Affiché selon (hover: none) plutôt que selon une largeur : la vraie question
   n'est pas « l'écran est-il petit » mais « l'appareil sait-il survoler ». Une
   tablette en 1024px n'a aucun survol et reçoit donc le CTA ; une fenêtre de
   bureau rétrécie sait survoler et garde le soulignement du titre. */
.row__cta { display: none; }
@media (hover: none) {
  .row__cta {
    display: inline-block;
    align-self: flex-start;   /* sinon le trait court sur toute la colonne */
    font-size: 0.9375rem;
    font-weight: 500;
    background-image: linear-gradient(currentColor, currentColor);
    background-position: 0 100%;
    background-repeat: no-repeat;
    background-size: 100% 1px;
  }
}

@media (min-width: 768px) {
  /* Les tags ne sont pas masqués en display:none mais rendus invisibles à l'œil
     tout en restant lisibles par un lecteur d'écran. Sinon, sur desktop, plus
     personne ne reçoit l'information : la version colonne est retirée du DOM
     accessible et la surimpression porte aria-hidden. */
  .tags-left {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* version desktop : en surimpression en haut à gauche de l'image */
  .tags-overlay {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 10;
    pointer-events: none;
  }
  .tags-overlay .pill {
    background: rgba(255, 255, 255, 0.75);
    opacity: 0;
    visibility: hidden;
    transform: translateY(20px);
    will-change: transform, opacity;
  }
  .row:hover .tags-overlay .pill {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }
  /* apparition en cascade : 50ms de décalage entre chaque pastille */
  .tags-overlay .pill:nth-child(1),
  .row:not(:hover) .tags-overlay .pill:nth-child(1) { transition: opacity .35s cubic-bezier(.17,.17,.2,1), transform .35s cubic-bezier(.17,.17,.2,1), visibility .35s cubic-bezier(.17,.17,.2,1); }
  .tags-overlay .pill:nth-child(2),
  .row:not(:hover) .tags-overlay .pill:nth-child(2) { transition: opacity .35s cubic-bezier(.17,.17,.2,1) 50ms, transform .35s cubic-bezier(.17,.17,.2,1) 50ms, visibility .35s cubic-bezier(.17,.17,.2,1) 50ms; }
  .tags-overlay .pill:nth-child(3),
  .row:not(:hover) .tags-overlay .pill:nth-child(3) { transition: opacity .35s cubic-bezier(.17,.17,.2,1) .1s, transform .35s cubic-bezier(.17,.17,.2,1) .1s, visibility .35s cubic-bezier(.17,.17,.2,1) .1s; }
}

/* ---------- 8. Parcours ---------- */
/* la colonne entière est un flex vertical à gap 40px : titre, chapô, liste */
.path__col {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;   /* 40px */
}

.path {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;   /* 24px */
}

.path li {
  display: flex;
  flex-direction: row;          /* inchangé en mobile : les dates restent à droite */
  justify-content: space-between;
  align-items: flex-start;
  gap: 1.5rem;
}
/* le filet est un border-top sur toutes les lignes sauf la première,
   d'où 24 (gap) + 1 + 24 (padding) = 49px entre deux entrées */
.path li + li {
  border-top: 1px solid var(--rule);
  padding-top: 1.5rem;
}

.path__org {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-weight: 400;
  font-size: 1.375rem;    /* 22px en desktop, 17px en mobile */
  line-height: 1.5;
  letter-spacing: normal;
}
.path__org em {
  font-style: normal;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--muted);
}
.path time {
  flex: none;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--muted);
  text-align: right;
}

/* ---------- 9. En-tête ---------- */
/* En-tête FIXE de 68px, identique en desktop et en mobile.
   C'est lui qui explique le padding-top du hero : 68 (en-tête) + 48 = 116px.
   Sans cette règle, l'en-tête reste dans le flux et les deux s'additionnent. */
.head {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  height: 68px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 18px var(--gut);
  background: var(--bg);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.02em;   /* -0.3px à 15px */
}
.head__id { display: flex; align-items: center; gap: 10px; }
.head__avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  overflow: hidden;
  flex: none;
  object-fit: cover;   /* utile si la classe est posée directement sur l'<img> */
}
/* sans ça, une photo non carrée déforme le cercle */
.head__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* nav et contact regroupés à droite, resserrés à 24px */
.head__nav {
  display: flex;
  gap: 1.5rem;
  margin-left: auto;
}
.head__burger {
  display: none;
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.menu { display: none; }

/* ---------- 10. Pied de page ---------- */
.foot {
  position: relative;
  overflow: hidden;   /* le lettrage peut déborder sans créer de scroll */
}
.foot__inner { padding-inline: var(--gut); }

/* la barre ne suit pas le rythme de 120px des sections : 32px en haut, 40 en bas */
.foot__bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
  border-top: 1px solid var(--rule);
  padding: 2rem 0 2.5rem;
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.02em;
}

.foot__social {
  display: flex;
  gap: 8px;
  margin-right: -8px;   /* compense le padding pour aligner le texte sur la gouttière */
}
.foot__social a { padding: 4px 8px; }

/* En desktop, « Écris-moi » rejoint les réseaux à droite plutôt que de flotter
   au milieu. Le margin-left négatif compense le padding du premier lien : sans
   lui, l'écart optique entre les deux textes serait de 32px et non des 24px
   utilisés dans la nav de l'en-tête. */
@media (min-width: 768px) {
  .foot__mail { margin-left: auto; }
  .foot__social { margin-left: -8px; }
}

/* --- pile de m du pied de page --- */
/* Les positions sont calculées en JS et appliquées en transform : aucune
   propriété de mise en page n'est touchée pendant l'animation, donc le
   navigateur n'a ni à recalculer le flux ni à repeindre le reste de la page. */
.pile {
  position: relative;
  height: clamp(13rem, 24vw, 22rem);
  overflow: hidden;
  user-select: none;
  pointer-events: none;   /* la pile ne doit pas gêner les liens du pied de page */
}
.pile__m {
  position: absolute;
  top: 0;
  left: 0;
  font-size: 40px;   /* seule source de vérité : script.js lit cette valeur */
  font-family: var(--alt, cursive);
  line-height: 1;
  color: var(--alt-fill, #ffffff);
  -webkit-text-stroke: 0.045em var(--alt-stroke, #1a2bff);
  will-change: transform;
}

/* ---------- 11. Page projet : modules assemblables ---------- */
/* Le principe : l'espacement vertical appartient au CONTENEUR, pas aux modules.
   Aucun module ne porte de margin, donc leur ordre n'a aucune importance —
   on peut les couper/coller librement dans le HTML. */
.case {
  display: flex;
  flex-direction: column;
  gap: var(--mod-gap);
  padding-top: 6.75rem;      /* 108px = 68 de l'en-tête fixe + 40 */
  /* le gap ne s'applique qu'ENTRE les modules : sans ce padding, le dernier
     module vient coller au filet du pied de page */
  padding-bottom: 5rem;      /* 80px */
}

/* les modules de texte suivent la gouttière commune du site */
.mod--intro,
.mod--text { padding-inline: var(--gut); }

/* le rail des visuels est plus large que celui du texte : 50px contre 120.
   C'est ce décalage qui fait respirer la page. */
.mod--media,
.mod--duo { padding-inline: clamp(0.75rem, 2.94vw, 3.125rem); }

.mod--duo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}

/* seule règle qui dépend du voisinage : deux blocs de visuels qui se suivent
   se resserrent à 20px au lieu de l'écart standard */
:is(.mod--media, .mod--duo) + :is(.mod--media, .mod--duo) {
  margin-top: calc(20px - var(--mod-gap));
}

/* .media vaut pour une image comme pour une vidéo : object-fit recadre le
   contenu dans le ratio imposé au lieu de le déformer, et display:block
   supprime l'espace que le navigateur réserve sous un élément en ligne. */
.media {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
.media img { display: block; width: 100%; height: auto; }

/* Visuel maté : au lieu de recadrer pour remplir le cadre, on contient le
   contenu en entier et on comble autour. Sert aux formats qui ne correspondent
   pas au ratio du module — une vidéo en 1512x987, une capture de page longue —
   et donne le même fond sombre que les mockups du projet. */
.media--matte {
  object-fit: contain;
  /* la couleur se règle au cas par cas avec --matte posé en style en ligne :
     sombre chez Hutchinson, beige chez Accor, pour rester dans l'univers du
     projet montré. Le sombre reste la valeur par défaut. */
  background: var(--matte, #1D1D1F);
  /* Le padding s'applique à la boîte de contenu d'un élément remplacé : le
     visuel se loge donc à l'intérieur, tandis que le fond continue de peindre
     jusqu'au bord du cadre. C'est ce qui donne la marge sombre tout autour. */
  padding: 8%;
  box-sizing: border-box;
}

/* --- titre et infos --- */
.case__title {
  font-size: clamp(2.4375rem, 5.5vw, 5.85rem);   /* 39px en mobile → 93,5px */
  line-height: 1;
  letter-spacing: -0.04em;
}
/* .facts est mutualisée avec l'accueil, où elle est centrée sous le hero.
   Ici elle s'aligne à gauche sous le titre, avec l'écart relevé de 53px. */
.mod--intro .facts {
  justify-content: flex-start;
  gap: 3.3125rem;      /* 53px */
  margin-top: 2rem;    /* 32px */
}

/* --- module texte --- */
.mod__label {
  font-size: 1.5rem;          /* 24px */
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.03em;
}
.mod__body {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;                /* le module d'espacement du site */
  max-width: 46.25rem;        /* 740px, comme partout ailleurs */
  font-size: 0.9375rem;       /* 15px */
  line-height: 1.5;
  letter-spacing: -0.02em;
}

/* Le chapô. C'est le seul contraste de corps de la page, et il porte toute la
   composition : 22px en poids 500 contre 15px en poids 400 pour les sections.
   Sans ce saut, la page est plate même avec la bonne grille. */
.mod__body--lead {
  font-size: 1.375rem;        /* 22px */
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.03em;
}

/* La chaîne d'étapes du module IA : encadrée de deux filets, elle se détache du
   corps de texte sans changer de taille. Même vocabulaire que les séparateurs
   de sections, donc elle ne crée pas un style de plus. */
.steps {
  padding-block: 1rem;
  border-block: 1px solid var(--rule);
  color: var(--muted);
}

/* Avant / après : même cadre que .steps, mais la chaîne passe en encre et
   l'étiquette reste grise. Deux .steps qui se suivent partagent leur filet,
   sinon le trait du milieu ferait double épaisseur. */
.steps + .steps { border-top: none; }
.steps--ba { color: var(--ink); }
.steps--ba span {
  display: inline-block;
  min-width: 5rem;
  color: var(--muted);
}

/* --- chiffres clés --- */
.stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3.5rem var(--gap);
  margin-top: 2.5rem;
}
.stat__n {
  /* échelle PROPRE aux chiffres : 42px en mobile, 68px en desktop.
     L'échelle du h2 descend à 28px en mobile, ce qui les écrasait. */
  font-size: 4.25rem;   /* 68px */
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.045em;
}
.stat__c {
  margin-top: 0.75rem;
  color: var(--muted);
}

/* ---------- 12. Mobile (< 768px, le point de bascule du site) ---------- */
@media (max-width: 767px) {
  :root { --rule-gap: 4.5rem; }   /* 72px : réduit mais toujours symétrique */

  .head__nav, .head__contact { display: none; }
  .head__burger { display: block; }

  /* overlay plein écran, sous l'en-tête qui reste visible.
     Le padding-top réserve la hauteur de l'en-tête (68px) pour que le
     centrage vertical se fasse dans l'espace restant, pas dans l'écran entier. */
  .menu {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1rem;              /* 16px */
    position: fixed;
    inset: 0;
    z-index: 90;            /* sous l'en-tête (100) */
    padding: 4.25rem var(--gut) 0;
    background: var(--bg);
    font-size: clamp(2.5rem, 14vw, 3.75rem);   /* 60px */
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: -0.045em;
  }
  .menu[hidden] { display: none; }

  /* pas de min-height ni de centrage en mobile : 108px = 68 (en-tête) + 40 */
  .hero {
    min-height: auto;
    justify-content: flex-start;
    padding: 6.75rem var(--gut) 2.5rem;
  }
  /* Aligné à gauche en mobile : sur 6 lignes dans 350px, le bord gauche d'un texte
     centré se déplace de 40px d'une ligne à l'autre, soit 11 % de la largeur contre
     4 % en desktop. Le centrage reste un parti pris jusqu'à 3 lignes ; au-delà il
     oblige l'œil à chercher le début de chaque ligne. Le bloc .facts juste en
     dessous est déjà aligné à gauche. */
  .hero__title {
    padding-inline: 0;
    text-align: left;
  }

  .facts {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 8px 40px;
  }
  .facts__row { display: contents; }        /* label / valeur sur une ligne */

  /* la grille passe en une colonne */
  .grid { grid-template-columns: 1fr; gap: 2rem; }
  /* l'étiquette de section s'écarte : numéro à gauche, intitulé à droite */
  .label.grid {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
  }

  /* les compétences restent sur DEUX colonnes en mobile */
  .tags li { font-size: 1rem; }        /* 16px */
  .path__org { font-size: 1.0625rem; } /* 17px */

  .row { padding-block: 1.75rem; }
  .row__shot { order: -1; }         /* visuel au-dessus du texte */
  .row__text { order: 0; }

  /* logos : marquee au lieu de la grille */
  .logos { display: none; }
  .marquee { display: block; }
  /* la boîte reste à 9.5rem × 5rem : c'est elle qui protège le logo */

  /* la ligne de parcours garde sa mise en page desktop : dates à droite */

  /* page projet */
  :root { --mod-gap: 4.5rem; }

  /* ⚠ .mod--intro .facts (0,2,0) écrase la règle .facts de ce media query (0,1,0).
     Il faut donc remettre l'écart mobile ici, sinon les lignes label/valeur
     héritent des 53px prévus pour le desktop. */
  .mod--intro .facts { gap: 8px 40px; }
  .mod--duo { grid-template-columns: 1fr; gap: 20px; }
  .case { padding-bottom: 3rem; }

  /* pied de page : barre empilée, 80px de padding haut */
  .foot__bar {
    flex-direction: column;
    align-items: flex-start;
    padding: 5rem 0 2.5rem;
  }
  /* les réseaux occupent toute la largeur et s'écartent aux deux bords ;
     les marges négatives compensent le padding des liens */
  .foot__social {
    align-self: stretch;
    justify-content: space-between;
    margin-inline: -8px;
  }

  .stats { grid-template-columns: 1fr; gap: 4rem; }
  .stat__n { font-size: 2.625rem; }   /* 42px */
}

/* ---------- 13. Mouvement réduit ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .marquee__track { animation: none; }
  /* la pile reste affichée, elle ne réagit simplement plus au curseur */
  * { transition-duration: 0.01ms !important; }
}
