/* Les sept moments (voir js/moments.js). Chaque règle qui change la page
   passe par `html[data-moments]` : sans script, en mouvement réduit ou sur
   le socle, cette feuille ne fait rien. */

/* =========================================================
   1. L'afficheur d'étage
   ========================================================= */
/* On est DANS la cabine : deux portes d'acier brossé, l'afficheur au-dessus,
   la fente de lumière entre les portes. Le voile laisse passer les clics. */
.afficheur {
  position: fixed; inset: 0; z-index: 9;
  pointer-events: none;
  overflow: hidden;
  background: #0b0b0a;
}
.afficheur__porte {
  position: absolute; top: 0; bottom: 0; width: 50.2%;
  background:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .025) 0 1px, transparent 1px 3px),
    linear-gradient(90deg, #23262a 0%, #3d4145 38%, #4b4f53 52%, #33363a 78%, #1e2023 100%);
  animation: porte-g 1s 2.35s cubic-bezier(.7, 0, .3, 1) both;
}
.afficheur__porte--g { left: 0; box-shadow: inset -6px 0 10px rgba(0, 0, 0, .55); }
.afficheur__porte--d { right: 0; animation-name: porte-d; box-shadow: inset 6px 0 10px rgba(0, 0, 0, .55); }
@keyframes porte-g { to { translate: -101% 0; } }
@keyframes porte-d { to { translate: 101% 0; } }
/* La gaine qui défile par la fente : on monte, la lumière descend. */
.afficheur__fente {
  position: absolute; top: 0; bottom: 0; left: calc(50% - 3px); width: 6px;
  background: repeating-linear-gradient(180deg, transparent 0 140px, rgba(224, 251, 171, .85) 140px 190px, transparent 190px 300px);
  background-size: 100% 300px;
  filter: blur(1px);
  box-shadow: 0 0 30px rgba(224, 251, 171, .35);
  animation: gaine 2.2s cubic-bezier(.45, 0, .35, 1) both, fente-fin .3s 2.25s ease both;
}
@keyframes gaine { from { background-position: 0 -900px; } to { background-position: 0 900px; } }
@keyframes fente-fin { to { opacity: 0; } }
.afficheur__plaque {
  position: absolute; left: 50%; top: 14vh; translate: -50% 0;
  width: max-content;
  display: grid; grid-template-columns: auto auto; grid-template-rows: auto auto; align-items: center;
  column-gap: 1.6rem; padding: 1.4rem 2.6rem 1.4rem 2rem;
  background: #050805; border: 3px solid #63676b; border-radius: 18px;
  box-shadow: 0 0 0 10px #2f3236, 0 30px 60px rgba(0, 0, 0, .6);
  animation: plaque-sort .45s 2.3s cubic-bezier(.6, 0, .4, 1) both;
}
@keyframes plaque-sort { to { opacity: 0; translate: -50% -40px; scale: .9; } }
.afficheur__fleche {
  width: 0; height: 0; justify-self: center;
  border-left: 1.1rem solid transparent; border-right: 1.1rem solid transparent;
  border-bottom: 1.6rem solid var(--tilleul);
  filter: drop-shadow(0 0 10px var(--tilleul));
  animation: clignote .34s steps(2, jump-none) 6 both;
}
@keyframes clignote { 0% { opacity: .25; } 100% { opacity: 1; } }
.afficheur__mot {
  grid-row: 2; font: 800 .9rem/1 var(--raleway); letter-spacing: .25em; text-transform: uppercase;
  color: rgba(224, 251, 171, .55);
}
.afficheur__chiffre {
  grid-row: 1 / 3; grid-column: 2;
  /* Largeur FIXE : sur téléphone la colonne se serrait et rognait le chiffre
     (« on ne voit pas 1, 2, 3 défiler », 04/10). */
  height: 1em; width: .62em; overflow: hidden; text-align: center;
  font: 400 clamp(5rem, 22vw, 10rem)/1 var(--anton); color: var(--tilleul);
  text-shadow: 0 0 24px rgba(224, 251, 171, .8), 0 0 70px rgba(224, 251, 171, .35);
}
.afficheur__rouleau { display: flex; flex-direction: column; animation: rouleau 2s .2s both; }
.afficheur__rouleau span { height: 1em; display: block; }
@keyframes rouleau {
  0%, 30%   { translate: 0 0; animation-timing-function: cubic-bezier(.7, 0, .3, 1); }
  48%, 66%  { translate: 0 -1em; animation-timing-function: cubic-bezier(.7, 0, .3, 1); }
  84%, 100% { translate: 0 -2em; }
}
/* Le « ding » : l'afficheur s'embrase sur le 3. */
.afficheur__plaque::after {
  content: ''; position: absolute; inset: -14px; border-radius: 26px;
  border: 3px solid var(--tilleul); opacity: 0;
  animation: ding .7s 1.95s ease-out both;
}
@keyframes ding { 0% { opacity: .9; scale: 1; } 100% { opacity: 0; scale: 1.35; } }
.afficheur--fini { opacity: 0; transition: opacity .4s ease; }
/* Derrière les portes, le néon attend qu'elles s'ouvrent pour s'allumer, et
   la photo arrive de plus près. */
/* ---- La montée : les portes se FERMENT, l'afficheur monte, le voile se
   retire au « ding » sur la cabine (dont la scène 3D ouvre les portes).
   Calée sur js/arrivee.js : arrivée au 3ᵉ à 3,2 s. ---- */
.afficheur--montee { position: absolute; z-index: 2; background: transparent; }
.afficheur--montee .afficheur__porte { animation: porte-ferme .6s cubic-bezier(.6, 0, .3, 1) both; }
.afficheur--montee .afficheur__porte--g { --depuis: -101%; }
.afficheur--montee .afficheur__porte--d { --depuis: 101%; }
@keyframes porte-ferme { from { translate: var(--depuis) 0; } to { translate: 0 0; } }
.afficheur--montee .afficheur__fente { animation: gaine 2.3s .55s cubic-bezier(.45, 0, .35, 1) both, fente-fin .3s 2.85s ease both; }
.afficheur--montee .afficheur__plaque { animation: plaque-entre .45s .35s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes plaque-entre { from { opacity: 0; translate: -50% -30px; } }
.afficheur--montee .afficheur__fleche { animation-delay: .6s; }
.afficheur--montee .afficheur__rouleau { animation-delay: .75s; }
.afficheur--montee .afficheur__plaque::after { animation-delay: 2.55s; }

/* ---- Le nom qui se range dans la barre ---- */
.nom-volant {
  position: fixed; left: 0; top: 0; z-index: 6;
  transform-origin: 0 0;
  margin: 0; white-space: nowrap; pointer-events: none;
  color: var(--tilleul);
  font-family: var(--anton); font-weight: 400; text-transform: uppercase; letter-spacing: .01em;
  text-shadow: 0 0 18px rgba(224, 251, 171, .35);
  will-change: transform;
}
html[data-moments] body[data-nom] .arrivee__nom { visibility: hidden; }
html[data-moments] body[data-nom="vole"] .entete__nom { visibility: hidden; }
/* La photo s'enfonce et s'assombrit pendant que le nom monte. */
html[data-moments] body[data-vue="accueil"][data-etape="palier-rdc"] #arrivee .arrivee__photo {
  scale: calc(1 + var(--defile, 0) * .07);
  filter: brightness(calc(1 - var(--defile, 0) * .45));
}

/* =========================================================
   2. La page danse sur la musique (--basse, --coup : js/pulsation.js)
   ========================================================= */
html[data-moments] .arrivee__nom { scale: calc(1 + var(--coup, 0) * .01); transform-origin: 0 60%; }
html[data-moments] body[data-lecture="en-cours"] .arrivee__nom { filter: brightness(calc(1 + var(--coup, 0) * .2)); }
@media (prefers-reduced-motion: no-preference) and (min-width: 721px) {
  html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) main > .salle::before { scale: calc(1 + var(--coup, 0) * .01); }
}
html[data-moments] main > .salle > h2 .lettre { display: inline-block; white-space: pre; will-change: translate; }
/* Sans musique, le titre DANSE quand la souris le survole : une vague qui
   court de la première à la dernière lettre, en boucle (Jonathan, 04/10).
   Avec la musique, c'est la grosse caisse qui mène (js/pulsation.js) : le
   survol se tait pour ne pas se battre avec elle. Ordinateur seulement. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  html[data-moments] body:not([data-lecture="en-cours"]) main > .salle > h2:hover .lettre {
    animation: titre-danse .9s cubic-bezier(.4, 0, .4, 1) infinite;
    animation-delay: calc(var(--j, 0) * 55ms);
  }
  html[data-moments] body:not([data-lecture="en-cours"]) main > .salle > h2:hover {
    text-shadow: 0 0 22px rgba(224, 251, 171, .35);
  }
}
@keyframes titre-danse {
  0%, 100% { translate: 0 0; }
  25%      { translate: 0 -.1em; }
  50%      { translate: 0 .025em; }
}
html[data-moments] body[data-lecture="en-cours"]:is([data-vue="accueil"], [data-vue="salle"]) main > .salle > h2 {
  text-shadow: 0 0 calc(10px + var(--coup, 0) * 34px) rgba(224, 251, 171, calc(.15 + var(--coup, 0) * .5));
}
.halo-musique {
  position: fixed; inset: 0; z-index: 3; pointer-events: none;
  background: radial-gradient(ellipse 75% 70% at 50% 50%, transparent 55%, rgba(224, 251, 171, .55) 100%);
  opacity: calc(var(--coup, 0) * .28);
}
body:not(:is([data-vue="accueil"], [data-vue="salle"])) .halo-musique { display: none; }
/* L'égaliseur, dans la barre, à droite du titre. */
.egaliseur {
  display: flex; align-items: flex-end; gap: 3px; height: 1.6rem;
  opacity: 0; transition: opacity .3s ease;
}
body[data-lecture="en-cours"] .egaliseur { opacity: 1; }
.egaliseur span {
  width: 4px; height: 100%;
  background: var(--tilleul);
  transform-origin: 50% 100%;
  scale: 1 calc(.08 + var(--v, 0) * .92);
}
.egaliseur span:nth-child(-n+4) { background: var(--ambre); }
.lecteur__titre { display: flex; align-items: center; gap: .6rem; }
.lecteur:has(.egaliseur) { grid-template-columns: auto minmax(0, 1fr) auto auto; }
/* Téléphone : l'égaliseur reste, plus fin, sur huit tiges. */
@media (max-width: 720px) {
  .egaliseur { gap: 2px; height: 1.2rem; }
  .egaliseur span { width: 3px; }
  .egaliseur span:nth-child(n+9) { display: none; }
}
/* Le bouton de lecture lâche une onde à chaque coup. */
body[data-lecture="en-cours"] .lecteur__lire {
  box-shadow: 0 0 0 calc(var(--coup, 0) * 9px) rgba(255, 190, 0, calc(var(--coup, 0) * .45));
}

/* =========================================================
   3. Le groupe, un par un
   ========================================================= */
.projecteur__fond {
  /* Pleine largeur de l'écran, quelle que soit la colonne (accueil ou salle). */
  position: absolute; top: 0; bottom: 0; left: calc(50% - 50vw); width: 100vw;
  z-index: 0; overflow: hidden; pointer-events: none;
}
/* `isolation` CONFINE les niveaux (z-index) du prénom géant, des portraits et
   du bandeau à l'intérieur de la section. Sans elle, dans la CABINE, ils se
   comparaient directement à la scène 3D (z-index 1) et, venant après elle
   dans la page, passaient DEVANT : la grille du groupe s'affichait par-dessus
   l'ascenseur (Jonathan, deux fois — 03/10 puis 04/10). */
#le-groupe { position: relative; isolation: isolate; }
/* Pas de `content-visibility` ici : son confinement de peinture fait de la
   section le repère des éléments FIXES — le bandeau PRÉNOM // INSTRUMENT se
   fixait au bas de la section, invisible pendant la 1re rangée (sur
   ordinateur, 04/10). La section est la première sous le hero : elle se
   peint de toute façon tout de suite. */
html[data-moments] #le-groupe { content-visibility: visible; }
.projecteur__geant {
  /* `top` : le centre du portrait éclairé (js/projecteur.js). */
  position: absolute; left: 0; top: 50%; translate: 100vw 0;
  margin-top: -.55em;
  font: 400 clamp(10rem, 30vw, 30rem)/1 var(--anton); text-transform: uppercase; white-space: nowrap;
  color: transparent;
  -webkit-text-stroke: 3px rgba(224, 251, 171, .5);
  text-shadow: 0 0 40px rgba(224, 251, 171, .12);
}
#le-groupe > :not(.projecteur__fond) { position: relative; z-index: 1; }
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .membres[data-projecteur] .membre img {
  filter: grayscale(1) brightness(.42);
  transition: filter .5s ease, transform .6s cubic-bezier(.2, .7, .2, 1);
}
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .membres[data-projecteur] .membre {
  transition: scale .6s cubic-bezier(.25, .9, .3, 1), box-shadow .4s ease, outline-color .3s ease;
  outline: 4px solid transparent; outline-offset: 0;
}
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .membres[data-projecteur] .membre.est-eclaire {
  scale: 1.035; z-index: 2;
  outline-color: var(--tilleul);
  box-shadow: 0 0 0 1px var(--tilleul), 0 30px 70px rgba(0, 0, 0, .55), 0 0 60px rgba(224, 251, 171, .18);
}
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .membres[data-projecteur] .membre.est-eclaire img { filter: none; }
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .membres[data-projecteur] .membre.est-eclaire .membre__nom { color: var(--tilleul); }
#le-groupe .projecteur__legende {
  /* Dans le flux, après la grille. Pendant qu'on parcourt la grille, il est
     FIXÉ au bas de l'écran, au-dessus de la barre de lecture (js/projecteur.js,
     classe `est-fixe`). Pas `sticky` : sur Android, un élément collant se cale
     sur un écran plus petit que l'écran réel quand la barre d'adresse se
     cache — le bandeau flottait plus haut et coupait Hugo et Nicolas (04/10).
     `fixed` se cale sur le même bas que la barre de lecture. */
  position: relative; z-index: 3 !important;
  display: flex; flex-wrap: wrap; gap: 0 .35em;
  margin: 1.4rem 0 0; max-width: none !important; padding: .45rem 0 .5rem;
  font: 400 clamp(2rem, 4.2vw, 4.2rem)/1.05 var(--anton); text-transform: uppercase;
  background: rgba(22, 22, 22, .92);
  /* Le fond s'étend sur toute la largeur, et SEULEMENT sur la largeur : son
     débordement de 40 px vers le haut (pour une ombre) était opaque et
     recouvrait les noms de la 2e rangée — c'était lui, Hugo et Nicolas coupés. */
  box-shadow: 0 0 0 100vmax rgba(22, 22, 22, .92);
  clip-path: inset(0 -100vmax);
}
#le-groupe .projecteur__legende.est-fixe {
  position: fixed !important; left: 0; right: 0; bottom: var(--lecteur-h, 0px); margin: 0;
  padding-left: var(--legende-gauche, 1rem);
}
.projecteur__legende span { display: inline-block; }
.projecteur__prenom { color: var(--blanc); }
.projecteur__role { color: var(--ambre); }
/* Ni légende ni prénom géant dans la cabine elle-même. Dans les SALLES de
   l'ascenseur, si : Jonathan veut les mêmes moments que sur l'accueil (03/10).
   `!important` parce que la légende est posée par un sélecteur d'identifiant. */
html:not([data-moments]) .projecteur__legende, html:not([data-moments]) .projecteur__fond,
body:not(:is([data-vue="accueil"], [data-vue="salle"])) .projecteur__legende, body:not(:is([data-vue="accueil"], [data-vue="salle"])) .projecteur__fond { display: none !important; }

/* =========================================================
   4. Le texte au tempo, et la platine
   ========================================================= */
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .bio[data-tempo] .mot { opacity: 0; transition: opacity .3s ease, color .3s ease, text-shadow .3s ease; }
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .bio[data-tempo] .mot.est-dit { opacity: 1; }
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .bio[data-tempo] .mot--cle.est-dit { color: var(--tilleul); }
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) .bio[data-tempo] .mot.est-courant { color: var(--tilleul); text-shadow: 0 0 14px rgba(224, 251, 171, .55); }
html[data-moments] .bio[data-tempo] p { font-size: clamp(1.15rem, 1.6vw, 1.45rem); line-height: 1.6; }

.platine {
  position: relative; display: block;
  width: min(30vw, 25rem); aspect-ratio: 1;
  padding: 0; border: 0; background: none; cursor: pointer;
  border-radius: 50%;
}
.platine:focus-visible { outline: 3px solid var(--ambre); outline-offset: 6px; }
.platine__anneau { position: absolute; inset: -14%; width: 128%; height: 128%; pointer-events: none; }
.platine__disque {
  position: absolute; inset: 0; border-radius: 50%;
  background:
    conic-gradient(from 20deg, transparent 0 8%, rgba(255, 255, 255, .1) 11%, transparent 15% 50%, rgba(255, 255, 255, .08) 61%, transparent 65%),
    repeating-radial-gradient(circle, #121212 0 2px, #1b1b1b 2px 4px),
    #101010;
  box-shadow: 0 25px 60px rgba(0, 0, 0, .6), inset 0 0 0 6px #0b0b0b;
  animation: tourner 1.8s linear infinite paused;
}
body[data-lecture="en-cours"] .platine__disque { animation-play-state: running; }
@keyframes tourner { to { rotate: 1turn; } }
.platine__etiquette {
  position: absolute; inset: 33%; border-radius: 50%;
  /* Le nom au-dessus du trou central, le morceau en dessous : le trou ne
     tombe plus sur une lettre. */
  display: grid; grid-template-rows: 1fr 1fr; justify-items: center; text-align: center; row-gap: 14px;
  background: var(--tilleul); color: var(--encre);
}
.platine__etiquette b { align-self: end; font: 400 clamp(.78rem, 1.45vw, 1.25rem)/.95 var(--anton); text-transform: uppercase; letter-spacing: .02em; }
.platine__etiquette i { align-self: start; font: 800 .62rem/1.2 var(--raleway); font-style: normal; letter-spacing: .12em; text-transform: uppercase; max-width: 8rem; }
.platine__etiquette::after { content: ''; position: absolute; left: calc(50% - 5px); top: calc(50% - 5px); width: 10px; height: 10px; border-radius: 50%; background: #101010; }
/* Le bras se pose quand ça joue. */
.platine__bras {
  position: absolute; right: -6%; top: -4%; width: 8%; height: 62%;
  transform-origin: 50% 6%; rotate: -24deg;
  transition: rotate .7s cubic-bezier(.3, 1.3, .5, 1);
}
.platine__bras::before { content: ''; position: absolute; left: 35%; top: 4%; width: 30%; height: 100%; border-radius: 6px; background: linear-gradient(90deg, #8d9194, #d9dcde, #8d9194); }
.platine__bras::after { content: ''; position: absolute; left: 0; top: 0; width: 100%; aspect-ratio: 1; border-radius: 50%; background: radial-gradient(circle at 35% 35%, #f2f2f2, #9a9ea1); }
body[data-lecture="en-cours"] .platine__bras { rotate: 2deg; }
html:not([data-moments]) .platine { display: none; }
@media (min-width: 1000px) {
  html[data-moments] body[data-vue="accueil"] #notre-musique {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: clamp(2rem, 5vw, 5rem); align-items: start;
  }
  html[data-moments] body[data-vue="accueil"] #notre-musique > * { grid-column: 1 / -1; }
  html[data-moments] body[data-vue="accueil"] #notre-musique > .bio { grid-column: 1; }
  html[data-moments] body[data-vue="accueil"] #notre-musique > .platine { grid-column: 2; grid-row: 2; margin-top: 1rem; }
}
@media (max-width: 999px) {
  .platine { width: min(70vw, 20rem); margin: 0 auto 3rem; }
}
body:not(:is([data-vue="accueil"], [data-vue="salle"])) .platine { display: none; }

/* =========================================================
   5. Le tableau à palettes
   ========================================================= */
.tableau {
  /* La hauteur d'une palette ; sa largeur en découle (format de vraie palette,
     étroit) et la lettre la remplit presque. */
  --haut: clamp(2rem, 3.4vw, 3rem);
  display: grid; gap: 4px; justify-content: center;
  margin: 2rem 0 1.5rem; padding: clamp(.7rem, 2vw, 1.3rem);
  background: #070707; border-radius: 12px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07), 0 30px 60px rgba(0, 0, 0, .5);
  overflow: hidden;
}
.tableau__ligne { display: grid; grid-template-columns: repeat(var(--colonnes, 24), calc(var(--haut) * .64)); gap: 2px; }
.palette {
  position: relative; display: grid; place-items: center;
  width: calc(var(--haut) * .64); height: var(--haut); overflow: hidden;
  background: linear-gradient(#232323 0 49%, #1b1b1b 51%);
  border-radius: 3px;
  font: 400 calc(var(--haut) * .78)/1 var(--anton);
  color: #fff;
  text-shadow: 0 0 1px rgba(255, 255, 255, .4);
  perspective: 300px;
}
/* Le trait de la charnière : présent, mais plus SOUS la lettre — avant, une
   barre noire de 2 px coupait chaque lettre en deux. */
.palette::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: rgba(0, 0, 0, .45); }
.tableau__ligne--ambre .palette { color: var(--ambre); text-shadow: 0 0 10px rgba(255, 190, 0, .35); }
.tableau__ligne--gris .palette { color: rgba(255, 255, 255, .62); }
.tableau__ligne--lieu .palette { color: var(--tilleul); }
.tableau__ligne--lieu + .tableau__ligne:not(.tableau__ligne--lieu) { margin-top: 6px; }
.tableau__ligne--vide .palette { background: #141414; }
/* Le tableau remplace VISUELLEMENT la liste ; la liste reste lue. */
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) #dates[data-tableau] .dates__archive-titre,
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) #dates[data-tableau] .dates-liste--archive {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
body:not(:is([data-vue="accueil"], [data-vue="salle"])) .tableau, html:not([data-moments]) .tableau { display: none; }
/* L'encart ambre se PLAQUE, avec un petit coup d'épaule. */
html[data-moments] body:is([data-vue="accueil"], [data-vue="salle"]) #dates.est-visible .encart-info {
  animation: plaquer .6s .35s cubic-bezier(.3, 1.5, .5, 1) both;
}
@keyframes plaquer {
  from { opacity: 0; scale: 1.1; rotate: 3deg; translate: 0 -12px; }
  to   { opacity: 1; scale: 1; rotate: -1.5deg; translate: 0 0; }
}

/* =========================================================
   6. La galerie en anneau, qui tourne seule (js/galerie-anneau.js)
   ========================================================= */
/* On occupe le centre de l'anneau. Grand angle (perspective courte) et
   rayon égal : la photo de face est à sa vraie taille, celles des côtés
   grossissent en s'approchant — c'est ce qui fait sentir le cercle. */
.galerie-anneau {
  --perspective: 650px;
  --rayon: 650px;
  --l: min(24vw, 21rem);
  position: relative;
  /* À la mesure des photos (4:3, zoomées de 14 % au centre) et du compteur :
     plus de grand vide au-dessus (« beaucoup d'espace vide », 04/10). */
  height: calc(var(--l) * .75 * 1.3 + 4.5rem);
  margin-block: -.5rem 1.5rem;
  overflow: hidden;
  perspective: var(--perspective);
}
.galerie-anneau__piste {
  position: absolute; left: 50%; top: 50%; width: 0; height: 0;
  transform-style: preserve-3d;
  transform: translateZ(var(--perspective));
}
.galerie-anneau__photo {
  position: absolute; left: calc(var(--l) / -2); top: calc(var(--l) * -.375);
  width: var(--l); height: calc(var(--l) * .75);
  backface-visibility: hidden;
  will-change: transform, opacity;
}
/* 4:3, photo entière (`contain`, jamais une tête coupée). */
.galerie-anneau__photo img {
  display: block; width: 100%; height: 100%; object-fit: contain; background: var(--encre);
  filter: grayscale(1) contrast(1.1);
  box-shadow: 0 30px 60px rgba(0, 0, 0, .5);
  transition: filter .5s ease, box-shadow .5s ease;
}
/* La photo arrêtée au centre : un peu de couleur et un liseré tilleul. */
.galerie-anneau__photo.est-au-centre img { filter: grayscale(.15) contrast(1.05); box-shadow: 0 40px 80px rgba(0, 0, 0, .65), 0 0 0 2px rgba(224, 251, 171, .5); }
/* La grille d'origine reste dans la page pour les lecteurs d'écran et le
   clavier (liens vers les photos en grand), mais l'anneau la remplace à l'œil. */
html[data-moments] #galerie[data-anneau] > .galerie-grille {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
html:not([data-moments]) .galerie-anneau { display: none; }
.viseur {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: calc(var(--l) * 1.1); height: calc(var(--l) * .83 + 1.6rem);
  pointer-events: none;
}
.viseur__coin { position: absolute; width: 3rem; height: 3rem; border: 4px solid var(--tilleul); }
.viseur__coin:nth-child(1) { left: 0; top: 0; border-right: 0; border-bottom: 0; }
.viseur__coin:nth-child(2) { right: 0; top: 0; border-left: 0; border-bottom: 0; }
.viseur__coin:nth-child(3) { left: 0; bottom: 0; border-right: 0; border-top: 0; }
.viseur__coin:nth-child(4) { right: 0; bottom: 0; border-left: 0; border-top: 0; }
.viseur__compte { position: absolute; left: 0; top: calc(100% + .8rem); font: 400 2rem/1 var(--anton); color: var(--tilleul); }
.viseur__reglages { position: absolute; right: 0; top: calc(100% + 1.1rem); font: 700 .8rem/1 var(--raleway); letter-spacing: .14em; color: rgba(255, 255, 255, .6); }
/* Téléphone : un anneau plus serré, des photos à la largeur du pouce. */
@media (max-width: 720px) {
  .galerie-anneau { --perspective: 380px; --rayon: 380px; --l: 46vw; }
  .viseur__compte { font-size: 1.4rem; }
  .viseur__reglages { display: none; }
}
.galerie-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; }

/* =========================================================
   7. Le bandeau ambre
   ========================================================= */
.bandeau {
  position: fixed; left: -20vw; right: -20vw; top: 0; bottom: 0; z-index: 8;
  pointer-events: none;
  background: var(--ambre);
  clip-path: polygon(14% 0, 100% 0, 86% 100%, 0 100%);
  display: flex; align-items: center; overflow: hidden;
  translate: -135% 0;
}
.bandeau__texte {
  white-space: nowrap; margin-inline: auto;
  font: 400 clamp(6rem, 20vw, 20rem)/1 var(--anton); text-transform: uppercase; letter-spacing: .02em;
  color: var(--fond);
}
/* Un peu d'air entre la galerie et le Booking : le panneau jaune ne part
   plus pendant qu'on regarde encore les photos (04/10, téléphone puis
   ordinateur). */
html[data-moments] body[data-vue="accueil"] #booking { margin-top: 18vh; }
/* L'adresse se tape, lettre après lettre. */
html[data-moments] .booking__mail.se-tape { animation: taper 1.3s steps(31, end) both; }
@keyframes taper { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* =========================================================
   Dans les salles de l'ascenseur : la même chose, dans une colonne étroite
   ========================================================= */
/* La colonne de lecture (62 caractères) serrait tout : Notre Musique, les
   Dates coupées, la galerie (03/10). Les salles prennent la largeur de
   l'accueil ; les paragraphes gardent leurs 60 caractères (.salle p).
   ⚠ `content-visibility: auto` impose un confinement de peinture : tout ce
   qui est censé couvrir l'écran (prénom géant, anneau) était coupé à la
   boîte de la section. Une seule salle est affichée à la fois : inutile. */
body[data-vue="salle"] main > .salle { max-width: none; content-visibility: visible; }
@media (min-width: 1000px) {
  html[data-moments] body[data-vue="salle"][data-salle="notre-musique"] #notre-musique {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: clamp(2rem, 5vw, 5rem); align-items: start;
  }
  html[data-moments] body[data-vue="salle"] #notre-musique > * { grid-column: 1 / -1; }
  html[data-moments] body[data-vue="salle"] #notre-musique > .bio { grid-column: 1; }
  html[data-moments] body[data-vue="salle"] #notre-musique > .platine { grid-column: 2; grid-row: 2; width: min(28vw, 24rem); margin: 1rem 0 0; }
}
body[data-vue="salle"] .platine { width: min(62vw, 17rem); margin: .5rem auto 2.5rem; }

/* Téléphone : deux portraits par rangée (plus petits, le prénom géant se
   voit derrière) ; la barre tient sur l'écran le plus étroit (« Booking »
   sortait du cadre à 360 px). */
@media (max-width: 720px) {
  html[data-moments] .membres { grid-template-columns: repeat(2, 1fr); gap: .8rem; }
  html[data-moments] .membre figcaption { padding: .55em .7em; }
  html[data-moments] .membre__role { font-size: .78rem; }
  .projecteur__geant { font-size: 42vw; }
  /* Le bandeau du bas, plus fin : il recouvrait le bas de la 2e rangée. */
  #le-groupe .projecteur__legende { font-size: 1.7rem; padding-block: .3rem .32rem; margin-top: 1rem; }
}
@media (max-width: 400px) {
  body > header .entete__nav a { font-size: .64rem !important; }
  body > header .entete__nav { gap: .2rem .45rem !important; }
}

/* ---- Mouvement réduit : défense en profondeur ---- */
@media (prefers-reduced-motion: reduce) {
  .afficheur, .nom-volant, .halo-musique, .bandeau, .projecteur__fond, .projecteur__legende, .tableau, .platine, .viseur, .galerie-flash { display: none !important; }
}
