/* ==========================================================================
   MON PREMIER ORCHESTRE, la mise en page.
   Feuille UNIQUE, partagee par index.html (l'app) et test/maquette.html (la
   reference figee). Une seule source : recopier ces regles dans les deux
   pages les ferait diverger au premier reglage.

   Trois zones : les controles en haut, la scene au centre, la reserve autour
   en paysage et en dessous en portrait. Bascule au point de rupture de 900 px.
   Les emplacements de scene sont en DEMI-CERCLE en paysage, tranche par
   Mathieu le 15 septembre 2026 contre une grille 3x2.
   ========================================================================== */


:root {
  --nuit: #141b2e;
  --nuit-clair: #1e2740;
  --bord: #33405e;
  --texte: #f5e9d7;
  --doux: #9fb0d0;
  --accent: #f2a65a;
  --bois: #d9b382;
  --bois-ombre: #bd9260;
  --rideau: #a63d40;
  --rideau-sombre: #7d2b2e;
  --essai: 0px;           /* hauteur d'une barre au dessus de l'app. La maquette la redefinit a 38px */
  --jeton: 68px;          /* cible tactile, plancher a 64 px */
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
/* L'attribut hidden n'est qu'un display: none de la feuille du navigateur :
   la moindre regle d'auteur qui pose un display le bat. Mesure faite, les
   boutons de l'import restaient visibles malgre hidden, parce qu'ils sont dans
   un .menu en display: flex. Cousin du piege deja consigne dans CLAUDE.md :
   hidden n'existe pas du tout sur un SVGElement. */
[hidden] { display: none !important; }
button { font: inherit; color: inherit; cursor: pointer; }
html, body { margin: 0; height: 100%; overflow: hidden; }
body {
  background: var(--nuit); color: var(--texte);
  font: 14px/1.35 -apple-system, system-ui, sans-serif;
  padding-top: env(safe-area-inset-top);
}

/* ======================= LA COQUE DE L'APP ======================= */
.app {
  height: calc(100dvh - var(--essai) - env(safe-area-inset-top));
  display: grid; gap: 8px; padding: 8px;
  padding-left: calc(8px + env(safe-area-inset-left));
  padding-right: calc(8px + env(safe-area-inset-right));
  padding-bottom: calc(8px + env(safe-area-inset-bottom));
  grid-template-areas: "ctrl" "scene" "res";
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto;
}
@supports not (height: 100dvh) {
  .app { height: calc(100vh - var(--essai) - env(safe-area-inset-top)); }
}

/* ======================= CONTROLES ======================= */
.ctrl {
  grid-area: ctrl; background: var(--nuit-clair); border: 1px solid var(--bord);
  border-radius: 14px; padding: 8px; display: flex; flex-direction: column; gap: 8px;
}
.rangee { display: flex; align-items: center; gap: 10px; min-width: 0; }

/* le selecteur de morceau : des vignettes colorees, reconnaissables sans lire */
.morceaux {
  display: flex; gap: 6px; min-width: 0; flex: 1 1 auto;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
  /* Le voile de bord dit « il y en a d'autres par la ». Il ne doit pas
     s'afficher quand il n'y a rien de plus a voir, sinon la derniere
     vignette a l'air eteinte alors qu'elle est la vignette choisie. Les deux
     bornes sont pilotees par app.js, qui regarde le defilement reel. */
  --f-g: 0%; --f-d: 100%;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--f-g),
                                              #000 var(--f-d), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 var(--f-g),
                                     #000 var(--f-d), transparent 100%);
}
.morceaux.deborde-gauche { --f-g: 12%; }
.morceaux.deborde-droite { --f-d: 88%; }
.morceaux::-webkit-scrollbar { display: none; }
.morceau { scroll-snap-align: start; }
.morceau {
  width: var(--jeton); height: var(--jeton); flex: 0 0 auto;
  border-radius: 12px; border: 3px solid transparent; position: relative;
  display: flex; align-items: flex-end; padding: 5px; overflow: hidden;
}
/* UN TITRE NE DOIT JAMAIS ETRE ROGNE EN SILENCE. Le jeton fait 64 px sur un
   iPhone SE, soit 48 px utiles, et un mot plus large que ca disparaissait sans
   rien dire : « Cinquième Symphonie » perdait son « nie » depuis sa livraison,
   et « The Entertainer » son « r ». Mesure au canvas : Symphonie 56,4 px et
   Entertainer 57,8 px pour 48 px utiles. Ca ne se voyait pas dans le code, ca
   sautait aux yeux sur le rendu du ruban a 375 px.
   overflow-wrap: anywhere coupe le mot au lieu de l'escamoter. Une coupure se
   voit et se comprend, un texte tronque ressemble a un bug.
   ET LA TAILLE SUIT LE JETON, parce que couper ajoute des lignes : a 9 px fixes,
   « Cinquième Symphonie (thème) » passait a CINQ lignes et sortait par le haut,
   le jeton etant aligne en bas. Mesure : 42 controles, 14 titres sur trois
   ecrans, aucun debordement ni en largeur ni en hauteur.
   Pas de « hyphens: auto » : il ne fait rien dans le navigateur sans tete, qui
   n'a pas le dictionnaire de cesure, donc je ne peux pas mesurer ce qu'il
   ferait sur le Safari de l'iPad. Il y changerait le nombre de lignes sans que
   le controle de hauteur l'ait vu. */
.morceau span {
  font-size: max(8px, calc(var(--jeton) * .125)); line-height: 1.05;
  color: #22160c; font-weight: 700;
  text-shadow: 0 1px 0 rgba(255,255,255,.35);
  overflow-wrap: anywhere;
}
.morceau.choisi { border-color: var(--texte); }
.morceau.choisi::after {
  content: ""; position: absolute; inset: auto 5px 100% auto;
}

/* les boutons ronds : play, suivant, engrenage */
.rond {
  width: var(--jeton); height: var(--jeton); flex: 0 0 auto;
  border-radius: 50%; border: 1px solid var(--bord); background: #2b3654;
  display: grid; place-items: center; color: var(--texte);
}
.rond svg { width: 46%; height: 46%; fill: currentColor; }
.rond.play {
  width: calc(var(--jeton) + 20px); height: calc(var(--jeton) + 20px);
  background: var(--accent); border-color: #c97f33; color: #22160c;
}
.rond.engrenage { background: transparent; color: var(--doux); }

/* Le bouton de lecture porte les deux icones, et c'est une CLASSE qui choisit,
   pas l'attribut hidden : `hidden` est une propriete de HTMLElement et pas de
   SVGElement, donc svg.hidden = true ne fait rien du tout. Le bouton affichait
   les deux icones a la fois. */
.rond.play #icone-pause { display: none; }
.rond.play.joue #icone-play { display: none; }
.rond.play.joue #icone-pause { display: block; }

/* Chargement des 13 instruments, au premier geste : 2,6 Mo, ca prend un
   moment et il faut le montrer plutot que de laisser un bouton inerte. */
@keyframes tourne { to { transform: rotate(360deg); } }
.rond.play.charge svg { display: none; }
.rond.play.charge::after {
  content: ""; width: 42%; height: 42%; border-radius: 50%;
  border: 4px solid rgba(34,22,12,.25); border-top-color: #22160c;
  animation: tourne .7s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .rond.play.charge::after { animation-duration: 2s; }
}

/* curseurs : tempo aimante sur trois reperes, et volume */
.curseur { flex: 1 1 130px; min-width: 110px; display: flex; flex-direction: column; gap: 2px; }
.piste {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 44px; margin: 0; padding: 0;
  background: transparent; display: block;
}
.piste::-webkit-slider-runnable-track {
  height: 18px; border-radius: 9px; background: #2b3654;
  border: 1px solid var(--bord);
}
.piste::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 32px; height: 32px; border-radius: 50%; margin-top: -8px;
  background: var(--texte); border: 3px solid var(--accent);
}
.piste::-moz-range-track {
  height: 18px; border-radius: 9px; background: #2b3654;
  border: 1px solid var(--bord);
}
.piste::-moz-range-thumb {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--texte); border: 3px solid var(--accent);
}
.piste:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.reperes { display: flex; justify-content: space-between; align-items: center; padding: 0 2px; }
.reperes svg {
  width: 30px; height: 30px;
  --base: var(--doux); --clair: #c3d0e6; --sombre: #5b6a8a; --fil: var(--texte);
}
/* le repere courant, en accent */
.reperes .actif { --base: var(--accent); --clair: #ffd49a; --sombre: #a8681f; }
.ligne-volume { display: flex; align-items: center; gap: 8px; flex: 1 1 120px; min-width: 0; }
.ligne-volume svg { width: 24px; height: 24px; flex: 0 0 auto; fill: var(--doux); }

/* ======================= LA SCENE ======================= */
.scene {
  grid-area: scene; position: relative; overflow: hidden; border-radius: 14px;
  background: linear-gradient(180deg, var(--bois) 0%, var(--bois-ombre) 100%);
  display: grid; grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  align-content: stretch; justify-items: stretch; padding: 30px 40px 12px;
}
/* projecteurs, deux cones de lumiere depuis le haut */
.scene::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(198deg, rgba(255,245,215,.38) 0 14%, transparent 42%),
    linear-gradient(162deg, rgba(255,245,215,.38) 0 14%, transparent 42%);
}
/* rideaux lateraux */
.rideau-g, .rideau-d {
  position: absolute; top: 0; bottom: 0; width: 34px; z-index: 2;
  background: repeating-linear-gradient(90deg,
    var(--rideau) 0 8px, var(--rideau-sombre) 8px 16px);
}
.rideau-g { left: 0; border-radius: 14px 0 0 14px; }
.rideau-d { right: 0; border-radius: 0 14px 14px 0; }
/* frise haute, festonnee */
.frise {
  position: absolute; left: 0; right: 0; top: 0; height: 26px; z-index: 3;
  background: var(--rideau);
  -webkit-mask-image: radial-gradient(14px 13px at 14px 100%, transparent 98%, #000 100%);
  mask-image: radial-gradient(14px 13px at 14px 100%, transparent 98%, #000 100%);
  -webkit-mask-size: 28px 100%; mask-size: 28px 100%;
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
}
.places {
  display: grid; gap: 10px; width: 100%; height: 100%;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(0, 120px));
  align-content: center; position: relative; z-index: 1;
}
.place {
  width: 100%; height: 100%; min-width: 64px; border-radius: 16px;
  border: 2px dashed rgba(90,50,20,.38); background: rgba(255,255,255,.14);
  display: grid; place-items: center; padding: 6px;
}
.place svg { width: 100%; height: 100%; }

/* Ecran court : on rend a la scene les 20 px de marge qu'elle gaspille,
   sans quoi l'emplacement tombe sous la cible tactile de 64 px. */
@media (max-height: 700px) {
  :root { --jeton: 64px; }
  .rond.play { width: calc(var(--jeton) + 12px); height: calc(var(--jeton) + 12px); }
  .ctrl { gap: 6px; }
  .frise { height: 22px; }
  .scene { padding: 25px 36px 8px; }
  .places { gap: 8px; }
  /* Zone sensible des curseurs resserree : 44 px sur deux curseurs prenaient
     52 px a la scene, et l'emplacement tombait a 61 px sur un iPhone SE. La
     piste visible ne change pas, seule la zone attrapable se resserre. */
  .piste { height: 34px; }
  .reperes svg { width: 24px; height: 24px; }
}

/* ======================= LA RESERVE ======================= */
.res-paysage { display: none; }
.res-portrait {
  grid-area: res; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 5px;
  background: var(--nuit-clair); border: 1px solid var(--bord);
  border-radius: 14px; padding: 8px;
}
.jeton {
  aspect-ratio: 1; min-width: 64px; min-height: 64px; border-radius: 13px;
  background: #2b3654; border: 1px solid var(--bord);
  display: grid; place-items: center; padding: 6px;
}
.jeton svg { width: 100%; height: 100%; }

/* ======================= PAYSAGE ======================= */
@media (min-width: 900px) {
  :root { --jeton: 84px; }
  .app {
    grid-template-areas: "ctrl ctrl ctrl" "resg scene resd";
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr);
  }
  .ctrl { flex-direction: row; align-items: center; gap: 16px; padding: 10px 14px; }
  .rangee { display: contents; }
  .rond.engrenage { order: 2; }       /* le DOM le met en rangee 1, ici il finit la ligne */
  .morceaux { flex: 1 1 auto; }       /* absorbe le mou : plus de morceaux visibles */
  .curseur { flex: 0 0 200px; }
  .ligne-volume { flex: 0 0 155px; }
  .res-portrait { display: none; }
  .res-paysage {
    display: grid; gap: 8px; align-content: start; justify-items: center;
    grid-template-columns: minmax(64px, auto);
    grid-template-rows: repeat(7, minmax(64px, 1fr));
    background: var(--nuit-clair); border: 1px solid var(--bord);
    border-radius: 14px; padding: 8px;
  }
  .res-paysage .jeton {
    height: 100%; width: auto; aspect-ratio: 1; max-height: 92px; min-width: 64px;
  }
  .res-a { grid-area: resg; }
  .res-b { grid-area: resd; }
  .scene { padding: 34px 46px 20px; }

  /* la scene en demi-cercle, voir docs/cadrage.md section 4.5 */
  .places {
    display: block; position: relative;
    --place: clamp(64px, 15%, 150px);
  }
  .place {
    position: absolute; width: var(--place); height: auto; aspect-ratio: 1;
    transform: translate(-50%, -50%); min-width: 64px;
  }
  .place:nth-child(1) { left:  8%; top: 82%; }
  .place:nth-child(2) { left: 24.8%; top: 46%; }
  .place:nth-child(3) { left: 41.6%; top: 28%; }
  .place:nth-child(4) { left: 58.4%; top: 28%; }
  .place:nth-child(5) { left: 75.2%; top: 46%; }
  .place:nth-child(6) { left: 92%; top: 82%; }
}

/* Pas assez de hauteur pour sept jetons de 64 px en une colonne : deux
   colonnes par cote. C'est le cas de l'iPad en paysage dans Safari, ou la
   barre d'adresse mange une centaine de pixels. */
@media (min-width: 900px) and (max-height: 700px) {
  .res-paysage {
    grid-template-columns: repeat(2, minmax(64px, auto));
    grid-template-rows: repeat(4, minmax(64px, 1fr));
  }
  .res-paysage .jeton { max-height: 76px; }
}
/* ==========================================================================
   L'INTERACTION. Tout ce qui suit ne sert qu'a l'app : la maquette est morte
   et n'en declenche rien, mais les regles peuvent rester ici sans effet.
   ========================================================================== */

/* Un appui sur un jeton ou un emplacement ne doit JAMAIS faire defiler la page
   ni ouvrir le menu systeme d'iOS. touch-action seulement sur les elements
   attrapables, pas sur l'app : sinon le selecteur de morceau ne defile plus. */
.jeton, .place, .rond {
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* --- le jeton vide de la reserve : le creux reste visible ---
   Decision validee : un enfant de 6 ans retrouve son instrument a la meme
   position. Le creux ne se referme pas. */
.jeton.vide { background: #212b47; border-style: dashed; }
.jeton.vide svg { visibility: hidden; }

/* --- l'emplacement libre contre l'emplacement occupe --- */
.place.libre { border-style: dashed; background: rgba(255,255,255,.12); }
.place.occupe {
  border-style: solid; border-color: rgba(90,50,20,.22);
  background: rgba(255,255,255,.3);
}
.place.libre svg { visibility: hidden; }

/* --- le fantome qui suit le doigt pendant un glisser --- */
#fantome {
  position: fixed; z-index: 50; width: 96px; height: 96px;
  margin: -48px 0 0 -48px; pointer-events: none;
  filter: drop-shadow(0 6px 14px rgba(0,0,0,.45));
  transition: opacity .12s;
}
#fantome svg { width: 100%; height: 100%; }
#fantome[hidden] { display: none; }
.jeton.enleve svg, .place.enleve svg { opacity: .25; }

/* --- la cible survolee pendant un glisser --- */
.place.visee { border-color: var(--accent); background: rgba(242,166,90,.35); }
.res-paysage.visee, .res-portrait.visee { border-color: var(--accent); }

/* --- scene pleine : l'instrument touche tremble, les 6 emplacements
       clignotent une fois. Pas de remplacement automatique. --- */
@keyframes tremble {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}
.jeton.refus { animation: tremble .36s; }
@keyframes clignote {
  0%, 100% { border-color: rgba(90,50,20,.38); }
  50% { border-color: var(--accent); background: rgba(242,166,90,.3); }
}
.place.clignote { animation: clignote .36s; }

/* ==========================================================================
   LE MINIMUM VIVANT. Trois animations, pas plus, et toutes coupees si
   l'appareil demande moins de mouvement.
   ========================================================================== */

/* 1. L'instrument posé tressaille quand SA partie declenche une note. C'est le
      moteur qui pose la classe, au temps audio, via Tone.Draw. */
@keyframes tressaut {
  0% { transform: scale(1); }
  30% { transform: scale(1.11) rotate(-2deg); }
  100% { transform: scale(1); }
}
.place.joue svg { animation: tressaut .22s ease-out; }

/* 2. La scene pulse a la mesure. */
.scene { transition: filter .18s ease-out; }
.scene.mesure { filter: brightness(1.09); }

/* 3. Les emplacements vides invitent, en CSS pur. Respiration lente, et
      decalee d'un emplacement a l'autre pour que ca ondule. */
@keyframes invite {
  0%, 100% { border-color: rgba(90,50,20,.30); }
  50% { border-color: rgba(90,50,20,.62); }
}
.place.libre { animation: invite 2.6s ease-in-out infinite; }
.place:nth-child(2).libre { animation-delay: .2s; }
.place:nth-child(3).libre { animation-delay: .4s; }
.place:nth-child(4).libre { animation-delay: .6s; }
.place:nth-child(5).libre { animation-delay: .8s; }
.place:nth-child(6).libre { animation-delay: 1s; }

@media (prefers-reduced-motion: reduce) {
  .place.libre, .jeton.refus, .place.clignote, .place.joue svg { animation: none; }
  .scene { transition: none; }
  .scene.mesure { filter: none; }
}

/* ==========================================================================
   LE PANNEAU DES CREDITS, derriere un appui long de 2 s sur l'engrenage.
   Regle dure n° 3 du projet : la banque de sons doit etre creditee.
   ========================================================================== */
/* Le panneau est plus haut que l'ecran d'un iPhone. Mesure faite : le bouton
   « Retour au jeu » tombait a 742 px pour une vue de 664, hors de l'ecran, et
   comme html et body sont en overflow: hidden, rien ne pouvait le ramener :
   la zone parent devenait un cul-de-sac, il fallait recharger la page.
   Donc le voile defile, et le centrage passe par « margin: auto » et non par
   place-items: center, qui rogne le HAUT du contenu des qu'il depasse. */
#parent {
  position: fixed; inset: 0; z-index: 60; display: flex;
  background: rgba(10,14,26,.82);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
}
#parent[hidden] { display: none; }
#parent .panneau {
  margin: auto;
  background: var(--nuit-clair); border: 1px solid var(--bord);
  border-radius: 16px; padding: 20px; max-width: 460px; width: 100%;
  font: 14px/1.55 -apple-system, system-ui, sans-serif;
}
#parent h2 { margin: 0 0 10px; font-size: 17px; color: var(--accent); }
#parent p { margin: 0 0 10px; color: var(--doux); }
#parent a { color: var(--accent); }
#parent .menu { display: flex; flex-wrap: wrap; gap: 8px; }
#parent .fin { font-size: 12px; margin-top: 14px; }
/* La classe et pas l'element : « Choisir un fichier » est une <label> qui
   enveloppe le champ natif, pas un <button>. La regle sur l'element seul la
   laissait a 22 px de haut, mesure faite. */
#parent .secondaire {
  flex: 1 1 auto; min-height: 56px; font-size: 14px; font-weight: 600;
  background: #2b3654; color: var(--texte); border: 1px solid var(--bord);
  border-radius: 10px; margin: 0; display: grid; place-items: center;
  text-align: center; padding: 4px 10px;
}
#parent .secondaire:disabled { opacity: .5; }
#parent button {
  font: inherit; margin-top: 8px; min-height: 64px; width: 100%;
  background: var(--accent); color: #22160c; border: 0; border-radius: 12px;
  font-weight: 700; font-size: 16px;
}
/* L'ENGRENAGE ET SON APPUI DE DEUX SECONDES.
   Deux secondes sans aucun retour visuel, c'est un bouton casse : on lache
   avant la fin et il ne se passe rien. L'anneau se remplit du bas vers le haut
   pendant l'appui, et sa duree vient de APPUI_LONG par --appui, donc le CSS et
   le JS ne peuvent pas deriver. clip-path plutot qu'un degrade conique, qui
   demanderait @property pour s'animer. */
.rond.engrenage { position: relative; }
.rond.engrenage.presse { color: var(--accent); background: rgba(242,166,90,.18); }
.rond.engrenage.presse::after {
  content: ""; position: absolute; inset: -4px; border-radius: 50%;
  border: 3px solid var(--accent); pointer-events: none;
  animation: remplir var(--appui, 2000ms) linear forwards;
}
@keyframes remplir {
  from { clip-path: inset(100% 0 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

/* L'astuce, montree quand on lache l'engrenage trop tot. Sans elle, un appui
   trop court ne dit rien du tout, et c'est exactement ce qui s'est passe. */
#astuce {
  position: fixed; z-index: 70; right: 12px;
  top: calc(10px + env(safe-area-inset-top));
  max-width: min(60vw, 260px); pointer-events: none;
  background: var(--nuit-clair); border: 1px solid var(--accent);
  color: var(--texte); border-radius: 10px; padding: 8px 10px;
  font: 13px/1.35 -apple-system, system-ui, sans-serif;
  box-shadow: 0 6px 18px rgba(0,0,0,.4);
}

/* ===========================================================================
   LA BIBLIOTHEQUE ET L'IMPORT, dans la zone parent. Trois pages derriere un
   bandeau d'onglets.

   Cibles tactiles : 64 px pour les actions d'une ligne de morceau, comme
   partout ailleurs dans le projet. C'est ce qui dicte la forme de la ligne,
   titre puis actions en dessous : cinq boutons de 64 px et un titre ne
   tiennent pas cote a cote sur la largeur d'un iPhone. Mesure : 5 x 64 + 4 x 6
   = 344 px, contre 310 px utiles dans le panneau a 390 px de large, donc les
   boutons partagent la largeur avec un plancher a 56 px quand ils sont cinq.
   =========================================================================== */
#parent .onglets { display: flex; gap: 6px; margin: 0 0 14px; }
#parent .onglet {
  flex: 1 1 0; min-width: 0; min-height: 56px; margin: 0; padding: 6px 4px;
  background: #2b3654; color: var(--doux); border: 1px solid var(--bord);
  border-radius: 10px; font-size: 13px; font-weight: 600; width: auto;
}
#parent .onglet.actif { background: var(--accent); color: #22160c; border-color: var(--accent); }
#parent .aide { font-size: 12px; color: var(--doux); opacity: .85; }
#parent .etat { font-size: 13px; color: var(--accent); min-height: 1.2em; }
#parent .etat:empty { min-height: 0; margin: 0; }
#parent .resume { font-size: 13px; }
#parent code { font-size: 12px; background: #2b3654; padding: 1px 4px; border-radius: 4px; }

#parent .liste { list-style: none; margin: 0 0 10px; padding: 0; }
#parent .liste .vide { color: var(--doux); font-size: 13px; padding: 10px 0; }
#parent .ligne-morceau, #parent .ligne-piste {
  border: 1px solid var(--bord); border-radius: 12px; padding: 10px;
  margin: 0 0 8px; background: rgba(255,255,255,.03);
}
#parent .ligne-morceau.masquee { opacity: .55; }
#parent .ligne-morceau.fait { border-color: var(--accent); }
#parent .ligne-morceau.refus { animation: tremble .45s; border-color: #d9534f; }
#parent .titre-morceau { display: flex; align-items: center; gap: 8px; }
#parent .pastille { width: 14px; height: 14px; border-radius: 50%; flex: 0 0 auto; }
#parent .titre-morceau .nom {
  flex: 1 1 auto; min-width: 0; color: var(--texte); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#parent .titre-morceau .origine { font-size: 11px; color: var(--doux); flex: 0 0 auto; }
#parent .actions { display: flex; gap: 6px; margin-top: 8px; }
#parent .action {
  flex: 1 1 0; min-width: 56px; min-height: 64px; width: auto; margin: 0;
  background: #2b3654; color: var(--texte); border: 1px solid var(--bord);
  border-radius: 10px; display: grid; place-items: center;
}
#parent .action svg { width: 24px; height: 24px; fill: currentColor; }
#parent .action:disabled { opacity: .3; }

#parent .ligne-piste .aide { margin: 6px 0; }
#parent .ligne-piste select, #parent .champ input {
  width: 100%; min-height: 56px; font: inherit; font-size: 15px;
  background: #2b3654; color: var(--texte);
  border: 1px solid var(--bord); border-radius: 10px; padding: 0 10px;
}
#parent .champ { display: block; font-size: 12px; color: var(--doux); margin: 0 0 10px; }
#parent .champ input { margin-top: 4px; }

/* Le champ de fichier natif est inutilisable tel quel : on l'etale,
   transparent, par-dessus une etiquette qui a l'air d'un bouton. Un simple
   « display: none » marcherait aussi, mais casse le clavier sur certains
   navigateurs. */
#parent .fichier { position: relative; overflow: hidden; display: grid; place-items: center;
  text-align: center; padding: 0 10px; }
#parent .fichier input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; font-size: 100px; cursor: pointer;
}
