@font-face {
  font-family: 'Designer';
  src: url('/fonts/designer.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
}

@font-face {
  font-family: 'Various';
  src: url('/fonts/various-regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
}

* {
  box-sizing: border-box
}

body {
  background: #FF5FBB;
  color: #fff;
  font-family: Inter, system-ui, sans-serif;
  text-align: center;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

#level-bg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
  user-select: none;
}

#three-container canvas {
  position: relative;
  z-index: 1;
  display: block;
}

/* Flash bleu plein écran */
#blue-flash {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(74, 108, 255, 0.85);
  z-index: 10000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.08s;
}

#blue-flash.active {
  opacity: 1;
}

.ath-left {
  position: fixed;
  top: 22px; /* laisse la place au réveil du timer (haut droite), aligné sur cette barre */
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  pointer-events: none;
  z-index: 9999;
}

/* HUD droite: timer */
.ath-right {
  position: fixed;
  top: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  pointer-events: none;
  z-index: 9999;
  padding: 0 14px;
}

/* Timer: visuel du niveau (barre + réveil) avec le temps écrit sur la barre.
   Aligné sur la barre de score (haut gauche): même hauteur de barre et même centre vertical.
   Position du texte, hauteur relative de la barre et contour viennent de levels.json (variables CSS). */
.audio-timer {
  --hud-bar-center: 77px; /* centre vertical de la barre de score: 22px (.ath-left top) + 55px */
  --hud-bar-h: 56px;      /* hauteur visible de la barre de score */
  --timer-text-x: 37.8;   /* % de la largeur de l'image */
  --timer-text-y: 59.1;   /* % de la hauteur de l'image (centre de la barre) */
  --timer-bar-h: 51.4;    /* hauteur de la barre en % de la hauteur de l'image */
  --timer-stroke: #0a3cc8;
  --timer-img-h: calc(var(--hud-bar-h) * 100 / var(--timer-bar-h));
  position: relative;
  height: var(--timer-img-h);
  margin-top: calc(var(--hud-bar-center) - var(--timer-img-h) * var(--timer-text-y) / 100);
}

.audio-timer-bg {
  display: block;
  height: 100%;
  width: auto;
  user-select: none;
}

.audio-timer-text {
  position: absolute;
  left: calc(var(--timer-text-x) * 1%);
  top: calc(var(--timer-text-y) * 1%);
  /* +0.076em: les chiffres de Designer sont dessinés au-dessus du centre de leur boîte */
  transform: translate(-50%, calc(-50% + 0.076em));
  font-family: 'Designer', sans-serif;
  font-size: calc(var(--hud-bar-h) * 0.5);
  line-height: 1;
  letter-spacing: 0.15em;
  padding-left: 0.15em; /* compense l'espacement ajouté après le dernier chiffre */
  white-space: nowrap;
  color: #fff;
  /* Contour épais dessiné sous le remplissage blanc */
  -webkit-text-stroke: calc(var(--hud-bar-h) * 0.07) var(--timer-stroke);
  paint-order: stroke fill;
}

/* HUD gauche: barre de score */
.progress-bar {
  position: relative;
  width: 500px;
  height: 100px;
}

.progress-bar .progress-bar-bg {
  position: absolute;
  z-index: 9997;
  top: 0;
  left: 0;
  width: 500px;
  height: 100px;
  object-fit: contain;
  pointer-events: none;
}

.progress-bar .progress-bar-icon {
  position: absolute;
  z-index: 10000;
  top: 0;
  left: 0;
  width: 500px;
  height: 100px;
  object-fit: contain;
  pointer-events: none;
}

.score-bar {
  /* Calé sur la maquette: texte ≈ 65 % de la largeur de la barre, juste sous celle-ci */
  position: absolute;
  top: 74px;
  left: 56px;
  font-family: 'Various', 'Designer', sans-serif;
  font-size: 29px;
  font-weight: normal;
  line-height: 1;
  white-space: nowrap;
  color: white;
  text-transform: uppercase;
  /* Contour orange épais dessiné sous le remplissage blanc */
  -webkit-text-stroke: 5px #FF6A00;
  paint-order: stroke fill;
  z-index: 10001;
}

/* « : 30.000XP » en police carrée (Various n'a ni chiffres ni ponctuation) */
.score-bar .score-value {
  font-family: 'Designer', sans-serif;
}

/* Image fixe au-dessus du canvas */
#niveau-image {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 100;
    width: 100%;
    height: 100%;
    object-fit: fill;
    pointer-events: none;
}

.progress-bar-fill-container {
  position: absolute;
  z-index: 9999;
  background-color: transparent;
  height: 34px;
  width: 413px;
  left: 66px;
  top: 39px;
  border-radius: 500px;
}

.progress-bar-fill {
  position: absolute;
  z-index: 9997;
  height: 100%;
  width: 0%;
  top: 0px;
  left: 0px;
  background: #FDFF9A;
  box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.3);
  filter: blur(1px);
  transition: width 0.15s linear;
  border-radius: 500px;
}

/* LOOSER: position aléatoire (ui/feedback.js) */
#looser-display {
  font-family: 'designer', Arial, sans-serif;
  letter-spacing: 0.08em;
  text-align: center;
  user-select: none;
  pointer-events: none;
}

/* Compteur de combo (haut centre) */
#combo-display {
  font-family: 'designer', Arial, sans-serif;
  letter-spacing: 0.05em;
  text-align: center;
  user-select: none;
  pointer-events: none;
}

/* Compteur de combo: image MASTA + nombre */
.combo-container {
  position: relative;
  display: inline-block;
}

.combo-number {
  position: absolute;
  top: 80%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 3rem;
  font-weight: bold;
  z-index: 10;
}

.combo-image {
  width: 300px;
  height: auto;
  object-fit: contain;
}

h1 {
  margin: 0 0 10px 0
}

.controls {
  margin: 12px 0
}

button {
  padding: 8px 12px;
  margin-left: 8px;
  border-radius: 8px;
  border: 1px solid #333;
  background: #1b1b1b;
  color: #fff;
  cursor: pointer
}

#game {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin: 30px auto;
  width: fit-content
}

.lane {
  position: relative;
  width: 110px;
  height: 420px;
  background: #111;
  border: 2px solid #222;
  overflow: hidden;
  border-radius: 8px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 12px;
  font-weight: 700;
  color: #777
}

.lane:after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 8px;
  bottom: 60px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.02))
}

.note {
  position: absolute;
  width: 100%;
  height: 18px;
  background: #00ff88;
  border-radius: 6px;
  left: 0;
  transform: translateY(-20px);
  box-shadow: 0 6px 18px rgba(0, 255, 136, 0.06)
}

.lane.active {
  box-shadow: 0 0 0 4px rgba(255, 0, 136, 0.06);
  border-color: #ff0077
}

#score {
  font-size: 18px
}

.overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  background: transparent;
  background-attachment: fixed;
  z-index: 9999;
  overflow: hidden;
  transition: transform 1200ms cubic-bezier(0.4, 0.0, 0.2, 1),
    opacity 1200ms cubic-bezier(0.4, 0.0, 0.2, 1),
    scale 1200ms cubic-bezier(0.4, 0.0, 0.2, 1);
  opacity: 1;
  scale: 1;
}

.chansons {
  width: 85%;
  margin: 0 auto;
  /* 3 cartes par ligne */
  display: grid;
  grid-template-columns: repeat(3, minmax(220px, 1fr));
  grid-auto-rows: 1fr;
  gap: clamp(18px, 3vw, 48px);
  align-items: stretch;
  justify-items: stretch;
  background-color: #452A7C1A;
  backdrop-filter: blur(10px);
  border-radius: 30px;
  border: 4px solid #FFFFFF33;
  padding: clamp(15px, 3.5vw, 40px) clamp(16px, 4vw, 50px);
}

@media (min-width: 2450px) {
  .chansons {
    max-width: 1400px;
    transform: scale(1.5);
  }
}

/* Écrans étroits: 3 colonnes plus serrées, puis 2, puis 1 */
@media (max-width: 900px) {
  .chansons {
    grid-template-columns: repeat(3, minmax(180px, 1fr));
    gap: clamp(12px, 4vw, 32px);
    padding: clamp(12px, 3vw, 36px);
  }
}

@media (max-width: 600px) {

  .chansons {
    grid-template-columns: repeat(2, minmax(160px, 1fr));
  }
}

@media (max-width: 420px) {

  .chansons {
    grid-template-columns: 1fr;
  }
}

.chanson {
  position: relative;
  width: 100%;
  /* Ratio fixe: pas de déformation quand le nombre de colonnes change */
  aspect-ratio: 3.5 / 5;
  max-height: calc(90vh - 40px);
  border-radius: 25px;
  /* lignes: difficulté, image, titre */
  border: 5px solid transparent;
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 13px;
  padding: 25px;
  overflow: hidden;
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}

/* Niveau verrouillé: grisé et non cliquable */
.chanson.locked {
  filter: grayscale(100%) brightness(80%);
  opacity: 0.6;
  pointer-events: none;
}
.chanson.locked::after {
  content: 'LOCKED';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Designer', sans-serif;
  font-size: clamp(24px, 3vw, 42px);
  color: rgba(255,255,255,0.95);
  -webkit-text-stroke: 1px #00000088;
  text-shadow:
    1px 1px 0 #0008,
    -1px 1px 0 #0008,
    1px -1px 0 #0008,
    -1px -1px 0 #0008;
}

.chanson .select-icon {
  position: absolute;
  height: 88%;
  width: auto;
  border: none;
  top: 50%;
  left: 2%;
  transform: translateY(-50%);
  opacity: 0;
  transition: opacity 200ms ease;
}

.chanson.focused .select-icon {
  opacity: 1;
}

.chanson.focused {
  outline: none;
  transform: scale(1.02);
  border-color: #dcdcdc6a;
}

.chanson.focused .difficulty {
  background-color: #3A8BFA;
  color: #3A8BFA;
  -webkit-text-stroke: 1px #FFFFFF;
  text-shadow:
    1px 1px 0 #FFFFFF,
    -1px 1px 0 #FFFFFF,
    1px -1px 0 #FFFFFF,
    -1px -1px 0 #FFFFFF,
    0 1px 0 #FFFFFF,
    1px 0 0 #FFFFFF,
    0 -1px 0 #FFFFFF,
    -1px 0 0 #FFFFFF;
}

.chanson.focused::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 25px;
  pointer-events: none;
  z-index: -1;
  background: linear-gradient(180deg, #00b5e294 0%, #8cff8694 100%);
  mix-blend-mode: hard-light;
  filter: blur(15px) saturate(2.1) brightness(2.4);
}

.chanson img {
  width: 100%;
  /* image carrée, recadrée sans déformation */
  aspect-ratio: 1 / 1;
  display: block;
  align-self: center;
  justify-self: center;
  grid-row: 2;
  object-fit: cover;
  margin: 0;
  border-radius: 50px;
  border: 3px solid #fff;
  z-index: 1;
}

.chanson h3 {
  grid-row: 3;
  margin-top: 6px;
  font-size: 1.5em;
  width: 100%;
  text-align: center;
  font-weight: normal;
  font-family: 'Designer', sans-serif;
  margin: 0;
  color: white;
  -webkit-text-stroke: 1px #3A8BFA;
  text-shadow:
    1px 1px 0 #3A8BFA,
    -1px 1px 0 #3A8BFA,
    1px -1px 0 #3A8BFA,
    -1px -1px 0 #3A8BFA,
    0 1px 0 #3A8BFA,
    1px 0 0 #3A8BFA,
    0 -1px 0 #3A8BFA,
    -1px 0 0 #3A8BFA;
}

.difficulty {
  position: relative;
  width: 100%;
  border-radius: 50px;
  background-color: #9AE1DB;
  font-family: 'Designer', sans-serif;
  font-size: 1.4em;
  font-weight: bold;
  border: 3px solid #FFFFFF;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  color: white;
  -webkit-text-stroke: 1px #3A8BFA;
  text-shadow:
    1px 1px 0 #3A8BFA,
    -1px 1px 0 #3A8BFA,
    1px -1px 0 #3A8BFA,
    -1px -1px 0 #3A8BFA,
    0 1px 0 #3A8BFA,
    1px 0 0 #3A8BFA,
    0 -1px 0 #3A8BFA,
    -1px 0 0 #3A8BFA;
}

.overlay.slide-out {
  transform: translateY(-20%);
  opacity: 0;
  scale: 1.5;
  pointer-events: none;
}

.intro-video-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Opaque: la scène 3D ne doit jamais apparaître pendant le fondu des vidéos */
  background: #000;
  z-index: 100010; /* au-dessus du loader et du menu */
  opacity: 1;
  transition: opacity 500ms ease;
}

.intro-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1s ease;
}

.intro-video.fade-in {
  opacity: 1;
}

/* Écran de score, par-dessus la vidéo de fin figée */
.end-ui {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: clamp(12px, 3vw, 28px);
  pointer-events: auto;
  z-index: 100020;
}

.end-score {
    font-family: 'Designer', sans-serif;
    font-weight: 700;
    color: white;
    text-transform: uppercase;
    font-size: 3rem;
    -webkit-text-stroke: 1px #00000088;
    text-shadow:
    1px 1px 0 #0008,
    -1px 1px 0 #0008,
    1px -1px 0 #0008,
    -1px -1px 0 #0008;
    background-color: #000000;
    border-radius: 50px;
    padding: 1rem;
}

.end-back-btn {
  width: 20%;
  height: auto;
  cursor: pointer;
  user-select: none;
  transition: transform 120ms ease;
  position: absolute;
  bottom: -10px;
  left: -10px;
  pointer-events: auto;
}

.end-back-btn:active {
  transform: scale(0.98);
}

/* Personnages de l'écran de score (positions de la maquette 2000×1125, centrées sur leur point) */
.end-onpus {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}

.end-onpus.shown {
  display: block;
}

.end-onpu {
  position: absolute;
  height: auto;
  transform: translate(-50%, -50%);
  user-select: none;
}

.end-onpu-tl {
  left: 19%;
  top: 33%;
  width: 21%;
}

.end-onpu-br {
  left: 82%;
  top: 71%;
  width: 26.5%;
}

/* onpu3 / onpu4 sont plus étroits (pas de traits de mouvement): même taille de disque */
.end-onpus-lose .end-onpu-tl {
  width: 15.5%;
}

.end-onpus-lose .end-onpu-br {
  width: 18.5%;
}

/* Colonne centrée sous le badge WIN/LOSE: score, Next level, Elevator unlocked */
.end-stack {
  position: absolute;
  top: 55%;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, 1.6vw, 24px);
  pointer-events: none;
}

/* Next level: rose si victoire, bleu si défaite */
.end-next-btn {
  width: 26%;
}

/* Retour ascenseur (niveau 1 à partir de 30000): plus petit que Next level */
.end-elevator-btn {
  width: 19%;
}

.end-next-btn,
.end-elevator-btn {
  height: auto;
  cursor: pointer;
  user-select: none;
  transition: transform 120ms ease;
  pointer-events: auto;
}

.end-next-btn:active,
.end-next-btn.pressed-scale,
.end-elevator-btn:active,
.end-elevator-btn.pressed-scale {
  transform: scale(0.96);
}

.skip-video-hint {
  position: absolute;
  bottom: 40px;
  right: 1%;
  transform: translateX(-50%);
  color: white;
  font-size: 14px;
  font-family: 'Designer', Inter, system-ui, sans-serif;
  text-align: center;
  padding: 12px 24px;
  background: rgba(0, 0, 0, 0.6);
  border-radius: 8px;
  animation: pulse-hint 2s ease-in-out infinite;
  pointer-events: none;
}

@keyframes pulse-hint {

  0%,
  100% {
    opacity: 0.7;
  }

  50% {
    opacity: 1;
  }
}

/* Loader */
.loader-overlay {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  background: #FF5FBB;
  z-index: 11000; /* au-dessus du menu */
  opacity: 1;
  transition: opacity 400ms ease;
}

.loader-overlay img#loader-img {
  width: min(40vw, 360px);
  height: auto;
  user-select: none;
  animation: vinyl-bounce 1.3s cubic-bezier(.215, .61, .355, 1) infinite;
  will-change: transform;
}

.loader-bottom-left {
  position: absolute;
  left: 18px;
  bottom: 18px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: white;
  font-weight: 600;
  text-transform: lowercase;
}

.loader-bottom-left .loader-text {
  font-size: 30px;
  font-family: 'Designer', sans-serif;
  font-weight: 200;
  letter-spacing: 0.1em;
  -webkit-text-stroke: 1px #FF0088;
  text-shadow:
    1px 1px 0 #FF0088,
    -1px 1px 0 #FF0088,
    1px -1px 0 #FF0088,
    -1px -1px 0 #FF0088,
    0 1px 0 #FF0088,
    1px 0 0 #FF0088,
    0 -1px 0 #FF0088,
    -1px 0 0 #FF0088;
  opacity: 0.85;
}

.spinner {
  width: 45px;
  height: 45px;
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 255, 0.18);
  border-top-color: white;
  animation: spinner-rot 800ms linear infinite;
}

@keyframes spinner-rot {
  to {
    transform: rotate(360deg);
  }
}

@keyframes vinyl-bounce {

  0%,
  100% {
    transform: translateY(0) scale(1);
  }

  30% {
    transform: translateY(-16px) scale(1.03);
  }

  50% {
    transform: translateY(0) scale(1);
  }

  70% {
    transform: translateY(-8px) scale(1.02);
  }
}

@media (prefers-reduced-motion: reduce) {
  .loader-overlay img#loader-img {
    animation: none;
  }
}

.bg_menu {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  object-fit: cover;
  z-index: -1;
  user-select: none;
}

.hidden {
  display: none !important;
}

.three-container {
  width: 100vw;
  height: 100vh;
}

#score {
  position: fixed;
  bottom: 20px;
  left: 20px;
  font-size: 24px;
  z-index: 10;
}

/* Bouton back en haut à gauche du menu */
.btn-back {
  position: absolute;
  bottom: 0px;
  left: 0px;
  width: 20%;
  height: auto;
  z-index: 1;
  user-select: none;
  cursor: pointer;
}

.btn-back:active {
  transform: scale(0.98);
}

/* Tremblement de la scène quand on rate une note */
@keyframes shake {

  0%,
  100% {
    transform: translate(0, 0) rotate(0deg);
  }

  10% {
    transform: translate(-5px, -5px) rotate(-0.5deg);
  }

  20% {
    transform: translate(5px, 5px) rotate(0.5deg);
  }

  30% {
    transform: translate(-5px, 5px) rotate(-0.5deg);
  }

  40% {
    transform: translate(5px, -5px) rotate(0.5deg);
  }

  50% {
    transform: translate(-8px, 0) rotate(-0.8deg);
  }

  60% {
    transform: translate(8px, 0) rotate(0.8deg);
  }

  70% {
    transform: translate(0, -8px) rotate(-0.5deg);
  }

  80% {
    transform: translate(0, 8px) rotate(0.5deg);
  }

  90% {
    transform: translate(-3px, -3px) rotate(-0.3deg);
  }
}

#three-container.shake {
  animation: shake 0.5s ease-in-out;
}

/* Rebond du compteur de combo */
@keyframes comboBounce {
  0% {
    transform: translate(-50%, -50%) scale(0.8) rotateX(0deg) rotateZ(0deg);
    opacity: 0;
  }

  50% {
    transform: translate(-50%, -50%) scale(1.3) rotateX(10deg) rotateZ(2deg);
    opacity: 1;
  }

  100% {
    transform: translate(-50%, -50%) scale(1.15) rotateX(0deg) rotateZ(0deg);
    opacity: 1;
  }
}

#combo-display {
  animation: comboBounce 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55) !important;
}

/* Popup « Êtes-vous sûr de vouloir quitter ? » de la librairie Axis (Échap): ajoutée hors du
   <body> sans z-index, elle passait derrière la piste et le HUD. L'élément n'a pas de taille:
   il ne bloque aucun clic quand la popup est fermée. */
axis-exit-overlay {
  position: relative;
  z-index: 2147483647;
}

/* --- Écran des commandes (ui/controlsScreen.js): même habillage que le menu --- */
.controls-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}

.controls-panel {
  width: min(85%, 1100px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 2.4vw, 32px);
  padding: clamp(18px, 3vw, 40px) clamp(18px, 4vw, 50px);
  background-color: #452A7C1A;
  backdrop-filter: blur(10px);
  border: 4px solid #FFFFFF33;
  border-radius: 30px;
}

.controls-title,
.controls-tips,
.controls-or,
.controls-btn {
  font-family: 'Designer', sans-serif;
  color: #fff;
  -webkit-text-stroke: 1px #3A8BFA;
}

.controls-title {
  margin: 0;
  font-size: clamp(22px, 3vw, 44px);
  font-weight: normal;
  text-align: center;
}

.controls-lanes {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 3vw, 48px);
  width: 100%;
}

.controls-lane {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 16px 8px 20px;
  border-radius: 24px;
  background: #00000026;
  border-bottom: 6px solid var(--lane-color);
}

.controls-axis {
  width: min(11vw, 130px);
  height: auto;
  user-select: none;
}

.controls-or {
  font-size: clamp(12px, 1.2vw, 18px);
  opacity: 0.9;
}

/* Touche de clavier en relief, liserée de la couleur de la lane */
.keycap {
  display: inline-grid;
  place-items: center;
  min-width: min(7vw, 84px);
  height: min(7vw, 84px);
  padding: 0 0.3em;
  border-radius: 16px;
  background: #fff;
  border: 4px solid var(--lane-color, #3A8BFA);
  box-shadow: 0 6px 0 #1d1236;
  font-family: 'Designer', sans-serif;
  font-size: min(4vw, 48px);
  color: #1d1236;
  -webkit-text-stroke: 0;
}

/* carré fixe (quelle que soit la lettre), à la taille du bouton Axis voisin: 2em × 0.9em = 1.8em du bouton */
.keycap-small {
  width: 2em;
  height: 2em;
  min-width: 0;
  padding: 0;
  border-width: 3px;
  border-radius: 10px;
  box-shadow: 0 3px 0 #1d1236;
  font-size: 0.9em;
  vertical-align: middle;
}

.controls-tips {
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: center;
  font-size: clamp(13px, 1.4vw, 20px);
  line-height: 1.7;
}

.controls-actions {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
}

.controls-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 10px 22px;
  border-radius: 999px;
  border: 3px solid #fff;
  background: #9AE1DB;
  font-size: clamp(14px, 1.5vw, 22px);
  cursor: pointer;
  transition: transform 120ms ease;
}

.controls-btn:active {
  transform: scale(0.97);
}

.controls-btn-start {
  background: #3A8BFA;
}

.controls-btn img {
  width: 1.8em;
  height: 1.8em;
}

/* --- Écran titre (ui/startScreen.js) ---
   Maquette 5120×2880 affichée en "cover": les positions sont en % de la maquette et
   les tailles en cqw (1cqw = 1 % de la largeur de la scène). */
.start-overlay {
  position: fixed;
  inset: 0;
  z-index: 12000; /* au-dessus du loader, sous les vidéos */
  overflow: hidden;
  background: #FF5FBB;
}

.start-stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: max(100vw, 100vh * 16 / 9);
  aspect-ratio: 16 / 9;
  translate: -50% -50%;
  container-type: inline-size;
}

.start-bg,
.start-particles {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.start-sparkles {
  position: absolute;
  left: 15.66%;
  top: 3.82%;
  width: 66.13%;
  height: 82.78%;
}

.start-particles svg,
.start-sparkles svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.start-logo {
  position: absolute;
  left: 17.52%;
  top: 18.23%;
  width: 64.71%;
  height: auto;
}

.start-stage img {
  user-select: none;
  pointer-events: none;
}

/* Délai et durée de chaque particule tirés au hasard en JS */
.start-particles svg > *,
.start-sparkles svg > * {
  transform-box: fill-box;
  transform-origin: center;
  animation: start-float 3s ease-in-out infinite alternate;
}

.start-sparkles svg > * {
  animation-name: start-twinkle;
  animation-direction: normal;
}

/* Unités du SVG (maquette 5120 px de large) */
@keyframes start-float {
  from { translate: -15px 30px; }
  to { translate: 15px -30px; }
}

@keyframes start-twinkle {
  0%, 100% { scale: 1; opacity: 1; rotate: 0deg; }
  50% { scale: 0.5; opacity: 0.35; rotate: 25deg; }
}

.start-buttons {
  position: absolute;
  left: 0;
  right: 0;
  top: 66.3%;
  display: flex;
  justify-content: center;
  gap: 3.1cqw;
  pointer-events: none; /* uniquement manette Axis ou clavier */
  user-select: none;
}

.start-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5cqw;
  width: 8.83cqw;
}

.start-btn-face {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
}

.start-btn-face img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.start-btn-on {
  opacity: 0;
}

.start-btn.is-on .start-btn-on {
  opacity: 1;
}

.start-btn.is-on .start-btn-face {
  animation: start-btn-press 320ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes start-btn-press {
  35% { scale: 0.85; }
}

/* Touche clavier de la lane, sous chaque bouton */
.start-key {
  display: grid;
  place-items: center;
  width: 2.2cqw;
  height: 2.2cqw;
  border: 0.2cqw solid #000;
  border-radius: 0.5cqw;
  box-shadow: 0 0.22cqw 0 #000;
  background: #fff;
  color: #000;
  font-family: 'Designer', sans-serif;
  font-size: 1.2cqw;
  transition: background 150ms ease, color 150ms ease;
}

.start-btn.is-on .start-key {
  background: #FB1F76;
  color: #fff;
}

.start-hint {
  position: absolute;
  left: 50.85%;
  top: 88.8%;
  width: 42.75%;
  height: auto;
  translate: -50% 0;
  animation: start-blink 1.6s ease-in-out infinite alternate;
}

/* Respiration douce (aller-retour), sans palier */
@keyframes start-blink {
  from { opacity: 1; }
  to { opacity: 0.25; }
}

/* --- Animations d'entrée des écrans ---
   `translate`/`scale` (et non `transform`) pour ne pas écraser les transform existants
   (carte sélectionnée, badges centrés, boutons appuyés). `backwards`: l'état de départ
   s'applique pendant le délai, puis l'élément retrouve son style normal. */
@keyframes rise-in {
  from { opacity: 0; translate: 0 24px; }
}

@keyframes fade-in {
  from { opacity: 0; }
}

@keyframes badge-pop {
  from { opacity: 0; scale: 0.5; }
  60% { opacity: 1; }
}

@keyframes onpu-pop {
  from { opacity: 0; scale: 0.3; rotate: -20deg; }
  60% { opacity: 1; }
}

@keyframes onpu-float {
  0%, 100% { translate: 0 0; rotate: -3deg; }
  50% { translate: 0 -18px; rotate: 3deg; }
}

/* Cartes du menu, en cascade */
.overlay.menu-enter .chanson {
  animation: rise-in 500ms cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}

.overlay.menu-enter .chanson:nth-child(2) {
  animation-delay: 80ms;
}

.overlay.menu-enter .chanson:nth-child(3) {
  animation-delay: 160ms;
}

/* Écran de score: badge puis score grandissent depuis le centre, puis boutons en cascade */
.end-ui:not(.hidden) {
  animation: fade-in 300ms ease backwards;
}

.end-ui:not(.hidden) #end-win-badge,
.end-ui:not(.hidden) #end-loose-badge {
  animation: badge-pop 650ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
}

.end-ui:not(.hidden) .end-stack > * {
  animation: rise-in 450ms ease-out backwards;
}

.end-ui:not(.hidden) .end-stack > .end-score {
  animation: badge-pop 550ms cubic-bezier(0.34, 1.56, 0.64, 1) 250ms backwards;
}

.end-ui:not(.hidden) .end-stack > :nth-child(2) {
  animation-delay: 350ms;
}

.end-ui:not(.hidden) .end-stack > :nth-child(3) {
  animation-delay: 450ms;
}

.end-ui:not(.hidden) .end-back-btn {
  animation: fade-in 400ms ease 500ms backwards;
}

/* Personnages: arrivent juste après le score, puis flottent (décalés l'un de l'autre) */
.end-ui:not(.hidden) .end-onpu-tl {
  animation:
    onpu-pop 600ms cubic-bezier(0.34, 1.56, 0.64, 1) 700ms backwards,
    onpu-float 3s ease-in-out 1300ms infinite;
}

.end-ui:not(.hidden) .end-onpu-br {
  animation:
    onpu-pop 600ms cubic-bezier(0.34, 1.56, 0.64, 1) 900ms backwards,
    onpu-float 3.4s ease-in-out 1500ms infinite reverse;
}

@media (prefers-reduced-motion: reduce) {
  .overlay.menu-enter .chanson,
  .end-ui:not(.hidden),
  .end-ui:not(.hidden) *,
  .start-overlay * {
    animation: none !important;
  }
}

/* --- Transitions entre écrans (ui/transitions.js) ---
   .is-cover: l'animation recouvre l'écran et reste couverte (fill forwards);
   .is-reveal: elle part de l'écran couvert et le découvre. */
.transition-layer {
  position: fixed;
  inset: 0;
  z-index: 150000;
  overflow: hidden;
}

/* Portes d'ascenseur: deux battants métalliques brossés */
.tr-doors .door {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50.5%;
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.07) 0 2px, transparent 2px 6px),
    linear-gradient(90deg, #7d838c, #d9dde2 30%, #a3a9b1 55%, #eef1f4 78%, #8e949c);
  box-shadow: inset 0 0 0 5px #4b5058, inset 0 0 40px rgba(0, 0, 0, 0.35);
}

.tr-doors .door.left { left: 0; translate: -100% 0; }
.tr-doors .door.right { right: 0; translate: 100% 0; }
.tr-doors.is-cover .door { animation: tr-to-origin 550ms cubic-bezier(0.6, 0, 0.35, 1) forwards; }
.tr-doors.is-reveal .door { translate: 0 0; }
.tr-doors.is-reveal .door.left { animation: tr-out-left 600ms cubic-bezier(0.6, 0, 0.35, 1) forwards; }
.tr-doors.is-reveal .door.right { animation: tr-out-right 600ms cubic-bezier(0.6, 0, 0.35, 1) forwards; }

/* Vinyle: un disque qui arrive en tournant et grossit jusqu'à couvrir l'écran */
.tr-vinyl .disc {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 160vmax;
  height: 160vmax;
  margin: -80vmax 0 0 -80vmax;
  border-radius: 50%;
  background:
    radial-gradient(circle, #111 0 1.2%, #ff5fbb 1.3% 11%, #111 11.2% 12%, transparent 12.2%),
    conic-gradient(from 20deg, transparent 0 10%, rgba(255, 255, 255, 0.14) 15%, transparent 22% 55%, rgba(255, 255, 255, 0.14) 62%, transparent 70%),
    repeating-radial-gradient(circle, #141414 0 0.35vmax, #262626 0.35vmax 0.7vmax);
  scale: 0;
}

.tr-vinyl.is-cover .disc { animation: disc-in 550ms cubic-bezier(0.5, 0, 0.3, 1) forwards; }
.tr-vinyl.is-reveal .disc { scale: 1; animation: disc-out 600ms cubic-bezier(0.6, 0, 0.4, 1) forwards; }

/* Volets BD: trois bandes rose / bleu / vert en diagonale, cernées de noir */
.tr-bands .bands {
  position: absolute;
  inset: -30%;
  display: flex;
  flex-direction: column;
  rotate: -12deg;
}

.tr-bands .band {
  flex: 1;
  margin: -10px 0;
  border-block: 10px solid #000;
  translate: -120% 0;
}

.tr-bands .band:nth-child(1) { background: #ff5fbb; }
.tr-bands .band:nth-child(2) { background: #3a8bfa; animation-delay: 70ms !important; }
.tr-bands .band:nth-child(3) { background: #2bdc5a; animation-delay: 140ms !important; }
.tr-bands.is-cover .band { animation: tr-to-origin 420ms cubic-bezier(0.7, 0, 0.3, 1) forwards; }
.tr-bands.is-reveal .band { translate: 0 0; animation: tr-out-right 460ms cubic-bezier(0.7, 0, 0.3, 1) forwards; }

/* Explosion BD: étoile jaune géante + « POW! » */
.tr-pow {
  display: grid;
  place-items: center;
}

.tr-pow .burst {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 230vmax;
  height: 230vmax;
  margin: -115vmax 0 0 -115vmax;
  scale: 0;
}

.tr-pow .burst polygon {
  fill: #ffe600;
  stroke: #000;
  stroke-width: 3;
  stroke-linejoin: round;
}

.tr-pow .pow {
  position: relative;
  font-family: 'Designer', sans-serif;
  font-size: 16vw;
  color: #ff3b7f;
  -webkit-text-stroke: 0.9vw #000;
  paint-order: stroke fill;
  rotate: -8deg;
  scale: 0;
}

.tr-pow.is-cover .burst { animation: burst-in 550ms cubic-bezier(0.34, 1.4, 0.64, 1) forwards; }
.tr-pow.is-cover .pow { animation: tr-scale-in 350ms cubic-bezier(0.34, 1.8, 0.64, 1) 200ms forwards; }
.tr-pow.is-reveal .burst { scale: 1; animation: burst-out 600ms cubic-bezier(0.6, 0, 0.4, 1) forwards; }
.tr-pow.is-reveal .pow { scale: 1; animation: tr-scale-out 250ms ease-in forwards; }

/* Iris cartoon: un cercle se referme sur le centre, puis se rouvre */
.tr-iris .hole {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 170vmax;
  height: 170vmax;
  translate: -50% -50%;
  border-radius: 50%;
  box-shadow: 0 0 0 200vmax #0b0614, inset 0 0 0 0.6vmax #ff5fbb;
}

.tr-iris.is-cover .hole { animation: iris-close 550ms cubic-bezier(0.55, 0, 0.4, 1) forwards; }
.tr-iris.is-reveal .hole { width: 0; height: 0; animation: iris-open 600ms cubic-bezier(0.6, 0, 0.45, 1) forwards; }

/* Glitch VHS: tranches qui arrivent par à-coups de chaque côté, aberration RVB, lignes de balayage */
.tr-glitch .slice {
  position: absolute;
  left: 0;
  width: 100%;
  height: 10.5%;
  background: #0d0a18;
  box-shadow: -8px 0 0 #ff00c8, 8px 0 0 #00f0ff;
  translate: var(--from) 0;
}

.tr-glitch .scanlines {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.06) 0 2px, transparent 2px 4px);
}

.tr-glitch.is-cover .slice { animation: tr-to-origin 380ms steps(6, end) forwards; }
.tr-glitch.is-reveal .slice { translate: 0 0; animation: slice-out 420ms steps(6, end) forwards; }

/* Pluie de notes: un rideau rose bordé de notes de musique descend, puis continue sa chute */
.tr-notes .curtain {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #ff5fbb, #b13dff);
  translate: 0 -115%;
}

.tr-notes .note {
  position: absolute;
  color: #fff;
  -webkit-text-stroke: 2px #6a1bb0;
  paint-order: stroke fill;
  line-height: 1;
}

.tr-notes.is-cover .curtain { animation: tr-to-origin 550ms cubic-bezier(0.5, 0, 0.35, 1) forwards; }
.tr-notes.is-reveal .curtain { translate: 0 0; animation: curtain-out 600ms cubic-bezier(0.6, 0, 0.4, 1) forwards; }

/* Zoom: le décor zoome vers le fond (JS sur #app) pendant que l'écran passe au noir */
.tr-zoom {
  background: #000;
  opacity: 0;
}

.tr-zoom.is-cover { animation: tr-opacity-in 550ms ease-in forwards; }
.tr-zoom.is-reveal { opacity: 1; animation: tr-opacity-out 600ms ease-out forwards; }

@keyframes tr-to-origin { to { translate: 0 0; } }
@keyframes tr-out-left { to { translate: -100% 0; } }
@keyframes tr-out-right { to { translate: 120% 0; } }
@keyframes tr-scale-in { to { scale: 1; } }
@keyframes tr-scale-out { to { scale: 0; } }
@keyframes tr-opacity-in { to { opacity: 1; } }
@keyframes tr-opacity-out { to { opacity: 0; } }
@keyframes disc-in { from { scale: 0; rotate: -540deg; } to { scale: 1; rotate: 0deg; } }
@keyframes disc-out { from { scale: 1; rotate: 0deg; } to { scale: 0; rotate: 540deg; } }
@keyframes burst-in { from { scale: 0; rotate: -40deg; } to { scale: 1; rotate: 0deg; } }
@keyframes burst-out { to { scale: 0; rotate: 40deg; } }
@keyframes iris-close { to { width: 0; height: 0; } }
@keyframes iris-open { from { width: 0; height: 0; } to { width: 170vmax; height: 170vmax; } }
@keyframes slice-out { to { translate: var(--to) 0; } }
@keyframes curtain-out { to { translate: 0 115%; } }

/* --- Animations quand on touche un piège (render/trapEffects.js) ---
   Éléments temporaires centrés sur la touche (.tfx) ou plein écran (.tfx-full).
   Numéros = indices de setTrapEffect (8 = Secousse de piste, uniquement en JS). */
.trap-fx-layer {
  position: fixed;
  inset: 0;
  z-index: 100004; /* au-dessus de la piste et du HUD, sous les vidéos de fin */
  pointer-events: none;
  overflow: hidden;
}

.tfx { position: absolute; width: 0; height: 0; }
.tfx-full { inset: 0; width: auto; height: auto; }

/* 0. Explosion: onde de choc + débris */
.tfx-explosion .ring {
  position: absolute;
  left: -12px;
  top: -12px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 6px solid #ff9500;
  animation: tfx-ring 500ms ease-out forwards;
}
.tfx-explosion .r2 { border-color: #ff3b30; animation-delay: 80ms; }
.tfx-explosion i {
  position: absolute;
  left: -7px;
  top: -7px;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  animation: tfx-debris 650ms cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}

/* 1. Éclair */
/* jaune cerné de noir, angles pointus (comme les éclairs du décor du niveau 3) */
.tfx-lightning .bolt { fill: none; stroke: #000; stroke-width: 12; stroke-linejoin: miter; stroke-miterlimit: 8; }
.tfx-lightning .core { stroke: #ffe600; stroke-width: 6; }
.tfx-lightning svg { animation: tfx-flicker 480ms steps(1) forwards; }
.tfx-lightning::before { content: ''; position: absolute; inset: 0; background: #fff6a0; animation: tfx-flash 160ms ease-out forwards; }

/* 2. Écran rouge */
.tfx-red {
  background: radial-gradient(ellipse at center, transparent 35%, rgba(255, 0, 40, 0.75) 100%);
  animation: tfx-fade 650ms ease-out forwards;
}

/* 3. Glitch: bandes colorées + image dédoublée (#app) */
.tfx-glitch i {
  position: absolute;
  left: 0;
  right: 0;
  mix-blend-mode: difference;
  animation: tfx-glitch-bar 380ms steps(4) forwards;
}
.tfx-glitching { animation: tfx-glitch 380ms steps(6) forwards; }

/* 4. Vitre brisée */
.tfx-crack polyline {
  fill: none;
  stroke: #fff;
  stroke-width: 3;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  filter: drop-shadow(0 0 2px #000);
  animation: tfx-draw 140ms ease-out forwards;
}
.tfx-crack circle { fill: #ffffffcc; stroke: #000; stroke-width: 2; }
.tfx-crack svg { animation: tfx-fade 900ms ease-in forwards; }

/* 5. Fumée */
.tfx-smoke i {
  position: absolute;
  left: -55px;
  top: -55px;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: radial-gradient(circle, #151515 0 50%, #15151599 62%, transparent 72%);
  filter: blur(2px);
  opacity: 0;
  animation: tfx-smoke 950ms ease-out forwards;
}

/* 6. −200 */
.tfx-minus span {
  position: absolute;
  translate: -50% -50%;
  font-family: 'Designer', sans-serif;
  font-size: clamp(40px, 5vw, 80px);
  color: #ff2e2e;
  -webkit-text-stroke: 5px #000;
  paint-order: stroke fill;
  white-space: nowrap;
  animation: tfx-minus 950ms ease-out forwards;
}

/* 7. BOOM BD */
.tfx-boom svg,
.tfx-boom span {
  position: absolute;
  translate: -50% -50%;
  animation: tfx-pop 850ms cubic-bezier(0.34, 1.6, 0.64, 1) forwards;
}
.tfx-boom svg { width: clamp(160px, 18vw, 280px); }
.tfx-boom polygon { fill: #ffe600; stroke: #000; stroke-width: 6; stroke-linejoin: round; }
.tfx-boom span {
  font-family: 'Designer', sans-serif;
  font-size: clamp(28px, 3.4vw, 54px);
  color: #ff2e2e;
  -webkit-text-stroke: 4px #000;
  paint-order: stroke fill;
  rotate: -8deg;
}

/* 9. Alarme: gyrophares rouge / bleu sur les côtés */
.tfx-alarm i {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 22vw;
  opacity: 0;
  animation: tfx-alarm 280ms steps(1) 3;
}
.tfx-alarm .left { left: 0; background: linear-gradient(90deg, rgba(255, 20, 40, 0.85), transparent); }
.tfx-alarm .right { right: 0; background: linear-gradient(270deg, rgba(40, 90, 255, 0.85), transparent); animation-delay: 140ms; }

@keyframes tfx-ring { to { scale: 10; opacity: 0; border-width: 1px; } }
@keyframes tfx-debris { to { translate: var(--dx) var(--dy); rotate: var(--r); scale: 0.3; opacity: 0; } }
@keyframes tfx-flicker { 0% { opacity: 1; } 20% { opacity: 0; } 35% { opacity: 1; } 55% { opacity: 0.2; } 70% { opacity: 1; } 100% { opacity: 0; } }
@keyframes tfx-flash { from { opacity: 0.35; } to { opacity: 0; } }
@keyframes tfx-fade { to { opacity: 0; } }
@keyframes tfx-glitch-bar { 0% { translate: 0 0; opacity: 0.9; } 50% { translate: var(--dx) 0; } 100% { translate: 0 0; opacity: 0; } }
@keyframes tfx-glitch {
  0% { filter: drop-shadow(6px 0 #ff00c8) drop-shadow(-6px 0 #00f0ff); translate: 4px 0; }
  33% { filter: drop-shadow(-8px 0 #ff00c8) drop-shadow(8px 0 #00f0ff); translate: -6px 2px; }
  66% { filter: drop-shadow(4px 0 #ff00c8) drop-shadow(-4px 0 #00f0ff); translate: 3px -2px; }
  100% { filter: none; translate: 0 0; }
}
@keyframes tfx-draw { to { stroke-dashoffset: 0; } }
@keyframes tfx-smoke { 0% { opacity: 0.9; scale: 0.3; } 100% { opacity: 0; scale: var(--s); translate: var(--dx) var(--dy); } }
@keyframes tfx-minus { 0% { scale: 0; } 18% { scale: 1.3; } 32% { scale: 1; translate: -50% -50%; } 100% { scale: 1; translate: -50% -180%; opacity: 0; } }
@keyframes tfx-pop { 0% { scale: 0; opacity: 1; } 30% { scale: 1; } 75% { opacity: 1; } 100% { scale: 1.1; opacity: 0; } }
@keyframes tfx-alarm { 0% { opacity: 1; } 50% { opacity: 0; } }
