* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

:root {
  --ink: #f3efe6;
  --ink-dim: rgba(243, 239, 230, .74);
  --ink-faint: rgba(243, 239, 230, .62);
  --void: #07070a;

  --ease: cubic-bezier(.16,.84,.44,1);
  /* Expo.easeInOut de GSAP — l'entrée de tous les blocs chez Capriati */
  --ease-expo: cubic-bezier(.87,0,.13,1);
  /* le rideau de Capriati, valeur relevée telle quelle */
  --ease-cap: cubic-bezier(.65,.05,.36,1);

  /* multiplicateur de tous les délais d'entrée : 1 à la première visite,
     compressé sur .seen (voir le script inline de index.html) */
  --seq: 1;

  /* une seule formule pour toutes les tailles d'écran */
  /* photo 10 (2026-09) : le visage tient la gauche, le mark rapetisse et se
     pousse à droite pour ne plus le couvrir. --mark-dx / --mark-dy décalent le
     mark depuis le centre ; la tige et l'axe suivent le même décalage */
  --mark-w: min(66vh, 60vw);
  --mark-dx: 8vw;
  --mark-dy: 0px;
  /* la tige du Ø est à 46,56 % de la largeur du mark, soit 3,44 % à gauche du centre */
  --tige-x: calc(50% + var(--mark-dx) - var(--mark-w) * .0344);
  /* débord de la photo par la gauche : la moitié ombrée du visage sort de l'écran */
  --bg-bleed: 30vw;
  --mark-opacity: .38;

  --edge-x: clamp(20px, 4vw, 60px);
  --edge-y: clamp(24px, 5vh, 46px);
  --rail-h: 46px;
  --micro: clamp(10px, .84vw, 11.5px);
}

/* deuxième visite dans la même session : l'intro s'exécute encore, en 4× plus court */
html.seen { --seq: .18; }
html.seen .loader { display: none; }

html, body {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  background: var(--void);
  color: var(--ink);
  font-family: 'Archivo', -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}

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

/* ---------- l'intro ----------
   La tige se TRACE (elle n'apparaît pas), respire une fois, puis se change
   en flash lumineux au moment exact où les deux panneaux s'écartent : c'est
   la lumière qui ouvre le rideau. Elle est posée sur --tige-x, donc le mark
   reprend la main à l'endroit où elle s'éteint.
------------------------------------------------------------------ */
.loader {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  animation: loader-off 0s linear calc(2.6s * var(--seq)) forwards;
}
@keyframes loader-off { to { visibility: hidden; } }

.curtain {
  position: fixed;
  top: 0;
  width: 51%;
  height: 100%;
  z-index: 51;
  background: var(--void);
  transform: translateX(0);
  animation-duration: .85s;
  animation-timing-function: var(--ease-cap);
  animation-delay: calc(1.7s * var(--seq));
  animation-fill-mode: forwards;
}
.curtain-l { left: 0;  animation-name: curtain-l; }
.curtain-r { right: 0; animation-name: curtain-r; }
@keyframes curtain-l { to { transform: translateX(-100%); } }
@keyframes curtain-r { to { transform: translateX(100%); } }

.loader-line {
  position: fixed;
  top: calc(50% + var(--mark-dy));
  left: var(--tige-x);
  z-index: 52;
  width: 1px;
  height: 46vh;
  margin-top: -23vh;
  background: linear-gradient(to bottom, transparent, var(--ink) 22%, var(--ink) 78%, transparent);
  opacity: 0;
  transform-origin: 50% 50%;
  animation:
    line-draw  .75s var(--ease-expo)   calc(.25s * var(--seq)) both,
    line-breath .7s ease-in-out        calc(1s   * var(--seq)),
    line-flare .85s var(--ease-cap)    calc(1.7s * var(--seq)) forwards;
}
@keyframes line-draw {
  from { opacity: 0;   transform: scaleY(0); }
  to   { opacity: .55; transform: scaleY(1); }
}
@keyframes line-breath { 0%, 100% { opacity: .55; } 50% { opacity: .16; } }
@keyframes line-flare {
  0%   { opacity: .55; transform: scaleY(1);    box-shadow: 0 0 0 0 rgba(243,239,230,0); }
  26%  { opacity: 1;   transform: scaleY(1.06); box-shadow: 0 0 34px 5px rgba(243,239,230,.55); }
  100% { opacity: 0;   transform: scaleY(1.3);  box-shadow: 0 0 64px 10px rgba(243,239,230,0); }
}

/* ---------- grain ---------- */
.noise {
  position: fixed;
  inset: -60px;
  z-index: 40;
  pointer-events: none;
  opacity: .05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  animation: grain 1.4s steps(4) infinite;
}
@keyframes grain {
  0%   { transform: translate(0,0); }
  25%  { transform: translate(-2%,1%); }
  50%  { transform: translate(1%,-2%); }
  75%  { transform: translate(-1%,-1%); }
  100% { transform: translate(0,0); }
}

/* ---------- le fond : la photo, en zoom lent ---------- */
.backdrop { position: fixed; inset: 0; z-index: 0; overflow: hidden; }

.bg {
  position: absolute;
  top: 0;
  left: calc(-1 * var(--bg-bleed));
  width: calc(100% + var(--bg-bleed));
  height: 100%;
  object-fit: cover;
  object-position: 38% 30%;
  /* la photo est sur fond noir : .58 (réglé pour l'ancienne, sur mur clair) l'éteignait */
  filter: grayscale(1) contrast(1.18) brightness(1.35);
  opacity: 0;
  animation: slow-zoom 18s ease-out calc(1.7s * var(--seq)) forwards;
}
@keyframes slow-zoom {
  0%   { opacity: 0; transform: scale(1.5); }
  18%  { opacity: 1; transform: scale(1.41); }
  100% { opacity: 1; transform: scale(1); }
}

.vignette {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(82% 66% at 24% 16%, rgba(7,7,10,0) 0%, rgba(7,7,10,.46) 50%, rgba(7,7,10,.97) 100%),
    linear-gradient(to bottom, rgba(7,7,10,.68) 0%, rgba(7,7,10,.10) 16%, rgba(7,7,10,.38) 54%, rgba(7,7,10,.97) 92%);
}

/* ---------- le NØTZ : le fond de tout ---------- */
.mark-host {
  position: fixed;
  inset: 0;
  z-index: 1;
  perspective: 1000px;
  overflow: hidden;
  pointer-events: none;
}
.mark-tilt {
  position: absolute;
  left: calc(50% + var(--mark-dx));
  top: calc(50% + var(--mark-dy));
  width: var(--mark-w);
  height: var(--mark-w);
  margin-left: calc(var(--mark-w) / -2);
  margin-top: calc(var(--mark-w) / -2);
  transform-style: preserve-3d;
  backface-visibility: hidden;
  will-change: transform;
}
.mark-img {
  display: block;
  width: 100%;
  height: 100%;
  mix-blend-mode: screen;
  opacity: 0;
  animation: mark-in 2s var(--ease) calc(1.9s * var(--seq)) forwards;
}
@keyframes mark-in { to { opacity: var(--mark-opacity); } }

/* ---------- filets verticaux ---------- */
.grid-lines {
  position: fixed;
  inset: 0;
  z-index: 2;
  display: flex;
  justify-content: space-between;
  padding: 0 var(--edge-x);
  pointer-events: none;
}
.grid-lines span {
  width: 1px;
  height: 100%;
  background: linear-gradient(to bottom, transparent, rgba(243,239,230,.06) 30%, rgba(243,239,230,.06) 70%, transparent);
}

/* ---------- micro-typo aux quatre coins ---------- */
.corner {
  position: fixed;
  z-index: 4;
  font-size: var(--micro);
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-shadow: 0 1px 3px rgba(0,0,0,.7);
  opacity: 0;
}
/* flex : en inline-flex dans une ligne de texte, LIVE tombait 1,5 à 2 px sous GIGS */
.corner-tl { display: flex; top: var(--edge-y); left: var(--edge-x);  animation: rise-in .9s var(--ease-expo) calc(2.3s  * var(--seq)) forwards; }
.corner-tr { top: var(--edge-y); right: var(--edge-x); animation: rise-in .9s var(--ease-expo) calc(2.45s * var(--seq)) forwards; }
.corner-bl { bottom: calc(var(--rail-h) + var(--edge-y)); left: var(--edge-x);  animation: rise-in .9s var(--ease-expo) calc(3.5s  * var(--seq)) forwards; }
.corner-br { bottom: calc(var(--rail-h) + var(--edge-y)); right: var(--edge-x); animation: rise-in .9s var(--ease-expo) calc(3.65s * var(--seq)) forwards; }

.rec { display: inline-flex; align-items: center; gap: .6em; }
.rec i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: #e14b3d;
  box-shadow: 0 0 8px #e14b3d;
  animation: pulse 1.8s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* ---------- les dates, dans le coin haut-droit ----------
   À droite parce que la vignette ouvre son trou de lumière en haut à gauche
   (at 24% 16%) : les couleurs y manquaient de contraste sur la photo.
   Une liste de tournée : la date en colonne, le lieu à côté, la ville et la
   note dessous. Deux lignes par gig, pour tenir au-dessus de l'axe central
   sur un téléphone. Chaque gig sort du flou l'un après l'autre (l'écho de
   « Coming soon »), séparés par le même filet 1px que le titre, puis reste. */
.gigs {
  /* LIVE, en face, n'est que sur la ligne du titre (court) : la liste,
     dessous, peut prendre toute la largeur sans le toucher */
  max-width: calc(100vw - 2 * var(--edge-x));
  text-transform: none;
  letter-spacing: 0;
}
.gigs-title {
  display: flex;
  align-items: center;
  gap: .9em;
  margin-bottom: .9em;
  text-transform: uppercase;
  letter-spacing: .26em;
}
.gigs-title::after {
  content: "";
  width: clamp(18px, 2.4vw, 32px);
  height: 1px;
  background: linear-gradient(to right, rgba(243,239,230,.38), transparent);
}
.gigs-list { list-style: none; display: flex; flex-direction: column; }
.gig {
  position: relative;
  display: grid;
  /* la colonne date prend la largeur de « 23–24.09 » : les lieux s'alignent */
  grid-template-columns: 6.6em 1fr;
  column-gap: 1.2em;
  row-gap: .35em;
  align-items: baseline;
  padding-block: .85em;
  /* un gig après l'autre, .55 s d'écart : cet écart n'est PAS compressé par
     --seq, sinon au rechargement (.18) ils tombent à 0,1 s et arrivent en pavé */
  animation: gig-in 1.1s var(--ease) calc(2.6s * var(--seq) + var(--i, 0) * .55s) both;
}
.gig:first-child { padding-top: 0; }
.gig + .gig::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: min(100%, 15em);
  height: 1px;
  background: linear-gradient(to right, rgba(243,239,230,.2), transparent);
}
@keyframes gig-in {
  from { opacity: 0; transform: translateY(10px); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: none; }
}
.gig-when {
  grid-row: 1 / 3;
  text-transform: uppercase;
  letter-spacing: .2em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-dim);
}
.gig-venue { font-size: calc(var(--micro) * 1.25); letter-spacing: .06em; color: var(--ink); }
.gig-note { grid-column: 2; letter-spacing: .04em; color: var(--ink-faint); }
/* le prochain devant, les suivants un cran en retrait */
.gig + .gig .gig-venue { color: var(--ink-dim); }

/* ---------- l'axe central ---------- */
.axis {
  /* le haut du bloc tombe à 60 % de l'écran… */
  --axis-top: .6;
  --axis-gap: 16px;
  position: fixed;
  /* centré sous le mark */
  left: calc(2 * var(--mark-dx));
  right: 0;
  top: 0;
  /* …mais le bloc s'arrête sur la ligne des deux coins du bas. Sur un écran
     bas, c'est l'espace au-dessus qui se tasse : « Coming soon » s'aligne sur
     © NOTZ au lieu de descendre sur le bandeau (il le touchait à 1600×698) */
  bottom: calc(var(--rail-h) + var(--edge-y));
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--axis-gap);
  padding: 0 var(--edge-x);
  text-align: center;
}
/* l'espace au-dessus du bloc : 60 % de l'écran entier (le 100 % d'ici
   s'arrête au-dessus des coins, d'où le rajout), compressible */
.axis::before {
  content: "";
  flex: 0 1 calc(var(--axis-top) * (100% + var(--rail-h) + var(--edge-y)) - var(--axis-gap));
}

.tagline {
  /* « ARTIST & PRODUCER » est 30 % plus court que « FRENCH ARTIST & PRODUCER » :
     sans compensation la ligne tombe de 474 a 330 px sur un 1440, l'axe central
     perd son ancrage et le bloc se ratatine sous le mark. Elle reprend sa
     largeur optique (421 px mesures) par l'interlettrage et un cran de corps,
     pas en grossissant seule. */
  font-size: clamp(1.02rem, 2.9vw, 1.62rem);
  font-weight: 300;
  letter-spacing: .3em;
  /* l'interlettrage s'applique aussi apres la derniere lettre : sans cette
     marge, la ligne centree est posee un demi-cran trop a gauche */
  margin-right: -.3em;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: 0 1px 4px rgba(0,0,0,.6);
  opacity: 0;
  animation: rise-in 1s var(--ease-expo) calc(2.6s * var(--seq)) forwards;
}
.tagline .amp {
  font-family: 'Cormorant Garamond', serif;
  font-style: italic;
  font-weight: 300;
  letter-spacing: 0;
  padding: 0 .16em;
}

.label {
  font-size: clamp(.72rem, 2.2vw, .92rem);
  letter-spacing: .12em;
  color: var(--ink-dim);
  text-shadow: 0 1px 4px rgba(0,0,0,.6);
  opacity: 0;
  animation: rise-in 1s var(--ease-expo) calc(2.95s * var(--seq)) forwards;
}
.label a { color: var(--ink); text-decoration: none; }
.label a span {
  background-image: linear-gradient(var(--ink), var(--ink));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size .35s var(--ease);
}
.label a:hover span, .label a:focus-visible span { background-size: 100% 1px; }

/* crédit, au-dessus du copyright dans le coin bas-gauche : même geste que le
   label, un cran plus discret. Le copyright reste sur la ligne de « Coming soon » */
.corner-bl { display: flex; flex-direction: column; gap: .9em; }
.credit { font-size: .92em; }
.credit a { color: var(--ink-dim); text-decoration: none; transition: color .35s var(--ease); }
.credit a span {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size .35s var(--ease);
}
.credit a:hover, .credit a:focus-visible { color: var(--ink); }
.credit a:hover span, .credit a:focus-visible span { background-size: 100% 1px; }

/* press kit, coin bas-droit : aligné sur la ligne du copyright, même geste que le crédit */
.press { position: relative; display: inline-flex; align-items: baseline; gap: .7em; color: var(--ink-dim); text-decoration: none; transition: color .35s var(--ease); }
/* le texte fait 10 px de haut : la zone tactile déborde, sans bouger la mise en page */
.press::after { content: ""; position: absolute; inset: -16px -12px; }
.press span {
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size .35s var(--ease);
}
.press i { font-style: normal; letter-spacing: 0; transition: transform .35s var(--ease); }
.press:hover, .press:focus-visible { color: var(--ink); }
.press:hover span, .press:focus-visible span { background-size: 100% 1px; }
.press:hover i, .press:focus-visible i { transform: translateY(2px); }

/* ---------- réseaux ---------- */
.links {
  display: flex;
  gap: clamp(1.5rem, 4.2vw, 2.6rem);
  align-items: flex-start;
  justify-content: center;
  margin-top: 1.5rem;
}
.link {
  /* noir & blanc : crème atténuée au repos, crème pleine au survol.
     Héritée par l'icône et l'onde */
  --net: var(--ink-dim);
  --orb: clamp(48px, 4.3vw, 60px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .62rem;
  color: var(--net);
  text-decoration: none;
  opacity: 0;
  /* les trois entrent l'un après l'autre, pas en bloc */
  animation: rise-in 1s var(--ease-expo) forwards;
}
.link:nth-child(1) { animation-delay: calc(3.25s * var(--seq)); }
.link:nth-child(2) { animation-delay: calc(3.4s  * var(--seq)); }
.link:nth-child(3) { animation-delay: calc(3.55s * var(--seq)); }
.link:nth-child(4) { animation-delay: calc(3.7s  * var(--seq)); }

/* la capsule : plus d'anneau au repos, l'icône pleine se suffit. Elle garde sa taille : c'est
   toujours elle la cible tactile (48px mini). */
.orb {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--orb);
  height: var(--orb);
  transition: transform .45s var(--ease);
}
/* l'onde : un anneau qui s'écarte vers l'extérieur au survol */
.orb::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1px solid var(--net);
  opacity: 0;
  transform: scale(.86);
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
.link svg {
  position: relative;
  z-index: 1;
  /* 68 % de la capsule : 41px de large sur grand écran. C'était 80 % (48px,
     la taille d'aminek.com), jugé un peu gros : -15 % sur le glyphe seul, la
     capsule ne bouge pas, donc la mise en page non plus.
     Hauteur libre : c'est la largeur qui est commune, pas une boîte carrée
     (sinon Instagram, plus haut que large, rétrécit) */
  width: 68%;
  height: auto;
  fill: currentColor;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .55));
  transition: filter .4s var(--ease), color .4s var(--ease);
}
/* le nuage SoundCloud est large et bas : à égale largeur, il pèse moitié
   moins que les trois autres. Deux crans de plus (81 % paraissait encore
   un peu petit à côté des autres) */
.link-sc svg { width: 90%; }
/* Instagram, carré plein aux coins arrondis, a plus de masse qu'un rond à
   largeur égale : il paraissait un cran au-dessus des trois autres */
.link-ig svg { width: 63%; }
.link-label {
  font-size: clamp(.57rem, .82vw, .66rem);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  opacity: 0;
  transform: translateY(-5px);
  transition: opacity .3s var(--ease), transform .3s var(--ease), color .3s var(--ease);
}

.link:hover, .link:focus-visible { --net: var(--ink); }
.link:hover .orb, .link:focus-visible .orb { transform: translateY(-4px); }
.link:hover .orb::after, .link:focus-visible .orb::after { opacity: .35; transform: scale(1); }
.link:hover svg, .link:focus-visible svg {
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .55)) drop-shadow(0 0 10px rgba(243, 239, 230, .35));
}
.link:hover .link-label, .link:focus-visible .link-label {
  opacity: 1;
  transform: translateY(0);
  color: var(--ink);
}
.link:focus-visible { outline: none; }

/* ---------- « Coming soon », sous les reseaux ----------
   Deux filets courts l'encadrent : c'est le meme trait 1px que celui des
   deux bandeaux, mais qui ne prend que la largeur du texte. Il entre en
   dernier de toute la sequence, une fois les capsules posees, et c'est un
   allumage : il sort d'un flou en resserrant ses lettres (le generique de
   film), s'embrase d'une lueur ambree qui retombe, pendant que les filets
   se tirent depuis le texte vers l'exterieur.
------------------------------------------------------------------ */
.soon {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(.6rem, 1.6vw, 1rem);
  margin-top: clamp(.7rem, 1.4vh, 1rem);
  opacity: 0;
  animation: soon-in 1.8s var(--ease) calc(4.1s * var(--seq)) forwards;
}
.soon::before,
.soon::after {
  content: "";
  flex: 0 0 auto;
  width: clamp(26px, 5vw, 54px);
  height: 1px;
  background: linear-gradient(to right, transparent, rgba(243,239,230,.38));
  transform-origin: right;
  animation: filet-draw 1.1s var(--ease) calc(4.5s * var(--seq)) both;
}
.soon::after {
  background: linear-gradient(to left, transparent, rgba(243,239,230,.38));
  transform-origin: left;
}
/* la lueur est posee sur le bloc entier : le texte ET les filets s'embrasent.
   Deux ombres : un coeur chaud serre, puis un halo ambre large */
@keyframes soon-in {
  0%   { opacity: 0; transform: translateY(14px); filter: blur(8px) brightness(1) drop-shadow(0 0 0 rgba(255,226,180,0)) drop-shadow(0 0 0 rgba(217,162,78,0)); }
  45%  { opacity: 1; transform: translateY(0); filter: blur(0) brightness(1.4) drop-shadow(0 0 3px rgba(255,226,180,.7)) drop-shadow(0 0 18px rgba(217,162,78,.85)); }
  100% { opacity: 1; transform: translateY(0); filter: blur(0) brightness(1) drop-shadow(0 0 0 rgba(255,226,180,0)) drop-shadow(0 0 0 rgba(217,162,78,0)); }
}
@keyframes filet-draw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.soon span {
  /* un cran au-dessus des micro-capitales des coins et du bandeau : c'est
     la seule annonce de la page */
  font-size: calc(var(--micro) * 1.22);
  font-weight: 500;
  letter-spacing: .42em;
  /* le letter-spacing s'applique aussi APRES la derniere lettre : sans la
     marge negative, le texte est centre avec ce vide, donc pose un demi-cran
     trop a gauche */
  margin-right: -.42em;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(243,239,230,.86);
  text-shadow: 0 1px 3px rgba(0,0,0,.7);
  /* l'ecart de depart des lettres ; resserre sur les ecrans etroits, ou il
     partage la ligne des coins */
  --track-from: 1.1em;
  animation: track-in 2.6s cubic-bezier(.33,1,.68,1) calc(4.1s * var(--seq));
}

/* le reflet : une lumiere blanche qui traverse le texte toutes les 6 s, la
   premiere fois des la fin de l'entree, avec une lueur ambree (le clair du
   duotone) qui monte et retombe sur son passage.
   La couleur opaque reste declaree HORS du @supports : sans background-clip
   le texte redeviendrait invisible, donc ligne vide. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .soon span {
    color: transparent;
    -webkit-text-fill-color: transparent;
    text-shadow: none;
    background-image: linear-gradient(100deg,
      rgba(243,239,230,.86) 0 40%, #fff 50%, rgba(243,239,230,.86) 60% 100%);
    background-size: 300% 100%;
    background-position: 100% 0;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    animation: track-in 2.6s cubic-bezier(.33,1,.68,1) calc(4.1s * var(--seq)),
               sheen 6s var(--ease) calc(5.8s * var(--seq)) infinite;
  }
}
@keyframes sheen {
  0%   { background-position: 100% 0; filter: drop-shadow(0 0 0 rgba(217,162,78,0)); }
  30%  { filter: drop-shadow(0 0 9px rgba(217,162,78,.6)); }
  60%  { background-position: 0% 0; filter: drop-shadow(0 0 0 rgba(217,162,78,0)); }
  100% { background-position: 0% 0; filter: drop-shadow(0 0 0 rgba(217,162,78,0)); }
}
/* sans image d'arrivee : les lettres reviennent a l'ecart que la cascade leur
   donne, media queries comprises */
@keyframes track-in {
  from { letter-spacing: var(--track-from); margin-right: calc(-1 * var(--track-from)); }
}

/* ---------- le bandeau, tout en bas ---------- */
.rail {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 5;
  height: var(--rail-h);
  display: flex;
  align-items: center;
  overflow: hidden;
  border-top: 1px solid rgba(243,239,230,.08);
  background: linear-gradient(to top, rgba(7,7,10,.92), rgba(7,7,10,0));
  -webkit-mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
  mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
  opacity: 0;
  animation: rise-in 1s var(--ease) calc(3.8s * var(--seq)) forwards;
}
.rail-track {
  display: flex;
  width: max-content;
  animation: rail-scroll 40s linear infinite;
}
.rail-group {
  display: flex;
  gap: 2.4em;
  padding-right: 2.4em;
  white-space: nowrap;
  font-size: var(--micro);
  font-weight: 500;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
/* hiérarchie sans changer de teinte : les genres devant, le reste en retrait */
.rail-group .rail-dim { color: var(--ink-faint); font-weight: 400; }
.rail-group .sep { color: rgba(243,239,230,.28); font-weight: 300; }
@keyframes rail-scroll { to { transform: translateX(-50%); } }

@keyframes rise-in {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- grands écrans : on monte d'un cran ---------- */
@media (min-width: 1100px) {
  .axis { --axis-gap: 18px; }
  .tagline { letter-spacing: .34em; margin-right: -.34em; }
  .links { margin-top: 1.7rem; }
}

/* ---------- écrans étroits ---------- */
@media (max-width: 720px) {
  /* téléphone : le visage à gauche mord sur le mark, remonté en haut à droite ;
     les dates, en relais sur une ligne, passent en haut à gauche : au centre de
     l'écran elles chargeaient le visage. LIVE part en face, à droite, sur la
     ligne de GIGS : empilés à gauche, les trois lignes surchargeaient le coin */
  :root { --mark-w: min(50vh, 96vw); --mark-dx: 24vw; --mark-dy: -13vh; --bg-bleed: 0px; --mark-opacity: .42; --rail-h: 40px; --micro: 9.5px; }
  .bg { object-position: 40% 30%; }
  /* sur téléphone le mark passe sur les cheveux éclairés : en « screen » il
     prenait la teinte de la photo. Sa couleur est réglée dans le PNG lui-même
     (logo-mark-neutre.png, gris pur). Le doré vu sur iPhone venait du duotone
     (mix-blend-mode: color) qui y débordait sur le mark : retiré le 17/09 */
  .mark-img { mix-blend-mode: normal; }
  .axis { --axis-top: .7; --axis-gap: 12px; left: 0; }
  .corner-tl { left: auto; right: var(--edge-x); }
  .corner-tr.gigs { left: var(--edge-x); right: var(--edge-x); }
  /* la ligne des dates passe sur le front éclairé : un halo sombre la détache */
  .gigs { text-shadow: 0 1px 3px rgba(0,0,0,.8), 0 0 14px rgba(7,7,10,.9); }
  .links { margin-top: 1rem; }
  .grid-lines { display: none; }
  .corner { letter-spacing: .22em; }
  .gigs { letter-spacing: 0; }
  .gigs-title { letter-spacing: .22em; }
  .rail-group { letter-spacing: .28em; }
  /* pas d'annonce sur téléphone : le bas de l'écran reste au crédit */
  .soon { display: none; }
  /* le bloc central s'arrête au-dessus des deux lignes du coin (crédit +
     copyright) et non plus sur le copyright : sinon sur 360×640 les réseaux
     descendaient sur « Made by Thibaut ». --foot : ces deux lignes + une respiration */
  .axis { --foot: 56px; bottom: calc(var(--rail-h) + var(--edge-y) + var(--foot)); }
  .axis::before { flex-basis: calc(var(--axis-top) * (100% + var(--rail-h) + var(--edge-y) + var(--foot)) - var(--axis-gap)); }
  .links { gap: clamp(1rem, 3.4vw, 1.5rem); }
}

/* ---------- telephones etroits ---------- */
@media (max-width: 420px) {
  .corner { letter-spacing: .17em; }
  .gigs { letter-spacing: 0; }
  .gigs-title { letter-spacing: .17em; }
}

@media (max-height: 620px) {
  /* le mark n'y grossit plus : depuis la photo 10 il se range à côté du visage */
  :root { --mark-w: min(66vh, 60vw); }
  /* le bloc central a grandi de ~50px avec la ligne « Coming soon » : sans
     ce relevement elle passe DERRIERE le bandeau du bas (mesure a 1280x598) */
  .axis { --axis-top: .52; }
  .soon { margin-top: clamp(.5rem, 1.2vh, .8rem); }
}

/* téléphone court (360×640, 375×667) : le bloc central remonte pour laisser la
   place au crédit ; le mark rapetisse et se rapproche du bord pour rester au-dessus
   de « Artist & Producer » */
@media (max-width: 720px) and (max-height: 700px) {
  :root { --mark-w: min(40vh, 96vw); --mark-dx: 27vw; --mark-dy: -14vh; }
}

/* très petit téléphone (320×568) : à -14vh le bas du mark passait sur
   « Artist & Producer » ; plus petit et plus haut, il reste 11 px au-dessus */
@media (max-width: 720px) and (max-height: 600px) and (min-height: 521px) {
  :root { --mark-w: 42vh; --mark-dy: -21vh; }
}

/* téléphone à plat : l'axe central remonte à hauteur des dates, en relais
   sur une ligne dans le coin droit */
@media (max-height: 520px) {
  /* l'axe recentré : décalé, il passait sous la liste */
  :root { --mark-dx: 0px; }
  .axis { left: 0; }
  .gigs-title { margin-bottom: .6em; }
}

/* ---------- les dates en relais (petits écrans) ----------
   script.js pose .is-relay sous 720 px de large ou 520 px de haut : la liste
   chargeait le téléphone. Les gigs se superposent dans la même case (la
   hauteur ne bouge jamais), un seul est allumé, sur une ligne, et passe la
   main toutes les 2,5 s par le même flou que leur entrée. Le filet du titre
   se trace pendant ce temps : c'est le seul signe que ça défile. */
.gigs.is-relay .gigs-list { display: grid; }
.gigs.is-relay .gig {
  grid-area: 1 / 1;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 1.1em;
  padding: 0;
  animation: none;
  opacity: 0;
  transform: translateY(7px);
  filter: blur(6px);
  transition: opacity .7s var(--ease), transform .7s var(--ease), filter .7s var(--ease);
}
.gigs.is-relay .gig.is-on { opacity: 1; transform: none; filter: none; }
.gigs.is-relay .gig.was-on { transform: translateY(-7px); }
.gigs.is-relay .gig::before, .gigs.is-relay .gig-note { display: none; }
.gigs.is-relay .gig-when { grid-row: auto; }
.gigs.is-relay .gig-venue {
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gigs.is-relay .gigs-title::after {
  width: 44px;
  transform-origin: left;
  transform: scaleX(0);
}
.gigs.is-relay .gigs-title.tick::after { animation: gig-tick 2.5s linear forwards; }
@keyframes gig-tick { to { transform: scaleX(1); } }

/* ---------- mouvement réduit ---------- */
@media (prefers-reduced-motion: reduce) {
  .loader { display: none; }
  .noise { display: none; }
  .bg, .mark-img, .corner, .tagline, .label, .links, .link, .rail, .soon {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .mark-img { opacity: var(--mark-opacity) !important; }
  .rail-track { animation: none !important; }
  .soon span, .soon::before, .soon::after { animation: none !important; }
  .rec i { animation: none !important; }
  .gig { animation: none; opacity: 1; transform: none; filter: none; }
  /* le relais tourne toujours (c'est du contenu), en simple fondu */
  .gigs.is-relay .gig { opacity: 0; transform: none; filter: none; }
  .gigs.is-relay .gig.is-on { opacity: 1; }
  .gigs.is-relay .gigs-title::after { transform: none; animation: none; }
}
