@font-face {
  font-family: "Matter";
  src: url("fonts/Matter-Regular.woff2?v=663fdcf8") format("woff2"), url("fonts/Matter-Regular.otf?v=68ea7a5f") format("opentype");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Matter";
  src: url("fonts/Matter-Medium.woff2?v=74ee70d2") format("woff2"), url("fonts/Matter-Medium.otf?v=148b1cb7") format("opentype");
  font-weight: 500;
  font-display: swap;
}

:root {
  --ink: #1d1d1d;
  --muted: #7b7b80;
  --caption: #858585;
  --hero-bg: #f5f5f5;
  --line: #ebebeb;
  --accent: #ffb700;
  --accent-ink: #a25e00;
  --accent-focus: #a25e00;
  --clock-sec: var(--accent);
  --page: #fff;
  --ink-strong: #000;   /* titres et horloge : noir pur en clair, blanc en sombre */
  color-scheme: light;
}
/* Couleur du bouton email tirée au hasard (script dans <head>), la trotteuse suit */
:root[data-accent="bleu"] { --accent: #85d9ff; --accent-ink: #296682; --accent-focus: #296682; }
:root[data-accent="rose"] { --accent: #ffc9c9; --accent-ink: #ad5353; --accent-focus: #ad5353; }
:root[data-accent="noir"] { --accent: #000; --accent-ink: #fff; --accent-focus: #000; --clock-sec: #f00; }
/* Contrastes renforcés (bouton du menu d'accès rapide, ou réglage « plus de contraste » du système) */
:root.contraste { --ink: #000; --muted: #3d3d42; --caption: #474747; }
:root.contraste:not([data-accent="noir"]) { --accent-ink: #000; --accent-focus: #000; }

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-font-smoothing: antialiased; }

body {
  margin: 0;
  overflow-x: clip;
  font-family: "Matter", system-ui, sans-serif;
  font-feature-settings: "ss02" 1;
  color: var(--ink);
  /* Le fond gris s'arrête au milieu du showreel (1030px dans la maquette) */
  background: linear-gradient(var(--hero-bg) 1030px, var(--page) 1030px);
}

img { display: block; max-width: none; }
h1, h2, h3, p, figure { margin: 0; }

/* Lien d'évitement : visible seulement au clavier */
/* Menu d'accès rapide : caché, il descend dès qu'un de ses liens prend le focus (touche Tab) */
.skip {
  position: absolute;
  left: max(16px, env(safe-area-inset-left, 0px));
  top: 16px;
  z-index: 10;
  display: flex;
  gap: 2px;
  padding: 4px;
  border-radius: 200px;
  background: var(--ink);
  font-size: 14px;
  transform: translateY(-200%);
  transition: transform .3s cubic-bezier(.65, 0, .25, 1);
}
.skip:focus-within { transform: none; }
.skip a,
.skip button {
  padding: 6px 12px;
  border-radius: 200px;
  color: var(--page);
  text-decoration: none;
}
.skip button {
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}
.skip button[aria-pressed="true"] { background: var(--page); color: var(--ink); }
.skip a:focus-visible,
.skip button:focus-visible { outline: 2px solid var(--page); outline-offset: -2px; }
.skip button[aria-pressed="true"]:focus-visible { outline-color: var(--accent); }
.works:focus { outline: none; }
@media (prefers-reduced-motion: reduce) { .skip { transition: none; } }
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.project__carousel:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* Bord liquide en haut et en bas de l'écran (liquid-edge.js, Chrome et Edge) */
.liquid-edge {
  position: fixed;
  left: 0;
  right: 0;
  z-index: 9;
  pointer-events: none;
}
.liquid-edge--top { top: 0; }
.liquid-edge--bottom { bottom: 0; }

/* ---------- Hero ---------- */

header.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-block: 177px 0;
  padding-left: max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
}

.hero__icon { width: 40px; height: 40px; flex: none; overflow: visible; }


.hero__intro {
  width: 376px;
  max-width: 100%;
  margin-top: 83px;
  font-size: 28px;
  font-weight: 400;
  line-height: 1.18;
  letter-spacing: -0.03em;
}
.hero__intro span { color: var(--muted); }
.hero__intro .w { color: inherit; }   /* mots découpés pour l'animation d'arrivée : gardent la couleur de leur phrase */

.pill {
  margin-top: 35px;
  padding: 8px 14px;
  border: 1.4px solid var(--accent);
  border-radius: 200px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.02em;
  text-decoration: none;
}
/* Survol : chaque lettre monte, la même arrive du bas (copie en text-shadow) */
.pill__text { display: inline-flex; height: 1.25em; overflow: hidden; vertical-align: top; }
.pill__char {
  display: inline-block;
  white-space: pre;
  text-shadow: 0 1.25em currentColor;
  transition: transform .5s cubic-bezier(.65, 0, .25, 1);
  transition-delay: calc(var(--i) * 14ms);
}
.pill:hover .pill__char,
.pill:focus-visible .pill__char { transform: translateY(-1.25em); }
@media (prefers-reduced-motion: reduce) {
  .pill__char { transition: none; }
}
.pill:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: 3px; }

.showreel {
  position: relative;
  width: 860px;
  max-width: 100%;
  aspect-ratio: 860 / 440;
  margin-top: 132px;
}
.showreel__media,
.showreel__glow {
  position: absolute;
  border-radius: 20px;
  object-fit: cover;
}
.showreel__media { inset: 0; width: 100%; height: 100%; }
/* Ombre : la vidéo elle-même, copiée en petit dans un canvas flouté puis agrandi
   (main.js). L'image floutée sert de fond en attendant la première image. */
.showreel__glow {
  left: -9.302%;
  top: -12.955%;
  width: 118.605%;
  height: 145.455%;
  border-radius: 0;
  pointer-events: none;
  background: url("assets/showreel-glow.png?v=1d1aa17a") center / 100% 100% no-repeat;
}

/* ---------- Travaux ----------
   Desktop : scène de 1440px calée sur la grille de la maquette
   (colonne des légendes jusqu'à 628px, carrousels à partir de 628px).
   Entre 900 et 1440px, main.js la réduit avec zoom. */

.works { margin-top: 240px; overflow-x: clip; }

.works__stage {
  position: relative;
  width: 1440px;
  margin: 0 auto;
  padding-block: 111px 96px;
}
.works__stage .project:last-of-type { margin-bottom: 0; }   /* footer plus proche : seul le padding du bas reste */

/* Lignes verticales de la grille */
.works__stage::before,
.works__stage::after {
  content: "";
  position: absolute;
  top: 15px;
  bottom: 0;
  width: 1px;
  background: var(--line);
}
.works__stage::before { left: 628px; }
.works__stage::after  { left: 1133px; } /* sous le dernier pixel de la 1re image (628 + 506), pour ne pas dépasser */

.fade { position: absolute; display: block; z-index: 4; pointer-events: none; }
.fade--top    { left: 0; top: 0; width: 100%; height: 132px; background: linear-gradient(var(--page), transparent); }
.fade--bottom { left: 0; bottom: 0; width: 100%; height: 200px; background: linear-gradient(transparent, var(--page)); }
.fade--left   { display: none; }

.works__title {
  position: absolute;
  left: 100px;
  top: 81px;
  width: 272px;
  font-size: 28px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.02em;
  text-wrap: balance;
  color: var(--ink-strong);
  /* s'efface quand le premier carrousel défile (--p0, réglé par main.js) */
  opacity: calc(1 - var(--p0, 0));
  transform: translateX(calc(var(--p0, 0) * -24px));
}

.project {
  --slide-h: 496px;
  position: relative;
  display: grid;
  grid-template-columns: 455px 173px minmax(0, 1fr);
  margin-bottom: 160px;
}

/* Lignes horizontales en haut et en bas de chaque carrousel */
.project::before,
.project::after {
  content: "";
  position: absolute;
  left: 372px;
  right: calc(min(0px, (1440px - 100vw) / 2));
  height: 1px;
  /* fondu à gauche, comme dans la maquette */
  background: linear-gradient(90deg, transparent, var(--line) 126px);
}
.project::before { top: 0; }
.project::after  { top: var(--slide-h); }

/* Légende */
.project__label {
  grid-column: 2;
  grid-row: 1;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 96px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
}
/* Le texte passe sous les visuels et s'efface quand ils arrivent (--p, réglé par main.js) */
.project__label > * {
  position: relative;
  z-index: 1;
  opacity: calc(1 - var(--p, 0));
  transform: translateX(calc(var(--p, 0) * -24px));
}
.project__label h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: -41px;
  font-size: 14px;
  font-weight: 500;
  line-height: normal;
  color: var(--ink-strong);
}
.project__label h3 span { white-space: nowrap; }
.pointer {
  position: relative;
  flex: 1;
  min-width: 40px;
  height: 8px;
  opacity: .4;
  mix-blend-mode: difference;
}
.pointer::before {
  content: "";
  position: absolute;
  left: 0;
  right: 7px;
  top: 3.5px;
  height: 1px;
  background: #b3b2b3;
}
.pointer::after {
  content: "";
  position: absolute;
  right: 0;
  top: 0.5px;
  width: 7px;
  height: 7px;
  border: 1px solid #b3b2b3;
  border-radius: 50%;
}
.project__desc { width: 145px; color: var(--caption); }
.project__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
  max-width: 160px;
}
.project__tags li {
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: 200px;
  font-size: 12px;
  color: var(--muted);
}
.project__logo { margin-top: 12px; height: auto; max-width: 150px; }

/* Boutons précédent / suivant (composants Blossom) : sous le carrousel, à droite */
.project__nav {
  position: absolute;
  z-index: 3;
  top: calc(var(--slide-h) + 44px);
  right: calc(40px - max(0px, (100vw - 1440px) / 2));
  display: flex;
  gap: 6px;
}
.project__nav blossom-prev button,
.project__nav blossom-next button {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--hero-bg);
  color: var(--muted);
  cursor: pointer;
  transition: background-color .2s, color .2s, opacity .2s;
}
.project__nav svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.project__nav button:hover { background: var(--line); color: var(--ink); }
.project__nav button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.project__nav button:disabled { opacity: .4; cursor: default; background: var(--hero-bg); color: var(--muted); }

/* Carrousel Blossom */
/* Le carrousel va d'un bord à l'autre de la fenêtre ;
   au repos, le premier visuel est calé sur la ligne des 628px. */
.project__carousel {
  grid-column: 1 / -1;
  grid-row: 1;
  position: relative;
  z-index: 2;
  --bleed: max(0px, (100vw - 1440px) / 2);
  margin-left: calc(-1 * var(--bleed));
  scroll-padding-inline-start: calc(628px + var(--bleed));
  /* les zones vides laissent passer les clics vers les flèches */
  pointer-events: none;
  display: flex;
  gap: 24px;
  inline-size: auto;
  max-inline-size: none;
  margin-right: calc(-1 * var(--bleed));
  padding: 0 120px 72px calc(628px + var(--bleed));
  margin-bottom: -72px;
  scroll-snap-type: x mandatory;
  --snap-type: x mandatory;
}
.slide {
  flex: none;
  height: var(--slide-h);
  overflow: hidden;
  border-radius: 10px;
  background: var(--hero-bg);
  scroll-snap-align: start;
  pointer-events: auto;
  box-shadow: 0 14px 22px rgba(0, 0, 0, .05), 0 40px 40px -20px rgba(0, 0, 0, .22);
}
/* Première image : toujours entre les deux lignes verticales (628 → 1134px) */
.slide:first-child { width: 506px; }

.slide img,
.slide video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}

/* ---------- Mobile : tout repasse dans le flux ---------- */

@media (max-width: 899px) {
  body { background: var(--page); }
  header.hero { background: var(--hero-bg); padding-block: 96px 48px; }
  .hero__intro { font-size: 24px; margin-top: 48px; }
  .showreel { margin-top: 64px; }

  .works { margin-top: 64px; padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); }
  .works__stage { width: auto; padding-block: 0 96px; zoom: 1 !important; }
  .works__stage::before, .works__stage::after,
  .project::before, .project::after, .fade, .pointer { display: none; }

  .works__title { position: static; width: auto; max-width: 272px; margin-bottom: 40px; }

  .project { --slide-h: 260px; display: flex; flex-direction: column; gap: 20px; margin-bottom: 64px; }
  .project__label { padding-top: 0; gap: 8px; }
  .project__label > * { opacity: 1; transform: none; }
  .slide:first-child { width: auto; }
  .project__label h3 { margin-right: 0; font-size: 18px; }
  .project__desc { width: auto; max-width: 40ch; }
  .project__tags { max-width: none; }
  .project__logo { display: none; }
  .project__nav { display: none; }

  .project__carousel {
    order: -1;
    gap: 12px;
    pointer-events: auto;
    margin-inline: calc(-1 * max(16px, env(safe-area-inset-left, 0px))) calc(-1 * max(16px, env(safe-area-inset-right, 0px)));
    padding: 0 16px 40px;
    margin-bottom: -40px;
    scroll-padding-inline: 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .project__carousel { scroll-behavior: auto; }
}

/* ---------- Pages projet (panneau page sheet) ----------
   Le mouvement et le panneau viennent de vendor/page-sheet.css ; ici, le contenu. */

/* Liens vers le projet dans les légendes de l'accueil */
.project__link { color: inherit; text-decoration: none; }
.project__link:hover span { text-decoration: underline; text-underline-offset: 3px; }
.project__more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: fit-content;
  padding: 5px 11px;
  border-radius: 200px;
  background: var(--hero-bg);
  color: var(--ink);
  font-size: 12px;
  text-decoration: none;
  transition: background-color .2s;
}
.project__more { line-height: 1.25; }
.project__more:hover { background: var(--line); }

/* Survol : les deux coins de l'icône s'écartent, avec un léger rebond */
.expand { width: 10px; height: 10px; overflow: visible; }
.expand path { vector-effect: non-scaling-stroke; transition: transform .45s cubic-bezier(.34, 1.8, .5, 1); }
.project__more:hover .expand__ne,
.project__more:focus-visible .expand__ne { transform: translate(2.5px, -2.5px); transition-delay: .12s; }
.project__more:hover .expand__sw,
.project__more:focus-visible .expand__sw { transform: translate(-2.5px, 2.5px); transition-delay: .12s; }
@media (prefers-reduced-motion: reduce) {
  .expand path { transition: none; }
}
.project__link:focus-visible,
.project__more:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.sheet { color: var(--ink); }
/* Couverture : en haut du panneau, avant le titre, avec la même marge sur les côtés et en haut */
.sheet .hero {
  --cover-gap: clamp(10px, 1.4%, 16px);
  margin: var(--cover-gap) var(--cover-gap) 0;
  aspect-ratio: 1974 / 1000;
  overflow: hidden;
  border-radius: 10px;
  background: var(--hero-bg);
}
.sheet .hero img,
.sheet .hero video,
.sheet-media img,
.sheet-media video { display: block; width: 100%; height: 100%; object-fit: cover; }

.copy {
  max-width: 640px;
  margin: 0 auto;
  padding: 88px 24px 72px;
  display: grid;
  gap: 52px;
}
.copy h1 { margin: 0; font-size: 40px; font-weight: 400; line-height: 1.05; letter-spacing: -0.03em; text-wrap: balance; }
.copy__lead { margin: 14px 0 20px; font-size: 22px; line-height: 1.25; letter-spacing: -0.02em; color: var(--muted); }
.copy .project__tags { max-width: none; }
.copy__part h2 {
  margin: 0 0 14px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--caption);
}
.copy__part p { margin: 0 0 14px; font-size: 17px; line-height: 1.55; }
.copy__part a { color: inherit; text-underline-offset: 3px; }
.copy__credits {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 8px 24px;
  margin: 20px 0 0;
  font-size: 15px;
  line-height: 1.4;
}
.copy__credits dt { color: var(--caption); }
.copy__credits dd { margin: 0; }

/* Visuels : même disposition que le site actuel (pleine largeur, 50/50, texte à côté d'un visuel).
   Deux colonnes au centre (920px max) et une marge de chaque côté, pour les visuels bord à bord. */
.sheet-gallery {
  display: grid;
  grid-template-columns: [full-start] minmax(16px, 1fr) [content-start] minmax(0, 448px) minmax(0, 448px) [content-end] minmax(16px, 1fr) [full-end];
  gap: 24px;
}
.sheet-gallery > * { grid-column: content; }
.sheet-gallery > .is-left { grid-column: 2; }
.sheet-gallery > .is-right { grid-column: 3; }
.sheet-media {
  margin: 0;
  max-width: 100%;
  overflow: hidden;
  border-radius: 10px;
  background: var(--hero-bg);
}
.sheet-media--narrow { width: 59%; justify-self: center; }   /* 729px sur 1240 dans le site actuel */
.sheet-gallery > .sheet-media--bleed { grid-column: full; border-radius: 0; }
.sheet-text {
  align-self: center;
  padding: 0 clamp(16px, 5%, 56px);
}
.sheet-text p { font-size: 15px; line-height: 1.55; }

.copy--end { padding-top: 104px; padding-bottom: 0; }
.sheet .hero + .copy { padding-top: 72px; }

.sheet-cta {
  max-width: 640px;
  margin: 0 auto;
  padding: 104px 24px 140px;
  display: grid;
  justify-items: start;
  gap: 24px;
}
.sheet-cta p { margin: 0; font-size: 28px; line-height: 1.18; letter-spacing: -0.03em; }
.sheet-cta p span { display: block; color: var(--muted); }
.sheet-cta .pill { margin: 0; }

/* Page introuvable */
.notfound {
  min-height: 100vh;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 16px;
  padding-inline: max(16px, env(safe-area-inset-left, 0px)) max(16px, env(safe-area-inset-right, 0px));
  text-align: center;
}
.notfound h1 { margin: 0; font-size: 28px; font-weight: 400; letter-spacing: -0.03em; }
.notfound p { margin: 0; color: var(--muted); }
.notfound .pill { margin: 8px 0 0; }
.notfound .notfound__en { margin-top: 24px; font-size: 14px; }
.notfound__en a { color: inherit; }

@media (max-width: 751px) {
  .copy { padding: 44px 20px 48px; gap: 40px; }
  .copy h1 { font-size: 32px; }
  .copy__lead { font-size: 19px; }
  .copy__credits { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .copy__credits dd { margin-bottom: 10px; }
  .sheet-gallery { gap: 12px; grid-template-columns: [full-start] 0 [content-start] minmax(0, 1fr) [content-end] 0 [full-end]; }
  .sheet-gallery > .is-left, .sheet-gallery > .is-right { grid-column: content; }
  .sheet-media--narrow { width: 100%; }
  .sheet-text { padding: 28px 8px; }
  .copy--end { padding-top: 64px; }
  .sheet-cta { padding: 72px 20px 96px; }
  .sheet-cta p { font-size: 24px; }
}

/* ---------- Pied de page : contact, réseaux, langue (même langage que le haut de page) ----------
   Calé sur la grille des projets (1440 px, réduite comme elle entre 900 et 1440 px) :
   texte, email et réseaux à gauche sous le titre « Quelques travaux… » (100 px),
   interrupteur sur la ligne verticale où commencent les images (628 px),
   © à droite sur les flèches du carrousel (40 px du bord de l'écran). */

.site-foot {
  --u: calc(min(100vw, 1440px) / 1440);
  background: var(--hero-bg);
}
.site-foot__in {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* en bas : au-dessus de la bande du bord liquide (5 % de l'écran), qui déformerait le texte */
  padding-block: 112px calc(5vh + 32px);
  padding-left: calc((100vw - min(100vw, 1440px)) / 2 + 100 * var(--u));
  padding-right: calc(40 * var(--u));
}
/* même texte que l'accroche du haut : 376px, 28px, 2e phrase en gris */
.site-foot__cta {
  width: 376px;
  max-width: 100%;
  font-size: 28px;
  line-height: 1.18;
  letter-spacing: -0.03em;
}
.site-foot__cta span { color: var(--muted); }

.site-foot__bar {
  display: grid;
  grid-template-columns: calc(528 * var(--u)) auto 1fr;
  align-items: center;
  width: 100%;
  margin-top: 112px;
  color: var(--muted);
  font-size: 13px;
  letter-spacing: -0.01em;
}
.site-foot__social { display: flex; gap: 20px; margin: 0; padding: 0; list-style: none; }
.site-foot__social a { color: inherit; text-decoration: none; transition: color .2s; }
.site-foot__social a:hover { color: var(--ink); }
.site-foot__social a:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: 3px; }
.site-foot__copy { justify-self: end; }

@media (max-width: 899px) {
  .site-foot__in { padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); }
  .site-foot__bar { grid-template-columns: 1fr auto 1fr; gap: 24px; }
}
@media (max-width: 751px) {
  .site-foot__in { padding-top: 96px; }
  .site-foot__cta { width: auto; font-size: 24px; }
  .site-foot__bar { grid-template-columns: 1fr auto; row-gap: 28px; margin-top: 96px; }
  .site-foot .lang-switch { grid-column: 1 / -1; grid-row: 1; justify-self: start; }
}

.lang-switch {
  --pad: 3px;
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 84px;
  height: 32px;
  padding: var(--pad);
  border-radius: 200px;
  background: var(--page);
}
/* Le rond : deux formes identiques, la 2e part un peu après la 1re ;
   le filtre les fait fusionner, d'où l'étirement liquide pendant le trajet. */
.lang-switch__goo {
  position: absolute;
  inset: var(--pad);
  filter: url(#lang-goo);
  pointer-events: none;
}
.lang-switch__goo i {
  position: absolute;
  inset: 0 50% 0 0;
  border-radius: 200px;
  background: var(--accent);
  /* le 1er rond file et dépasse un peu, le 2e traîne derrière : un col se forme puis se résorbe */
  transition: transform .6s cubic-bezier(.65, 0, .25, 1.2);
}
.lang-switch__goo i + i { transition: transform .75s cubic-bezier(.6, 0, .3, 1) .14s; }
.lang-switch[data-lang="en"] .lang-switch__goo i { transform: translateX(100%); }

.lang-switch a {
  position: relative;
  display: grid;
  place-items: center;
  border-radius: 200px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.02em;
  text-decoration: none;
  transition: color .3s .25s;
}
.lang-switch[data-lang="fr"] a[lang="fr"],
.lang-switch[data-lang="en"] a[lang="en"] { color: var(--accent-ink); }
.lang-switch a:hover { color: var(--ink); }
.lang-switch a:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .lang-switch__goo i, .lang-switch a { transition: none; }
}

/* ---------- Animation d'arrivée (accueil) ----------
   Classe .intro posée dans <head> avant l'affichage : pas de flash.
   Tout est en CSS : si un script échoue, la page s'affiche quand même.
   « backwards » : rien ne reste appliqué une fois l'animation finie. */

:root { --intro-ease: cubic-bezier(.16, 1, .3, 1); }

/* L'horloge : le cadran se trace d'un trait depuis midi, les 4 points perlent
   dans le sens des aiguilles d'une montre, les aiguilles poussent depuis le centre
   sur midi puis tournent vite jusqu'à l'heure réelle (rotation : main.js). */
/* le pointillé n'existe que pendant le tracé : ensuite le cercle et les aiguilles redeviennent pleins (pas de jour à la jointure) */
@keyframes clock-draw {
  from { stroke-dasharray: 1 2; stroke-dashoffset: 1; }
  to   { stroke-dasharray: 1 2; stroke-dashoffset: 0; }
}
@keyframes clock-dot {
  from { opacity: 0; transform: scale(0); }
  to   { opacity: 1; transform: none; }
}
.clock__dot { transform-box: fill-box; transform-origin: center; }
/* le texte s'écrit mot par mot : chaque mot sort d'un flou profond en remontant un peu */
@keyframes intro-word {
  0%   { opacity: 0; filter: blur(14px); transform: translateY(.3em) scale(1.04); }
  45%  { opacity: .85; }
  100% { opacity: 1; filter: blur(0); transform: none; }
}
@keyframes intro-show { from { opacity: 0; } }
/* le mail : un point de couleur apparaît au centre, s'étire en pilule, puis l'adresse se révèle */
@keyframes pill-open {
  0%   { opacity: 0; clip-path: inset(0 calc(50% - 1.2em) round 200px); }
  22%  { opacity: 1; clip-path: inset(0 calc(50% - 1.2em) round 200px); animation-timing-function: cubic-bezier(.7, 0, .15, 1); }
  100% { opacity: 1; clip-path: inset(0 0 round 200px); }
}
@keyframes pill-text { from { color: transparent; } }
@keyframes intro-rise {
  from { opacity: 0; transform: translateY(80px) scale(.94); }
  to   { opacity: 1; transform: none; }
}
@keyframes intro-fade {
  from { opacity: 0; transform: translateY(40px); }
  to   { opacity: 1; transform: none; }
}

/* ordre : le texte s'écrit, puis l'horloge (goutte), le mail, le showreel, les projets */
.intro .clock { --c: .6s; }   /* finit avec le dernier mot du texte (~2,5 s) */
.intro .clock__dial { animation: clock-draw .85s cubic-bezier(.65, 0, .35, 1) var(--c) backwards; }
.intro .clock__dot { animation: clock-dot .45s cubic-bezier(.34, 1.8, .5, 1) calc(var(--c) + .2s + var(--d) * 170ms) backwards; }
.intro .clock line { animation: clock-draw .35s var(--intro-ease) calc(var(--c) + .7s) backwards; }
.intro .hero__intro .w {
  display: inline-block;
  animation: intro-word 1.1s cubic-bezier(.22, .8, .25, 1) calc(.15s + var(--i) * 36ms) backwards;
}
/* si le découpage n'a pas eu lieu (script bloqué), le texte apparaît d'un bloc */
.intro .hero__intro:not(.is-split) { animation: intro-show .8s ease .15s backwards; }
.intro header .pill {
  animation: pill-open 1s linear 2.2s backwards, pill-text .5s ease 2.9s backwards;
}
.intro .showreel {
  animation: intro-rise 1.4s var(--intro-ease) 2.6s backwards;
}
.intro .works {
  animation: intro-fade 1.2s var(--intro-ease) 2.9s backwards;
}

/* ---------- Arrivée du footer (main.js) : même effet que le haut, au moment où il entre à l'écran ----------
   Les animations sont posées en pause (l'état de départ s'affiche grâce à « backwards »),
   puis lancées par la classe .foot-in. Sans script, le footer s'affiche normalement. */
.foot-reveal .site-foot__cta .w {
  display: inline-block;
  animation: intro-word 1.1s cubic-bezier(.22, .8, .25, 1) calc(.05s + var(--i) * 36ms) backwards;
}
/* le footer est aligné à gauche : la pilule part d'un point à gauche et s'étire vers la droite */
@keyframes pill-open-left {
  0%   { opacity: 0; clip-path: inset(0 calc(100% - 2.4em) 0 0 round 200px); }
  22%  { opacity: 1; clip-path: inset(0 calc(100% - 2.4em) 0 0 round 200px); animation-timing-function: cubic-bezier(.7, 0, .15, 1); }
  100% { opacity: 1; clip-path: inset(0 0 0 0 round 200px); }
}
.foot-reveal .pill {
  animation: pill-open-left 1s linear .55s backwards, pill-text .5s ease 1.25s backwards;
}
/* l'interrupteur : même ouverture que la pilule email, mais depuis le centre (comme en haut) */
.foot-reveal .lang-switch { animation: pill-open 1s linear .9s backwards; }
/* le rond de couleur n'arrive qu'une fois la pilule blanche ouverte (sinon il dépasse dans le point du départ) */
@keyframes toggle-blob { from { opacity: 0; transform: scale(.6); } }
.foot-reveal .lang-switch__goo { animation: toggle-blob .5s cubic-bezier(.34, 1.5, .5, 1) 1.65s backwards; }
.foot-reveal .lang-switch a { animation: pill-text .5s ease 1.65s backwards; }
.foot-reveal .site-foot__cta .w, .foot-reveal .pill, .foot-reveal .lang-switch, .foot-reveal .lang-switch__goo, .foot-reveal .lang-switch a { animation-play-state: paused; }
.foot-in .site-foot__cta .w, .foot-in .pill, .foot-in .lang-switch, .foot-in .lang-switch__goo, .foot-in .lang-switch a { animation-play-state: running; }

/* ---------- Carrousels en pile (exemple « Smart Stack » de Blossom) ----------
   Un visuel carré à la fois, calé entre les deux lignes verticales (628 → 1134 px).
   En glissant, la carte qui sort rétrécit à 80 % et la suivante grandit : l'échelle suit
   la position de chaque carte dans le carrousel (view-timeline), sans JavaScript.
   Navigateurs sans cette fonction (Firefox) : même pile, sans le changement d'échelle. */
.project:has(.project__carousel--stack) { --slide-h: 506px; }
/* La pile part de la ligne des 628 px et va jusqu'au bord droit de la fenêtre :
   les cartes suivantes restent visibles à 80 %. À gauche, les cartes qui sortent
   disparaissent sur la ligne. */
.project__carousel--stack {
  --card: 506px;
  grid-column: 3;
  width: auto;
  margin: 0 calc(-1 * var(--bleed)) -72px 0;
  /* à droite : de quoi amener la dernière carte au bord gauche ; en bas : place pour l'ombre */
  padding: 0 calc(306px + var(--bleed)) 72px 0;
  scroll-padding-inline: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--card);
  gap: 0;
  pointer-events: auto;
}
.project__carousel--stack .slide {
  width: 100%;
  height: var(--slide-h);
  overflow: visible;
  border-radius: 0;
  background: none;
  box-shadow: none;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  view-timeline-name: --slide;
  view-timeline-axis: inline;
  /* zone de mesure ramenée à la place de la carte principale (comme l'exemple Blossom
     sur un carrousel d'une carte) : taille normale calée au bord gauche, 80 % dès qu'elle
     s'en éloigne d'environ 0,7 carte */
  view-timeline-inset: calc(var(--card) * .3) calc(100% - var(--card) * .7);
}
.slide__in {
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 10px;
  background: var(--hero-bg);
  box-shadow: 0 14px 22px rgba(0, 0, 0, .05), 0 40px 40px -20px rgba(0, 0, 0, .22);
}
@keyframes stack-slide {
  0%   { scale: .8; }
  50%  { scale: 1; }
  100% { scale: .8; }
}
@supports (animation-timeline: view()) {
  .slide__in {
    animation: stack-slide cubic-bezier(0, .5, 1, .5) both;
    animation-timeline: --slide;
    animation-range: cover;
  }
}
@media (max-width: 899px) {
  .project:has(.project__carousel--stack) { --slide-h: auto; }
  .project__carousel--stack { --card: calc(100vw - 32px); width: 100%; margin: 0 0 -64px; padding: 0 0 64px; grid-auto-columns: 100%; }
  .project__carousel--stack .slide { height: auto; aspect-ratio: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .slide__in { animation: none; }
}

/* ---------- Golden hour (clic sur l'horloge, main.js) ----------
   Un ciel derrière la page : dégradé à 4 couleurs, soleil (ou lune) flou qui monte et
   descend selon l'heure, grain léger. Les fonds de la page deviennent transparents ;
   quand le ciel est sombre (.sky-dark), le texte passe en clair. Les visuels ne sont pas teintés.
   .golden : fonds transparents ; .golden-sky : ciel visible (fondu de 1,2 s). */
@property --sky-1 { syntax: "<color>"; inherits: true; initial-value: #fff; }
@property --sky-2 { syntax: "<color>"; inherits: true; initial-value: #fff; }
@property --sky-3 { syntax: "<color>"; inherits: true; initial-value: #fff; }
@property --sky-4 { syntax: "<color>"; inherits: true; initial-value: #fff; }
@property --sun-c { syntax: "<color>"; inherits: true; initial-value: #fff; }
@property --sun-y { syntax: "<percentage>"; inherits: true; initial-value: 50%; }
@property --sun-x { syntax: "<percentage>"; inherits: true; initial-value: 50%; }
@property --sun-s { syntax: "<length>"; inherits: true; initial-value: 300px; }
@property --sun-o { syntax: "<number>"; inherits: true; initial-value: 0; }
.ambiance {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  background: linear-gradient(var(--sky-1) 0%, var(--sky-2) 34%, var(--sky-3) 66%, var(--sky-4) 100%);
}
/* le soleil : un disque très flou, un peu écrasé, avec un halo plus large autour */
.ambiance::before,
.ambiance::after {
  content: "";
  position: absolute;
  left: var(--sun-x);
  top: var(--sun-y);
  width: var(--sun-s);
  aspect-ratio: 1.15;
  border-radius: 50%;
  background: var(--sun-c);
  opacity: var(--sun-o);
  transform: translate(-50%, -50%);
  filter: blur(calc(var(--sun-s) * .12));
  transition: left .8s ease, top .8s ease, width .8s ease, opacity .8s ease, --sun-c .8s ease;
}
.ambiance::after {
  width: calc(var(--sun-s) * 1.9);
  opacity: calc(var(--sun-o) * .35);
  filter: blur(calc(var(--sun-s) * .35));
}
/* grain */
.ambiance i {
  position: absolute;
  inset: 0;
  opacity: .22;
  mix-blend-mode: overlay;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Le ciel n'habille que le haut de page : en arrivant sur les projets, il s'efface
   en fondu vers le blanc (--sky-fade, de 0 à 1, réglé au scroll par main.js). */
@property --sky-on { syntax: "<number>"; inherits: true; initial-value: 0; }
.ambiance { opacity: calc(var(--sky-on) * (1 - var(--sky-fade, 0))); transition: --sky-on 1.2s ease, --sky-1 .8s ease, --sky-2 .8s ease, --sky-3 .8s ease, --sky-4 .8s ease; }
.golden-sky { --sky-on: 1; }
/* sous le ciel, le même fond que la page normale : quand le ciel s'efface, on retombe
   exactement sur ce que la page affichera, sans saut */
html.golden { background: linear-gradient(var(--hero-bg) 1030px, var(--page) 1030px); }
.golden body,
.golden header.hero { background: transparent; }
/* ciel coloré : texte du haut de page en blanc */
/* ciel coloré : texte du haut de page en blanc. Lié au ciel visible (.golden-sky) pour que
   le texte et l'horloge changent de couleur en fondu, à l'aller comme au retour. */
header.hero { transition: color .9s ease, text-shadow .9s ease, background-color .9s ease; }
.hero__intro span { transition: color .9s ease; }
/* mobile : le haut de page a son propre fond gris, il revient en fondu */
@media (max-width: 899px) { html.golden { background: var(--page); } }
.clock [stroke="#000"], .clock [fill="#000"] { transition: stroke .9s ease, fill .9s ease; }
.clock__sec { transition: stroke .9s ease; }
.golden-sky.sky-dark header.hero {
  --ink: #fff;
  --clock-sec: rgba(255, 255, 255, .55);   /* trotteuse : blanc transparent sur le ciel */
  --muted: rgba(255, 255, 255, .72);
  color: var(--ink);
  text-shadow: 0 1px 14px rgba(0, 0, 0, .18);
}
.golden-sky.sky-dark header.hero .pill { text-shadow: none; }
.golden-sky.sky-dark .clock [stroke="#000"] { stroke: var(--ink); }
.golden-sky.sky-dark .clock [fill="#000"] { fill: var(--ink); }
/* le dégradé blanc du haut des projets ferait un bord net sur le ciel qui s'efface */
.golden .fade--top { display: none; }
.clock { cursor: pointer; border-radius: 50%; outline: none; -webkit-tap-highlight-color: transparent; }
.clock:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: 4px; }
@media (prefers-reduced-motion: reduce) { .ambiance, .ambiance::before, .ambiance::after { transition: none; } }


/* ---------- Thème sombre ----------
   Automatique selon le réglage de l'appareil ; l'interrupteur du pied de page le force
   (data-theme="dark" ou "light" sur <html>, posé avant l'affichage par le script du <head>). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
  --ink: #ededeb;
  --muted: #8e8e94;
  --caption: #8a8a8f;
  --hero-bg: #141414;
  --line: #272727;
  --page: #0b0b0b;
  --ink-strong: #fff;
  --sheet-bg: #161616;
  --sheet-dim-color: #000;
  --sheet-dim: .6;
  color-scheme: dark;
  }
  :root:not([data-theme="light"])[data-accent="noir"] { --accent: #fff; --accent-ink: #000; --accent-focus: #fff; }
  :root:not([data-theme="light"]).contraste { --ink: #fff; --muted: #c4c4c9; --caption: #bdbdbd; }
  :root:not([data-theme="light"]) .project__logo { filter: invert(1); }
}
:root[data-theme="dark"] {
  --ink: #ededeb;
  --muted: #8e8e94;
  --caption: #8a8a8f;
  --hero-bg: #141414;
  --line: #272727;
  --page: #0b0b0b;
  --ink-strong: #fff;
  --sheet-bg: #161616;
  --sheet-dim-color: #000;
  --sheet-dim: .6;
  color-scheme: dark;
}
:root[data-theme="dark"][data-accent="noir"] { --accent: #fff; --accent-ink: #000; --accent-focus: #fff; }
:root[data-theme="dark"].contraste { --ink: #fff; --muted: #c4c4c9; --caption: #bdbdbd; }
:root[data-theme="dark"] .project__logo { filter: invert(1); }
.clock [stroke="#000"] { stroke: var(--ink-strong); }
.clock [fill="#000"] { fill: var(--ink-strong); }
.sheet-handle::before { background: var(--ink-strong); }

/* changement de thème au clic : fondu bref des couleurs (pas des mouvements) */
.theme-anim, .theme-anim *:not(.lang-switch__goo i) {
  transition: background-color .4s ease, color .4s ease, border-color .4s ease, fill .4s ease, stroke .4s ease !important;
}

/* Interrupteur clair / sombre : même pilule et même goutte que celui de la langue */
.site-foot__bar { grid-template-columns: calc(528 * var(--u)) auto auto 1fr; }
.theme-switch { margin-left: 8px; }
.theme-switch[data-mode="dark"] .lang-switch__goo i { transform: translateX(100%); }
.theme-switch button {
  position: relative;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 200px;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color .3s .25s;
}
.theme-switch svg { width: 16px; height: 16px; }
.theme-switch[data-mode="light"] button[data-mode="light"],
.theme-switch[data-mode="dark"] button[data-mode="dark"] { color: var(--accent-ink); }
.theme-switch button:hover { color: var(--ink); }
.theme-switch button:focus-visible { outline: 2px solid var(--accent-focus); outline-offset: 2px; }
.foot-reveal .theme-switch button { animation: pill-text .5s ease 1.75s backwards; animation-play-state: paused; }
.foot-in .theme-switch button { animation-play-state: running; }
@media (max-width: 899px) {
  .site-foot__bar { grid-template-columns: 1fr auto auto 1fr; }
}
@media (max-width: 751px) {
  .site-foot__bar { grid-template-columns: 1fr auto; }
  .site-foot .lang-switch { grid-column: 1; }
  .site-foot .theme-switch { grid-column: 2; grid-row: 1; justify-self: end; margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) { .theme-switch button { transition: none; } }
