﻿@font-face {
  font-family: "PIX Dot";
  src: url("/static/fonts/PIX-DOT-1-100.ttf") format("truetype");
  font-display: swap;
}
@font-face {
  font-family: "PIX Dot 140";
  src: url("/static/fonts/PIX-DOT-1-140.ttf") format("truetype");
  font-display: swap;
}
:root {
  /* PLUS AUCUN TRAIT AMBRE (30/07, demande utilisateur : « eliminer tout trait ou
     trait de contour ambre de la charte graphique ; le remplacer par de l'ivoire
     translucide ou le supprimer quand on peut »). --bord valait #37302a, un brun
     chaud : c'est LUI qui dessinait les 114 contours du site. Il devient de
     l'IVOIRE TRANSLUCIDE -- la meme teinte que le texte, a 16 % : le trait se lit
     encore, mais il appartient enfin a la palette au lieu de la contredire.
     Une variable, tous les traits : c'est le seul endroit a toucher. */
  /* PLUS DE BRUN AMBRE DANS LES FONDS (30/07, precision utilisateur : « le fond
     ambre ou brun de la liste des vinyles et des filtres… je ne veux plus revoir ce
     brun ambre »). --fond valait #16120f et --carte #221c17 : deux bruns chauds
     (teinte ~26 deg, 20 % de saturation) qui juraient avec le reste du site. Ils
     deviennent NEUTRES -- meme clarte, saturation nulle -- de sorte que rien ne
     change en contraste ni en lisibilite, seule la couleur s'en va. L'ivoire du
     texte et de l'accent, lui, RESTE : c'est la chaleur voulue de la charte. */
  --fond: #141416; --carte: #1e1e21; --bord: rgba(237, 228, 216, .16);
  --texte: #ede4d8; --sourd: #a89b8a; --accent: #f2ecdf;  /* blanc cassé */
  --vert: #7ac074; --rouge: #d9605e;
  --titres: "PIX Dot", system-ui, sans-serif;
}
* { box-sizing: border-box; }
/* GARDE (18/07, bug prod /wantlist) : l'attribut hidden gagne TOUJOURS —
   sans elle, une règle « display: flex » sur un id (ex. #wl-voile,
   #fe-tag-nouveau) bat le [hidden] du navigateur et le voile s'affiche
   ouvert dès le chargement. */
[hidden] { display: none !important; }
/* navigation sans rechargement (18/07) : page suivante en cours de fetch */
html.nav-charge, html.nav-charge body { cursor: progress; }
body {
  margin: 0; background: var(--fond); color: var(--texte);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  min-height: 100vh;
}
.entete {
  padding: 12px 24px; border-bottom: 1px solid var(--bord);
  position: sticky; top: 0; z-index: 300; background: var(--fond);
}
/* 22/07 (bug utilisateur) : le lecteur (pilule ~31px) est plus HAUT que les autres
   éléments de l'en-tête (26px) → quand il apparaît/disparaît, la hauteur de la barre
   changeait de 5px et décalait tout. On RÉSERVE la hauteur du lecteur (min-height) →
   la barre garde la MÊME hauteur avec ou sans lecteur, plus de décalage. */
.entete-ligne { display: flex; justify-content: space-between; align-items: center;
                min-height: 31px; }
.entete-gauche { display: flex; align-items: center; gap: 14px; }
/* 31/07 (2e passe) : plus AUCUN pictogramme à gauche — .ico-entete/.ico-scan
   purgés, le scan vit dans le menu ⋮ et la loupe à gauche de la langue */
/* « CRUCIAL WAX Shop » sur la boutique publique (18/07) */
.logo-shop { font-family: var(--titres); font-size: 15px; color: var(--accent);
             margin-left: 10px; letter-spacing: 1px; }
.entete-titres { padding-top: 7px; font-size: 13px; white-space: nowrap;
                 overflow: hidden; text-overflow: ellipsis; }
#et-titre { font-family: var(--titres); color: var(--accent); }
/* 31/07 (demande utilisateur) : loupe SANS contour à côté du logo — remplace
   le bouton encadré qui vivait dans la barre de vues */
.entete-loupe { display: inline-flex; align-items: center; background: none;
                border: 0; padding: 0; color: var(--sourd); cursor: pointer;
                line-height: 0; }
.entete-loupe:hover { color: var(--accent); }
.entete-loupe svg { width: 18px; height: 18px; }
/* 31/07 (demande utilisateur) : la déconnexion devient un MENU déroulant (⋮) —
   stats, compte, ajout de release, sets DJ, collection ; sortie en pied de liste.
   Visible aussi au défilement (c'est la navigation, plus un simple lien). */
.menu-nav { position: relative; }
.menu-nav-bouton { display: inline-flex; align-items: center; justify-content: center;
                   width: 26px; height: 26px; color: var(--sourd); cursor: pointer;
                   list-style: none; }
.menu-nav-bouton::-webkit-details-marker { display: none; }
.menu-nav-bouton::marker { content: ""; }
.menu-nav-bouton:hover, .menu-nav[open] .menu-nav-bouton { color: var(--texte); }
.menu-nav-bouton svg { width: 18px; height: 18px; }
.menu-nav-liste { position: absolute; top: calc(100% + 10px); right: 0; z-index: 330;
                  display: flex; flex-direction: column; min-width: 170px; padding: 6px;
                  background: var(--carte); border: 1px solid var(--bord);
                  border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, .55); }
.menu-nav-liste a { display: flex; align-items: center; gap: 10px;
                    padding: 8px 12px; border-radius: 7px;
                    color: var(--texte); text-decoration: none; font-size: 13px;
                    white-space: nowrap; }
.menu-nav-liste a svg { width: 16px; height: 16px; flex: none; }
.menu-nav-liste a:hover { background: rgba(255, 255, 255, .06); color: var(--accent); }
.menu-nav-liste .menu-nav-sortie { margin-top: 5px; border-top: 1px solid var(--bord);
                                   border-radius: 0 0 7px 7px; color: var(--sourd); }
.menu-nav-liste .menu-nav-sortie:hover { color: var(--accent); }
/* trait de groupe : la section des VUES de la collection (Liste/Release/Grille,
   31/07 — le sélecteur de vues a rejoint le menu, la barre des pages a disparu) */
.menu-nav-liste .menu-nav-section { margin-top: 5px; border-top: 1px solid var(--bord);
                                    border-radius: 0; }
/* 22/07 : logo « Crucial wax » (capitale initiale), PIX 140, taille 20px (retour
   à la taille initiale le 24/07). « PIX 120 » n'existe pas (variantes : 60/100/140/200). */
.logo { font-family: "PIX Dot 140", var(--titres); font-size: 20px;
        font-weight: 400; color: var(--texte); text-decoration: none;
        letter-spacing: .01em; white-space: nowrap; /* JAMAIS sur 2 lignes */ }
.nav-droite { display: flex; align-items: center; gap: 14px; }
/* SANS CADRE, comme les icônes de la barre (30/07, demande utilisateur). Il ne
   restait plus que lui à porter une boîte : deux lettres encadrées au milieu de
   pictogrammes qui n'en ont pas. Le fond et la bordure s'en vont ; la couleur
   d'accent au survol suffit à dire qu'on peut cliquer. */
select.selecteur-langue {
  background: none; color: var(--texte); border: 0;
  padding: 5px 4px; font-size: 12px; cursor: pointer;
  /* sans la flèche native (18/07, gain de place) : les DEUX LETTRES seules */
  appearance: none; -webkit-appearance: none; text-align: center;
}
select.selecteur-langue:hover { color: var(--accent); }
/* le contour de focus reste, mais discret : on ne retire pas un repère au clavier */
select.selecteur-langue:focus-visible { outline: 1px solid var(--bord); outline-offset: 2px; }
select.selecteur-langue:focus { outline: none; }
/* 22/07 (bug utilisateur) : les LISTES DÉROULANTES (options) suivaient le thème par
   défaut du navigateur → menu BLANC alors que le texte est clair (--texte) → illisible
   (blanc sur blanc). On force le fond SOMBRE + texte clair sur toutes les <option>. */
option, optgroup { background-color: var(--carte); color: var(--texte); }
.conteneur { max-width: 860px; margin: 0 auto; padding: 40px 24px 60px; }
body.large .conteneur { max-width: 1180px; }
h1, h2 { font-family: var(--titres); font-weight: 400; letter-spacing: .02em; }
h1 { font-size: 26px; margin: 0 0 12px; }
.sourd { color: var(--sourd); }
.erreur { color: var(--rouge); }
.succes { color: var(--vert); }
.fort { font-weight: 700; }

.héros { text-align: center; padding: 72px 0 40px; }
/* accroche discrète (19/07) : une ligne sobre et modeste, pas un slogan */
.héros h1 { font-size: 16px; font-weight: 400; color: var(--sourd);
            letter-spacing: .04em; margin: 0 0 26px; }
.accroche { font-size: 17px; max-width: 560px; margin: 14px auto; }
.actions { margin-top: 30px; display: flex; gap: 14px; justify-content: center; }

.bouton {
  display: inline-block; background: var(--accent); color: #141416;
  font-weight: 700; text-decoration: none; border: none; cursor: pointer;
  border-radius: 9px; padding: 10px 22px; font-size: 15px;
}
.bouton:hover { filter: brightness(1.1); }
.bouton.discret { background: transparent; color: var(--texte); border: 1px solid var(--bord); font-weight: 400; }
.bouton.discret:hover { border-color: var(--accent); color: var(--accent); filter: none; }
.bouton.inactif { background: var(--bord); color: var(--sourd); cursor: not-allowed; }
.bouton.danger { background: var(--rouge); color: #141416; }

.carte-formulaire, .carte-info {
  background: var(--carte); border: 1px solid var(--bord); border-radius: 14px;
  padding: 28px 30px; max-width: 430px; margin: 30px auto;
}
.carte-info { max-width: 560px; margin: 20px 0; }
form label { display: block; margin: 14px 0 4px; color: var(--sourd); font-size: 13px; }
form input, form select {
  width: 100%; background: var(--fond); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 8px; padding: 9px 12px;
  font-size: 15px; margin-top: 4px;
}
form input:focus, form select:focus { outline: none; border-color: var(--accent); }
form .bouton { margin-top: 20px; width: 100%; }
.large-form { max-width: 520px; }
.large-form h2 { font-size: 15px; color: var(--accent); margin: 22px 0 2px;
                 border-top: 1px solid var(--bord); padding-top: 18px; }
.large-form h2:first-of-type { border-top: none; padding-top: 0; }
.aide { color: var(--sourd); font-size: 12px; margin: 3px 0 0; }
.tri-cascade { display: flex; gap: 8px; }
.tri-cascade select { flex: 1; min-width: 0; }
.point-couleur { display: inline-block; width: 16px; height: 16px;
                 border-radius: 50%; border: 1px solid var(--bord);
                 vertical-align: middle; }
.col-couleur { text-align: center; }

/* --- mur de pochettes par couleur --- */
.mur { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px;
       margin: 18px 0 40px; }
.mur-case { text-decoration: none; color: var(--sourd); min-width: 0; }
.mur-case img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block;
                border-radius: 4px; }
.mur-case:hover img { outline: 2px solid var(--accent); }
.mur-titre { display: block; font-size: 10px; line-height: 1.35; margin-top: 3px;
             overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
             -webkit-box-orient: vertical; }
.mur-case:hover .mur-titre { color: var(--texte); }
@media (max-width: 900px) {
  .mur { grid-template-columns: repeat(4, 1fr); }
}
/* case de wantlist sans vignette : un carré sourd à la place de l'image */
.mur-vide { display: block; width: 100%; aspect-ratio: 1; border-radius: 4px;
            background: var(--carte); border: 1px solid var(--bord); }
/* étiqueter la wantlist (18/07) : ＋ discret sur la carte, chips dessous,
   panneau partagé centré sur voile sombre */
.wl-case { position: relative; }
.wl-case a { text-decoration: none; color: inherit; }
.wl-tag-btn { position: absolute; top: 4px; right: 4px; z-index: 4;
              width: 22px; height: 22px; border-radius: 50%;
              border: 1px solid var(--bord); background: rgba(20, 20, 22, .78);
              color: var(--sourd); font-size: 13px; line-height: 1;
              cursor: pointer; opacity: 0; }
.wl-case:hover .wl-tag-btn { opacity: 1; }
.wl-tag-btn:hover { color: var(--accent); border-color: var(--accent); }
.wl-tags { display: block; margin-top: 2px; }
.wl-tags .tag { font-size: 9px; padding: 0 5px; margin: 1px 2px 0 0; }
#wl-voile { position: fixed; inset: 0; z-index: 400;
            background: rgba(10, 8, 6, .62); backdrop-filter: blur(6px);
            display: flex; align-items: center; justify-content: center; }
#wl-boite { position: relative; width: min(520px, 92vw);
            background: var(--carte); border: 1px solid var(--bord);
            border-radius: 12px; padding: 20px 22px;
            box-shadow: 0 18px 50px rgba(0, 0, 0, .55); }
#wl-boite h2 { margin: 0 34px 12px 0; font-size: 16px; }
#wl-fermer { position: absolute; top: 12px; right: 12px; width: 24px;
             height: 24px; background: none; border: 1px solid var(--bord);
             border-radius: 6px; color: var(--sourd); cursor: pointer; }
#wl-fermer:hover { color: var(--rouge); border-color: var(--rouge); }
#wl-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 14px;
            min-height: 24px; }
#wl-chips .wl-x { background: none; border: none; color: inherit;
                  cursor: pointer; font-size: 10px; padding: 0 0 0 2px; }
#wl-ajout { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
#wl-ajout select, #wl-ajout input { background: var(--fond); color: var(--texte);
            border: 1px solid var(--bord); border-radius: 6px;
            padding: 5px 8px; font-size: 13px; }
#wl-ajout select { max-width: 150px; }
#wl-ajout input { flex: 1 1 130px; min-width: 110px; }
#wl-ajout .bouton { width: auto; margin: 0; padding: 5px 14px; font-size: 12.5px; }

/* étiquette en SOURDINE (18/07) : déroger aux genres/styles Discogs — la
   chip reste mais en GRANDE TRANSPARENCE ; le survol la ravive pour la lire */
.tag-sourdine { opacity: .22; }
.tag-sourdine:hover { opacity: 1; }
/* bouton sourdine de la page de gestion */
.etq-mute { flex: none; width: 26px; height: 24px; background: none;
            border: 1px solid var(--bord); border-radius: 6px;
            cursor: pointer; font-size: 12px; line-height: 1;
            opacity: .45; filter: grayscale(1); }
.etq-mute:hover { opacity: 1; border-color: var(--accent); }
.etq-mute.actif { opacity: 1; filter: none; border-color: var(--accent); }
.etq-sourdine-formes { display: flex; gap: 8px; flex-wrap: wrap; }

/* chip-LIEN vers la gestion des étiquettes (rose des couleurs) */
a.chip-lien { text-decoration: none; display: inline-flex; align-items: center;
              gap: 4px; }
a.chip-lien:hover { border-color: var(--accent); color: var(--accent); }

/* --- gestion des étiquettes : rose des couleurs + lignes d'édition (18/07) --- */
.etq-haut { display: flex; gap: 28px; align-items: flex-start;
            margin: 14px 0 26px; flex-wrap: wrap; }
.etq-roue { flex: 0 1 460px; min-width: 300px; }
.etq-roue svg { width: 100%; height: auto; display: block;
                background: rgba(20, 20, 22, .55); border: 1px solid var(--bord);
                border-radius: 10px; padding: 12px; box-sizing: border-box;
                touch-action: none; }   /* le doigt fait tourner l'aiguille */
.etq-roue .roue-genre { cursor: grab; }
.etq-roue svg.roue-glisse, .etq-roue svg.roue-glisse .roue-genre {
                cursor: grabbing; }
/* anomalies visuelles (18/07, X sur la capture) : sur cette page les titres
   de section n'ont PAS de trait horizontal — et le bloc texte de la roue
   s'aligne sur le HAUT du cadre */
body.etiquettes .titre-section { border-top: none; padding-top: 0; }
.etq-roue-texte .titre-section { margin-top: 0; }
.etq-roue-texte { flex: 1 1 300px; max-width: 52ch; }
.etq-roue-texte form { margin: 10px 0 0; }
.etq-roue-texte .bouton { width: auto; }
/* créer une nouvelle étiquette (19/07) : nom + catégorie + bouton, une ligne */
.etq-creer { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
             margin: 4px 0 22px; }
.etq-creer input[type="text"] { flex: 0 1 260px; background: var(--fond);
             color: var(--texte); border: 1px solid var(--bord);
             border-radius: 6px; padding: 6px 10px; font-size: 14px; }
.etq-creer select { background: var(--fond); color: var(--texte);
             border: 1px solid var(--bord); border-radius: 6px;
             padding: 6px 8px; font-size: 13px; }
.etq-creer .bouton { width: auto; margin: 0; padding: 6px 16px; }
.etq-liste { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 26px; }
.etq-ligne { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
             padding: 6px 10px; background: var(--carte);
             border: 1px solid var(--bord); border-radius: 8px; }
.etq-chip { flex: none; border: 1px solid; border-radius: 999px;
            padding: 2px 10px; font-size: 12px; max-width: 180px;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.etq-ligne input[type="text"] { flex: 1 1 140px; min-width: 110px;
            background: var(--fond); color: var(--texte);
            border: 1px solid var(--bord); border-radius: 6px;
            padding: 4px 8px; font-size: 13px; }
.etq-ligne select { background: var(--fond); color: var(--texte);
            border: 1px solid var(--bord); border-radius: 6px;
            padding: 4px 6px; font-size: 12.5px; max-width: 160px; }
.etq-n { flex: none; font-size: 12px; }
/* 18/07 (demande utilisateur) : sur bureau, les lignes deviennent une
   GRILLE à colonnes fixes — chip, sourdine, nom, catégorie, parent (cellule
   vide si sans objet), nb de disques (aligné à droite), Enregistrer, ✕ :
   tout tombe sur les mêmes verticales, ligne après ligne */
@media (min-width: 901px) {
  .etq-ligne { display: grid; gap: 8px 10px; align-items: center;
    grid-template-columns: 170px 26px minmax(130px, 1fr) 140px 170px
                           84px max-content 32px; }
  .etq-chip { max-width: 100%; justify-self: start; }
  .etq-ligne input[type="text"] { width: 100%; min-width: 0; }
  .etq-ligne select { width: 100%; max-width: none; }
  .etq-n { justify-self: end; text-align: right; white-space: nowrap; }
}
.etq-ligne .bouton { width: auto; margin: 0; padding: 4px 12px; font-size: 12px; }
.etq-suppr:hover { border-color: var(--rouge); color: var(--rouge); }
@media (max-width: 900px) {
  .etq-haut { display: block; }
  .etq-roue { max-width: 420px; margin-bottom: 14px; }
}

/* --- sets DJ : liste des sets et constructeur --- */
.ligne-nouveau-set { display: flex; gap: 10px; max-width: 460px; margin: 16px 0; }
.ligne-nouveau-set input { flex: 1; background: var(--fond); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 8px; padding: 9px 12px; }
.ligne-nouveau-set .bouton { width: auto; margin: 0; white-space: nowrap; }
.liste-sets { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
              gap: 14px; margin: 20px 0; }
.carte-set { display: flex; flex-direction: column; gap: 6px; background: var(--carte);
             border: 1px solid var(--bord); border-radius: 12px; padding: 16px 18px;
             text-decoration: none; color: var(--texte); }
.carte-set:hover { border-color: var(--accent); }
.carte-set-nom { font-family: var(--titres); font-size: 16px; }
.carte-set-notes { font-size: 12px; white-space: nowrap; overflow: hidden;
                   text-overflow: ellipsis; }
.entete-set { display: grid; grid-template-columns: 1fr auto auto; gap: 10px;
              align-items: center; max-width: 780px; margin: 14px 0; }
.set-nom { font-family: var(--titres); font-size: 18px; background: var(--fond);
           color: var(--texte); border: 1px solid var(--bord); border-radius: 8px;
           padding: 8px 12px; min-width: 0; }
.entete-set .bouton { width: auto; margin: 0; }
.set-notes { grid-column: 1 / -1; background: var(--fond); color: var(--texte);
             border: 1px solid var(--bord); border-radius: 8px; padding: 8px 12px;
             font: 13px/1.5 inherit; resize: vertical; }
.set-nom:focus, .set-notes:focus { outline: none; border-color: var(--accent); }
#set-liste { margin: 10px 0; max-width: 840px; }
.set-ligne { display: flex; align-items: center; gap: 12px; padding: 7px 12px;
             border: 1px solid var(--bord); border-radius: 10px; margin-bottom: 6px;
             background: var(--carte); cursor: grab; }
.set-ligne.survole { border-color: var(--accent); }
.set-pos { width: 26px; text-align: right; color: var(--sourd); flex: none;
           font-variant-numeric: tabular-nums; }
.set-ligne img, .set-mini-vide { width: 40px; height: 40px; object-fit: cover;
                                 border-radius: 5px; background: var(--fond); flex: none; }
.set-txt { flex: 1; min-width: 0; }
.set-titre { display: block; white-space: nowrap; overflow: hidden;
             text-overflow: ellipsis; font-size: 14px; }
.set-meta { display: block; font-size: 12px; }
.set-piste { display: block; width: 100%; margin-top: 4px; background: var(--fond);
             color: var(--sourd); border: 1px solid var(--bord); border-radius: 6px;
             padding: 3px 8px; font-size: 12px; }
.set-piste.choisie { color: var(--texte); border-color: var(--accent); }
/* `relative` et non `static` (01/08, bug utilisateur : « le ＋ pour la file ne
   s'affiche pas dans les sets ») : le ＋ de mise en attente est un enfant
   ABSOLU du bouton — sans ancre, il allait se caler sur un ancêtre lointain,
   loin du morceau survolé quand il n'était pas carrément hors de l'écran.
   `relative` sans décalage ne déplace rien : elle ne fait qu'offrir l'ancre. */
.set-ligne .apercu-btn { position: relative; width: 28px; height: 28px; flex: none; }
/* le ＋ DÉBORDE légèrement du petit ▶ des sets (01/08, demande utilisateur :
   « décaler un peu plus vers le haut et la droite ») : sur un bouton de 28 px,
   posé dans le coin il mangeait le triangle. Il reste ATTACHÉ au bouton (le
   survol vise toujours le même élément — pas de clignotement de curseur, leçon
   du 31/07), simplement il chevauche le vide de la ligne. */
.set-ligne .apercu-suite { top: -6px; right: -6px; }
.set-actions { display: flex; gap: 4px; flex: none; }
.set-btn { background: none; border: 1px solid var(--bord); border-radius: 6px;
           color: var(--sourd); cursor: pointer; width: 26px; height: 26px;
           font-size: 11px; }
.set-btn:hover { border-color: var(--accent); color: var(--accent); }
.set-btn:disabled { opacity: .3; cursor: default; }
.set-btn.retirer:hover { border-color: var(--rouge); color: var(--rouge); }
#set-recherche { width: 100%; max-width: 460px; background: var(--fond);
                 color: var(--texte); border: 1px solid var(--bord);
                 border-radius: 8px; padding: 9px 12px; margin: 6px 0 10px; }
#set-recherche:focus { outline: none; border-color: var(--accent); }
#set-catalogue { max-width: 840px; max-height: 430px; overflow-y: auto;
                 border: 1px solid var(--bord); border-radius: 10px;
                 background: var(--carte); }
.cat-ligne { display: flex; align-items: center; gap: 12px; padding: 6px 12px;
             border-bottom: 1px solid var(--bord); cursor: pointer; }
.cat-ligne:last-child { border-bottom: none; }
.cat-ligne:hover { background: #26262a; }
.cat-ligne img { width: 34px; height: 34px; object-fit: cover; border-radius: 4px;
                 flex: none; }
.cat-txt { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden;
           text-overflow: ellipsis; font-size: 13px; }
.cat-meta { color: var(--sourd); font-size: 12px; flex: none; }
.cat-badge { flex: none; color: var(--sourd); font-size: 12px;
             border: 1px solid var(--bord); border-radius: 999px; padding: 2px 9px; }
.cat-ligne.dans-set { opacity: .6; }
.cat-ligne.dans-set .cat-badge { border-color: var(--vert); color: var(--vert); }
.pied-set { margin: 26px 0; }
.pied-set .bouton { width: auto; }

/* --- aperçu audio multisource (boutique + feuilletage) --- */
.apercu-btn { width: 34px; height: 34px; border-radius: 50%;
              /* 23/07 (retour utilisateur ×2 : ▶ décentré dans le cercle) : le
                 GLYPHE texte « ▶ » a des métriques imprévisibles selon la fonte
                 (Segoe le rend décalé même en flex-center) → on le MASQUE
                 (font-size 0) et on dessine un TRIANGLE GÉOMÉTRIQUE en clip-path
                 (::before), centré par flex + correction optique 3px (le centre
                 optique d'un triangle ▶ est à ~43 % de sa largeur). currentColor
                 → le survol accent marche. Tous les ▶ (boutique, feuilletage,
                 explorateur, sets) deviennent identiques. */
              display: inline-flex; align-items: center; justify-content: center;
              line-height: 1; font-size: 0;
              border: 1px solid var(--bord); background: rgba(30, 30, 33, .85);
              color: var(--texte); cursor: pointer; }
.apercu-btn::before { content: ""; display: block; width: 12px; height: 13px;
                      margin-left: 3px; background: currentColor;
                      clip-path: polygon(0 0, 100% 50%, 0 100%); }
.apercu-btn:hover { border-color: var(--accent); color: var(--accent); }
.apercu-btn.joue { border-color: var(--accent); color: var(--accent); }
.article { position: relative; }
.article .apercu-btn { position: absolute; top: 8px; right: 8px; z-index: 5; }
/* ▶ en surimpression sur la pochette du feuilletage (16/07) */
/* 22/07 (demande utilisateur) : le ▶ ALIGNÉ sur le chip de flèches (même largeur
   36px, même bord droit right:4 → même X vertical) et MÊME FOND que le chip
   (rgba .55) — boutons homogènes sur le bord droit de la pochette. */
/* outils aux COINS BAS de la pochette (23/07, demande utilisateur) : ✎
   (édition) à gauche, ＋ INFO à droite — cercles VIDES (fond transparent,
   bordure claire), le + est GÉOMÉTRIQUE (leçon du ▶ : pas de glyphe texte). */
.fl-pochette .fl-coin { position: absolute; bottom: 12px; z-index: 5;
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid rgba(242, 236, 223, .8); background: transparent;
  color: var(--accent); cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background .18s; }
.fl-pochette .fl-coin:hover { background: rgba(20, 20, 22, .5); }
.fl-pochette .fl-editer { left: 4px; font-size: 16px; line-height: 1; }
.fl-pochette .fl-info { right: 4px; }
/* Save/Cancel = sous-boutons du ✎ pendant l'édition (24/07, demande utilisateur) :
   ✓ (enregistrer) et ✕ (annuler) au coin bas-gauche, le crayon est masqué. */
.fl-pochette.poche-edite .fl-editer { display: none; }
#fl-edit-actions { position: absolute; left: 4px; bottom: 12px; z-index: 6;
  display: flex; gap: 6px; }
#fl-edit-actions .fl-coin { position: static; font-size: 17px; line-height: 1; }
.fl-edit-annuler { color: var(--texte); }
.fl-info::before { content: ""; width: 16px; height: 16px; flex: none;
  transition: transform .25s;
  background:
    linear-gradient(currentColor, currentColor) center / 16px 2px no-repeat,
    linear-gradient(currentColor, currentColor) center / 2px 16px no-repeat; }
.fl-info.ouvert::before { transform: rotate(45deg); }   /* déployé : le + devient ✕ */
.fl-pochette .fl-jouer { position: absolute; top: 12px; right: 4px; z-index: 5;
                         width: 36px; height: 36px;
                         /* PAS de font-size ici : il ressusciterait le glyphe
                            texte masqué par la base (triangle clip-path, 23/07) */
                         background: rgba(20, 20, 22, .55); }
/* (18/07 : le ▶ flottant de la fiche a disparu — écoute via la pochette) */
/* le lecteur vit DANS la barre d'en-tête, à gauche de la déconnexion —
   même forme sur bureau et mobile (le titre s'efface sur petit écran).
   LARGEUR FIXE : la pastille ne se redimensionne pas selon le titre ou le
   compteur, donc les boutons ‹ › ne bougent jamais d'une piste à l'autre */
#cw-lecteur { position: relative; display: flex; align-items: center; gap: 8px;
              width: min(380px, 42vw);
              background: var(--carte); border: 1px solid var(--bord);
              border-radius: 999px; padding: 4px 12px; font-size: 12.5px; }
#cw-lecteur .lect-mute, #cw-lecteur .lect-pp {
                         flex: none; background: none; border: none;
                         cursor: pointer; padding: 0; line-height: 0;
                         color: var(--sourd); }
#cw-lecteur .lect-mute:hover, #cw-lecteur .lect-pp:hover { color: var(--accent); }
#cw-lecteur .lect-mute svg, #cw-lecteur .lect-pp svg { width: 15px; height: 15px; }
#cw-lecteur .lect-source { flex: none; color: var(--sourd); font-size: 11px;
                           border: 1px solid var(--bord); padding: 1px 7px;
                           border-radius: 999px; }
/* le titre prend l'espace restant ; s'il déborde, il DÉFILE lentement en
   aller-retour (classe .defile posée par apercu.js) au lieu d'être coupé */
#cw-lecteur .lect-titre { flex: 1 1 auto; min-width: 0; overflow: hidden;
                          white-space: nowrap; position: relative;
                          cursor: pointer; touch-action: none; }
/* voile de progression (18/07) : se remplit au fil du morceau, DERRIÈRE le
   texte (qui reste lisible) ; cliquer/glisser le titre déplace la lecture */
#cw-lecteur .lect-progres { position: absolute; left: 0; top: 0; bottom: 0;
                            width: 0; z-index: 0; pointer-events: none;
                            background: rgba(242, 236, 223, .22);
                            transition: width .18s linear; }
#cw-lecteur .lect-titre.scrute .lect-progres { transition: none; }
#cw-lecteur .lect-titre .lt-int { display: inline-block; position: relative;
                                  z-index: 1; }
#cw-lecteur .lect-titre.defile .lt-int {
  animation: lect-defile var(--lect-d, 8s) linear infinite alternate; }
@keyframes lect-defile {
  0%, 14%   { transform: translateX(0); }
  86%, 100% { transform: translateX(var(--lect-dx, 0)); } }
#cw-lecteur .lect-fermer { flex: none; background: none; border: none;
                           color: var(--sourd); cursor: pointer; font-size: 14px; }
#cw-lecteur .lect-fermer:hover { color: var(--rouge); }
/* navigation entre pistes (albums Bandcamp) : ‹ › + « n/N ▾ » déplie la
   liste — minimal et discret, la liste s'ouvre AU-DESSUS de la barre */
#cw-lecteur .lect-nav { flex: none; background: none; border: none;
                        color: var(--sourd); cursor: pointer; font-size: 17px;
                        padding: 0 2px; line-height: 1; }
#cw-lecteur .lect-nav:hover { color: var(--accent); }
#cw-lecteur .lect-liste-btn { flex: none; background: none;
                              border: 1px solid var(--bord); border-radius: 999px;
                              color: var(--sourd); cursor: pointer;
                              font-size: 11px; padding: 2px 8px;
                              font-variant-numeric: tabular-nums;
                              text-align: center; }
#cw-lecteur .lect-liste-btn:hover { border-color: var(--accent);
                                    color: var(--accent); }
#cw-lecteur .lect-pistes { position: absolute; top: calc(100% + 10px);
                           right: 0; min-width: 240px; max-width: 320px;
                           max-height: 46vh; overflow-y: auto; z-index: 320;
                           background: var(--carte); border: 1px solid var(--bord);
                           border-radius: 12px; padding: 6px;
                           box-shadow: 0 10px 30px rgba(0,0,0,.5); }
#cw-lecteur .lect-piste { display: block; width: 100%; text-align: left;
                          background: none; border: none; color: var(--texte);
                          cursor: pointer; font-size: 12.5px; padding: 5px 8px;
                          border-radius: 8px; white-space: nowrap;
                          overflow: hidden; text-overflow: ellipsis; }
#cw-lecteur .lect-piste:hover { background: #26262a; }
#cw-lecteur .lect-piste.actif { color: var(--accent); }

.ligne-clip { display: flex; gap: 10px; align-items: center; margin-top: 12px; }
.ligne-clip input[type="file"] { flex: 1; min-width: 0; }
.ligne-clip .bouton { width: auto; margin: 0; white-space: nowrap; }

/* --- historique des ventes Discogs --- */
tr.annulee td { color: var(--sourd); text-decoration: line-through; }
tr.annulee td a { color: var(--sourd); }

/* --- boutique : bloc de confiance vendeur (profil Discogs) --- */
/* en-tête boutique (18/07) : nom du vendeur en majuscules + nombre de ventes
   du site en exposant discret */
/* boutique (23/07, 2e passe — remplace la tête FIGÉE) : la tête (nom + profil +
   vues) DÉFILE avec la page ; au défilement (> 60px, body.defile de base.html),
   le NOM DE LA BOUTIQUE apparaît DANS LA BARRE SUPÉRIEURE, au même emplacement
   horizontal que le grand nom (bord gauche du conteneur centré 1180px —
   clampé à 200px pour ne jamais chevaucher le logo sur écran étroit).
   Décoratif (pointer-events none) ; bureau seulement (l'en-tête mobile est
   déjà dense). */
#entete-boutique-nom { display: none; position: fixed; top: 0; z-index: 310;
  height: var(--entete-h, 56px); align-items: center; pointer-events: none;
  left: max(200px, calc((100vw - 1180px) / 2 + 24px));
  font-family: var(--titres); font-size: 17px; letter-spacing: .02em;
  color: var(--texte); }
@media (min-width: 901px) {
  body.defile #entete-boutique-nom { display: flex; }
}
.boutique-nom { text-transform: uppercase; }
/* le nombre de ventes : deux fois plus grand et en fonte PIX (18/07) */
.boutique-ventes { font-family: var(--titres); font-size: .76em;
                   color: var(--sourd); margin-left: 6px;
                   letter-spacing: normal; font-weight: 400; }
.profil-vendeur { font-size: 13px; margin: -4px 0 16px; }
.profil-vendeur .profil-note { color: var(--vert); font-weight: 700; }
.profil-vendeur .attribution { font-size: 11px; }
/* 24\07 (demande utilisateur) : « Expédie depuis X » et « n disques en
   vente » sur la MÊME LIGNE sous le nom de la boutique */
.bq-ligne-infos { display: flex; flex-wrap: wrap; align-items: baseline;
                  gap: 4px 26px; margin: -4px 0 18px; }
.bq-ligne-infos .profil-vendeur { margin: 0; }

/* --- boutique : choix de la vue par le visiteur --- */
.vues-boutique { display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
                 margin: 0 0 20px; }
/* --- WANTLIST refondue (23/07) : rangée de filtres (tags cumul ET + filtres
   ENREGISTRÉS par nom). 24/07 (demande utilisateur) : vues + filtres +
   pagination sur UNE SEULE LIGNE (#wl-barre, repli en ligne sur étroit). --- */
#wl-barre { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px;
            margin: 0 0 16px; }
#wl-barre .vues-boutique, #wl-barre #wl-filtres,
#wl-barre #bq-pagination { margin: 0; }
#wl-filtres { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
#wl-filtre-plus { background: var(--carte); border: 1px solid var(--bord);
  color: var(--sourd); border-radius: 999px; padding: 4px 12px; font-size: 12px;
  font-family: inherit; cursor: pointer; }
#wl-filtre-plus:hover { border-color: var(--accent); color: var(--texte); }
#wl-filtres .fl-chip { cursor: pointer; }
/* ▶ d'écoute d'un MORCEAU (24/07, capture utilisateur) : le REPÈRE (B3) du
   morceau analysé EST le bouton play — un ▶ après la chip BPM décalait les
   temps. Le bouton ANNULE le cercle .apercu-btn (texte du repère visible) ;
   au survol souris, le repère devient le triangle (sous hover:hover — au
   doigt, un toucher joue directement, leçon iOS de l'entrée 131). */
/* la géométrie de colonne vient de .fd-piste-rep (flex none, min-width 30px) —
   NE PAS poser width:auto ici : le bouton rétrécissait et B3 se décalait
   (capture utilisateur 24/07) */
.fd-rep-jouer { width: auto; height: auto; border: none; background: none;
  border-radius: 0; padding: 0; margin: 0; cursor: pointer;
  font-family: inherit; font-size: inherit; color: var(--sourd);
  text-align: left; display: inline-flex; align-items: center;
  justify-content: flex-start; min-width: 30px; flex: none;
  box-sizing: border-box; }
.fd-rep-jouer::before { display: none; }
@media (hover: hover) {
  .fd-rep-jouer:hover { font-size: 0; color: var(--accent); }
  .fd-rep-jouer:hover::before { display: block; width: 9px; height: 10px;
    margin-left: 1px; }
}
/* spécifications de l'audio conservé (popover BPM) */
.fd-bpm-specs { padding: 0 14px 8px; font-size: 11px; }

/* SURNOM d'un morceau (24/07, culture picó — le « piconema ») : à la suite du
   titre, dans l'accent, italique doux ; ＋ ghost discret en édition. */
.fd-piste-surnom { color: var(--accent); font-style: italic; margin-left: 7px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 40%; flex: none; }
.fd-surnom-add { background: none; border: none; color: var(--sourd);
  opacity: .4; cursor: pointer; font: inherit; padding: 0 2px; margin-left: 5px; }
.fd-surnom-add:hover { opacity: 1; color: var(--texte); }
.fd-surnom-inp { width: 130px; background: rgba(255, 255, 255, .07);
  color: var(--texte); border: 1px solid var(--accent); border-radius: 4px;
  font: inherit; font-style: normal; padding: 0 5px; }

/* durée SAISIE d'un morceau (23/07, demande utilisateur) : en ROUGE = hors
   base Discogs ; « -:-- » discret en édition pour l'indiquer ; petit champ. */
.fd-piste-duree.fd-duree-saisie { color: var(--rouge); }
.fd-duree-add { background: none; border: none; color: var(--sourd); opacity: .5;
  cursor: pointer; font: inherit; padding: 0; }
.fd-duree-add:hover { opacity: 1; color: var(--texte); }
.fd-duree-inp { width: 54px; background: rgba(255, 255, 255, .07);
  color: var(--texte); border: 1px solid var(--accent); border-radius: 4px;
  font: inherit; padding: 0 4px; }

/* choix d'analyse BPM (23/07) : téléverser un extrait OU coller un lien
   (YouTube / URL audio) — mini-popover, mêmes boutons que les actions BPM */
.fd-bpm-pop .fd-bpm-choix { display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px; padding: 10px 12px; }
.fd-bpm-url { width: 220px; max-width: 60vw; background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.13); border-radius: 6px;
  color: var(--texte); padding: 4px 10px; font-size: 12px; font-family: inherit; }
.fd-bpm-url:focus { border-color: var(--accent); outline: none; }
#wl-garde-nom, #col-garde-nom { background: rgba(255, 255, 255, 0.05);
  color: var(--texte); border: 1px solid rgba(255, 255, 255, 0.13);
  border-radius: 6px; padding: 4px 10px; font-size: 12px;
  font-family: inherit; width: 160px; }
#wl-garde-nom:focus, #col-garde-nom:focus { border-color: var(--accent); outline: none; }
.wl-garde-chip, .col-garde-chip { display: inline-flex; align-items: center;
  gap: 6px; cursor: pointer; }
.wl-garde-x, .col-garde-x { background: none; border: none; color: inherit;
  cursor: pointer; padding: 0; font-size: 10px; line-height: 1; opacity: .65; }
.wl-garde-x:hover, .col-garde-x:hover { opacity: 1; }
a.fl-chip { text-decoration: none; }

/* --- boutique « magazine » : groupes par artiste/label avec description --- */
.groupe-boutique { margin: 34px 0 6px; }
.groupe-boutique h2 { font-family: var(--titres); font-weight: 400;
                      font-size: 24px; margin: 0 0 6px; letter-spacing: .03em;
                      border-top: 1px solid var(--bord); padding-top: 22px; }
.groupe-desc { max-width: 640px; color: var(--sourd); font-size: 14px;
               line-height: 1.6; margin: 0 0 14px; }
.grille-descriptions { display: grid;
                       grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
                       gap: 14px; margin: 14px 0; }
.desc-groupe { margin: 0; max-width: none; padding: 16px 18px; }
.desc-groupe h3 { margin: 0 0 8px; font-size: 14px; font-weight: 700; }
.desc-groupe textarea { width: 100%; background: var(--fond); color: var(--texte);
                        border: 1px solid var(--bord); border-radius: 8px;
                        padding: 8px 10px; font: 13px/1.5 inherit; resize: vertical; }
.desc-groupe textarea:focus { outline: none; border-color: var(--accent); }
.desc-groupe .bouton { margin-top: 8px; width: auto; padding: 6px 14px; font-size: 12px; }

/* --- boutique : galerie recto/verso et panier --- */
.article-vues { display: flex; gap: 6px; margin: 8px 0 0; }
.article-vues img { width: 44px; height: 44px; object-fit: cover; cursor: pointer;
                    border-radius: 6px; border: 1px solid var(--bord); opacity: .7; }
.article-vues img:hover { opacity: 1; }
.article-vues img.active { border-color: var(--accent); opacity: 1; }
/* z-index 210 : AU-DESSUS de la tête figée de la boutique (200) — sinon le panier
   (bouton + panneau, en haut à droite) passe derrière la tête sur bureau (23/07). */
#panier-bouton { position: fixed; top: 84px; right: 20px; z-index: 210;
                 background: var(--accent); color: #141416; border: none;
                 border-radius: 999px; padding: 9px 16px; font-size: 15px;
                 font-weight: 700; cursor: pointer;
                 box-shadow: 0 6px 18px rgba(0,0,0,.45); }
/* 23/07 (demande utilisateur) : le panier vit dans la BARRE SUPÉRIEURE, à gauche
   du sélecteur de langue — compacté au gabarit de l'en-tête, plus de flottant */
#panier-bouton.dans-entete { position: static; top: auto; right: auto;
                             padding: 4px 12px; font-size: 13px;
                             box-shadow: none; z-index: auto; }
#panier-panneau { position: fixed; top: 134px; right: 20px; z-index: 210;
                  width: min(360px, calc(100vw - 40px));
                  max-height: calc(100vh - 90px); overflow-y: auto;
                  background: var(--carte); border: 1px solid var(--bord);
                  border-radius: 14px; padding: 18px 20px;
                  box-shadow: 0 14px 40px rgba(0,0,0,.55); }
#panier-panneau h2 { margin: 0 0 10px; font-size: 17px; }
.panier-ligne { display: flex; align-items: center; gap: 10px; padding: 7px 0;
                border-bottom: 1px solid var(--bord); }
.panier-ligne img { width: 38px; height: 38px; object-fit: cover; border-radius: 5px; }
.panier-ligne-titre { flex: 1; min-width: 0; font-size: 13px;
                      overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.panier-ligne-prix { font-size: 13px; white-space: nowrap; }
.panier-ligne-retirer { background: none; border: none; color: var(--sourd);
                        cursor: pointer; font-size: 14px; }
.panier-ligne-retirer:hover { color: var(--rouge); }
#panier-total-ligne { display: flex; justify-content: space-between;
                      margin: 12px 0 6px; font-size: 15px; }
/* destination + port estimé (grille zone × gabarit du vendeur) */
#panier-destination-ligne, #panier-port-ligne, #panier-total-port-ligne {
  display: flex; justify-content: space-between; align-items: center;
  margin: 4px 0; font-size: 13.5px; }
#panier-total-port-ligne { font-size: 15px; border-top: 1px solid var(--bord);
                           padding-top: 6px; margin-top: 8px; }
#panier-destination select { background: var(--carte); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 8px; padding: 4px 8px; }
select#panier-destination { background: var(--carte); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 8px; padding: 4px 8px;
  font-size: 12.5px; max-width: 60%; }
.panier-note { font-size: 12px; margin: 6px 0; }
/* grille de saisie des frais de port (page paramètres) */
.grille-expedition { border-collapse: collapse; margin: 4px 0 16px; }
.grille-expedition th, .grille-expedition td { padding: 5px 8px;
  font-size: 12.5px; text-align: left; border: none; }
.grille-expedition thead th { color: var(--sourd); font-size: 11px;
  text-transform: uppercase; letter-spacing: .04em; }
.grille-expedition tbody th { color: var(--sourd); font-weight: 400; }
.grille-expedition input { width: 84px; }
#panier-panneau .bouton { width: 100%; margin-top: 8px; text-align: center; }
a { color: var(--accent); }

/* --- tableau de bord : cartes KPI --- */
.actions-dash { justify-content: flex-start; margin: 18px 0 8px; }
.ligne-sync { display: flex; align-items: center; gap: 12px; font-size: 13px;
              margin: 0 0 6px; }
.ligne-sync form { margin: 0; }
.ligne-sync .bouton { width: auto; margin: 0; padding: 5px 12px; font-size: 12px; }
.titre-section { font-size: 16px; color: var(--accent); margin: 26px 0 4px;
                 border-top: 1px solid var(--bord); padding-top: 16px; }
.ligne-boutique { font-size: 14px; margin: 4px 2px 0; }
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
        gap: 14px; margin: 24px 0; }
.kpi { background: var(--carte); border: 1px solid var(--bord); border-radius: 12px;
       padding: 16px 18px; }
.kpi .valeur { font-family: var(--titres); font-size: 22px; font-weight: 400;
               color: var(--accent); }
.kpi .libelle { color: var(--sourd); font-size: 13px; margin-top: 4px; }

/* --- explorateur de collection --- */
.outils { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 20px 0 14px; }
#recherche { flex: 1 1 240px; max-width: 340px; background: var(--carte); color: var(--texte);
             border: 1px solid var(--bord); border-radius: 8px; padding: 8px 12px; font-size: 14px;
             margin: 0; }
.chip { background: var(--carte); border: 1px solid var(--bord); color: var(--sourd);
        border-radius: 20px; padding: 5px 14px; font-size: 13px; cursor: pointer; }
.chip:hover { border-color: var(--accent); color: var(--texte); }
/* le chip ACTIF etait le brun le plus franc de la feuille (#3a2417, teinte 26 deg,
   43 % de saturation) : c'est lui qu'on voyait sous les filtres de la liste. Il
   passe a l'IVOIRE TRANSLUCIDE, comme les traits -- l'etat actif se lit alors par
   la meme matiere que le reste du site. */
.chip.actif { background: rgba(237, 228, 216, .14); border-color: var(--accent);
              color: var(--accent); }
select.filtre-auto { background: var(--carte); color: var(--sourd); border: 1px solid var(--bord);
                     border-radius: 20px; padding: 5px 10px; font-size: 13px; max-width: 190px; }
select.filtre-auto:focus { outline: none; border-color: var(--accent); color: var(--texte); }
/* PAS d'overflow:hidden ici : il casserait les en-têtes collants (sticky) —
   les coins arrondis sont posés sur les cellules d'angle à la place. */
table.explorateur { width: 100%; border-collapse: collapse; background: var(--carte);
                    border: 1px solid var(--bord); border-radius: 12px; }
/* 23/07 (passe multi-écrans) : sous 1220px les tables larges (collection 1166,
   historique 1118, ventes 925) faisaient DÉFILER LA PAGE horizontalement (mobile
   ET iPad paysage). Elles défilent désormais DANS leur boîte (display:block →
   la table devient son propre conteneur de défilement). NB assumé : sous ce
   seuil l'en-tête sticky (entrée 27) ne colle plus — un conteneur qui défile
   neutralise position:sticky vis-à-vis de la page. */
/* SEUIL RELEVE 1219 -> 1339 px (30/07). La colonne Disque etant passee a 430 px,
   la somme des colonnes de /collection atteint ~1276 px : a 1280 px de fenetre, la
   PAGE se mettait a defiler de biais. On elargit donc la plage ou le tableau
   defile DANS SA BOITE. C'etait cela ou reprendre les 110 px a ses voisines --
   precisement ce qu'il fallait eviter. */
@media (max-width: 1339px) {
  table.explorateur { display: block; overflow-x: auto; max-width: 100%; }
}
/* la grille d'expédition (3×3, /parametres) débordait de ~30px sur mobile */
@media (max-width: 900px) {
  .grille-expedition { display: block; overflow-x: auto; max-width: 100%; }
}
.explorateur thead th:first-child { border-top-left-radius: 12px; }
.explorateur thead th:last-child { border-top-right-radius: 12px; }
.explorateur tbody tr:last-child td:first-child { border-bottom-left-radius: 12px; }
.explorateur tbody tr:last-child td:last-child { border-bottom-right-radius: 12px; }
.explorateur th, .explorateur td { padding: 8px 12px; text-align: left;
                                   border-bottom: 1px solid var(--bord); }
/* En-têtes de colonnes FIGÉS au défilement, juste sous l'en-tête du site
   (hauteur variable exposée en --entete-h par le script de base.html). */
.explorateur thead th { position: sticky; top: var(--entete-h, 60px);
                        z-index: 5; box-shadow: 0 1px 0 var(--bord); }
.explorateur th { background: #26262a; color: var(--sourd); font-size: 12px;
                  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; }
.explorateur th.triable { cursor: pointer; user-select: none; }
.explorateur th.triable:hover { color: var(--accent); }
.explorateur tbody tr:hover td { background: #26262a; }
/* La colonne DISQUE est elargie (320 -> 430 px, 30/07 : « elargir un peu la
   colonne record sans pour autant reduire les autres »). Elle ne prend rien aux
   voisines : un tableau repartit d'abord la place selon le CONTENU, or les autres
   colonnes ne portent que des valeurs courtes -- un prix, une date, un format --
   et laissent du mou sur un ecran large. Relever le plafond de la seule colonne
   longue lui donne ce mou, sans y toucher. */
.explorateur .disque { max-width: 430px; overflow: hidden; text-overflow: ellipsis;
                       white-space: nowrap; }
.explorateur .disque a { color: var(--texte); text-decoration: none; }
.explorateur .disque a:hover { color: var(--accent); text-decoration: underline; }
.explorateur .format { max-width: 120px; overflow: hidden; text-overflow: ellipsis;
                       white-space: nowrap; color: var(--sourd); font-size: 13px; }
.explorateur .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.explorateur .vert { color: var(--vert); }
.etiquette { display: inline-block; border: 1px solid var(--bord); color: var(--sourd);
             border-radius: 20px; padding: 0 9px; font-size: 11.5px; white-space: nowrap; }
.etiquette.vendu { opacity: .6; }
.canal { display: inline-block; border: 1px solid var(--bord); color: var(--sourd);
         border-radius: 6px; padding: 0 7px; font-size: 11.5px; white-space: nowrap; }
.explorateur .num.manquant { color: var(--rouge); }
.explorateur .num.manquant::after { content: " !"; }
.explorateur td.editable { cursor: pointer; }
.explorateur td.editable:hover { text-decoration: underline dotted var(--accent); }
input.edition-prix { width: 86px; background: var(--fond); color: var(--texte);
                     border: 1px solid var(--accent); border-radius: 6px;
                     padding: 3px 6px; font-size: 13px; text-align: right; }
input.edition-prix:focus { outline: none; }
/* 21/07 : édition SUR PLACE des autres champs (date, vendeur, canal, état) */
.explorateur td.editable-champ { cursor: pointer; }
.explorateur td.editable-champ:hover { text-decoration: underline dotted var(--accent); }
.edition-champ { width: 100%; box-sizing: border-box; background: var(--fond);
                 color: var(--texte); border: 1px solid var(--accent);
                 border-radius: 6px; padding: 3px 6px; font-size: 13px; }
.edition-champ:focus { outline: none; }
select.edition-etat { width: auto; margin: 0 4px 0 0; padding: 3px 4px; }
.icone-notes { margin-left: 6px; cursor: help; font-size: 12px; }
a.editer, button.editer { text-decoration: none; font-size: 15px; opacity: .6; }
a.editer:hover, button.editer:hover { opacity: 1; }
.ligne-champs { display: flex; gap: 12px; }
.ligne-champs label { flex: 1; }
form textarea { width: 100%; background: var(--fond); color: var(--texte);
                border: 1px solid var(--bord); border-radius: 8px; padding: 9px 12px;
                font-size: 14px; font-family: inherit; margin-top: 4px; resize: vertical; }
form textarea:focus { outline: none; border-color: var(--accent); }
.badge-champ { font-family: system-ui, sans-serif; font-size: 11px; font-weight: 400;
               color: var(--sourd); border: 1px solid var(--bord); border-radius: 20px;
               padding: 1px 8px; margin-left: 8px; letter-spacing: 0; text-transform: none; }
.actions-form { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 20px; }
.actions-form .bouton { width: auto; margin-top: 0; flex: 1; }

/* --- pictogrammes de condition : rond = média, carré = pochette --- */
.conditions { white-space: nowrap; }
.picto { display: inline-flex; align-items: center; justify-content: center;
         min-width: 26px; height: 18px; padding: 0 4px; margin-right: 4px;
         font-size: 10px; font-weight: 700; color: #141416; vertical-align: middle;
         /* toujours en police système (comme la boutique) — jamais la PIX
            héritée d'un titre (18/07, demande utilisateur) */
         font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
.picto.rond { border-radius: 10px; }
.picto.carre { border-radius: 3px; }

/* --- étiquettes (tags) --- */
.tag { display: inline-flex; align-items: center; gap: 4px; border: 1px solid;
       border-radius: 20px; padding: 1px 9px; font-size: 11.5px; margin: 2px 4px 2px 0;
       white-space: nowrap; }
/* Étiquettes de pressage/format (version, format) : chip PLEINE et carrée,
   pour se distinguer au premier coup d'œil des genres/styles en contour. */
.tag-presse { color: #141416; font-weight: 700; border-radius: 4px;
              text-transform: uppercase; letter-spacing: .03em; font-size: 10.5px; }
/* reissue/repress sur la ligne Année de la fiche : blanc, tout simplement */
.presse-blanc { background: #fff; border-color: #fff; margin: 0;
                vertical-align: 1px; }
/* décalage à gauche SEULEMENT quand une année précède le chip (20/07 : sans
   année, REISSUE doit être aligné à gauche comme les autres valeurs de la grille) */
.presse-decale { margin-left: 10px; }
.tags-ligne { margin-top: 4px; }
.tags-assignes { margin: 8px 0 14px; min-height: 24px; }
.tag-retirer { background: none; border: none; color: inherit; cursor: pointer;
               font-size: 14px; line-height: 1; padding: 0; margin: 0; width: auto; }
.ajout-tag { display: flex; gap: 8px; align-items: stretch; flex-wrap: wrap; }
.ajout-tag select { width: auto; margin: 0; }
.ajout-tag input { flex: 1; min-width: 160px; margin: 0; }
.ajout-tag .bouton { width: auto; margin: 0; white-space: nowrap; }
/* une liste déroulante stricte par catégorie d'étiquette */
.ligne-tag-cat { display: flex; gap: 8px; align-items: center; margin: 7px 0; flex-wrap: wrap; }
.ligne-tag-cat .cat-nom { flex: 0 0 64px; font-size: 11px; text-transform: uppercase;
                          letter-spacing: .05em; font-weight: 700; }
.ligne-tag-cat select { flex: 1; min-width: 150px; margin: 0; }
.ligne-tag-cat .nom-libre { flex: 1; min-width: 130px; margin: 0; }
.ligne-tag-cat .bouton { width: auto; margin: 0; padding: 7px 14px; font-size: 13px; }
.tag-cat-label { color: var(--sourd); font-size: 11px; text-transform: uppercase;
                 letter-spacing: .05em; margin: 0 2px 0 10px; align-self: center; }
.tag-cat-label:first-child { margin-left: 0; }
.barre-tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.barre-tags:empty, .barre-tags[hidden] { display: none; }
.tag-filtre { background: var(--carte); border: 1px solid var(--bord); color: var(--sourd);
              border-radius: 20px; padding: 4px 13px; font-size: 13px; cursor: pointer; }
.tag-filtre:hover { border-color: var(--tc); color: var(--texte); }
.tag-filtre.actif { background: var(--tc); border-color: var(--tc); color: #141416; font-weight: 700; }

/* --- feuilletage vertical : pochettes à gauche, fiche détaillée à droite ---
   Page « pleine fenêtre » : tout tient dans l'écran, sans défilement de page,
   et la taille des pochettes suit la fenêtre (vh/vw). */
body.plein { height: 100vh; overflow: hidden;
             display: flex; flex-direction: column; }
/* LE FOND DU SITE EST LA SCÈNE AU REPOS DU FOND VIVANT (30/07, demande
   utilisateur) : fond-repos.webp, rendu par la même campagne Blender que les
   couches animées — l'ancienne image IA fond-studio.webp créait une dissonance
   sous et autour de l'animation. Le fichier est régénéré à chaque campagne :
   le fond statique ne peut plus diverger de la scène animée.
   Voile plus léger sur les pages plein écran — le calque fixe est défini en
   fin de fichier (fond partout). */
body.plein::before {
  background:
    linear-gradient(rgba(16, 16, 18, 0.60), rgba(16, 16, 18, 0.86)),
    url("/static/fond-repos.webp") center / cover no-repeat;
}
body.plein .conteneur { max-width: 1500px; flex: 1 1 auto; min-height: 0;
                        width: 100%; padding: 8px 24px 10px; display: flex;
                        flex-direction: column; overflow: hidden; }
#fl-entete { display: flex; align-items: baseline; gap: 14px; flex: none; }
#fl-entete h1 { font-size: 20px; margin: 0; }
#fl-entete a { text-decoration: none; font-size: 13px; }
/* 17/07 (capture annotée) : sur bureau la ligne titre + icônes de vues MONTE
   DANS la barre d'en-tête (entre le logo et la déconnexion) — la page gagne
   toute sa hauteur. Généralisé à TOUTES les pages qui portent #fl-entete
   (feuilletage, stats, collection, mur, sets, chambre) : l'en-tête est
   sticky, le fixed reste donc calé dessus même quand la page défile. */
@media (min-width: 901px) {
  /* 18/07 (capture annotée) : la barre n'est plus centrée mais CALÉE À
     GAUCHE, juste après le logo et la loupe — les pages de vues n'y mettent
     que les icônes, les autres gardent leur titre au même endroit */
  #fl-entete { position: fixed; top: 0; height: 50px; z-index: 310;
    left: 265px; width: max-content;
    max-width: calc(100vw - 265px - 560px); align-items: center; gap: 12px;
    margin: 0; }
  #fl-entete h1 { font-size: 15px; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  /* boutons d'action dans la barre (ex. /ventes) : compactés à sa hauteur */
  #fl-entete .bouton { padding: 4px 12px; font-size: 12px; margin: 0;
                       width: auto; white-space: nowrap; }
}

#fl-formats { display: flex; flex-wrap: wrap; gap: 12px; margin: 8px 0 10px;
              flex: none; }   /* gap 8 -> 12 : interligne x1,5 (30/07) */
/* 30/07 (demande utilisateur) : les filtres du feuilletage ne sont PLUS des
   chips -- TEXTE PUR en PIX Dot 140, sans boite ni contour, un peu plus grand
   qu'avant, et plus aere (interligne x1,5). L'etat actif parle par la couleur
   d'accent, le survol par l'eclaircissement. Scope #fl-formats : les .fl-chip
   de la wantlist et d'ailleurs gardent leur habit de chip. */
#fl-formats .fl-chip { background: none; border: none; color: var(--texte);
           border-radius: 0; padding: 2px 2px;
           font-family: "PIX Dot", var(--titres); font-size: 14.5px;
           /* interligne un peu plus genereux (30/07) : la fonte pixel est dense, et
              chaque filtre gagne a respirer dans sa propre ligne, independamment de
              l espace que la repartition laisse entre eux. */
           line-height: 1.65;
           cursor: pointer; }
/* LE COMPTE N'EST PAS DU MÊME ORDRE QUE LE NOM (30/07, demande utilisateur : « ne
   garder que le nom ALL, 7", 10" en PIX et laisser les nombres entre parenthèses
   avec l'autre police, à 60 % de la taille »).
   Le nom est un TITRE — il désigne une famille de disques, et la fonte pixel lui va.
   Le compte n'est qu'une quantité, qui change à chaque synchronisation : le mettre
   dans la même fonte et la même taille lui donnait le même poids qu'au nom. En
   police de texte et à 60 %, il redevient ce qu'il est — une précision. */
#fl-formats .fl-chip .fl-chip-n { color: var(--sourd);
   font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
   font-size: 60%; }
#fl-formats .fl-chip:hover { color: var(--accent); }
/* actif : l'ivoire et l'accent sont trop proches pour se distinguer seuls —
   le trait dessous marque la selection, dans l'esprit de la fonte pixel */
#fl-formats .fl-chip.actif { background: none; color: var(--accent); font-weight: 400;
           text-decoration: underline; text-underline-offset: 4px; }
/* ailleurs (wantlist...), l'ancien habit */
.fl-chip { background: var(--carte); border: 1px solid var(--bord); color: var(--sourd);
           border-radius: 999px; padding: 5px 14px; font-size: 13px; cursor: pointer; }
.fl-chip:hover { border-color: var(--accent); color: var(--texte); }
.fl-chip.actif { background: var(--accent); border-color: var(--accent);
                 color: #141416; font-weight: 700; }
/* 23/07 (demande utilisateur) : filtre par TAGS dans la bande — le « ＋ » est un
   <select> stylé comme un chip (clic ouvre la liste des étiquettes ; option sombre
   via la garde globale) ; les chips de tag actifs se retirent au clic (le ✕ n'est
   qu'un repère — cliquer n'importe où sur la chip retire le filtre). */
.fl-tag-plus { appearance: none; -webkit-appearance: none; text-align: center;
               cursor: pointer; }
.fl-tag-chip { cursor: pointer; }
/* « Par couleur » = pastille-ICÔNE (symbole 3 cercles, intersection pleine) —
   compacte, monochrome (currentColor suit la couleur du chip) — 20/07 */
.fl-chip-ico { display: inline-flex; align-items: center; justify-content: center;
               padding: 4px 10px; }
.ico-couleur { display: block; }
/* 21/07 (retour utilisateur + capture annotée) : sur bureau ÉTROIT (901–1739px,
   où la marge est trop petite pour faire FLOTTER la bande sans couvrir la
   pochette — cf. plus bas), les filtres deviennent une COLONNE VERTICALE, 1er
   enfant de #fl-split, À GAUCHE de la pochette. La pochette garde sa colonne
   #fl-gauche (42%) ; c'est la fiche (droite) qui cède la largeur. La bande est
   calée en haut (padding-top:20 comme #fl-scene). Marche à TOUTE hauteur de
   fenêtre (contrairement au flottant, dépendant de la marge disponible). */
@media (min-width: 901px) and (max-width: 1739px) {
  #fl-split > #fl-formats {
    flex: none; flex-direction: column; flex-wrap: nowrap;
    align-self: flex-start; width: 62px; max-width: 62px;
    /* 21/07 : bande calée EN HAUT (pas au milieu) — l'aligner aux rangées d'infos
       la faisait flotter au centre et, une fois AÉRÉE, elle chevauchait le bac.
       En haut il y a de la place pour espacer les chips sans collision. */
    margin: 20px 4px 0 0; gap: 14px; }   /* interligne x1,5 (9 -> 14) — 30/07 */
  /* 22/07 : bande RÉTRÉCIE 80->62px (chip ALL raccourci « ALL » au lieu de
     « Todos/TODO » -> le plus long « ALL (1067) » = 50,8px à 11px tient à 62px
     avec padding 3px 4px). Gain ~18px rendu à la fiche. Texte 11px conservé,
     chips UNIFORMES calés à gauche comme le bac ; gap 9 = air vertical. */
  /* AGRANDIS ×1,5, ET PLUS AÉRÉS (30/07, demande utilisateur : « agrandir ×1,5 la
     taille des textes à gauche de la pochette » puis « il fallait juste augmenter
     l'interligne entre ALL, 7", 10" »).
     12,5 → 18,75 px, et le plus long libellé (« ALL (994) ») passe de 62 à 93 px :
     la bande s'élargit à 104 px, sans quoi le compte entre parenthèses serait rogné.
     L'écart suit la même proportion, 14 → 22 px. La bande reste CALÉE EN HAUT : on
     avait essayé de répartir les filtres sur toute la hauteur, ce n'était pas ce qui
     était demandé — et cela les faisait tomber sur le bac à set, qui occupe le bas
     de la même colonne. */
  #fl-split > #fl-formats { width: 104px; max-width: 104px; gap: 22px; }
  #fl-split > #fl-formats .fl-chip { width: 100%; box-sizing: border-box;
    font-size: 18.75px; padding: 0; text-align: left;
    white-space: nowrap; overflow: hidden; }
}
/* 21/07 (demande utilisateur) : sur GRAND écran (le conteneur est centré à
   1500px → il reste de la marge à gauche), les filtres de format passent en
   BANDE VERTICALE FLOTTANTE dans cette marge. Sortis du flux → le bloc
   pochette/fiche/bac REMONTE et gagne de la place en bas pour les longues
   tracklists/crédits. Seuil ABAISSÉ à 1740px (21/07) : le chip « autres » ne
   montre plus que « … » (feuilletage.js), la bande fait ~90px de large → il ne
   faut plus que ~120px de marge, soit (1740−1500)/2. Sous 1740px (plus assez de
   marge), les filtres restent HORIZONTAUX en haut (repli). */
@media (min-width: 1740px) {
  /* MÊME RÉGLAGE QUE LA BANDE INTÉGRÉE (30/07) : ×1,5, plus large, plus aérée. */
  #fl-formats {
    position: fixed; left: 16px; top: 92px; z-index: 200; margin: 0;
    flex-direction: column; flex-wrap: nowrap; align-items: stretch;
    width: 104px; max-width: 104px; gap: 22px; }
  #fl-formats .fl-chip { width: 100%; box-sizing: border-box; font-size: 18.75px;
    padding: 0; text-align: left; white-space: nowrap; overflow: hidden; }
}

/* 22/07 (demande utilisateur) : plus d'air entre le bord droit de la pochette et le
   texte de la fiche (gap 24 → 38px) — compensé par une 3e colonne un peu plus étroite
   (voir #fd-colonnes/#fd-bas-zone : 0.6fr → 0.52fr). */
#fl-split { display: flex; gap: 38px; margin: 0; align-items: stretch;
            flex: 1 1 auto; min-height: 0; }
/* 20/07 : colonne de la pochette RÉTRÉCIE (48 → 42 %) pour décaler la pochette à
   gauche et donner de la largeur aux 3 colonnes de la fiche. Sûr désormais : la
   pochette est bornée par 100% de SA colonne (règle @media min-width:901px plus
   bas), donc elle se cale dedans et n'est JAMAIS rognée quelle que soit la
   hauteur/largeur de fenêtre (le piège du 44vw est levé). */
#fl-gauche { flex: 0 0 42%; position: relative; overflow: hidden;
             user-select: none; }
#fl-scene { position: absolute; inset: 0;
            display: flex; align-items: center; justify-content: center;
            overflow: hidden; }
/* 20/07 (demande utilisateur) : sur BUREAU la pochette est CALÉE EN HAUT (petit
   gap sous les filtres) au lieu d'être centrée — ça libère la PARTIE BASSE pour
   la fiche qui déborde, le bac (arête inf. = celle du carré) et « À propos »
   dessous. Le centrage flex d'une pochette absolue = sa position statique, donc
   flex-start la remonte ; les flèches ▲▼ sont recalées au centre par aligner(). */
@media (min-width: 901px) {
  #fl-scene { align-items: flex-start; padding-top: 20px; }
  /* 21/07 (capture utilisateur) : #fl-gauche ÉPOUSE la pochette (au lieu d'une
     colonne fixe à 42 %). Sur une fenêtre BASSE la pochette est bornée par la
     hauteur (100vh−280) donc plus étroite que 42 % → avant, elle était centrée
     dans la colonne, laissant une COLONNE VIDE à sa gauche (contre la bande de
     chips) ET à sa droite (contre la fiche). En dimensionnant #fl-gauche à la
     pochette, ces deux colonnes vides disparaissent. */
  #fl-gauche { flex: 0 0 auto; width: min(calc(100vh - 280px), 42%, 800px); }
}
.fl-pochette { position: absolute; width: min(62vh, 40vw, 640px);
               height: min(62vh, 40vw, 640px);
               transition: transform .4s cubic-bezier(.22, .61, .36, 1),
                           opacity .4s cubic-bezier(.22, .61, .36, 1),
                           filter .4s cubic-bezier(.22, .61, .36, 1);
               cursor: grab; box-shadow: 0 12px 34px rgba(0,0,0,.55);
               background: var(--carte); border: 1px solid var(--bord); }
/* les disques d'avant et d'après sont COMPLÈTEMENT flous (pas seulement
   sous les bandes) ; seul le disque central est net */
/* feuilletage SIMPLE (14/07) : une seule pochette, plus de voisins floutés */
.fl-pochette img.flippable { cursor: pointer; }
.fl-pochette.immediat { transition: none; }
.fl-pochette img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fl-pochette.centrale { cursor: default; }
.fl-vinyle { width: 100%; height: 100%; border-radius: 50%;
             background: radial-gradient(circle at 50% 50%,
               #1e1e21 0%, #1e1e21 18%, #0b0b0d 19%, #17171a 36%,
               #0b0b0d 37%, #181819 58%, #0b0b0d 59%, #131315 100%);
             display: flex; align-items: center; justify-content: center; }
.fl-vinyle span { font-family: var(--titres); font-size: 40px; color: var(--accent);
                  background: #141416; border-radius: 50%; width: 34%; height: 34%;
                  display: flex; align-items: center; justify-content: center; }
/* 18/07 (capture annotée) : les flèches quittent le haut/bas de la pochette
   pour une PAIRE VERTICALE posée sur son bord droit, à mi-hauteur — le
   calc(50% + min(...)) suit la moitié de la taille réelle de la pochette,
   borné pour ne jamais sortir de la colonne */
.fl-nav { position: absolute; z-index: 120;
          left: min(calc(50% + min(31vh, 20vw, 320px) + 4px), calc(100% - 46px));
          transform: none;
          width: 40px; height: 40px; border: none; background: none;
          color: var(--texte); font-size: 17px; cursor: pointer; }
.fl-nav:hover { color: var(--accent); }
#fl-prec { top: calc(50% - 46px); }
#fl-suiv { top: calc(50% + 6px); }
/* 22/07 (demande utilisateur) : sur /disques les 2 flèches ▲▼ sont RAPPROCHÉES
   dans un CHIP vertical (pilule), séparées d'un TRAIT ; la moitié haut/bas
   S'ALLUME au défilement vers le haut/bas (flashNav, feuilletage.js). Le chip
   porte le positionnement ; les flèches redeviennent STATIQUES dedans. Le .fl-nav
   de base garde son positionnement absolu pour /stats (#st-prec/#st-suiv). */
.fl-nav-chip { position: absolute; z-index: 120;
  left: min(calc(50% + min(31vh, 20vw, 320px) + 4px), calc(100% - 40px));
  top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; align-items: stretch;
  background: rgba(20, 20, 22, .55); border: 1px solid var(--bord);
  border-radius: 13px; overflow: hidden; }
#fl-nav-chip .fl-nav { position: static; left: auto; transform: none;
  width: 34px; height: 30px; font-size: 15px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  transition: background .3s, color .3s; }
.fl-nav-trait { height: 1px; margin: 0 6px; background: var(--bord); }
/* la moitié correspondante s'allume brièvement au défilement */
#fl-nav-chip.allume-haut #fl-prec,
#fl-nav-chip.allume-bas #fl-suiv { background: var(--accent); color: #141416; }
/* 18/07 (capture annotée) : le compteur monte EN HAUT À GAUCHE du bac */
/* 21/07 (demande utilisateur) : compteur « n / total » RETIRÉ du feuilletage. */
#fl-compteur { display: none; position: absolute; left: 10px; top: 8px; z-index: 120;
               margin: 0; font-size: 13px; }

/* --- grille de catégorie (16/07) : cliquer une chip d'étiquette de la fiche
   remplace le bac par la grille des pochettes portant cette étiquette ;
   la fiche de droite garde exactement son format. --- */
#fl-gauche.grille #fl-scene, #fl-gauche.grille .fl-nav-chip,
#fl-gauche.grille #fl-compteur { display: none; }
/* 19/07 (demande utilisateur) : la grille de catégorie tient dans le CARRÉ de
   la pochette (mêmes dimensions que .fl-pochette, centrée) — 3 « bacs »
   (colonnes) font la largeur, 3 rangées visibles, le reste défile
   VERTICALEMENT ; la hauteur de rangée est posée par feuilletage.js
   (calerGrille) pour montrer exactement trois rangées. */
#fl-grille { position: absolute; top: 50%; left: 50%;
             transform: translate(-50%, -50%);
             width: min(62vh, 40vw, 640px); height: min(62vh, 40vw, 640px);
             z-index: 130; }
/* 19/07 (demande utilisateur) : le carré (cases) remplit TOUT le carré et garde
   sa taille ; le tag choisi + le nombre passent SOUS le carré (avant au-dessus,
   ce qui décalait/rétrécissait le carré à l'ouverture) */
#fl-grille-tete { position: absolute; top: 100%; left: 0; right: 0;
                  margin-top: 10px; display: flex; align-items: center;
                  gap: 10px; padding: 0 2px; }
#fl-grille-tete .tag { margin: 0; font-size: 13px; padding: 3px 12px; }
#fl-grille-fermer { margin-left: auto; width: 28px; height: 28px;
                    border-radius: 50%; border: 1px solid var(--bord);
                    background: rgba(30, 30, 33, .85); color: var(--texte);
                    /* 23/07 (retour utilisateur iPad) : la ✕ n'était pas CENTRÉE dans
                       le cercle (display block + padding navigateur) → flex center */
                    display: inline-flex; align-items: center; justify-content: center;
                    padding: 0;
                    font-size: 13px; line-height: 1; cursor: pointer; }
#fl-grille-fermer:hover { border-color: var(--accent); color: var(--accent); }
/* 18/07 (capture annotée) : la grille de catégorie se lit comme un BAC —
   des TRANCHES de pochettes empilées en COLONNES verticales (le regard
   descend une colonne puis passe à la suivante) ; le SURVOL dégage la
   pochette ENTIÈRE à sa place, par-dessus les voisines */
#fl-grille-cases { position: absolute; inset: 0;   /* remplit le carré (19/07) */
                   overflow-y: auto; overflow-x: hidden;
                   display: grid; grid-template-columns: repeat(3, 1fr);
                   grid-auto-rows: 120px;   /* défaut ; feuilletage.js pose la
                                               vraie hauteur = 3 rangées visibles */
                   gap: 6px; padding: 2px;
                   scrollbar-width: none; }
#fl-grille-cases::-webkit-scrollbar { display: none; }
.flg-case { position: relative; cursor: pointer; overflow: hidden;
            background: var(--carte); border: 1px solid var(--bord);
            box-shadow: 0 4px 12px rgba(0, 0, 0, .4); }
/* l'image remplit sa case (pochette carrée) ; pointer-events none : le clic et
   le survol visent toujours la CASE dessous */
.flg-case img { width: 100%; height: 100%; object-fit: cover;
                object-position: center; display: block;
                pointer-events: none; }
.flg-case .fl-vinyle { height: 100%; }
.flg-case .fl-vinyle span { font-size: 12px; }
@media (hover: hover) {
  .flg-case:hover { border-color: var(--accent); z-index: 6; }
}
.flg-case.actif { outline: 2px solid var(--accent); outline-offset: -2px;
                  z-index: 5; }

/* --- abonnement du service boutique (18/07) : graphisme aligné sur la
   boutique (cartes translucides sur le fond studio), textes agrandis,
   goodies et comparatif gratuit / payant --- */
.abo-etat-bandeau { background: rgba(255, 255, 255, .09);
                    border: 1px solid rgba(255, 255, 255, .5);
                    border-radius: 12px; padding: 16px 20px; margin: 16px 0 6px;
                    max-width: 640px; }
.abo-etat-titre { font-family: var(--titres); font-size: 19px; margin: 0 0 4px; }
.abo-intro { font-size: 16px; line-height: 1.65; max-width: 640px; margin: 12px 0 4px; }
.abo-plans { display: flex; flex-wrap: wrap; gap: 18px; margin: 22px 0; }
.abo-carte { position: relative; flex: 1 1 240px; max-width: 320px;
             text-align: center; background: rgba(255, 255, 255, .09);
             border: 1px solid rgba(255, 255, 255, .5); border-radius: 14px;
             padding: 26px 22px; }
.abo-carte-actif { border-color: var(--accent); }
.abo-carte h2 { font-size: 23px; margin: 0 0 6px; }
.abo-prix { font-family: var(--titres); font-size: 42px; color: var(--accent);
            margin: 8px 0 10px; line-height: 1; }
.abo-prix span { font-family: system-ui, sans-serif; font-size: 15px;
                 color: var(--sourd); }
.abo-ruban { position: absolute; top: 12px; right: -2px; background: var(--vert);
             color: #141416; font-size: 12px; font-weight: 700;
             padding: 3px 10px; border-radius: 4px 0 0 4px; }
.abo-carte .bouton { width: 100%; margin-top: 6px; font-size: 15px; padding: 10px; }
.abo-section { font-size: 20px; margin: 32px 0 10px; }
.abo-goodies { list-style: none; padding: 0; margin: 0 0 8px; max-width: 640px; }
.abo-goodies li { position: relative; padding: 9px 0 9px 28px; font-size: 15px;
                  line-height: 1.5; border-bottom: 1px solid var(--bord); }
.abo-goodies li::before { content: "♦"; position: absolute; left: 4px; top: 9px;
                          color: var(--accent); }
.abo-comparatif { width: 100%; max-width: 640px; border-collapse: collapse;
                  margin: 6px 0 14px; }
.abo-comparatif th, .abo-comparatif td { padding: 11px 10px;
                  border-bottom: 1px solid var(--bord); text-align: left;
                  font-size: 15px; }
.abo-comparatif thead th { color: var(--sourd); font-weight: 700;
                           text-align: center; white-space: nowrap; }
.abo-comparatif thead th:first-child { text-align: left; }
.abo-comparatif thead th.col-payant { color: var(--accent); }
.abo-comparatif td.mark { text-align: center; font-size: 17px; width: 22%; }
.abo-comparatif td.oui { color: var(--vert); }
.abo-comparatif td.non { color: var(--sourd); }
/* mobile : le comparatif tient sans défilement horizontal (en-têtes qui
   reviennent à la ligne, marges resserrées) */
@media (max-width: 560px) {
  /* table-layout fixe = la table tient EXACTEMENT dans la largeur (les
     cellules reviennent à la ligne au lieu d'étirer à max-content) */
  .abo-comparatif { table-layout: fixed; width: 100%; }
  .abo-comparatif th, .abo-comparatif td { padding: 8px 5px; font-size: 13px;
                                            overflow-wrap: anywhere; }
  .abo-comparatif thead th { white-space: normal; }
  .abo-comparatif td.mark { width: 16%; font-size: 15px; }
  .abo-plans { gap: 12px; }
  .abo-prix { font-size: 36px; }
}

/* GENRE et STYLE en CHIPS dans la grille de la fiche (18/07) : la rangée
   peut replier (bat le nowrap-ellipsis des .fd-v de bureau), chips un cran
   plus petites pour rester à la hauteur des lignes voisines */
.fd-grille .fd-v.fd-v-chips { white-space: normal; overflow: visible;
                              text-overflow: clip; display: flex;
                              flex-wrap: wrap; gap: 5px 9px;
                              align-items: center;
                              /* 21/07 : les chips étaient ~1,4px trop HAUT vs leur
                                 libellé (métrique chip vs texte) → petit décalage
                                 vers le bas pour aligner le centre des chips sur
                                 celui du libellé (mesuré : 1,4px = alignement). */
                              padding-top: 1.5px; }
.fd-v-chips .tag { margin: 0; font-size: 10.5px; padding: 0 8px; }

/* --- reçu de commande (jalon G, 18/07) : page publique + impression --- */
.page-commande { max-width: 560px; }
.recap-commande { width: 100%; border-collapse: collapse; margin: 18px 0 14px; }
.recap-commande td { padding: 7px 4px; border-bottom: 1px solid var(--bord); }
.recap-commande td.num { text-align: right; white-space: nowrap; }
.recap-commande .recap-total td { border-bottom: none; padding-top: 12px; }
.forme-ligne { display: flex; gap: 6px; }
/* suivi de commande (invité) + marquage d'expédition (vendeur) — 18/07 */
.suivi-form { display: flex; gap: 8px; margin: 12px 0 8px; max-width: 440px; }
.suivi-form input { flex: 1; }
.forme-expedier { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.forme-expedier input { width: auto; flex: 1 1 110px; min-width: 90px;
                        margin: 0; font-size: 12px; padding: 4px 8px; }
#panier-paypal { display: block; width: 100%; margin-bottom: 8px; }
#panier-paypal.inactif { opacity: .45; pointer-events: none; }
@media print {
  .page-commande { max-width: none; }
  .recap-commande td { border-color: #bbb; }
}

/* flèche blanche « aimantée » vers le bac pendant un glisser (18/07) —
   remplace le curseur interdit du navigateur hors des zones de dépôt */
/* aperçu de DÉPÔT (19/07, demande utilisateur) : un simple CERCLE BLANC avec
   un « + » bien centré, qui suit le curseur pendant le glisser */
#bac-fleche { position: fixed; left: 0; top: 0; z-index: 400;
              pointer-events: none; }
.bac-drag-plus { display: flex; align-items: center; justify-content: center;
                 width: 44px; height: 44px; border-radius: 50%;
                 border: 3px solid #fff; background: rgba(20, 20, 22, .70);
                 box-shadow: 0 6px 18px rgba(0, 0, 0, .55); }
/* le « + » : SVG symétrique, centré au pixel (19/07) */
.bac-drag-plus svg { width: 22px; height: 22px; display: block;
                     stroke: #fff; stroke-width: 3; stroke-linecap: round;
                     fill: none; }
/* un morceau de la tracklist se glisse vers le bac (18/07) */
.fd-piste[draggable] { cursor: grab; }

/* --- bac à set (16/07) : carré fixe en bas à gauche — on y DÉPOSE des
   pochettes (glisser-déposer), on clique pour nommer et créer le set --- */
#bac-set { position: fixed; left: 18px; bottom: 16px; z-index: 300;
           width: 58px; height: 58px; border: 2px solid var(--texte);
           border-radius: 4px; background: rgba(20, 20, 22, .65);
           cursor: pointer; opacity: .55;
           transition: opacity .2s, transform .15s, border-color .15s; }
#bac-set::before { content: ""; position: absolute; inset: 12px 10px;
           background: repeating-linear-gradient(90deg,
             var(--sourd) 0 3px, transparent 3px 11px);
           opacity: .8; }
#bac-set:hover, #bac-set.garni { opacity: 1; }
#bac-set.pret { border-color: var(--accent); transform: scale(1.1); opacity: 1; }
#bac-set.pouls { animation: bac-pouls .35s ease; }
@keyframes bac-pouls { 40% { transform: scale(1.18); } 100% { transform: scale(1); } }
#bac-set-n { position: absolute; top: -9px; right: -9px; min-width: 20px;
           height: 20px; padding: 0 5px; border-radius: 10px;
           background: var(--accent); color: #141416; font-size: 12px;
           font-weight: 700; display: flex; align-items: center;
           justify-content: center; }
@media (max-width: 900px) { #bac-set { display: none; } } /* pas de glisser tactile */
/* 21/07 (demande utilisateur) : la boîte du bac s'ALIGNE horizontalement avec la
   bande de chips (même bord gauche). Bureau étroit : la bande est en flux, à
   gauche du contenu centré → même bord (max(24px, marge+24)). Grand écran : la
   bande FLOTTE à 16px → le bac aussi. */
@media (min-width: 901px) and (max-width: 1739px) {
  #bac-set { left: max(24px, calc((100vw - 1500px) / 2 + 24px)); }
}
@media (min-width: 1740px) { #bac-set { left: 16px; } }

/* voile de nommage du set : page assombrie + champ centré (façon recherche
   macOS/iOS) */
#voile-set { position: fixed; inset: 0; z-index: 400;
             background: rgba(10, 8, 6, .55);
             backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
             display: flex; align-items: center; justify-content: center; }
#voile-set[hidden] { display: none; }
#voile-set-boite { width: min(560px, 86vw); margin-top: -10vh; }
#voile-set-nom { width: 100%; font-family: var(--titres); font-size: 26px;
             padding: 15px 22px; border-radius: 14px;
             border: 1px solid rgba(255, 255, 255, .35);
             background: rgba(30, 30, 33, .94); color: var(--texte);
             outline: none; box-shadow: 0 18px 60px rgba(0, 0, 0, .55); }
#voile-set-nom:focus { border-color: var(--accent); }
#voile-set-nom::placeholder { color: var(--sourd); }
#voile-set-note { text-align: center; margin: 14px 0 0; font-size: 13px; }
/* bac LIÉ à un set existant : nom au-dessus du carré, liseré accent */
#bac-set.lie { border-color: var(--accent); }
/* 22/07 (demande utilisateur) : l'intitulé du set (ex. « Reggae mixtape ») passe
   AU-DESSOUS du bac (top:100%) au lieu d'au-dessus (bottom:100%). */
#bac-set-nomlie { position: absolute; top: calc(100% + 8px); left: 0;
                  max-width: 190px; white-space: nowrap; overflow: hidden;
                  text-overflow: ellipsis; font-size: 11px; color: var(--texte);
                  background: rgba(20, 20, 22, .85); border: 1px solid var(--bord);
                  border-radius: 6px; padding: 2px 9px; }
/* …ou ajouter à un set existant (voile, mode libre) */
#voile-set-sets { margin-top: 18px; }
#voile-set-sets > p { text-align: center; font-size: 12px; margin: 0 0 8px; }
#voile-set-liste { display: flex; flex-direction: column; gap: 6px;
                   max-height: 220px; overflow-y: auto; }
.voile-set-item { text-align: left; font-family: inherit; font-size: 14px;
                  color: var(--texte); background: rgba(30, 30, 33, .92);
                  border: 1px solid var(--bord); border-radius: 10px;
                  padding: 9px 14px; cursor: pointer; }
.voile-set-item:hover { border-color: var(--accent); }
/* voile en mode LIÉ : nom du set + Ouvrir / Détacher */
#voile-set-lie { text-align: center; }
#voile-set-lienom { font-family: var(--titres); font-size: 20px;
                    margin: 0 0 16px; color: var(--texte); }
#voile-set-lie .fe-boutons { display: flex; justify-content: center; gap: 10px; }
#voile-set-lie .bouton { width: auto; text-decoration: none; }

/* --- recherche de disques (loupe de l'en-tête, 18/07) --- */
.ico-loupe, .ico-reglages { display: inline-flex; background: none; border: none;
             padding: 0; color: var(--sourd); cursor: pointer; line-height: 0; }
.ico-loupe:hover, .ico-reglages:hover { color: var(--texte); }
.ico-loupe svg, .ico-reglages svg { width: 20px; height: 20px; }
#voile-rech { position: fixed; inset: 0; z-index: 400;
              background: rgba(10, 8, 6, .55);
              backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
              display: flex; align-items: flex-start; justify-content: center;
              padding-top: 14vh; }
#voile-rech[hidden] { display: none; }
#voile-rech-boite { width: min(560px, 90vw); }
#voile-rech-champ { width: 100%; font-family: var(--titres); font-size: 22px;
              padding: 13px 20px; border-radius: 14px;
              border: 1px solid rgba(255, 255, 255, .35);
              background: rgba(30, 30, 33, .94); color: var(--texte);
              outline: none; box-shadow: 0 18px 60px rgba(0, 0, 0, .55); }
#voile-rech-champ:focus { border-color: var(--accent); }
#voile-rech-champ::placeholder { color: var(--sourd); }
#voile-rech-resultats { margin-top: 12px; display: flex; flex-direction: column;
              gap: 6px; max-height: 56vh; overflow-y: auto; }
.rech-item { display: flex; align-items: center; gap: 12px; padding: 7px 10px;
             border: 1px solid var(--bord); border-radius: 10px;
             background: rgba(30, 30, 33, .92); color: var(--texte);
             text-decoration: none; font-size: 14px; }
.rech-item:hover { border-color: var(--accent); }
.rech-item img, .rech-vinyle { width: 40px; height: 40px; flex: none;
             object-fit: cover; border-radius: 4px; background: #17171a; }
.rech-texte { min-width: 0; white-space: nowrap; overflow: hidden;
              text-overflow: ellipsis; }
#voile-rech-vide { text-align: center; margin: 12px 0 0; font-size: 13px; }

/* chips d'étiquettes cliquables dans la fiche (mêmes couleurs que les spans) ;
   au survol : INVERSION (fond couleur, texte sombre) — 16/07. Le !important
   bat la couleur posée en style inline par le JS. */
.tag-clic { background: transparent; font-family: inherit; cursor: pointer; }
.tag-clic:hover { background: var(--tc); color: #141416 !important; }

#fl-droite { flex: 1; min-width: 0; display: flex; flex-direction: column;
             justify-content: center; padding: 0; overflow: hidden; }
/* La fiche est une colonne flex : quand la fenêtre manque de hauteur, seule la
   liste des morceaux (#fd-pistes) se comprime — jusqu'à son min-height — au
   lieu de faire apparaître une DEUXIÈME barre de défilement sur la fiche.
   Le défilement de la fiche entière ne reste qu'en dernier recours. */
#fl-detail { width: 100%; min-height: 340px; max-height: 100%;
             overflow-y: auto; position: relative;
             display: flex; flex-direction: column; }
#fl-detail > *, #fd-principal > * { flex: none; }
#fl-detail #fd-pistes { flex: 0 1 auto; }
#fl-detail > .editer { position: absolute; top: 4px; right: 2px;
                       font-size: 16px; text-decoration: none; }
/* `.expl-fiche-titre` PARTAGE la règle (31/07) : l'explorer doit ressembler à la
   vue du membre, et le plus sûr moyen est qu'ils lisent la MÊME déclaration —
   recopier des valeurs, c'est accepter qu'elles divergent à la première retouche. */
#fd-titre, .expl-fiche-titre {
            font-family: var(--titres); font-weight: 400; font-size: 16px;
            margin: 0 0 6px; line-height: 1.35; min-height: 46px;
            padding-right: 26px; display: block; overflow: hidden; }
/* titre en DEUX lignes (16/07) : le titre du disque, puis l'auteur en
   dessous — chaque ligne bornée à une seule (ellipse) ; un peu d'air entre
   les deux (proportionnel à la taille du titre) */
.fd-titre-l1, .fd-titre-a { display: block; white-space: nowrap;
                            overflow: hidden; text-overflow: ellipsis; }
.fd-titre-l1 { margin-bottom: 0.32em; }
.fd-titre-a { font-size: 0.72em; }
#fd-titre a { color: var(--texte); text-decoration: none; }
#fd-titre a:hover { color: var(--accent); }
#fd-sous { margin: 0 0 16px; font-size: 14px; min-height: 22px; }
#fd-sous .picto { margin-left: 6px; }
/* 18/07 : rangées à HAUTEUR MINIMALE uniforme — les lignes à chips
   (genre/style) étaient plus tassées que les lignes de texte (16px contre
   21) ; grid-auto-rows égalise, align-items center recentre, et le gap
   passe de 7 à 9px pour donner « à peine un peu plus d'air » */
.fd-grille { display: grid; grid-template-columns: 120px 1fr; gap: 9px 22px;
             margin: 0 0 12px; align-items: center;
             grid-auto-rows: minmax(22px, auto); }
/* les deux groupes (Discogs puis CrucialWax) ne portent plus d'intitulé :
   un simple espace les sépare */
.fd-grille-cw { margin-top: 6px; }
.fd-l { color: var(--sourd); font-size: 11px; text-transform: uppercase;
        letter-spacing: .05em; }
.fd-v { font-size: 14px; min-width: 0; overflow-wrap: anywhere;
        font-variant-numeric: tabular-nums; }
/* 20/07 (demande utilisateur) : sur les lignes de CHIPS (genre/style), le label
   et les chips se calent EN HAUT (pas centrés) — quand les chips débordent sur
   plusieurs lignes, ils se classent depuis le titre vers le bas, le titre reste
   aligné sur la 1re ligne au lieu de flotter au centre. */
.fd-l-haut, .fd-v-haut { align-self: start; }
.fd-l-haut { padding-top: 3px; }
.fd-editable { cursor: pointer; }
.fd-editable:hover { text-decoration: underline dotted var(--accent); }
#fd-fermer { display: none; }  /* visible seulement en fiche mobile dépliée */
/* case de vérification des éditions Net Cost / Net Price : « ancien → nouveau »,
   il faut cocher pour enregistrer (anti fausse manip) */
.confirme-edition { display: inline-flex; align-items: center; gap: 6px;
                    white-space: nowrap; cursor: pointer; font-size: 13px; }
.confirme-edition input { width: 15px; height: 15px; margin: 0;
                          accent-color: var(--accent); cursor: pointer; }
.confirme-edition s { color: var(--sourd); }
.confirme-edition b { color: var(--accent); font-weight: 700; }
/* zone de statut : simple texte — jamais cliquable (sinon, positionnée en
   absolu, elle intercepte des clics du formulaire d'édition sous elle) */
#fd-statut { min-height: 20px; margin: 8px 2px 0; font-size: 13px;
             pointer-events: none; }
#fd-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px;
           min-height: 50px; align-content: flex-start; }
#fd-pistes { min-height: 54px; max-height: 128px; overflow-y: auto;
             margin: 0 0 12px; font-size: 12px; line-height: 1.5; }
/* la tracklist du visiteur : mêmes corps et interligne, mais elle respire — sa
   colonne n'a ni champs d'édition ni crédits à loger en dessous. */
.expl-pistes { font-size: 12px; line-height: 1.5; margin: 14px 0 0;
               overflow-y: auto; }
.fd-piste { display: block; }
/* le morceau = repère | CORPS. Le corps (colonne, démarre après le repère)
   porte la ligne HAUTE (titre extensible · temps JUSTIFIÉ À DROITE via
   margin-left auto + emplacement BPM réservé « 000 ») ET, en dessous, les
   crédits — qui s'ALIGNENT donc sous le titre sans indent artificiel et
   peuvent occuper plusieurs lignes (20/07, demande utilisateur). */
.fd-piste-ligne { display: flex; align-items: baseline; gap: 6px; }
.fd-piste-rep { flex: none; min-width: 30px; color: var(--sourd); }
.fd-piste-corps { flex: 1 1 auto; min-width: 0; }
/* align-items flex-start : quand le titre passe sur 2 lignes, le TEMPS reste en
   HAUT à droite (aligné sur la 1re ligne), il ne descend pas (20/07). */
.fd-piste-haut { display: flex; align-items: flex-start; gap: 6px; }
/* 20/07 (demande utilisateur) : un titre de morceau trop long PASSE À LA LIGNE
   (au lieu de l'ellipse qui « arrivait » au temps) — il n'atteint donc jamais
   le temps mm:ss et ne le chevauche pas ; le temps garde sa place à droite. */
.fd-piste-titre { flex: 0 1 auto; min-width: 0; white-space: normal;
                  overflow-wrap: anywhere; }
.fd-piste-duree { flex: none; margin-left: auto; text-align: right;
                  font-variant-numeric: tabular-nums; }
/* 22/07 (demande utilisateur « rapprocher les temps de leurs titres d'un tag de
   trois caractères ») : la reserve a droite du temps passe de 26 a 52px (un
   « 000 » de plus) -> le temps mm:ss glisse ~26px vers la gauche, plus pres du
   titre. Toujours cale a droite (colonne alignee), juste ecarte du bord. */
.fd-piste-bpm { flex: none; width: 52px; text-align: right;
                font-variant-numeric: tabular-nums; }
/* 22/07 (demande utilisateur) : note « feu » 🔥 par morceau, flammes cliquables au
   bout de la ligne (clic = +1, jusqu'à 5, 6e clic = 0). Au survol PROLONGÉ (délai
   .5s) d'un morceau NON noté, une flamme FANTÔME apparaît (affordance de notation). */
.fd-piste-feu { flex: none; cursor: pointer; font-size: 11px; line-height: 1;
                letter-spacing: -2px; margin-left: 6px; min-width: 12px;
                white-space: nowrap; user-select: none; }
.fd-piste-feu:hover { filter: brightness(1.25); }
.fd-piste-feu:empty::before { content: "🔥"; opacity: 0; transition: opacity .25s .5s; }
.fd-piste:hover .fd-piste-feu:empty::before { opacity: .3; }
/* 22/07 (« puis bpm ») : slot BPM par morceau — chip « ~128 » (clic → graphe)
   quand analyse ; bouton ♪ d'analyse en mode edition (televerser un extrait). */
.fd-bpm-chip, .fd-bpm-add, .fd-bpm-gerer { font: inherit; font-size: 10.5px; line-height: 1;
  background: rgba(255,255,255,.08); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 9px; padding: 1px 6px;
  cursor: pointer; white-space: nowrap; font-variant-numeric: tabular-nums; }
.fd-bpm-add, .fd-bpm-gerer { color: var(--accent); font-size: 12px; padding: 0 6px; }
/* audio d'écoute sans BPM : ♪ en léger contour (se distingue du ♪ « ajouter ») */
.fd-bpm-gerer { border-color: var(--accent); }
.fd-bpm-chip:hover, .fd-bpm-add:hover:not(:disabled),
.fd-bpm-gerer:hover:not(:disabled) { background: var(--accent); color: #141416; }
.fd-bpm-add:disabled, .fd-bpm-gerer:disabled { opacity: .55; cursor: default; }
/* popover du graphe BPM (appende au body, position fixed, cale pres de la chip) */
.fd-bpm-pop { position: fixed; z-index: 360; background: var(--carte);
  border: 1px solid var(--bord); border-radius: 10px; padding: 8px;
  box-shadow: 0 10px 30px rgba(0,0,0,.5); max-width: 96vw; }
/* le SVG serveur n'a qu'un viewBox (pas de width/height) -> il faut une largeur
   DEFINIE au conteneur, sinon il s'effondre a 0. width:100% + height:auto scale
   via le viewBox. */
.fd-bpm-pop-corps { width: 440px; max-width: 84vw; }
.fd-bpm-pop-corps svg { display: block; width: 100%; height: auto; }
.fd-bpm-attente { display: block; font-size: 12px; color: var(--sourd);
  padding: 22px 30px; text-align: center; }
.fd-bpm-pop-actions { display: flex; gap: 8px; margin-top: 6px; justify-content: flex-end; }
.fd-bpm-pop-actions button { font: inherit; font-size: 11px; padding: 3px 10px;
  cursor: pointer; background: rgba(255,255,255,.08); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 7px; }
.fd-bpm-pop-actions button:hover { background: var(--accent); color: #141416; }
/* 20/07 (demande utilisateur) : un morceau SANS crédit/annotation gagne une
   ligne d'espacement (le crédit fait sinon la séparation) ; SYSTÉMATIQUE pour
   les singles (une seule colonne). */
.fd-piste-sans-cred { margin-bottom: .85em; }
#fd-pistes.pistes-simple .fd-piste { margin-bottom: .85em; }
/* tracklist LONGUE sur DEUX colonnes (20/07, demande utilisateur) : face A |
   face B pour éviter de défiler. La classe .pistes-deux + les 2 blocs
   .pistes-col sont posés par le JS quand la liste déborde en une seule colonne
   (bureau uniquement). Deux colonnes FLEX : elles grandissent en hauteur et
   #fd-pistes défile verticalement en dernier recours — jamais de débordement
   horizontal (le piège de column-count sur une hauteur bornée). */
@media (min-width: 901px) {
  #fd-pistes.pistes-deux { display: flex; gap: 22px; align-items: flex-start; }
  #fd-pistes.pistes-deux .pistes-col { flex: 1 1 0; min-width: 0; }
}
/* 22/07 (demande utilisateur) : le CONTENU des notes utilisateur s'affiche au blanc
   des AUTRES textes clairs (--texte #ede4d8) — comme les crédits et les infos release.
   Le libellé « NOTES » reste muet comme les autres libellés (voir .fd-notes-t plus bas). */
#fd-notes { font-size: 13px; margin: 0; min-height: 39px; color: var(--texte);
            display: -webkit-box; -webkit-line-clamp: 2;
            -webkit-box-orient: vertical; overflow: hidden; }
/* titre « NOTES » AU-DESSUS du contenu des notes utilisateur (20/07, demande
   utilisateur) — plus de « Notes — … » sur la même ligne. Le titre reprend le
   style des libellés de la grille (majuscules, sourd). */
.fd-notes-t { display: block; text-transform: uppercase; font-size: 10.5px;
              letter-spacing: .04em; margin-bottom: 3px; }
#fd-notes .fd-notes-t { color: var(--sourd); }   /* libellé muet, contenu blanc */
/* Fenêtre BASSE (pochettes grandes par rapport à la hauteur disponible) : la
   fiche se compacte — titre et notes sur 1 ligne, interlignes réduits — pour
   tenir sans barre de défilement ; #fd-pistes reste la seule zone qui défile. */
@media (max-height: 760px) {
  #fl-detail { min-height: 0; }
  #fd-titre { font-size: 14px; min-height: 0;
              margin-bottom: 4px; }
  #fd-sous { margin-bottom: 8px; }
  .fd-grille { gap: 3px 18px; margin-bottom: 8px; }
  .fd-v { font-size: 13px; }
  #fd-tags { min-height: 26px; margin-bottom: 8px; }
  #fd-pistes { margin-bottom: 8px; }
  #fd-notes { min-height: 19px; -webkit-line-clamp: 1; }
}
/* Fenêtre TRÈS basse : la fiche défile de toute façon — la liste des morceaux
   s'affiche alors en entier pour qu'il n'y ait qu'UNE seule barre (la fiche),
   jamais deux imbriquées. */
@media (max-height: 620px) {
  #fl-detail #fd-pistes { max-height: none; min-height: 0;
                            overflow: visible; flex: none; }
}
/* BUREAU (retour du 13/07) : la pochette centrale remplit la colonne en
   carré ; les disques d'avant/après dépassent UN PEU en haut et en bas,
   sous un REFLET FLOUTÉ (bande --bande, calée par le JS) qui garde l'effet
   de défilement ; la fiche s'aligne sur le carré — titre en haut, limite
   basse des informations à la même marge (padding posé par le JS). */
@media (min-width: 901px) {
  /* 20/07 : la pochette est bornée par la LARGEUR DE SA COLONNE (100%) et non
     par 44vw → elle se cale dans #fl-gauche sans JAMAIS déborder/être rognée,
     même si on rétrécit la colonne pour élargir les 3 colonnes de la fiche.
     aspect-ratio garde le carré ; 100vh-280px la borne aussi en hauteur. */
  .fl-pochette { width: min(100vh - 280px, 100%, 800px);
                 height: auto; aspect-ratio: 1 / 1; }
  /* les bandes-reflets floutées haut/bas ont disparu avec la pile de
     voisins (feuilletage simple du 14/07) — le fond studio reste net */
  #fl-droite { justify-content: flex-start; }
  /* la fiche occupe EXACTEMENT la hauteur du carré : la tracklist absorbe
     l'espace libre pour que la dernière ligne tombe sur la limite basse ;
     la ligne d'état (confirmations d'édition) vit dans la bande basse */
  #fl-detail { height: 100%; max-height: none; }
  #fl-detail #fd-pistes { flex: 1 1 auto; max-height: none; }
  #fl-droite { position: relative; }
  #fd-statut { position: absolute; left: 0; right: 0; margin: 0;
               bottom: calc(var(--bande, 64px) / 2 - 10px); }
}

/* aucune barre de défilement visible dans la fiche (la molette et le doigt
   continuent de défiler) */
#fl-detail, #fd-pistes { scrollbar-width: none; }
#fl-detail::-webkit-scrollbar, #fd-pistes::-webkit-scrollbar { display: none; }

/* Mobile / écrans étroits (retour iPhone SE du 13/07) : la POCHETTE occupe
   quasiment tout l'écran ; la fiche passe PAR-DESSUS, ancrée en bas, sur un
   voile FLOUTÉ de plus en plus net vers le bas qui laisse lire les textes ;
   UN SEUL défilement : celui du texte de la fiche (la tracklist s'y affiche
   en entier, jamais de barre imbriquée). */
@media (max-width: 900px) {
  /* la barre supérieure tient sur UNE SEULE ligne (18/07, retour
     « chevauchement ») : marges et écarts resserrés, logo insécable */
  .entete { padding: 10px 12px; }
  .entete-ligne { gap: 8px; }
  .entete-gauche { gap: 10px; flex: none; }
  .logo { font-size: 15px; }
  .nav-droite { gap: 8px; }
  .entete-loupe svg { width: 19px; height: 19px; }
  select.selecteur-langue { padding: 4px 6px; }
  /* lecteur d'en-tête compact : le titre s'efface, la liste des pistes le
     garde ; restent ♪ ‹ › n/N ▾ ✕ */
  #cw-lecteur { width: auto; max-width: 46vw; gap: 6px; padding: 3px 9px; }
  #cw-lecteur .lect-titre { display: none; }
  body.plein .conteneur { padding: 6px 12px 0; }
  /* 19/07 (retour utilisateur « où sont les stats sur mobile ? ») : sur les
     pages PLEIN ÉCRAN (/disques, /stats), la barre de VUES (menu Liste/
     Release/Grille + Sets + Stats) était masquée sur mobile → la navigation
     et les stats étaient introuvables. Elle reste désormais visible, compacte
     et EN FLUX (la page défile déjà sous elle) ; le fixed n'existe qu'au-delà
     de 901px. */
  body.plein #fl-entete { display: flex; flex: none; align-items: center;
                          margin: 0 0 8px; }
  #fl-entete { flex-wrap: wrap; row-gap: 4px; }
  #fl-formats { margin: 6px 0 8px; gap: 9px; }   /* x1,5 (30/07) */
  .fl-chip { padding: 4px 10px; font-size: 12px; }
  /* FEUILLETAGE MOBILE v5 (18/07, demande utilisateur « plus lisible ») :
     mise en page EN FLUX — la pochette en haut, les informations DESSOUS,
     la page défile verticalement ; balayer la pochette HORIZONTALEMENT
     change de disque. Plus de voile qui se déplie. */
  body.plein { height: auto; min-height: 100vh; overflow: auto; display: block; }
  body.plein .conteneur { display: block; overflow: visible; height: auto; }
  #fl-split { display: block; position: static; }
  #fl-gauche { position: relative; height: min(94vw, 60vh); overflow: visible; }
  .fl-pochette { width: min(86vw, 54vh); height: min(86vw, 54vh); }
  /* 19/07 : la grille de catégorie suit la taille de la pochette MOBILE
     (sans ce palier elle tombait à 40vw ≈ 150px, illisible) */
  #fl-grille { width: min(86vw, 54vh); height: min(86vw, 54vh); }
  /* l'en-tête (tag + nombre + ✕) passe SOUS le carré et déborde de #fl-gauche :
     ménager la place quand la grille est ouverte pour ne pas chevaucher la
     fiche qui suit dans le flux (19/07, revue mobile) */
  #fl-gauche.grille { margin-bottom: 46px; }
  /* le geste remplace les flèches ; reste le compteur sous la pochette */
  .fl-nav, .fl-nav-chip { display: none; }
  #fl-compteur { right: 10px; bottom: 2px; top: auto; left: auto; }
  /* la fiche suit dans le flux, complète — le défilement de PAGE la révèle */
  #fl-droite { position: static; display: block; padding: 6px 2px 26px; }
  #fl-detail { min-height: 0; max-height: none; overflow: visible; }
  /* la fiche RESPIRE (18/07, retour « informations très serrées ») : les
     morceaux à la taille bureau avec un interligne large, crédits sur
     plusieurs lignes, grille espacée — la page défile, l'air est gratuit */
  #fl-detail #fd-pistes { max-height: none; min-height: 0;
                            overflow: visible; flex: none;
                            font-size: 15px; line-height: 1.9;
                            margin: 18px 0 16px; }
  #fl-detail #fd-pistes .sourd { font-size: 12.5px; }
  .fd-piste { padding: 2px 0; }
  .fd-piste-cred { white-space: normal; overflow: visible;
                   font-size: 11.5px; line-height: 1.5; margin: 2px 0 7px; }
  .fd-hw { margin-top: 12px; }
  #fd-bas { margin-top: 16px; }
  #fd-fermer { display: none; }
  #fd-sous { margin-bottom: 12px; }
  #fd-titre { font-size: 17px; min-height: 0; overflow: visible; }
  /* 20/07 (demande utilisateur) : sur mobile (écran vertical, titres qui
     débordent) la 1re ligne du titre passe sur DEUX lignes si besoin — les
     pictos d'état média/pochette qui la suivent restent TOUJOURS visibles
     (au lieu d'être poussés hors écran par l'ellipse). */
  .fd-titre-l1 { white-space: normal; }
  /* notes completes, sauts de ligne respectes + ecart avec les etiquettes (18/07) */
  #fd-notes { display: block; white-space: pre-wrap; overflow: visible;
              margin-top: 18px; }
  .fd-grille { gap: 7px 14px; grid-template-columns: 96px 1fr; }
  #fd-tags { min-height: 26px; gap: 8px; }
  #fd-statut { margin: 4px 2px 0; }
  /* colonnes de la fiche empilées (le bloc min-901 ne s'applique pas ici) */
  #fd-colonnes { display: block; }
}

/* écrans TRÈS étroits (18/07) : la barre garde UNE ligne même avec le
   lecteur ouvert — ses ‹ › s'effacent (la liste « n/N ▾ » change de piste) */
@media (max-width: 520px) {
  .entete { padding: 9px 8px; }
  .entete-gauche { gap: 7px; }
  .nav-droite { gap: 6px; }
  .logo { font-size: 13.5px; }
  #cw-lecteur { gap: 5px; padding: 2px 6px; }
  #cw-lecteur .lect-nav { display: none; }
  /* la sourdine aussi : les boutons de volume du téléphone font ce travail */
  #cw-lecteur .lect-mute { display: none; }
  #cw-lecteur .lect-liste-btn { font-size: 10.5px; }
  select.selecteur-langue { padding: 3px 5px; font-size: 11px; }
}

/* 31/07 : la BARRE DE VUES a entièrement disparu (_vues.html supprimé) — toutes
   ses règles .vues-* sont purgées. Le sélecteur Liste/Release/Grille, les icônes
   d'action (sets, stats, ＋, scan, réglages) et la loupe vivent dans l'en-tête :
   menu ⋮ (.menu-nav) et .entete-loupe. NB : .vues-boutique (chips des vitrines)
   n'a aucun rapport et reste. */
/* tableau de bord à DEUX portes : tuiles larges */
/* --- TABLEAU DE BORD sans défilement (24/07, demande utilisateur) : sur
   bureau/tablette (≥901px) tout tient dans la fenêtre — les listes (registre,
   signaux, achats) deviennent des COLONNES à défilement INTERNE. Mobile :
   flux et défilement de page inchangés. --- */
@media (min-width: 901px) {
  body.tableau-plein { height: 100vh; overflow: hidden;
                       display: flex; flex-direction: column; }
  body.tableau-plein .conteneur { flex: 1 1 auto; min-height: 0;
                                  display: flex; flex-direction: column;
                                  overflow: hidden; }
  body.tableau-plein .dash-listes { display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 0 26px; flex: 1 1 auto; min-height: 0; align-items: stretch; }
  body.tableau-plein .dash-col { display: flex; flex-direction: column;
                                 min-height: 0; }
  body.tableau-plein .dash-col .carte-info { flex: 1 1 auto; min-height: 0;
    overflow-y: auto; scrollbar-width: thin; margin-bottom: 10px; }
}
.dash-deux { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
             max-width: 640px; }
.dash-deux .tuile { padding: 26px 22px 20px; font-size: 17px; }
/* 24/07 (demande utilisateur) : COLLECTION / WANTLIST / SHOP agrandies, au style
   TRANSLUCIDE encadré de /compte (rgba blanc léger + bordure discrète). */
.dash-grandes { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
                max-width: 960px; gap: 16px; }
.dash-grandes .tuile { padding: 42px 30px 34px; font-size: 23px;
  background: rgba(255, 255, 255, 0.03); border: 1px solid var(--bord);
  border-radius: 12px; }
.dash-grandes .tuile:hover { border-color: var(--accent);
  background: rgba(255, 255, 255, 0.05); }
.dash-grandes .tuile-note { margin-top: 9px; font-size: 13px; }

/* --- tableau de bord minimaliste (13/07) --- */
.dash-vie { font-size: 13.5px; margin: 2px 0 0; }
.dash-vie strong { color: var(--texte); font-weight: 600; }
.dash-tuiles { display: grid; gap: 10px; margin: 16px 0 22px;
               grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
.tuile { display: block; background: var(--carte); border: 1px solid var(--bord);
         border-radius: 12px; padding: 18px 16px 14px; color: var(--texte);
         text-decoration: none; font-family: var(--titres); font-size: 15px;
         letter-spacing: .02em; }
.tuile:hover { border-color: var(--accent); }
/* dashboard : cartes des listes (registre/signaux/achats) au style translucide
   encadré de /compte (24/07, demande utilisateur). */
.dash-listes .carte-info { background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--bord); border-radius: 12px; }
.tuile-note { display: block; margin-top: 5px; color: var(--sourd);
              font-family: system-ui, sans-serif; font-size: 11.5px;
              letter-spacing: 0; }

/* --- la « room » v2 (18/07) : bacs de pochettes en quinconce.
   24/07 (demande utilisateur) : tri + filtres + compteur sur UNE SEULE LIGNE
   (#ch-barre), homogène avec la wantlist/boutique — repli en ligne si étroit. */
#ch-barre { display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap;
            margin: 10px 0 4px; }
#ch-barre select { padding: 5px 8px; font-size: 12.5px; }
#ch-barre .ch-others { font-size: 12.5px; }
#ch-tri { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
          margin: 0; }
#ch-tri select { width: auto; margin: 0; padding: 6px 10px; font-size: 13px;
          background: var(--carte); color: var(--texte);
          border: 1px solid var(--bord); border-radius: 8px; cursor: pointer; }
#ch-tri .bouton { width: auto; margin: 0; padding: 6px 14px; font-size: 12px; }
/* barre de FILTRES par étiquette (19/07) : affiner les bacs avant de les
   former ; regrouper les tout petits dans « autres » */
#ch-filtres { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
              margin: 0; }
#ch-filtres select { width: auto; margin: 0; padding: 6px 10px; font-size: 13px;
              background: var(--carte); color: var(--texte);
              border: 1px solid var(--bord); border-radius: 8px; cursor: pointer;
              max-width: 220px; }
#ch-tag-actifs { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ch-filtre-actif { margin: 0; cursor: default; }
.ch-filtre-x { cursor: pointer; margin-left: 2px; opacity: .8; }
.ch-filtre-x:hover { opacity: 1; }
#ch-filtres .ch-others { display: inline-flex; align-items: center; gap: 6px;
              font-size: 13px; color: var(--sourd); cursor: pointer; }
/* v3 (18/07, retour utilisateur) : chaque bac = la GRILLE d'étiquette du
   feuilletage — pochettes en grille VERTICALE, défilement vertical de la
   page (barres de défilement invisibles), et le bac est identifié par ses
   CHIPS d'étiquettes colorées sur UNE SEULE ligne (pas de titres). */
body.chambre { scrollbar-width: none; }
body.chambre::-webkit-scrollbar { display: none; }
.ch-bac { margin: 22px 0 6px; }
.ch-bac-tags { display: flex; align-items: center; gap: 6px; margin: 0 0 10px;
               white-space: nowrap; overflow: hidden; }   /* UNE ligne, toujours */
.ch-bac-tags .tag { margin: 0; flex: none; }
.ch-bac-tags .sourd { flex: none; font-size: 12px; }
.ch-grille { display: grid; align-content: start; gap: 10px;
             grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
.ch-case { display: block; aspect-ratio: 1 / 1; overflow: hidden;
           background: var(--carte); border: 1px solid var(--bord);
           box-shadow: 0 6px 18px rgba(0, 0, 0, .4); cursor: pointer; }
.ch-case img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ch-case:hover { border-color: var(--accent); }
.ch-case .fl-vinyle span { font-size: 15px; }

/* --- la chambre d'écoute (PLAN §11, prototype) --- */
.chambre-scene { margin: 12px auto 0; max-width: 900px; }
.chambre-scene svg { width: 100%; height: auto; display: block; }
.chambre-platine { display: flex; align-items: center; gap: 10px;
                   justify-content: center; margin: 16px 0 0; font-size: 14px;
                   color: var(--sourd); }
.chambre-platine .apercu-btn { position: relative; flex: none; }  /* ancre du ＋ */

/* --- collection Bandcamp (PLAN §12) --- */
.bc-actions { display: flex; align-items: center; gap: 14px; margin: 10px 0 18px; }
.bc-grille { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
             gap: 14px; }
.bc-carte { background: var(--carte); border: 1px solid var(--bord);
            border-radius: 12px; overflow: hidden; display: flex;
            flex-direction: column; position: relative; }
.bc-image { position: relative; display: block; aspect-ratio: 1; }
.bc-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* ▶ : lecture immédiate dans le lecteur CrucialWax (un seul clic) */
.bc-jouer { position: absolute; right: 8px; top: 8px; width: 36px; height: 36px;
            border-radius: 50%; background: rgba(20, 20, 22, .85);
            border: 1px solid var(--bord); color: var(--texte);
            font-size: 13px; cursor: pointer; }
.bc-jouer:hover { border-color: var(--accent); color: var(--accent); }
.bc-ecoute { font-size: 12px; }
/* la date d'achat et le vendeur sont des champs LIBRES (parfois une phrase
   entière) : colonnes plafonnées, texte complet en infobulle */
.explorateur td.date-achat { max-width: 108px; white-space: nowrap;
                             overflow: hidden; text-overflow: ellipsis; }
.explorateur td.vendeur { max-width: 140px; white-space: nowrap;
                          overflow: hidden; text-overflow: ellipsis; }
/* ▶ discret dans les lignes du tableau de la collection */
.explorateur .apercu-btn { position: relative; width: 22px; height: 22px;
                           padding: 0; margin-left: 6px;
                           vertical-align: middle; }   /* relative = ancre du ＋ */
/* petit bouton : triangle réduit d'autant (le font-size:9px d'avant ressusciterait
   le glyphe texte masqué — triangle clip-path, 23/07) */
.explorateur .apercu-btn::before { width: 8px; height: 9px; margin-left: 2px; }
.bc-infos { padding: 10px 12px; display: flex; flex-direction: column; gap: 3px;
            font-size: 13.5px; }
.bc-infos a { color: var(--texte); text-decoration: none; }
.bc-infos a:hover { color: var(--accent); }
.bc-vinyle { color: var(--accent); }
.bc-lecteur { margin: 0; }
.bc-lecteur iframe { display: block; }

/* --- boutique publique --- */
.grille-boutique { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
                   gap: 16px; margin: 24px 0; }
/* carte PLATE et TRANSLUCIDE (retour utilisateur 14/07) : un seul cadre
   périphérique, fond semi-transparent sur la page, aucun encadrement interne.
   16/07 : fond un peu plus opaque et contour BLANC (contraste), plus ambré */
.article { background: rgba(255, 255, 255, 0.09);
           /* trait aminci de 25 % (18/07) : 1px mais intensité 0,9 → 0,675
              (une bordure < 1px est arrondie au pixel d'écran, résultat
              incohérent selon les machines) */
           /* 23/07 (demande utilisateur) : plus de contour de carte */
           border: none;
           border-radius: 12px; padding: 16px 18px 0; overflow: hidden;
           display: flex; flex-direction: column; gap: 8px; box-shadow: none; }
.article-image { display: block; margin: -16px -18px 4px; }
.article-image img { width: 100%; aspect-ratio: 1; object-fit: cover;
                     border-radius: 12px 12px 0 0; display: block; }
.article-vinyle { display: flex; align-items: center; justify-content: center;
                  width: 100%; aspect-ratio: 1; border-radius: 12px 12px 0 0;
                  background: radial-gradient(circle at 50% 50%,
                    #1e1e21 0%, #1e1e21 18%, #0b0b0d 19%, #17171a 36%,
                    #0b0b0d 37%, #181819 58%, #0b0b0d 59%, #131315 100%); }
.article-vinyle span { font-family: var(--titres); font-size: 34px; color: var(--accent);
                       background: #141416; border-radius: 50%; width: 30%; aspect-ratio: 1;
                       display: flex; align-items: center; justify-content: center; }
/* les informations d'une fiche restent TOUJOURS sur une seule ligne (18/07) */
/* 23/07 (demande utilisateur) : texte des cartes un peu RÉDUIT (titre 13.5,
   méta 12) */
.article-titre { white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
                 font-size: 13.5px; }
.article-titre a { color: var(--texte); text-decoration: none; font-weight: 700; }
.article-titre a:hover { color: var(--accent); }
/* 23/07 (demande utilisateur : « empêcher la déformation des étiquettes ») :
   la méta était un bloc nowrap-ellipsis ENTIER → quand le format est long, les
   pictos d'état en bout de ligne étaient ROGNÉS en plein milieu (pilule coupée
   = « déformée »). Désormais la méta est un FLEX : le TEXTE (span) s'ellipse,
   les pictos flex:none restent toujours entiers. */
.article-meta { color: var(--sourd); font-size: 12px;
                display: flex; align-items: center; gap: 4px; min-width: 0; }
.article-meta-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis;
                    white-space: nowrap; }
.article-meta .picto { flex: none; margin-right: 0; }
.article-prix { display: flex; align-items: baseline; gap: 10px; margin-top: auto; }
.prix-site { font-family: var(--titres); font-size: 18px; color: var(--accent); }
.prix-barre { color: var(--sourd); text-decoration: line-through; font-size: 13px; }
/* pied de carte : trait horizontal au-dessus, prix | ADD séparés d'un trait
   vertical, bouton SANS cadre propre (gain de place, design plat) */
.article-pied { display: flex; align-items: stretch; margin: 8px -18px 0;
                margin-top: auto;
                /* 23/07 : ligne transparente qui CAPTE LE FOND — couleur du
                   fond de page a travers la carte translucide */
                border-top: 1px solid rgba(20, 20, 22, 0.85); }
/* IMPÉRATIF : prix et bouton restent chacun sur UNE ligne (nowrap),
   sinon le pied se déforme (retour utilisateur : « 35.00 » / « € » cassés) */
.article-pied-prix { flex: 1 1 auto; display: flex; align-items: baseline;
                     gap: 8px; padding: 11px 14px; min-width: 0;
                     white-space: nowrap; overflow: hidden; }
.article-pied .ajouter-panier { flex: none; border: none; background: none;
    border-left: 1px solid rgba(20, 20, 22, 0.85); color: var(--accent);
    font-family: var(--titres); font-size: 13px; letter-spacing: 1px;
    padding: 0 16px; cursor: pointer; white-space: nowrap; }
/* survol AJOUTER : INVERSION — rectangle blanc (adouci à 65 % d'opacité),
   texte noir (18/07 ; la surbrillance ambrée est supprimée) */
.article-pied .ajouter-panier:hover { background: rgba(255, 255, 255, 0.65);
                                      color: #141416; }
/* ordre manuel : la fiche en cours de déplacement s'estompe (proprio) */
.article.en-deplacement { opacity: .45; }
.article[draggable="true"] { cursor: grab; }

/* --- boutique : BLOCS DE NOTE éditoriaux (mode édition « crayon », 19/07) --- */
/* 23/07 (demande utilisateur) : un texte de note plus long que la cellule doit
   pouvoir se LIRE → la carte DÉFILE (overflow-y auto). Le centrage passe de
   justify-content:center (qui COUPE le haut d'un contenu débordant) à
   margin:auto sur .note-vue — centré quand court, défilable depuis le HAUT
   quand long. */
.article-note { background: rgba(255, 255, 255, 0.06);
                border: 1px solid rgba(255, 255, 255, 0.28);
                border-radius: 12px; padding: 18px 20px; min-height: 120px;
                display: flex; flex-direction: column; justify-content: flex-start;
                gap: 8px; overflow-y: auto; scrollbar-width: thin;
                /* CAP : sans lui une note longue ÉTIRAIT toute la rangée de la
                   grille (cellule géante) au lieu de défiler */
                max-height: min(480px, 62vh); }
.article-note .note-vue { margin: auto 0; }
.article-note.large { grid-column: span 2; }
.note-titre-vue { font-family: var(--titres); font-weight: 400; font-size: 22px;
                  color: var(--accent); letter-spacing: .02em;
                  /* 23/07 (demande utilisateur) : un espace entre le titre de la
                     note et son texte */
                  margin: 0 0 10px; }
.note-texte-vue { margin: 0; color: var(--texte); font-size: 14px; line-height: 1.6;
                  white-space: pre-wrap; }
/* édition en place du bloc de note (montrée seulement en mode édition) */
.note-edit { display: none; flex-direction: column; gap: 8px; }
.note-edit .note-titre, .note-edit .note-texte {
  width: 100%; background: var(--fond); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 8px; padding: 8px 10px;
  font: 14px/1.5 inherit; }
.note-edit .note-titre { font-family: var(--titres); font-size: 18px; }
.note-edit textarea.note-texte { resize: vertical; }
.note-edit .note-titre:focus, .note-edit .note-texte:focus {
  outline: none; border-color: var(--accent); }
.note-actions { display: flex; align-items: center; gap: 10px; }
.note-actions button, .note-glisser { background: none; border: none;
  color: var(--sourd); cursor: pointer; font-size: 15px; padding: 2px 6px;
  line-height: 1; }
.note-actions button:hover { color: var(--accent); }
.note-large[aria-pressed="true"] { color: var(--accent); }
.note-glisser { cursor: grab; margin-right: auto; }

/* --- boutique : barre et affordances du MODE ÉDITION --- */
#bq-edit-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
               margin: 4px 0 18px; }
/* le crayon d'édition, DANS la rangée des vues à droite de « Par couleur »
   (19/07) : chip accent bien visible, icône ✎ */
.bq-crayon-chip { text-decoration: none; border-color: var(--accent);
                  color: var(--accent); font-size: 15px; line-height: 1.1;
                  padding: 6px 13px; cursor: pointer; }
.bq-crayon-chip:hover { background: var(--accent); color: #141416; }
#bq-outils { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 10px; }
#bq-etat { font-size: 13px; }
/* « Ranger par » (24/07) : cascade de tri cumulatif en mode édition, on gèle
   l'ordre calculé dans l'agencement (base éditable à la main) */
.bq-ranger-bloc { display: inline-flex; flex-wrap: wrap; align-items: center;
                  gap: 6px; padding: 4px 10px; border: 1px solid var(--bord);
                  border-radius: 8px; }
.bq-ranger-lbl { font-size: 12.5px; margin-right: 2px; }
.bq-tri-critere { font-size: 12.5px; padding: 3px 4px; }
#bq-ranger { border-color: var(--accent); color: var(--accent); }
#bq-ranger:hover { background: var(--accent); color: #141416; }
/* pagination de la boutique (19/07) : « n par page » + navigation */
#bq-pagination { display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
                 margin: 0 0 18px; font-size: 13px; }
/* boutique (24\07, capture utilisateur) : la pagination vit DANS la rangée des
   chips de vues, calée à droite — même ligne, comme la wantlist et la grille */
.vues-boutique #bq-pagination { margin: 0 0 0 auto; }
/* 24\07 (demande utilisateur) : la rangée vues + pagination se FIGE sous la
   barre supérieure au défilement — BUREAU seulement (sur mobile un bandeau
   opaque masquait le panier, leçon de l'entrée 207) ; fond translucide flouté
   comme l'en-tête ; z-index 200 < panier (210) < en-tête (300) */
@media (min-width: 901px) {
  body.boutique-vitrine .vues-boutique { position: sticky;
    top: var(--entete-h, 56px); z-index: 200; background: rgba(20, 20, 22, .88);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    padding: 10px 0; margin: 0 0 14px; }
}
#bq-pagination label { color: var(--sourd); }
#bq-par-page { width: auto; margin: 0 0 0 6px; padding: 5px 8px; font-size: 13px; }
#bq-pages { display: inline-flex; align-items: center; gap: 8px; }
.bq-page-btn { width: auto; margin: 0; padding: 2px 12px; font-size: 17px;
               line-height: 1.2; background: none; border: 1px solid var(--bord);
               border-radius: 8px; color: var(--texte); cursor: pointer; }
.bq-page-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.bq-page-btn:disabled { opacity: .4; cursor: default; }
.bq-page-info { color: var(--sourd); font-variant-numeric: tabular-nums; }
#bq-aide { flex-basis: 100%; margin: 0; font-size: 13px; display: none; }
body.bq-edition #bq-aide { display: block; }
body.bq-edition .note-vue { display: none; }
body.bq-edition .note-edit { display: flex; }
/* pendant l'édition : chaque cellule se démarque (déplaçable) */
body.bq-edition .article,
body.bq-edition .article-note { outline: 1px dashed rgba(255, 255, 255, 0.35);
                                outline-offset: 2px; }
/* --- galerie d'images du mode édition (23/07, PLAN §16) : ✕ = retirée de la
   vue (estompée + désaturée, re-cliquable) ; ＋ = carré de MÊME taille avec un
   cercle et un + (même dessin que l'aperçu du bac à set). Visible SEULEMENT
   pendant l'édition — remplace la rangée de vignettes standard. --- */
.bq-galerie { display: none; }
body.bq-edition .article-vues { display: none; }
body.bq-edition .bq-galerie { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0; }
.bq-img { position: relative; width: 44px; height: 44px; flex: none;
          cursor: grab; }   /* les vignettes se GLISSENT pour choisir l'ordre —
          la 1re visible = la pochette (23/07, retour utilisateur) */
.bq-img img { width: 100%; height: 100%; object-fit: cover; display: block;
              border-radius: 6px; border: 1px solid var(--bord);
              transition: opacity .2s, filter .2s; }
.bq-img.img-masquee img { opacity: .35; filter: grayscale(1); }
.bq-img-x { position: absolute; top: -6px; right: -6px; z-index: 2;
  width: 18px; height: 18px; border-radius: 50%; padding: 0;
  border: 1px solid var(--bord); background: rgba(20, 20, 22, .92);
  color: var(--texte); font-size: 10px; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; }
.bq-img-x:hover { border-color: var(--accent); color: var(--accent); }
/* 23/07 (demande utilisateur) : croix VIDE (fond transparent, glyphe sourd)
   sur une image masquee — re-cliquer restaure */
.bq-img.img-masquee .bq-img-x { background: transparent; color: var(--sourd);
                                border-color: var(--bord); }
.bq-img-add { width: 44px; height: 44px; flex: none; border-radius: 6px;
  border: 1px dashed var(--bord); background: none; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; }
.bq-img-add:hover { border-color: var(--accent); }
.bq-img-add-cercle { display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%; border: 2px solid #fff;
  background: rgba(20, 20, 22, .70); }
.bq-img-add-cercle svg { width: 14px; height: 14px; display: block;
  stroke: #fff; stroke-width: 2.5; stroke-linecap: round; fill: none; }
.bq-img-add.envoi { opacity: .5; cursor: progress; }
/* bloc SOUS LA POCHETTE en édition (23/07, capture annotée) : la galerie
   d'images (une ligne, mêmes vignettes .bq-img que la boutique) PUIS les
   NOTES — position absolue dans #fl-gauche (top posé par brancherGalerie =
   bas du carré + 10px) ; mobile : en flux sous la pochette */
#fd-sous-poche { position: absolute; left: 2px; right: 2px; z-index: 120; }
.fd-galerie { display: flex; flex-wrap: nowrap; overflow-x: auto; overflow-y: visible;
              gap: 8px; padding: 6px 2px 4px; scrollbar-width: thin; }
#fd-sous-poche .fd-notes-l { margin: 4px 0 4px; }
#fd-sous-poche .fd-notes-edit textarea { min-height: 52px; }
@media (max-width: 900px) { #fd-sous-poche { position: static; margin-top: 10px; } }

/* --- création d'une release LOCALE (23/07) — même logique que le formulaire
   Discogs « Add Release » : Size | Speed | Description en colonnes de cases,
   tracklist en lignes répétables. --- */
.creation-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }
.creation-format-grille { display: grid; grid-template-columns: 1fr 1fr 1.4fr;
  gap: 8px 20px; margin: 10px 0 4px; }
.creation-ss-titre { margin: 4px 0 6px; color: var(--sourd); font-size: 12px;
  text-transform: uppercase; letter-spacing: .05em; }
.creation-case { margin: 3px 0; font-size: 13px; }
.creation-descs { display: flex; flex-wrap: wrap; gap: 2px 16px; margin: 6px 0; }
.creation-descs .creation-case { flex: 0 0 auto; }
.creation-piste { display: flex; gap: 8px; align-items: center; margin: 6px 0; }
.creation-piste .cp-repere { width: 74px; flex: none; }
.creation-piste .cp-titre { flex: 1; min-width: 0; }
.creation-piste .cp-duree { width: 84px; flex: none; }
.creation-piste .cp-retirer { flex: none; width: 26px; height: 26px;
  border-radius: 50%; border: 1px solid var(--bord); background: none;
  color: var(--sourd); cursor: pointer; font-size: 11px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; }
.creation-piste .cp-retirer:hover { border-color: var(--accent); color: var(--accent); }
#creation-ajouter-piste { width: auto; margin-top: 6px; }
#creation-suppr { margin-top: 14px; }
#creation-suppr .bouton { width: auto; }
@media (max-width: 700px) {
  .creation-2col, .creation-format-grille { grid-template-columns: 1fr; }
}
/* marqueur LOCAL sur la fiche du feuilletage (release à id négatif) */
.fd-local { margin-left: 10px; text-decoration: none; font-size: 10px; }
/* ✕ retirer une fiche de sa position (elle repart à la fin) — coin HAUT
   GAUCHE (le ▶ d'écoute occupe le coin droit) */
.bq-retirer { position: absolute; top: 8px; left: 8px; z-index: 6;
  width: 26px; height: 26px; border-radius: 50%; border: none;
  background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 13px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; line-height: 1; }
.bq-retirer:hover { background: var(--accent); color: #141416; }
@media (max-width: 560px) { .article-note.large { grid-column: 1 / -1; } }
label.case { display: flex; align-items: center; gap: 8px; color: var(--texte);
             font-size: 14px; margin-top: 16px; }
label.case input { width: auto; margin: 0; }

/* --- liste des alertes du moniteur --- */
.liste-alertes { list-style: none; margin: 10px 0 0; padding: 0; }
.alerte { display: flex; align-items: baseline; gap: 8px; padding: 7px 0;
          border-bottom: 1px solid var(--bord); font-size: 14px; }
.alerte:last-child { border-bottom: none; }
.alerte-icone { flex: none; }
.alerte a { color: var(--texte); text-decoration: none; }
.alerte a:hover { color: var(--accent); }
.alerte-detail { color: var(--sourd); flex: 1; }
.alerte-date { color: var(--sourd); font-size: 12px; flex: none; }

/* --- statistiques (courbes SVG serveur) --- */
.stat-bloc { margin: 20px 0 30px; }
.stat-bloc h2 { font-size: 16px; margin: 0 0 8px; }
.stat-bloc .graphe { width: 100%; height: auto; display: block; }
.stat-bloc .aide { margin-top: 6px; }

/* --- /stats harmonisée sur le feuilletage (17/07) : graphique dans le
   CARRÉ de gauche, infos + liste des visualisations à droite --- */
/* barre de filtres de /stats (19/07) : décennie / format / genre / style,
   cumulatifs — flex:none pour ne pas manger la hauteur du carré */
#st-filtres { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
              flex: none; margin: 8px 0 0; }
#st-filtres select { background: var(--carte); border: 1px solid var(--bord);
                     color: var(--texte); border-radius: 8px; padding: 6px 10px;
                     font-size: 13px; font-family: inherit; max-width: 190px; }
#st-filtres .bouton { width: auto; margin: 0; }
/* exceptions « sauf » (19/07) : chaque catégorie = un groupe include + zone
   d'exclusion (label sourd + sélecteurs actifs + bouton ＋) */
.st-filtre-cat { display: inline-flex; align-items: center; gap: 6px; }
.st-sauf { display: inline-flex; align-items: center; gap: 4px; }
.st-sauf-lbl { font-size: 11px; color: var(--texte); opacity: .5;
               text-transform: lowercase; letter-spacing: .02em; }
#st-filtres [data-sauf] { max-width: 160px; }
.st-sauf-plus { background: none; border: 1px solid var(--bord);
                color: var(--texte); border-radius: 8px; width: 26px; height: 30px;
                padding: 0; font-size: 14px; line-height: 1; cursor: pointer;
                display: inline-flex; align-items: center; justify-content: center; }
.st-sauf-plus:hover { border-color: var(--accent); color: var(--accent); }
#st-split { display: flex; gap: 24px; align-items: stretch;
            flex: 1 1 auto; min-height: 0; margin-top: 10px; }
/* 19/07 (demande utilisateur) : plus d'espace en LARGEUR pour aérer les
   graphiques — la colonne de gauche s'élargit et le graphique est CALÉ EN
   HAUT À GAUCHE (align-items/justify-content: flex-start), en gardant les
   distances minimales : couloir des flèches à droite (padding-right 54px),
   petit dégagement en haut (padding-top), et la gouttière vers la colonne
   texte (gap de #st-split). */
/* 19/07 (capture annotée) : le HAUT du graphique s'aligne sur le HAUT du titre
   de la colonne de droite (padding-top identique à #st-droite) — le graphe ne
   part plus 54 px trop haut ; il garde ainsi une distance nette sous les
   filtres. */
#st-gauche { flex: 0 0 56%; position: relative; overflow: hidden;
             display: flex; align-items: flex-start; justify-content: flex-start;
             padding: 60px 54px 0 0; }
#st-scene { width: 100%; height: 100%; display: block; }
/* largeur pleine ; hauteur bornée à la colonne (les graphiques presque carrés
   ne débordent plus par le bas — l'aire du carré est préservée) */
#st-scene svg { width: 100%; max-width: 100%; height: auto; max-height: 100%;
                display: block;
                /* 20/07 (demande utilisateur) : plus de carte encadrée — un fond
                   très sombre SUBTIL, sans rebord ni ombre portée */
                background: rgba(20, 20, 22, .3);
                border-radius: 8px; padding: 14px; box-sizing: border-box; }
/* infobulle des barres (18/07) : survol souris ou appui maintenu mobile */
#st-tip { position: absolute; z-index: 140; pointer-events: none;
          background: #141416; border: 1px solid var(--bord);
          border-radius: 6px; padding: 4px 9px; font-size: 12.5px;
          color: var(--texte); white-space: nowrap;
          box-shadow: 0 6px 18px rgba(0, 0, 0, .5); }
/* même paire verticale, dans le COULOIR à droite du carré (hors graphique) */
#st-gauche .fl-nav { left: auto; right: 8px; }
#st-gauche #st-prec { top: calc(50% - 46px); }
#st-gauche #st-suiv { top: calc(50% + 6px); bottom: auto; }
/* compteur dans le couloir de droite, aligné sur le HAUT du graphe */
#st-compteur { position: absolute; right: 8px; left: auto; top: 62px; margin: 0;
               font-size: 13px; }
#st-droite { flex: 1; min-width: 0; display: flex; flex-direction: column;
             min-height: 0; padding: 60px 0 10px; }
/* le gabarit de la fiche, épuré : le TITRE comme celui d'un disque, puis
   ses commentaires — rien d'autre (17/07, retour utilisateur) */
#st-titre { font-family: var(--titres); font-weight: 400; font-size: 28px;
            line-height: 1.2; margin: 0 0 22px; }
#st-note { margin: 0; font-size: 14px; line-height: 1.65; max-width: 46ch; }
/* phrase d'analyse didactique + légende du graphique (18/07) — la zone
   flexible passe sur la légende pour garder le pied en bas */
#st-analyse { margin: 12px 0 0; font-size: 14px; line-height: 1.65;
              max-width: 46ch; color: var(--texte); }
#st-analyse:empty, #st-note:empty { margin: 0; }
#st-legende { flex: 1 1 auto; min-height: 0; margin: 14px 0 0;
              display: flex; flex-wrap: wrap; gap: 6px 14px;
              align-content: flex-start; max-width: 52ch; }
#st-legende:empty { margin: 0; }
.leg-item { display: inline-flex; align-items: center; gap: 6px;
            font-size: 12.5px; color: var(--sourd); white-space: nowrap; }
.leg-puce { width: 11px; height: 11px; border-radius: 3px; flex: none; }
.st-pied { flex: none; display: flex; align-items: center; gap: 14px;
           margin: 12px 0 0; }
.st-pied .bouton { width: auto; margin: 0; }
@media (max-width: 900px) {
  /* 20/07 (demande utilisateur) : pas de diapo sur mobile — on empile TOUTES
     les stats et la PAGE DÉFILE pour les voir. La diapo (#st-split) est masquée ;
     #st-slides est révélé par stats.js (hidden levé). Chaque stat montre son
     TITRE (::before data-titre), son graphique dimensionné, sa note/analyse. */
  #st-split { display: none; }
  #st-slides { display: block; }
  .st-slide { margin: 0 0 30px; }
  .st-slide::before { content: attr(data-titre); display: block;
    font-family: var(--titres); font-weight: 400; font-size: 20px;
    line-height: 1.2; margin: 4px 0 10px; }
  .st-slide svg { width: 100%; height: auto; display: block;
    background: rgba(20, 20, 22, .3); border-radius: 8px;
    padding: 12px; box-sizing: border-box; }
  .st-slide .aide, .st-slide .analyse { font-size: 13px; line-height: 1.6;
    margin: 8px 0 0; }
  .st-slide .st-legende-src { display: flex; flex-wrap: wrap; gap: 6px 14px;
    margin: 8px 0 0; }
}

/* --- nettoyage des donnees (fusion de vendeurs + historique) --- */
.liste-fusions { display: flex; flex-direction: column; gap: 10px; margin: 12px 0 26px; }
.carte-fusion { display: flex; align-items: center; justify-content: space-between;
                gap: 14px; flex-wrap: wrap; padding: 10px 14px;
                border: 1px solid var(--bord); border-radius: 10px; }
.fusion-variantes { display: flex; gap: 12px; flex-wrap: wrap; }
.fusion-variante { white-space: nowrap; }
/* 23/07 (passe multi-écrans) : un vendeur au nom long étirait chaque select à
   ~980px (2 côte à côte = débordement MÊME sur bureau) → borné + repli à la
   ligne. Le nom complet reste lisible dans la liste dépliée. */
.fusion-action { display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
                 min-width: 0; }   /* item flex : peut rétrécir (min-width:auto
                 propage sinon la largeur intrinsèque des selects, non bornée) */
.fusion-action select { margin: 0; width: auto; max-width: min(340px, 100%);
                        min-width: 0; }
.sync-oui { color: #7ac074; }
.sync-non { color: var(--sourd); }
.manip-detail { margin-top: 4px; }
/* 24/07 : case « mes dates ambiguës sont en JJ/MM/AAAA » (nettoyage des dates) */
.dates-jm { display: block; margin: 8px 0 2px; font-size: 13px; color: var(--texte); }
.dates-jm input { margin-right: 6px; vertical-align: middle; }
.manip-detail summary { cursor: pointer; font-size: 12px; }
.manip-detail ul { margin: 6px 0 0; padding-left: 18px; font-size: 13px; }
.manip-annulee td { opacity: 0.55; }

/* --- rapport de collection (une page, imprimable) --- */
.page-rapport { max-width: 720px; }
.page-rapport p { margin: 14px 0; font-size: 15px; line-height: 1.6; }
.stat-rapport { margin: 30px 0; text-align: center; }
.dash-vie .fiab { color: var(--sourd); text-decoration: none; }
.dash-vie .fiab:hover { color: var(--accent); }
@media print {
  .entete, .sans-impression { display: none !important; }
  body { background: #fff; color: #111; }
  .page-rapport p { color: #111; }
  .page-rapport .sourd { color: #555; }
}

/* --- pied de page + page a-propos --- */
/* 18/07 (capture annotée) : le lien « À propos » vit en BAS À DROITE */
footer.pied { max-width: none; margin: 40px 0 18px; padding: 0 26px;
              text-align: right; }
footer.pied a { color: var(--sourd); font-size: 12px; text-decoration: none; }
footer.pied a:hover { color: var(--accent); }
.apropos-carte { display: flex; gap: 34px; align-items: flex-start;
                 flex-wrap: wrap; margin-top: 22px; }
.apropos-camembert { flex: none; }
.apropos-version { font-family: var(--titres); font-size: 20px; margin: 0 0 4px; }
.jalons { list-style: none; margin: 12px 0 0; padding: 0; font-size: 14px; }
.jalons li { padding: 3px 0; color: var(--sourd); }
.jalons li.fait { color: var(--texte); }
.jalons .jalon-etat { display: inline-block; width: 18px; color: var(--accent); }

/* --- encart d'accueil (guide 4 etapes) --- */
.accueil-titre { font-family: var(--titres); font-size: 17px; margin: 0 0 10px; }
.etapes-accueil { margin: 0; padding-left: 22px; }
.etapes-accueil li { padding: 7px 0; display: flex; align-items: center;
                     justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.etapes-accueil li span:first-child { flex: 1 1 260px; }
.etapes-accueil li.fait { color: var(--sourd); }
.etapes-accueil li.fait span:first-child::after { content: " ✓"; color: #7ac074; }
.etapes-accueil form { margin: 0; }

/* --- section Compte des parametres --- */
.compte-liens { display: flex; gap: 12px; flex-wrap: wrap; margin: 12px 0 24px; }
.compte-lien { flex: 1 1 260px; display: flex; flex-direction: column; gap: 4px;
               padding: 12px 16px; border: 1px solid var(--bord);
               border-radius: 10px; text-decoration: none;
               background: rgba(255, 255, 255, 0.03); }
.compte-lien .fort { color: var(--texte); }
.compte-lien:hover { border-color: var(--accent); }
.compte-lien:hover .fort { color: var(--accent); }

/* --- passe mobile : nettoyage --- */
.table-roulante { overflow-x: auto; }
.table-roulante table { min-width: 640px; }
@media (max-width: 900px) {
  .carte-fusion { flex-direction: column; align-items: stretch; }
  .fusion-action { justify-content: space-between; }
}


/* --- mode edition en place de la fiche du feuilletage --- */
#fe-form { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px;
           margin-top: 10px; overflow-y: auto; min-height: 0; }
.fe-champ { display: flex; flex-direction: column; gap: 2px; margin: 0; }
.fe-champ > span { color: var(--sourd); font-size: 11px; }
.fe-champ input, .fe-champ select, .fe-champ textarea {
  width: 100%; background: rgba(20, 20, 22, 0.72); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 7px; padding: 6px 9px;
  /* famille EXPLICITE : « font: 13px/1.4 inherit » était invalide et
     laissait le textarea des notes en MONOSPACE (capture du 14/07) */
  font-family: inherit; font-size: 13px; line-height: 1.4; margin: 0; }
.fe-champ input:focus, .fe-champ select:focus, .fe-champ textarea:focus {
  outline: none; border-color: var(--accent); }
.fe-large { grid-column: 1 / -1; }
.fe-large textarea { resize: vertical; }
.fe-boutons { grid-column: 1 / -1; display: flex; align-items: center;
              gap: 10px; margin-top: 6px; flex-wrap: wrap; }
.fe-boutons .bouton { width: auto; margin: 0; padding: 8px 16px; font-size: 13px; }
.fe-plus { font-size: 12px; text-decoration: none; margin-left: auto; }
.fe-plus:hover { color: var(--accent); }
button.editer { background: none; border: none; cursor: pointer;
                font-size: inherit; padding: 0; color: inherit; }

/* --- mode edition : blocs etiquettes + clip integres (pas de 2e page) --- */
.fe-bloc { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 4px; }
.fe-bloc > span { color: var(--sourd); font-size: 11px; }
#fe-tags, #fe-clip { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
#fe-tags .tag { display: inline-flex; align-items: center; gap: 4px; }
.fe-tag-x { background: none; border: none; cursor: pointer; color: inherit;
            font-size: 10px; padding: 0 2px; opacity: .7; }
.fe-tag-x:hover { opacity: 1; }
/* 23/07 (capture utilisateur) : #fe-tag-choix RETIRÉ de ces règles héritées —
   la liste TAG suit EXACTEMENT les règles .fd-v-edit select des autres champs
   de la colonne (largeur/hauteur/padding homogènes à tous les breakpoints) */
#fe-tag-cat, #fe-tag-parent { width: auto; margin: 0; padding: 4px 8px;
  background: rgba(20, 20, 22, 0.72); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 7px; font-size: 12px; }
/* la ligne de création (nom + catégorie + « sous un genre » + OK) REVIENT À LA
   LIGNE : sinon le bouton OK débordait hors de la fiche (overflow:hidden) et
   restait inaccessible (20/07, bug utilisateur) */
#fe-tag-nouveau { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  flex-basis: 100%; }
#fe-tag-parent { max-width: 150px; }
#fe-tag-nom { width: 130px; margin: 0; padding: 4px 8px; font-size: 12px;
  background: rgba(20, 20, 22, 0.72); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 7px; }
#fe-tag-ok { padding: 4px 10px; font-size: 12px; margin: 0; width: auto; }
#fe-clip input[type=file] { font-size: 12px; border: none; background: none;
                            padding: 0; width: auto; }
.apercu-btn.statique { position: relative; }   /* sort du flux absolu, garde l'ancre du ＋ */

/* fiche en DEUX COLONNES de paires : tout tient sans defiler (14/07) */
@media (min-width: 901px) {
  .fd-grille { grid-template-columns: 92px 1fr 92px 1fr; gap: 6px 14px; }
}

/* --- le fond studio PARTOUT (14/07 : la transparence se constate ailleurs).
   18/07 : le fond quitte le background du body (background-attachment:
   fixed est IGNORÉ par les navigateurs mobiles — l'image bougeait pendant
   les balayages) pour un CALQUE position:fixed, immobile par nature. --- */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -1;
  background:
    linear-gradient(rgba(16, 16, 18, 0.80), rgba(16, 16, 18, 0.90)),
    url("/static/fond-repos.webp") center / cover no-repeat;
}
@media print { body::before { display: none; } }
.entete { background: rgba(20, 20, 22, 0.82);
          backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }

/* --- ZERO defilement dans la fiche (bureau) : tout est borne --- */
@media (min-width: 901px) {
  #fe-form { grid-template-columns: repeat(3, 1fr); gap: 6px 10px;
             overflow: hidden; }
  .fe-champ input, .fe-champ select, .fe-champ textarea { padding: 5px 8px;
             font-size: 12px; }
  .fe-champ > span, .fe-bloc > span { font-size: 10px; }
  .fe-boutons { margin-top: 4px; }
  .fe-boutons .bouton { padding: 6px 14px; font-size: 12px; }
  #fd-titre { overflow: hidden; }  /* 2 lignes titre/auteur, gérées par les spans */
  #fd-notes { display: -webkit-box; -webkit-line-clamp: 1;
              -webkit-box-orient: vertical; overflow: hidden; }
  /* 20/07 (revue) : plus de plafond 30px sur les tags additionnels — ils étaient
     rognés à ~1 rangée et INACCESSIBLES. Ils s'affichent tous ; si nombreux,
     c'est #fd-extra (overflow-y:auto dans le calage fixe) qui défile. */
  #fd-tags { max-height: none; }
  #fl-detail #fd-pistes { min-height: 0; }
}
@media (min-width: 901px) {
  #fd-tags { min-height: 0; }              /* la reservation 2 rangees battait max-height */
  #fd-sous { margin-bottom: 8px; }
  #fl-detail .fd-grille { margin-bottom: 8px; }
  #fl-detail { overflow: hidden; }          /* jamais de defilement en lecture */
}

/* --- schema « l'ont / le veulent » : barres face a face, chiffres dedans --- */
.fd-hw { display: flex; align-items: center; gap: 8px; margin: 4px 0 10px; }
.fd-hw-lib { color: var(--sourd); font-size: 10px; flex: none; }
.fd-hw-zone { flex: 1 1 0; display: flex; min-width: 0; }
.fd-hw-g { justify-content: flex-end; }   /* la barre « l'ont » pousse vers le centre */
.fd-hw-d { justify-content: flex-start; }
.fd-hw-barre { display: flex; align-items: center; padding: 0 7px;
               height: 18px; font-size: 11px; font-weight: 700;
               color: #141416; border-radius: 4px; min-width: 0;
               overflow: hidden; }
.fd-hw-g .fd-hw-barre { background: var(--vert); justify-content: flex-start;
                        border-radius: 9px 3px 3px 9px; }
.fd-hw-d .fd-hw-barre { background: var(--rouge); justify-content: flex-end;
                        border-radius: 3px 9px 9px 3px; }

/* blocs texte de la fiche legerement compactes (14/07) */
@media (min-width: 901px) {
  #fl-detail { font-size: 13px; }
  #fl-detail .fd-l { font-size: 11px; }
  #fl-detail .fd-grille { margin-bottom: 6px; gap: 4px 12px; }
  #fd-sous { margin-bottom: 6px; }
}

/* --- fiche bureau : UNE SEULE COLONNE (14/07), toujours sans defilement ---
   une paire libelle | valeur par ligne, interlignes minimaux */
@media (min-width: 901px) {
  .fd-grille { grid-template-columns: 96px 1fr; gap: 2px 12px; font-size: 12px; }
  #fl-detail { font-size: 12px; }
  #fl-detail .fd-l { font-size: 10.5px; }
  #fl-detail .fd-grille { margin-bottom: 5px; }
  .fd-grille-cw { margin-top: 4px; }
  .fd-hw { margin: 3px 0 7px; }
  #fd-titre { font-size: 15px; margin-bottom: 4px; }
  #fd-sous { margin-bottom: 5px; }
  #fd-tags { margin-bottom: 4px; }
  #fd-notes { margin: 0; }
}
@media (min-width: 901px) {
  /* chaque valeur tient sur UNE ligne (ellipse) : aucune rangee double */
  .fd-grille .fd-v { white-space: nowrap; overflow: hidden;
                     text-overflow: ellipsis; min-width: 0; }
  #fd-sous { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
@media (min-width: 901px) {
  /* libelles aussi sur UNE ligne (les traductions longues pliaient) */
  .fd-grille { grid-template-columns: 104px 1fr; }
  .fd-grille .fd-l { white-space: nowrap; overflow: hidden;
                     text-overflow: ellipsis; min-width: 0; }
  /* titre et notes : une ligne, garanti (nowrap bat les line-clamp captifs) */
  #fd-titre { display: block; white-space: nowrap; overflow: hidden;
              text-overflow: ellipsis; }
  #fd-notes { display: block; white-space: nowrap; overflow: hidden;
              text-overflow: ellipsis; }
}
/* barres l'ont/le veulent : sans texte, moitie de largeur, calees a gauche */
.fd-hw { width: 50%; }

/* --- fiche en TROIS colonnes (20/07, refonte) : HAUT = infos Discogs |
   coût/prix + tags | notes ; BAS = face A | face B | crédits/matrix. Colonnes
   1 & 2 ÉGALES, colonne 3 plus fine. Pochette à sa taille (on n'a pas rétréci
   #fl-gauche — ça rogne la pochette sur fenêtres hautes). --- */
#fd-colonnes { display: grid; grid-template-columns: 1fr 1fr 0.52fr;
               gap: 6px 18px; flex: none; align-items: start; }
#fd-principal { min-width: 0; display: flex; flex-direction: column; }
#fd-extra { min-width: 0; }
#fd-notes-col { min-width: 0; display: flex; flex-direction: column; min-height: 0; }
/* NOTES en ÉDITION (24/07) : sous la barre have/want, prennent toute la hauteur
   restante de la colonne. */
#fd-notes-edit-col { display: flex; flex-direction: column; min-height: 0; flex: 1; }
#fd-notes-edit-col .fd-notes-l { display: block; margin: 0 0 4px; }
#fd-notes-edit-col textarea { flex: 1; width: 100%; min-height: 90px; resize: none;
  box-sizing: border-box; font: inherit; font-size: 12px; line-height: 1.45;
  padding: 6px 8px; color: var(--texte); background: rgba(255, 255, 255, .05);
  border: 1px solid var(--bord); border-radius: 6px; }
/* 24/07 (capture utilisateur) : en ÉDITION, le corps est en DEUX panneaux —
   GAUCHE (infos + champs + tracklist) qui grandit, DROITE (have/want + notes)
   sur TOUTE LA HAUTEUR de la fiche (colonnes + tracklist). */
/* 24/07 (capture utilisateur) : en ÉDITION, la colonne NOTES (col3 de #fd-colonnes)
   remplit la hauteur de la ZONE DES COLONNES (align-self:stretch → suit la hauteur
   de la colonne des champs). La tracklist reste PLEINE LARGEUR en dessous
   (#fd-bas-zone, inchangée) → aucune compression des morceaux, aucun débordement. */
#fl-detail.edition #fd-notes-col { align-self: stretch; }
/* zone BASSE : mêmes 3 colonnes ; la tracklist occupe les 2 premières
   (face A | face B via .pistes-deux), les crédits/matrix la 3e. Prend le reste
   de la hauteur ; chaque zone défile en dernier recours. */
#fd-bas-zone { display: grid; grid-template-columns: 1fr 1fr 0.52fr;
               grid-template-rows: auto 1fr;
               gap: 6px 18px; flex: 1 1 auto; min-height: 0; margin-top: 10px; }
/* 22/07 (demande utilisateur) : bandeau « CRÉDITS ▾ » dans la 3e COLONNE (au-dessus
   de rien — les crédits DÉPLOYÉS restent en colonnes 1-2), calé à GAUCHE → aligné
   sur le bord gauche de la barre want/have (même colonne 3, mêmes gabarits de grille
   que la zone haute). min-height constant → la tracklist démarre à un Y CONSTANT. */
#fd-bas-tete { grid-column: 3; grid-row: 1; display: flex;
               justify-content: flex-start; align-items: center; min-height: 18px; }
.fd-cred-toggle { display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  background: none; border: none; padding: 1px 2px; color: var(--sourd);
  font-family: inherit; font-size: 11px; }
.fd-cred-toggle:hover, .fd-cred-toggle.ouvert { color: var(--texte); }
.fd-cred-toggle .fd-cred-lbl { text-transform: uppercase; letter-spacing: .05em; }
.fd-cred-toggle .fd-cred-flg { font-size: 13px; line-height: 1; }
/* 22/07 (demande utilisateur) : tracklist ET crédits dans la MÊME zone GAUCHE
   (colonnes 1-2 UNIQUEMENT — jamais la 3e), empilés. #fd-bas-gauche défile en
   dernier recours ; placerCredits() choisit « sous les morceaux » vs « repli +
   flèche » selon la place. La 3e colonne de la zone basse reste vide. */
#fd-bas-gauche { grid-column: 1 / 3; grid-row: 2; display: flex; flex-direction: column;
                 gap: 10px; min-width: 0; min-height: 0; overflow-y: auto;
                 scrollbar-width: none; }
#fd-bas-gauche::-webkit-scrollbar { display: none; }
/* dans la zone gauche la tracklist montre tout son contenu (c'est #fd-bas-gauche
   qui défile) — on neutralise le max-height/scroll propre de #fd-pistes. */
#fl-detail #fd-bas-gauche #fd-pistes { max-height: none; min-height: 0;
                                       overflow: visible; flex: none; }
/* 20/07 : un SINGLE (une seule colonne, bureau) reste ~demi-largeur — les temps se
   justifient près du titre, pas au bord lointain des 2 colonnes. */
@media (min-width: 901px) {
  #fd-bas-gauche #fd-pistes.pistes-simple { max-width: calc(50% - 9px); }
}
/* 23/07 (retour utilisateur iPad) : entre 901 et 1279px la fiche est trop étroite
   pour SCINDER la tracklist en 2 colonnes (face A | face B) — les titres étaient
   écrasés (~27px) et wrappaient sur 3-5 lignes (« aberrations visuelles »). On
   repasse en UNE colonne pleine largeur : .pistes-deux s'empile (bloc), et le
   .pistes-simple n'est plus capé à 50%. Le 2-colonnes ne s'applique qu'à ≥1280px. */
@media (min-width: 901px) and (max-width: 1279px) {
  #fl-detail #fd-bas-gauche #fd-pistes.pistes-deux { display: block; }
  #fl-detail #fd-bas-gauche #fd-pistes.pistes-simple { max-width: none; }
}
/* 22/07 : crédits sur DEUX COLONNES MAX (grille 2 col) dans la zone gauche.
   Masqués par défaut (attribut hidden → la garde globale [hidden] !important
   gagne) ; placerCredits() les révèle sous les morceaux ou au déploiement. */
#fd-credits { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px;
              align-content: start; min-width: 0; font-size: 12px; line-height: 1.5;
              color: var(--texte); }   /* 22/07 : crédits/matrix au blanc des infos release (#ede4d8) */
#fd-credits .fd-cred-bloc { min-width: 0; }
/* 24/07 : Companies/Matrix/Notes empilés (colonne gauche) | Credits (colonne
   droite) → plus de trou entre Companies et Notes. */
#fd-credits .fd-cred-col { min-width: 0; }
#fd-credits .fd-notes-t { color: var(--sourd); }   /* les libellés restent muets */
#fd-credits::-webkit-scrollbar { display: none; }
.fd-cred-bloc { margin: 0 0 10px; white-space: pre-wrap; }
/* 20/07 (demande utilisateur) : la barre have/want vit dans la COLONNE 3, AU
   DESSUS des notes — position FIXE (elle ne « danse » plus d'une fiche à
   l'autre) ; pleine largeur de la colonne, calée en haut. */
/* 22/07 (demande utilisateur) : une ligne de vide entre la barre want/have et les
   notes utilisateur → marge basse 12 → 30px (~une ligne de plus). */
#fl-detail #fd-notes-col .fd-hw { width: 100%; margin: 0 0 30px; }
@media (max-width: 900px) { #fl-detail #fd-notes-col .fd-hw { margin-top: 12px; } }
/* 20/07 : le sélecteur d'ajout d'étiquette vit sur UNE RANGÉE « TAG | liste »
   (classe .fd-grille pour aligner label/valeur comme les champs au-dessus) ; la
   liste déroulante prend le graphisme .fd-v-edit (identique à Canal/Devise) ; les
   chips (tags posés) sont dessous. */
/* 23/07 (capture « homogène ») : le choix TAG n'a PLUS de boîte propre — il
   EST un .fd-v-edit select et suit LEURS règles (padding/hauteur/fond/focus)
   à tous les breakpoints ; on ne force que la pleine largeur de la cellule. */
.fd-v-edit #fe-tag-choix { width: 100%; height: auto; margin: 0; }
/* 23/07 (capture « homogène ») : LA CAUSE RACINE du TAG plus étroit — la
   rangée est un enfant FLEX de #fe-tags, sa largeur suivait la plus LONGUE
   OPTION du menu (intrinsèque) au lieu de la colonne → pleine largeur forcée */
.fe-tag-ajout { flex-basis: 100%; min-width: 0; }
.fe-tag-chips { display: flex; flex-wrap: wrap; gap: 4px 5px; margin-top: 6px; }
.fe-tag-chips:empty { margin: 0; }
@media (max-width: 900px) {
  /* mobile : tout s'empile sur une seule colonne */
  #fd-colonnes, #fd-bas-zone { display: block; }
  #fd-pistes, #fd-credits { overflow: visible; }
  /* 22/07 : crédits EMPILÉS (une colonne) sur mobile ; la zone gauche et le
     bandeau passent en flux (la page défile). */
  #fd-credits { grid-template-columns: 1fr; }
  #fd-bas-gauche { overflow: visible; }
  #fd-bas-tete { margin-bottom: 4px; }
}
@media (min-width: 901px) {
  /* 23/07 : le bloc notes S'ÉTEND sous sa colonne (la col3 de la zone basse est
     libre depuis le départ du bandeau + INFO) — flex:none + max-height posé par
     calerNotes() jusqu'au bas de la fiche ; défile en interne au-delà. Le
     conteneur #fd-notes-col reste capé (calage constant de la tracklist) et
     laisse déborder (overflow visible par défaut) ; position relative + z-index
     pour passer AU-DESSUS de #fd-bas-zone (peinture ET molette). */
  #fd-notes-col #fd-notes { flex: none; min-height: 0; overflow-y: auto;
                            -webkit-line-clamp: unset; scrollbar-width: none;
                            white-space: pre-wrap; display: block;
                            position: relative; z-index: 5; }
  #fd-notes-col #fd-notes::-webkit-scrollbar { display: none; }
  /* 20/07 (demande utilisateur) : en LECTURE, la zone HAUTE a une HAUTEUR FIXE
     → la tracklist et les crédits (zone basse) commencent TOUJOURS à la même
     hauteur, quel que soit le disque : les textes ne « dansent » plus d'une
     fiche à l'autre. Chaque colonne se cale en haut (stretch) et défile en
     secours ; dans la colonne 1 la grille défile mais le ruban have/want reste
     épinglé en bas (jamais rogné). SCOPÉ À LA LECTURE (:not(.edition)) :
     l'édition, avec ses 10+ champs, garde son flux naturel. La HAUTEUR FIXE
     elle-même est gardée par min-height:700px (bloc plus bas) — sur une fenêtre
     BASSE le carré devient trop court pour 250px et rognerait la zone basse. */
  /* 21/07 : la grille contribue sa hauteur NATURELLE (grow-to-fit) — un disque
     à 6-7 styles ÉTIRE #fd-colonnes (via min-height plus bas) au lieu de rogner
     ses chips. Les notes (col3) et col2, elles, DÉFILENT sans étirer la rangée. */
  #fl-detail:not(.edition) #fd-principal { min-height: 0; overflow: visible; }
  #fl-detail:not(.edition) #fd-principal .fd-grille { flex: none; overflow: visible; }
  #fl-detail:not(.edition) #fd-principal .fd-hw { flex: none; }
  #fl-detail:not(.edition) #fd-extra { min-height: 0; overflow-y: auto;
                             scrollbar-width: none; }
  #fl-detail:not(.edition) #fd-extra::-webkit-scrollbar { display: none; }
}
/* min-height 210px (au lieu d'une hauteur FIXE) : la zone haute démarre à 210
   → le bloc bas (tracklist/crédits) REMONTE de ~2 lignes vs les 250px d'avant
   (demande utilisateur 21/07) et reste à hauteur CONSTANTE pour l'immense
   majorité des disques (grille ≤ 152px). Les rares disques à 6-7 styles (grille
   jusqu'à ~230px) ÉTIRENT la rangée au lieu de rogner leurs chips — un léger jeu
   sur ces disques, préférable à des styles cachés. Actif seulement en fenêtre
   assez HAUTE (seuil 700px) : plus bas, le carré est trop court et la fiche
   entière défile (bloc max-height:699px). */
@media (min-width: 901px) and (min-height: 700px) {
  #fl-detail:not(.edition) #fd-colonnes { min-height: 210px; align-items: stretch; }
  /* col2 (tags) et col3 (have/want + notes) ne doivent PAS étirer la rangée :
     capées à 210, leur trop-plein DÉFILE (overflow:auto posé plus haut). Seule la
     grille (col1) peut faire grandir #fd-colonnes — un disque à beaucoup de styles
     s'étire au lieu de rogner ses chips ; les notes longues, elles, défilent. */
  #fl-detail:not(.edition) #fd-extra,
  #fl-detail:not(.edition) #fd-notes-col { max-height: 210px; }
}
/* FENÊTRE BASSE (< 700px de haut) : le calage fixe ne tiendrait pas dans le
   carré → on rend #fd-colonnes à sa hauteur naturelle et on laisse la FICHE
   ENTIÈRE défiler (une seule barre, cachée) au lieu de rogner la zone basse
   SANS défilement possible (#fl-detail est overflow:hidden en lecture). */
@media (min-width: 901px) and (max-height: 699px) {
  #fl-detail:not(.edition) { overflow-y: auto; }
  #fl-detail:not(.edition) #fd-colonnes { height: auto; align-items: start; }
  #fl-detail:not(.edition) #fd-bas-zone { flex: none; }
  #fl-detail:not(.edition) #fd-principal,
  #fl-detail:not(.edition) #fd-principal .fd-grille,
  #fl-detail:not(.edition) #fd-extra,
  #fl-detail:not(.edition) #fd-bas-gauche,
  #fl-detail:not(.edition) #fd-pistes,
  #fl-detail:not(.edition) #fd-credits { overflow: visible; }
}

/* --- typographie HOMOGENE du mode edition (capture utilisateur 14/07) :
   une seule famille (celle du site) et une seule taille pour TOUS les
   controles — champs, selecteurs, zone notes, boutons, fichier --- */
#fe-form input, #fe-form select, #fe-form textarea, #fe-form button {
  font-family: inherit; font-size: 12px; line-height: 1.4; }
#fe-form .fe-champ > span, #fe-form .fe-bloc > span {
  font-family: inherit; font-size: 10.5px; letter-spacing: .02em; }
#fe-tag-cat, #fe-tag-nom, #fe-tag-parent { padding: 5px 8px; height: 28px; }
#fe-tag-ok { height: 28px; padding: 0 12px; }
#fe-clip input[type=file] { color: var(--sourd); }
#fe-clip input[type=file]::file-selector-button {
  font-family: inherit; font-size: 12px; background: transparent;
  color: var(--texte); border: 1px solid var(--bord); border-radius: 7px;
  padding: 4px 12px; margin-right: 10px; cursor: pointer; }
#fe-clip input[type=file]::file-selector-button:hover {
  border-color: var(--accent); color: var(--accent); }
#fe-form .fe-boutons .bouton { font-family: inherit; font-size: 12px;
  padding: 7px 16px; border-radius: 7px; }
/* le format est une ligne de la grille (blanc, aligne) sur bureau :
   la sous-ligne grise ne sert plus qu'au mobile (fiche repliee) */
@media (min-width: 901px) {
  #fd-sous { display: none; }
}
/* respiration entre les infos et les titres du disque (14/07) */
@media (min-width: 901px) {
  #fd-principal #fd-pistes { margin-top: 18px; padding-top: 8px; }
}

/* --- ruban have/want v3 (14/07) : UNE barre calee a gauche, partagee
   vert | rouge au prorata, chiffres dedans ; 50/50 avec 0|0 sans infos --- */
.fd-hw { display: flex; align-items: stretch; gap: 1px; }
.fd-hw-g, .fd-hw-d { display: flex; align-items: center; justify-content: center;
  height: 18px; font-size: 11px; font-weight: 700; color: var(--texte);
  padding: 0 6px; min-width: 0; overflow: hidden; }
/* couleurs en SOURDINE (23/07, capture « MUTE ») : vert/rouge désaturés,
   fondus dans la palette du site — chiffres en clair pour rester lisibles */
.fd-hw-g { background: #55704f; border-radius: 9px 0 0 9px; flex: none;
           box-sizing: border-box; }
.fd-hw-d { background: #83544e; border-radius: 0 9px 9px 0; flex: 1 1 0; }

/* --- edition EN MIROIR (14/07) : les champs remplacent les valeurs
   exactement a leur place dans la grille de droite --- */
.fd-v-edit { overflow: visible !important; }
/* --- mode ÉDITION : champs PROPRES et DISCRETS (20/07, demande utilisateur —
   « peu visible par son élégance ») : fond translucide très léger, bordure
   douce, coins arrondis, transition ; focus = accent net + halo subtil. --- */
.fd-v-edit input, .fd-v-edit select, .fd-v-edit textarea {
  width: 100%; color: var(--texte); font-family: inherit; margin: 0;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.13); border-radius: 6px;
  font-size: 12px; line-height: 1.5;
  transition: border-color .15s, background .15s, box-shadow .15s; }
.fd-v-edit input, .fd-v-edit select { padding: 3px 8px; }
.fd-v-edit input:hover, .fd-v-edit select:hover,
.fd-v-edit textarea:hover { border-color: rgba(255, 255, 255, 0.24); }
.fd-v-edit input:focus, .fd-v-edit select:focus, .fd-v-edit textarea:focus {
  outline: none; border-color: var(--accent);
  background: rgba(255, 255, 255, 0.08);
  box-shadow: 0 0 0 2px rgba(242, 236, 223, .12); }
.fd-v-edit textarea { padding: 5px 8px; margin: 6px 0 0; resize: vertical; }
/* R1 (20/07, demande utilisateur) : la saisie des notes est AÉRÉE — un titre
   « NOTES » (comme en lecture) puis une grande zone de texte. */
.fd-notes-l { display: block; margin: 12px 0 4px; }
.fd-notes-edit { margin: 0; }
.fd-notes-edit textarea { min-height: 104px; margin-top: 0; }
/* R2 (20/07) : légende sous « Choisir un fichier » (extrait audio) */
.fd-clip-aide { display: block; margin-top: 5px; font-size: 11px; line-height: 1.4; }
.fd-tags-edit { min-height: 0; max-height: none !important;
                overflow: visible !important; margin-top: 8px; }
.fd-clip-edit { display: flex; align-items: center; gap: 8px; margin-top: 8px;
                font-size: 12px; }
.fd-clip-edit input[type=file] { font-family: inherit; font-size: 12px;
  color: var(--sourd); border: none; background: none; padding: 0; width: auto; }
.fd-clip-edit input[type=file]::file-selector-button {
  font-family: inherit; font-size: 12px; background: transparent;
  color: var(--texte); border: 1px solid var(--bord); border-radius: 7px;
  padding: 3px 10px; margin-right: 8px; cursor: pointer; }
#fd-extra .fe-boutons { margin-top: 10px; }
/* le mode édition DÉFILE (#fl-detail.edition overflow-y:auto) → les champs
   respirent (élégance, 20/07) au lieu d'être tassés pour tenir dans le carré */
.fd-v-edit input, .fd-v-edit select { padding: 2px 8px; font-size: 12px; }
#fd-extra .fd-tags-edit #fe-tags { gap: 4px 5px; }
.fd-tags-edit .tag { font-size: 10px; padding: 1px 6px; }
#fe-tag-cat, #fe-tag-parent { height: 22px; padding: 1px 5px; font-size: 11px; }
#fe-tag-nom { height: 22px; padding: 1px 6px; font-size: 11px; width: 100px; }
#fe-tag-ok { height: 22px; padding: 0 9px; font-size: 11px; }
.fd-v-edit textarea { margin-top: 4px; padding: 4px 8px; font-size: 12px; }
.fd-clip-edit { margin-top: 5px; }
#fd-extra .fe-boutons { margin-top: 7px; }
#fd-extra .fe-boutons .bouton { padding: 5px 13px; font-size: 12px; }
.fd-tags-edit { margin-top: 6px; }

/* --- reglages fins du 14/07 (retours utilisateur) --- */
@media (min-width: 901px) {
  /* ecart entre la derniere ligne d'infos et le ruban (16/07 : accentue,
     capture annotee — le ruban et les etiquettes descendent ensemble) */
  .fd-hw { margin-top: 24px; }
  /* les etiquettes de la colonne droite descendent d'autant : elles restent
     alignees avec le ruban (les deux grilles ont le meme nombre de lignes) */
  #fd-extra #fd-tags { margin-top: 24px; }
  /* les titres du disque : encore plus ecartes, et texte agrandi */
  #fd-principal #fd-pistes { margin-top: 28px; font-size: 13.5px; }
  #fd-principal #fd-pistes .sourd { font-size: 12px; }
  /* titre principal de chaque disque agrandi */
  #fd-titre { font-size: 19px; }
  /* respiration sous le bloc titre/auteur avant les grilles (16/07) */
  #fd-titre, .expl-fiche-titre { margin-bottom: 22px; }
  /* ecart AGRANDI entre les etiquettes du disque et les notes (18/07) */
  #fd-extra #fd-notes { margin-top: 22px; }
}

/* --- notes EN ENTIER (14/07) : le texte se deroule, plus d'ellipse ;
   18/07 : les SAUTS DE LIGNE saisis sont respectes (pre-wrap) --- */
@media (min-width: 901px) {
  #fd-notes { white-space: pre-wrap; display: block; overflow: visible;
              text-overflow: clip; }
}
/* mode EDITION de la fiche (18/07) : interlignes compactes pour que tout
   tienne SANS defiler — les boutons Enregistrer/Annuler restent visibles
   (la respiration de lecture ajoutee le 16/07 debordait en edition) */
@media (min-width: 901px) {
  /* 19/07 (zone coupée signalée) : en édition la fiche prend TOUTE la hauteur
     (l'alignement sur le carré est retiré côté JS) et DÉFILE en dernier
     recours — les boutons du bas ne sont plus coupés ni sous « À propos » */
  #fl-detail.edition { overflow-y: auto; }
  #fl-detail.edition #fd-titre { margin-bottom: 8px; }
  #fl-detail.edition .fd-hw { margin-top: 9px; }
  #fl-detail.edition #fd-extra #fd-tags { margin-top: 6px; }
  #fl-detail.edition #fd-principal #fd-pistes { margin-top: 10px; }
  #fl-detail.edition .fd-grille { gap: 2px 12px; margin-bottom: 4px; }
  #fl-detail.edition #fd-extra .fe-boutons { margin-top: 6px; }
}
/* fenetre confortable : les blocs d'edition S'ECARTENT verticalement
   (18/07, capture annotee « ecarter » — chips / ajout / notes / clip /
   boutons respirent vers le bas, la colonne a la place) */
@media (min-width: 901px) and (min-height: 821px) {
  #fl-detail.edition #fd-extra #fd-tags,
  #fl-detail.edition .fd-tags-edit { margin-top: 18px; }
  #fl-detail.edition #fe-tags { row-gap: 10px; }
  /* le sélecteur TAG vit dans une rangée de grille (label | valeur) : il
     remplit la cellule, comme les autres selects (plus de flex-basis/max-width) */
  #fl-detail.edition .fd-v-edit #fe-tag-choix { flex-basis: auto; max-width: none; }
  #fl-detail.edition .fd-v-edit textarea { margin-top: 16px; }
  #fl-detail.edition .fd-clip-edit { margin-top: 15px; }
  #fl-detail.edition #fd-extra .fe-boutons { margin-top: 20px; }
}
/* fenetre basse : l'edition se compacte encore (l'edition DÉFILE, donc les notes
   gardent une taille correcte — plus de plafond 44px qui les écrasait, 20/07) */
@media (min-width: 901px) and (max-height: 760px) {
  #fl-detail.edition .fd-notes-edit textarea { min-height: 70px; }
  #fl-detail.edition .fd-tags-edit { max-height: 56px; overflow: hidden; }
  #fl-detail.edition .fd-v-edit input, #fl-detail.edition .fd-v-edit select {
    padding: 0 5px; font-size: 11px; }
  #fl-detail.edition .fd-clip-edit { margin-top: 2px; }
}
/* --- pastille boutique du titre : vert = en vente sur la boutique --- */
.fd-pastille { display: inline-block; width: 9px; height: 9px;
  border-radius: 50%; margin-left: 9px; vertical-align: middle;
  background: transparent; border: 1px solid var(--bord); }
/* 18/07 (capture « blanc ») : la pastille « en vente » est BLANCHE */
.fd-pastille.en-vente { background: #f2ecdf; border-color: #f2ecdf; }
/* 20/07 : en vente, la pastille est un LIEN vers la boutique — curseur main,
   pas de soulignement (le cercle est vide) ; léger effet au survol */
a.fd-pastille { cursor: pointer; text-decoration: none; padding: 0; }
a.fd-pastille.en-vente:hover { box-shadow: 0 0 0 2px rgba(242, 236, 223, .35); }

/* --- titre double + morceaux agrandis + credits + partie basse (14/07) ---
   16/07 : titre reduit de 25 % (38 -> 28px) et passe en DEUX lignes */
@media (min-width: 901px) {
  /* la fiche du visiteur suit la même montée en taille : c'est ici que se joue le
     titre à 28 px, et l'oublier laissait l'explorer à la valeur de base, 16 px —
     l'écart le plus visible entre les deux pages (31/07). */
  #fd-titre, .expl-fiche-titre { font-size: 28px; line-height: 1.2; }
  #fd-principal #fd-pistes { font-size: 15px; }
  #fd-principal #fd-pistes .sourd { font-size: 12.5px; }
}
/* credits d'un morceau : sous le titre (aligné via .fd-piste-corps, plus
   d'indent artificiel), discret ; PEUT wrapper sur plusieurs lignes puisque
   rien n'est à sa droite (20/07, demande utilisateur — plus d'ellipse) */
.fd-piste-cred { display: block; font-size: 11px; line-height: 1.35;
  margin: 1px 0 3px; white-space: normal; }
/* étiquette(s) du NOM DU SET (22/07) : un morceau dans un set DJ. Bloc SOUS le
   titre (ne serre pas la ligne du titre). BLANCHE pour l'instant (couleur
   définissable plus tard, demande utilisateur). */
.fd-piste-sets { display: flex; flex-wrap: wrap; gap: 4px; margin: 2px 0 3px; }
.fd-piste-set { font-size: 10px; line-height: 1.5; padding: 0 7px;
  background: #f2ecdf; color: #141416; border-radius: 8px; max-width: 100%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* étiquettes PAR MORCEAU (19/07) : petites chips À LA SUITE du titre,
   sur la ligne principale (avant le temps justifié à droite) ; ✕ en édition */
.fd-piste-tags { flex: none; display: inline-flex; flex-wrap: wrap; gap: 4px;
                 margin-left: 6px; }
/* 23/07 (demande utilisateur) : quand le morceau a des INFORMATIONS (crédits),
   ses tags passent SOUS la ligne du titre — le texte reste propre */
.fd-piste-tags-bas { display: flex; margin: 2px 0 1px; }
.tag-piste { display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; padding: 0 6px; border-radius: 999px; border: 1px solid;
  vertical-align: middle; }
.fd-pt-x { background: none; border: none; cursor: pointer; color: inherit;
  font-size: 9px; line-height: 1; padding: 0; opacity: .7; }
.fd-pt-x:hover { opacity: 1; }
/* ligne de morceau = cible de dépôt d'un tag glissé (édition) */
.fd-piste.piste-cible { outline: 1px dashed var(--accent); outline-offset: 2px;
  border-radius: 4px; }
/* cible d'un GLISSER-DÉPOSER de fichier audio depuis l'ordinateur (24/07) */
.fd-piste.piste-audio-cible { outline: 2px dashed var(--accent); outline-offset: -2px;
  background: rgba(242, 236, 223, .09); border-radius: 6px; }
/* partie basse : credits / matrix / notes de la fiche Discogs */
/* partie basse REPLIÉE (18/07) : seuls les intitulés restent — cliquer en
   déplie un, la tracklist garde la priorité de l'espace */
/* 19/07 (demande utilisateur) : plus de trait séparatif au-dessus des
   crédits en vue release — un simple espace suffit */
#fd-bas { flex: none; margin-top: 12px; padding-top: 0;
          border-top: none; font-size: 11px;
          color: var(--sourd); }
#fd-bas-onglets { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; }
.fd-bas-onglet { background: none; border: none; padding: 0; cursor: pointer;
                 color: var(--sourd); font-size: 11px; font-weight: 700;
                 font-family: inherit; }
.fd-bas-onglet::after { content: " ▾"; font-weight: 400; }
.fd-bas-onglet:hover { color: var(--texte); }
.fd-bas-onglet.actif { color: var(--accent); }
.fd-bas-onglet.actif::after { content: " ▴"; }
#fd-bas-contenu { margin: 4px 0 0; display: -webkit-box; -webkit-line-clamp: 3;
                  -webkit-box-orient: vertical; overflow: hidden; }
#fd-bas-contenu[hidden] { display: none; }

/* --- format entre parentheses a la suite du titre + pastilles (14/07) ---
   16/07 : le format passe A LA TAILLE DU TITRE, les pastilles (etat + boutique)
   sont agrandies a la meme echelle */
.fd-titre-format { font-size: 1em; color: var(--sourd); margin-left: 12px;
                   font-weight: 400; vertical-align: 0; }
/* dans le titre de la fiche : MÊME format que la boutique (18/07) */
#fd-titre .picto { font-size: 10px; height: 18px; min-width: 26px;
                   padding: 0 4px; vertical-align: middle; margin-left: 10px; }
#fd-titre .fd-pastille { width: 0.5em; height: 0.5em; vertical-align: middle;
                         margin-left: 12px; }

/* --- mode « Explorer » (démo publique lecture seule, 25/07) --- */
.explorer-page .conteneur { display: flex; flex-direction: column; }
.expl-tete { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
             flex: none; padding: 4px 0 14px; }
.expl-titre { font-family: var(--titres); font-size: 22px; }
.expl-intro { font-size: 13px; flex: 1 1 240px; }
.expl-tete .bouton { flex: none; }
.expl-split { flex: 1 1 auto; min-height: 0; display: flex; gap: 38px;
              align-items: stretch; }
.expl-gauche { flex: 0 0 42%; position: relative; overflow: hidden;
               display: flex; align-items: center; justify-content: center; }
.expl-scene { display: flex; align-items: center; justify-content: center;
              width: 100%; height: 100%; }
.expl-cover { width: min(62vh, 40vw, 640px); aspect-ratio: 1 / 1;
              box-shadow: 0 14px 40px rgba(0, 0, 0, .5); background: #0b0b0d; }
.expl-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.expl-cover img.expl-flip { cursor: pointer; }
.expl-nav { position: absolute; z-index: 10; right: 6px; top: 50%;
            transform: translateY(-50%); display: flex; flex-direction: column;
            align-items: center; border: 1px solid var(--bord); border-radius: 20px;
            background: rgba(20, 20, 22, .55); padding: 4px 0; }
.expl-fleche { background: none; border: none; color: var(--texte); cursor: pointer;
               font-size: 17px; line-height: 1; padding: 4px 8px; }
.expl-fleche:hover { color: var(--accent); }
.expl-nav-trait { height: 1px; width: 18px; background: var(--bord); margin: 2px 0; }
.expl-compteur { position: absolute; top: 6px; left: 8px; font-size: 12px;
                 font-variant-numeric: tabular-nums; }
.expl-droite { flex: 1; min-width: 0; }
.expl-fiche { height: 100%; overflow-y: auto; scrollbar-width: none;
              padding-right: 4px; }
.expl-fiche::-webkit-scrollbar { display: none; }
.expl-fiche-titre { margin-bottom: 18px; }
.expl-t1 { display: block; font-family: var(--titres); font-size: 28px;
           line-height: 1.05; }
.expl-ta { display: block; font-size: 16px; color: var(--sourd); margin-top: 6px; }
.expl-marche { display: flex; align-items: center; gap: 12px; margin: 16px 0; }
.expl-hw { display: flex; width: 60%; min-width: 220px; border-radius: 6px;
           overflow: hidden; font-size: 12px; font-weight: 700; }
.expl-hw-g, .expl-hw-d { padding: 5px 9px; color: var(--texte); white-space: nowrap; }
.expl-hw-g { background: #55704f; text-align: left; }
.expl-hw-d { background: #83544e; text-align: right; }
.expl-hype { font-size: 12.5px; color: var(--accent); white-space: nowrap; }
.expl-pistes { margin-top: 8px; }
.expl-piste { display: flex; align-items: baseline; gap: 10px; padding: 3px 0;
              font-size: 14px; }
.expl-piste-rep { color: var(--sourd); font-size: 11.5px; min-width: 26px; flex: none; }
.expl-piste-titre { flex: 1 1 auto; min-width: 0; overflow: hidden;
                    text-overflow: ellipsis; white-space: nowrap; }
.expl-piste-temps { color: var(--sourd); font-size: 12.5px; flex: none;
                    font-variant-numeric: tabular-nums; }

@media (max-width: 900px) {
  body.explorer-page.plein { height: auto; overflow: auto; }
  .expl-split { flex-direction: column; gap: 18px; }
  .expl-gauche { flex: none; }
  .expl-cover { width: min(86vw, 54vh); }
  .expl-nav { display: none; }
  .expl-fiche { height: auto; overflow: visible; }
}

/* ===== FOND VIVANT (jalon platine 3D) =======================================
   Quand un morceau joue, le disque TOURNE et le bras AVANCE dans le fond.
   Trois couches rendues sous la MEME camera Blender -> calees par construction :
   image de fond + video du plateau (boucle) + video du bras (positionnee).
   Le calque remplace body::before, sinon on aurait deux fonds superposes.
   Actif seulement si le drapeau window.CW_FOND_VIVANT est pose (fond-vivant.js). */
body.fond-vivant::before { display: none; }
#cw-fond-vivant { position: fixed; inset: 0; z-index: -1; pointer-events: none;
                  overflow: hidden; }
#cw-fond-vivant > * { position: absolute; inset: 0;
                      width: 100%; height: 100%; object-fit: cover; }
/* meme voile que le fond d'origine, pour garder la lisibilite du texte */
#cw-fond-vivant .fv-voile {
  background: linear-gradient(rgba(16, 16, 18, 0.80), rgba(16, 16, 18, 0.90)); }
body.plein #cw-fond-vivant .fv-voile {
  background: linear-gradient(rgba(16, 16, 18, 0.60), rgba(16, 16, 18, 0.86)); }
/* FONDU CROISE entre les quatre fonds (29/07). Deux <img> superposees : celle qui
   arrive monte en opacite pendant que l'autre descend. 420 ms -- assez long pour que
   l'oeil ne saisisse pas la difference de decor, assez court pour rester discret.
   Coupe si l'utilisateur demande moins d'animation. */
/* EMPILEMENT EXPLICITE des cinq calques. Il le faut depuis que le fondu donne un
   z-index a l'image entrante : sans ces valeurs, elle passerait AU-DESSUS des
   videos du plateau et du bras (un element a z-index chiffre bat tous ceux qui
   sont en `auto`, quel que soit l'ordre dans le document). De bas en haut :
   ancien fond < nouveau fond < plateau < bras < voile. */
#cw-fond-vivant .fv-fond  { transition: opacity .42s ease; z-index: 0; }
#cw-fond-vivant .fv-spin  { z-index: 2; }
/* L'ETIQUETTE s'intercale entre le plateau et le bras : elle est posee SUR le
   disque, mais le bras doit passer par-dessus elle. Elle est ronde (c'est une
   etiquette) et n'intercepte aucun clic. */
/* l'enveloppe de l'etiquette : plein cadre, en espace ECRAN — c'est elle qui
   porte le masque du trou (fixe a l'ecran, l'image tourne dedans) */
#cw-fond-vivant .fv-label-zone { position: absolute; inset: 0; z-index: 3;
  pointer-events: none; }
#cw-fond-vivant .fv-label { z-index: 3; border-radius: 50%;
                            pointer-events: none; object-fit: cover;
                            width: auto; height: auto; }
#cw-fond-vivant .fv-bras  { z-index: 4; }
#cw-fond-vivant .fv-fader { z-index: 4; }
#cw-fond-vivant .fv-voile { z-index: 5; }
/* L'ENTREE : au-dessus des fonds et des couches, sous le voile. Elle s'efface sur son
   image finale, qui EST deja le fond de repos -- d'ou un fondu tres court : il ne
   masque pas un changement d'image, seulement la bascule d'une video a une image. */
#cw-fond-vivant .fv-entree { z-index: 4; transition: opacity .38s ease; }
@media (prefers-reduced-motion: reduce) {
  #cw-fond-vivant .fv-fond { transition: none; } }
@media print { #cw-fond-vivant { display: none; } }

/* FLUIDITÉ du fond vivant : on isole chaque couche dans son propre plan de
   composition GPU (translateZ + will-change) — sans cela, une image de vidéo
   qui change peut forcer le navigateur à repeindre une partie de la page.
   `contain: paint` lui promet en plus que rien ne déborde du calque. */
#cw-fond-vivant { contain: paint; }
#cw-fond-vivant > * { transform: translateZ(0); backface-visibility: hidden; }
#cw-fond-vivant .fv-spin, #cw-fond-vivant .fv-bras { will-change: transform; }

/* ── OUTIL DE CALAGE DE L'ÉTIQUETTE (29/07) ────────────────────────────────
   Le fond de rendu (1668×943) est affiché à la largeur disponible ; l'étiquette
   et ses poignées sont posées PAR-DESSUS, dans le même repère, à la même
   échelle. `aspect-ratio` réserve la place avant que l'image ne soit chargée :
   sans lui, la scène ferait 0 de haut au premier calcul et les poignées se
   dessineraient hors champ. */
#cal-barre { display: flex; flex-wrap: wrap; gap: 18px 26px; align-items: center;
             margin: 14px 0 12px; }
#cal-barre label { display: flex; align-items: center; gap: 8px;
                   font-size: 12.5px; color: var(--sourd); }
#cal-barre input[type="range"] { width: 150px; }
#cal-barre .cal-val { font-variant-numeric: tabular-nums; min-width: 46px;
                      color: var(--texte); }
#cal-barre .cal-case { gap: 6px; }
#cal-scene { position: relative; width: 100%; max-width: 1180px;
             aspect-ratio: 1668 / 943; overflow: hidden;
             border: 1px solid var(--bord); border-radius: 4px;
             background: rgba(20, 20, 22, .6); }
#cal-fond { position: absolute; inset: 0; width: 100%; height: 100%;
            object-fit: cover; }
#cal-label { position: absolute; top: 0; left: 0; border-radius: 50%;
             pointer-events: none; }
#cal-poignees { position: absolute; inset: 0; cursor: crosshair;
                touch-action: none; }
#cal-poignees .cal-poignee { cursor: grab; }
#cal-actions { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
@media (max-width: 900px) {
  #cal-barre input[type="range"] { width: 110px; }
}

/* ═══════════ CALAGE D'UNE IMAGE SUR SA GRILLE (30/07) ═══════════
   Panneau posé sur le CARRÉ de la pochette, comme la grille d'étiquettes. La
   grille est la vérité et l'image bouge dessous : elle DÉBORDE volontairement
   du cercle extérieur — c'est la condition du calage à la main (demande
   utilisateur). Le panneau, lui, coupe : sans quoi l'image couvrirait la fiche. */
/* ATELIER PLEIN ÉCRAN (30/07) : posé sur le carré de la pochette il ne faisait
   que ~300 px, et le poser sur la colonne pochette+fiche ne changeait rien -- ce
   bloc a la hauteur de la pochette. Un outil de précision mérite la fenêtre : on
   couvre donc tout, sous l'en-tête, et le plan de travail devient le plus grand
   carré possible. */
/* FOND SOMBRE MAIS PAS NOIR : l'atelier est un calque de travail, pas une boite
   opaque -- on garde le decor derriere, en sourdine, pour ne pas perdre le fil. */
.cal-boite { position: fixed; inset: calc(var(--entete-h, 56px) + 8px) 20px 20px;
  z-index: 340; background: rgba(11, 11, 13, .82); backdrop-filter: blur(6px);
  border: 1px solid var(--bord); border-radius: 4px; overflow: hidden;
  display: flex; flex-direction: column; }
.cal-scene { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center; }
/* LE PLAN DE TRAVAIL est le plus grand CARRE qui tienne dans le panneau : la
   geometrie d une grille de disque n a de sens que dans un carre, et un panneau
   large deformerait cercles et axes. */
.cal-plan { position: relative; flex: none; overflow: hidden;
  cursor: grab; touch-action: none; }
.cal-plan:active { cursor: grabbing; }
/* l'image DEMARRE a la taille de la grille (58 %) et non plus a 76 % : elle a
   ainsi tout le tour libre pour se decaler sans etre coupee -- la zone de
   securite demandee pour les pressages decentres (30/07). Elle deborde toujours
   volontairement du cercle des qu'on l'agrandit. */
.cal-img { position: absolute; left: 50%; top: 50%;
  transform-origin: center center; user-select: none; -webkit-user-drag: none; }
.cal-grille { position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; }
.cal-barre { flex: none; display: flex; align-items: center; gap: 6px;
  padding: 5px 6px; background: rgba(20, 20, 22, .92);
  border-top: 1px solid var(--bord); }
.cal-choix { flex: 1 1 auto; min-width: 0; font-size: 11px; padding: 3px 4px;
  background: rgba(20, 20, 22, .72); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 4px; }
.cal-rot { flex: none; display: inline-flex; align-items: center; }
.cal-rot-champ { width: 62px; font-size: 11px; padding: 3px 4px; text-align: right;
  background: rgba(20, 20, 22, .72); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 4px;
  font-variant-numeric: tabular-nums; }
/* la corbeille : seulement sur les photos perso, au coin BAS-droit pour ne pas
   se confondre avec le ✕ de masquage, en haut */
/* LA CROIX QUI EFFACE SE SIGNALE (30/07) : sur une image perso deja masquee, le
   prochain appui la detruit -- elle devient donc ROUGE au survol. C'est le seul
   endroit du site ou un clic efface un fichier ; il n'a pas a ressembler aux
   autres. */
.fd-galerie .bq-img.img-masquee[data-source="perso"] .bq-img-x:hover {
  color: var(--rouge); border-color: var(--rouge); }
.cal-valeurs { flex: none; font-size: 10.5px; color: var(--sourd);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.cal-boite button { flex: none; width: 22px; height: 22px; padding: 0;
  border: 1px solid var(--bord); border-radius: 50%; background: none;
  color: var(--sourd); cursor: pointer; line-height: 1; }
.cal-boite button:hover { color: var(--texte); border-color: var(--accent); }
/* une vignette déjà classée porte un point rouge discret */
.fd-galerie .bq-img.img-calee::after { content: ""; position: absolute;
  left: 3px; bottom: 3px; width: 5px; height: 5px; border-radius: 50%;
  background: #e8503c; opacity: .85; }

/* ═══════ LES DISQUES DÉCOUPÉS N'ONT RIEN DERRIÈRE EUX (30/07) ═══════
   Retour utilisateur, capture à l'appui : les quatre coins d'un label créé
   apparaissaient NOIRS. La découpe était pourtant bonne — alpha nul aux coins,
   vérifié sur le fichier — mais les cadres qui PORTENT l'image peignent, eux, un
   fond, une bordure et une ombre : c'est cela qu'on voyait à travers.
   On les reconnaît sans rien stocker : seule la découpe produit des PNG dans
   /static/photos/ (les photos téléversées y sont enregistrées en JPEG). Un
   sélecteur suffit donc, et il vaut pour la pochette du feuilletage comme pour les
   vignettes et les cartes de la boutique. */
.fl-pochette:has(img[src*="/static/photos/"][src*=".png"]),
.article-image:has(img[src*="/static/photos/"][src*=".png"]),
.bq-img:has(img[src*="/static/photos/"][src*=".png"]) {
  background: none; border-color: transparent; box-shadow: none; }
.fl-pochette img[src*="/static/photos/"][src*=".png"],
.bq-img img[src*="/static/photos/"][src*=".png"],
.article-image img[src*="/static/photos/"][src*=".png"] {
  border-color: transparent; background: none;
  /* `cover` recadrerait le disque : on le montre ENTIER, il est déjà cadré au plus
     juste par la découpe */
  object-fit: contain; }

/* la piece RENDUE qui s'assombrit au defilement : plein cadre, opaque, sous les
   couches animees. `object-fit: cover` comme les fonds — c'est le meme cadrage. */
#cw-fond-vivant .fv-lumieres { position: absolute; inset: 0; width: 100%;
  height: 100%; object-fit: cover; z-index: 1; pointer-events: none; }

/* LES FAMILLES de la liste des jalons (30/07) : un intertitre discret, qui range
   sans alourdir — la liste faisait vingt-sept lignes d'affilée, on n'y distinguait
   plus ce qui relevait de la collection, de la boutique ou du décor. */
.jalon-famille {
  list-style: none; margin: 18px 0 7px; padding: 0;
  font-family: var(--titres); font-size: 12px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--sourd);
}
.jalons > .jalon-famille:first-child { margin-top: 0; }

/* « Les petits plaisirs » de /a-propos (30/07) : une liste aérée, sans puces
   rondes — un tiret ivoire discret, comme les jalons juste au-dessus. */
.goodies { list-style: none; padding: 0; margin: 14px 0 30px; max-width: 760px; }
.goodies li {
  position: relative; padding-left: 20px; margin-bottom: 11px;
  line-height: 1.6; color: var(--texte);
}
.goodies li::before {
  content: "—"; position: absolute; left: 0;
  color: var(--texte); opacity: .35;
}

/* MEME ESPACEMENT DE PART ET D'AUTRE DE LA LISTE (30/07, capture annotée : deux
   « A » à égaliser). Le tableau de la collection réclame 1276 px au minimum depuis
   que la colonne Disque est passée à 430 ; le conteneur, lui, était plafonné à
   1180. Un tableau ne descend pas sous sa largeur minimale : il DÉBORDAIT donc du
   conteneur, et toujours vers la droite — d'où une marge gauche de 377 px pour 247
   à droite. La page avait pourtant 353 px de libre de chaque côté : ce n'est pas le
   tableau qu'il fallait rogner, c'est le conteneur qui était trop étroit pour lui.
   On l'élargit sur les seules pages qui portent une liste, et les marges
   redeviennent symétriques par construction. Sous 1340 px la règle ne sert plus :
   le tableau y défile déjà dans sa propre boîte. */
body.large:has(table.explorateur) .conteneur { max-width: 1400px; }

/* … et les quinze derniers pixels d'écart viennent de la BARRE DE DÉFILEMENT, qui
   n'occupe qu'un bord : un conteneur centré sur la fenêtre se retrouve décalé de sa
   largeur. On réserve donc la gouttière DES DEUX CÔTÉS — le centrage redevient
   exact, et la page ne sursaute plus quand la barre apparaît ou disparaît. */
html { scrollbar-gutter: stable both-edges; }


/* LE VOILE NOIR DE LA TRANSITION (30/07). Au-dessus de tout, y compris de
   l'en-tête : ce qui passe par le noir doit passer par le noir en entier. Il
   n'intercepte aucun clic — on peut continuer à agir pendant qu'il monte. */
.fv-noir {
  position: fixed; inset: 0; z-index: 9000; background: #000;
  opacity: 0; pointer-events: none;
  transition: opacity .55s ease;
}
.fv-noir.visible { opacity: 1; }
/* `immediat` sert à couvrir l'écran SANS transition, avant le premier rendu de la
   page qui arrive : sans elle, on verrait la chambre une fraction de seconde avant
   qu'elle ne soit recouverte, ce qui est le contraire du but. */
.fv-noir.immediat { transition: none; }
.fv-noir:not(.visible) { transition: opacity .9s ease; }

/* LES OPTIONS DE CONNEXION DESCENDENT (30/07, demande utilisateur). L'accueil est
   désormais habité par l'animation d'entrée : les boutons collés sous le titre lui
   coupaient la vue. On donne au bloc toute la hauteur disponible et on l'aligne en
   bas — le décor occupe le champ, les actions attendent où on les cherche. */
@media (min-width: 901px) {
  body.entree-site .héros {
    min-height: calc(100vh - var(--entete-h, 56px) - 120px);
    display: flex; flex-direction: column; justify-content: flex-end;
  }
  body.entree-site .héros .actions { margin-bottom: 8px; }
}

/* ═════ L'ENTRÉE DU SITE EN QUATRE TEMPS (30/07) — voir intro.js ═════
   Toute la séquence se règle par TROIS variables posées sur <body> au fil du
   défilement : la part de noir, celle de l'élévation frontale, celle de la pièce.
   Le JS ne touche à aucune règle — il pose trois nombres, le style fait le reste.
   C'est ce qui permet de couper l'animation d'une seule ligne (`intro-finie`)
   sans avoir à défaire quoi que ce soit. */
body.intro-scene { --intro-noir: 0; }

/* L'ENTREE COMMENCE VRAIMENT AU NOIR (30/07, revue adversariale — trouvaille
   confirmée, et le défaut était visible dès la première image).

   Le décor de repos — la pièce vue en plongée — était peint sous le titre en
   attendant que `entree.webm` ait sa première image : on voyait donc « Crucial wax »
   posé de part et d'autre d'un VIDE, sur un décor qui n'est pas celui de l'entrée.
   Deux couches s'en chargeaient, et il fallait les traiter séparément :

   • `body::before`, qui porte le fond fixe du site ;
   • les deux images `.fv-fond` de `fond-vivant.js`.

   Pour ces dernières, une règle d'opacité N'AURAIT RIEN FAIT : le script leur pose
   une opacité EN LIGNE dès leur création, et une déclaration en ligne l'emporte sur
   la feuille de style. C'est d'ailleurs pour cela que les variables `--intro-frontal`
   et `--intro-studio`, qui pilotaient jadis ces opacités, étaient inertes — elles
   ont été retirées. On agit donc sur `visibility`, que l'attribut de style ne touche
   pas : le décor de repos n'a rien à faire sur la page d'entrée, et il n'y est plus.

   Reste le noir, qui devient le fond de la page. C'est le premier temps de la
   séquence, et il n'était pas joué. */
/* … MAIS SEULEMENT SI L'ÉLÉVATION PREND LA PLACE (31/07). `entree-active` est posée
   par fond-vivant.js au moment où la vidéo est réellement créée. Sans cette
   condition, un visiteur ayant demandé « moins d'animation » — ou dont le navigateur
   ne lit pas le WebM — voyait la porte d'entrée du site en ÉCRAN NOIR : on avait
   éteint le décor pour une vidéo qui ne venait jamais. */
body.intro-scene.entree-active { background: #000; }
body.intro-scene.entree-active::before { display: none; }
body.intro-scene.entree-active #cw-fond-vivant .fv-fond { visibility: hidden; }
/* L'ÉLÉVATION FRONTALE ARRIVE EN FONDU depuis ce noir — sa classe `posee` est mise
   par fond-vivant.js quand la vidéo est prête à peindre, pas quand elle est
   demandée : apparaître avant d'avoir une image à montrer, c'est apparaître noir
   sur noir, puis sauter. */
body.intro-scene.entree-active #cw-fond-vivant .fv-entree { opacity: 0;
  transition: opacity .9s ease; }
body.intro-scene.entree-active #cw-fond-vivant .fv-entree.posee { opacity: 1; }

/* la page a besoin de deux écrans à parcourir ; le second est vide, il n'est là
   que pour donner du chemin au défilement */
/* De quoi DÉFILER, sans plus : la séquence ne se déroule plus au fil de la page —
   descendre ne sert qu'à découvrir les options. Deux écrans n'auraient plus rien à
   montrer. */
#intro-espace { height: 78vh; pointer-events: none; }

/* NOIR DE DÉPART ET NOIR DE PASSAGE, le même voile. Sous l'en-tête (300) mais
   au-dessus de tout le reste : ce qui passe par le noir y passe en entier, sauf la
   barre, qui doit rester le point fixe pendant que le décor change. */
body.intro-scene::after {
  content: ""; position: fixed; inset: 0; z-index: 250; background: #000;
  opacity: var(--intro-noir); pointer-events: none;
  transition: opacity .12s linear;
}
/* les deux décors, réglés en sens inverse l'un de l'autre */

/* LE TITRE POSÉ SUR LE PLATEAU — GÉOMÉTRIE MESURÉE, PAS ESTIMÉE (30/07).
   Sur le rendu (1668 × 943), l'adaptateur occupe x 763→907 : il fait donc 8,63 %
   de la largeur du cadre et son centre tombe à 50,06 % — au milieu, à un pixel
   près. La vidéo est affichée en `cover`, ce qui rogne symétriquement : son centre
   horizontal reste le centre de l'écran quelle que soit la fenêtre. Centrer les
   deux mots suffit donc à leur donner la MÊME distance A de part et d'autre — il
   n'y a rien à corriger à la main, la symétrie est acquise par construction.

   Reste à choisir l'écart. Il vaut la largeur de l'adaptateur PLUS deux fois A, et
   cette largeur dépend de la fenêtre : en `cover`, l'image se cale sur la plus
   contraignante des deux dimensions. Au-delà du rapport du cadre (1,769) c'est la
   largeur qui commande — 8,63 vw ; en deçà, la hauteur — 144/943, soit 15,27 vh.
   Un `max()` choisit tout seul la bonne branche, sans media query et sans seuil
   écrit en dur.

   La LIGNE DU PLATEAU se calcule de la même façon : la base de l'adaptateur est à
   49,31 % de la hauteur du cadre, ce qui donne 49,31 vh quand l'image est calée en
   hauteur, et 50 vh − 0,39 vw quand elle l'est en largeur. Là encore un `min()`
   bascule de lui-même au bon rapport. */
#intro-titre {
  --A: clamp(46px, 4.4vw, 132px);        /* la distance, égale des deux côtés */
  /* MESURÉE SUR LA BOÎTE RÉELLE, PAS EN UNITÉS DE FENÊTRE (30/07, revue
     adversariale). `vh` se résout sur le GRAND viewport — celui qu'on aurait si la
     barre d'adresse était repliée — tandis que la boîte fixe qui porte la vidéo
     suit la zone RÉELLEMENT visible. Sur un ordinateur les deux coïncident ; sur un
     téléphone elles diffèrent de la hauteur de la barre, soit soixante à quatre-
     vingt-dix pixels. Le décor et le titre auraient donc été calés sur deux
     hauteurs différentes : le titre serait tombé à côté de l'adaptateur, qui ne fait
     que soixante-cinq pixels de haut à cette taille — et, la séquence se jouant au
     DÉFILEMENT, la barre se replie en cours de route, si bien que l'écart aurait
     changé pendant qu'on regarde.
     `--fvw` et `--fvh` sont posées par intro.js d'après la boîte elle-même, et
     remises à jour quand elle change. Les valeurs de repli ne servent que le temps
     d'une image, avant que le script ait mesuré. */
  --fvw: 100vw; --fvh: 100vh;
  --adaptateur: max(calc(var(--fvw) * 0.0863), calc(var(--fvh) * 0.1527));
  position: fixed; inset: 0; z-index: 260; pointer-events: none;
  /* LA PERSPECTIVE, ET C'ÉTAIT ELLE LE COUPABLE. On avait d'abord posé 1400 px sur
     un plan large comme l'écran : le point de fuite se trouvait donc PLUS PRÈS que
     la largeur de l'objet lui-même — un très grand angle, qui fait loucher. Le mot
     de gauche enflait en s'approchant, celui de droite fondait en s'éloignant, et
     l'on ne lisait plus un objet qui tourne mais toute l'image qui gîte.
     À 3600 px le point de fuite est loin devant la scène : il reste juste ce qu'il
     faut de profondeur pour comprendre qu'une chose tourne, sans la caricature. */
  perspective: 3600px;
  /* LA COUPE EST FIXE PAR RAPPORT À L'ÉCRAN, et c'est pour cela que le cadre fait
     toute la fenêtre : un `clip-path` se mesure sur la boîte de l'élément, si bien
     qu'une boîte qui se déplace emporterait sa coupe avec elle. Ici la boîte ne
     bouge pas — seul le texte monte à l'intérieur — et la ligne de coupe reste le
     bas de la barre supérieure, comme demandé. */
  clip-path: inset(var(--entete-h, 56px) 0 0 0);
}
#intro-titre .intro-rang {
  position: absolute; left: 0; right: 0;
  /* LA LIGNE VISÉE N'EST PLUS LA BASE DE L'ADAPTATEUR MAIS SON MILIEU (30/07) :
     l'utilisateur veut la bande des minuscules « entre le bas et le haut de
     l'adaptateur ». Sur le rendu, l'adaptateur va de 39,45 % à 49,31 % de la
     hauteur du cadre — son milieu tombe donc à 44,38 %. Comme pour la largeur, la
     projection en `cover` donne deux expressions selon le rapport de la fenêtre, et
     un `min()` choisit la bonne : au-delà du rapport du cadre c'est la largeur qui
     commande, en deçà la hauteur.
     `--cale` est posée par intro.js : c'est le décalage qui amène le milieu de la
     bande des minuscules — et non le milieu de la boîte — sur cette ligne. */
  --cale: 0px;
  --tour: 0deg;
  top: min(calc(var(--fvh) * 0.5 - var(--fvw) * 0.03177), calc(var(--fvh) * 0.4438));
  /* LE TITRE S'EFFACE, IL NE TOURNE PLUS (30/07, demande utilisateur : « remplacer
     l'effet de tourner du titre dans la présentation uniquement par un fade out du
     texte »).

     Le quart de tour aura eu trois vies — le plan entier qui basculait, chaque mot
     tournant sur soi, puis le bloc solidaire autour de l'axe. Aucune ne s'imposait
     assez pour valoir la lecture qu'elle coûtait : sur un texte, une rotation
     attire l'œil sur le MOUVEMENT plutôt que sur le mot. Un fondu ne raconte rien
     et ne dérange rien ; il laisse la scène partir sans commentaire.
     `--tour` demeure, inutilisée : la règle du cadre garde sa perspective, prête si
     l'on veut revenir en arrière. */
  transform: translateY(calc(-50% + var(--cale)));
  transition: opacity .8s ease;
  /* UNE GRILLE, ET NON UNE RANGEE CENTREE. Centrer une rangee centre le BLOC des
     deux mots, pas le VIDE entre eux : « Crucial » etant nettement plus large que
     « wax », l'ecart se decalait de la moitie de la difference -- mesure a 94 px,
     soit A negatif d'un cote et 175 px de l'autre. Deux colonnes EGALES encadrant
     une colonne centrale de largeur fixe reglent le probleme par la geometrie : la
     colonne du milieu est forcement centree, chaque mot se plaque contre elle, et A
     est le meme des deux cotes sans qu'on ait rien a compenser. */
  display: grid; align-items: baseline;
  grid-template-columns: 1fr calc(var(--adaptateur) + 2 * var(--A)) 1fr;
  font-family: "PIX Dot 140", var(--titres);
  font-size: clamp(34px, 4.6vw, 88px);
  color: var(--texte); letter-spacing: 1px; white-space: nowrap;
  text-shadow: 0 2px 18px rgba(0, 0, 0, .75);
}
#intro-titre .intro-gauche { grid-column: 1; justify-self: end; }
#intro-titre .intro-droite { grid-column: 3; justify-self: start; }
body.intro-finie #intro-titre { display: none; }

/* Le titre ne devient plus le logo : la barre garde le sien, du début à la fin.
   Le grand texte, lui, ne sort pas par le haut — il tourne sur place. */
/* de même pour les options : le décor d'abord, les actions ensuite */
body.intro-scene:not(.intro-finie) #intro-actions { opacity: 0; }
body.intro-scene #intro-actions { transition: opacity .35s ease; }

/* MOBILE : les deux mots ne tiennent pas de part et d'autre à cette taille, et le
   plateau n'occupe pas la même place dans un cadre étroit. On réduit, sans changer
   la chorégraphie — c'est le même geste, à une autre échelle. */
/* MOBILE : le cadre étant étroit, c'est la HAUTEUR qui commande le `cover` et
   l'adaptateur y devient large — l'écart calculé suffit, on réduit seulement A et
   le corps du texte pour que les deux mots tiennent. */
@media (max-width: 900px) {
  #intro-titre { --A: clamp(14px, 3.4vw, 40px); }
  #intro-titre .intro-rang { font-size: clamp(19px, 5.4vw, 34px); letter-spacing: 0; }
  #intro-espace { height: 62vh; }
}

/* LES OPTIONS DE CONNEXION, FIXES ET AU-DESSUS DU VOILE (30/07). Dans le flux du
   document elles défilaient hors de l'écran avec la page — la séquence dure deux
   écrans, elles étaient parties bien avant la fin. Fixées, elles restent sous les
   yeux ; posées à 261, au-dessus du voile noir (250) et au niveau du titre, le
   décor peut changer derrière elles sans les emporter. */
body.intro-scene #intro-actions {
  position: fixed; left: 0; right: 0; top: 72vh; z-index: 261;
  margin: 0; display: flex; justify-content: center; gap: 14px; flex-wrap: wrap;
}
@media (max-width: 900px) {
  body.intro-scene #intro-actions { top: auto; bottom: 9vh; gap: 9px; }
}

}


/* CONNEXION PAR UN COMPTE GOOGLE (30/07) — le bouton reprend la boîte des autres
   boutons du site plutôt que la charte de Google : on est chez nous, et un bouton
   d'une autre marque au milieu d'un formulaire fait tache. Le « G » suffit à dire
   ce que c'est. */
.social-sep { display: flex; align-items: center; gap: 12px; margin: 20px 0 14px;
              color: var(--sourd); font-size: 12px; }
.social-sep::before, .social-sep::after {
  content: ""; flex: 1; height: 1px; background: var(--bord); }
a.bouton.social { display: inline-flex; align-items: center; gap: 10px;
                  justify-content: center; width: 100%; box-sizing: border-box; }
.social-g { font-family: var(--titres); font-size: 15px; line-height: 1;
            color: var(--accent); }
.aide { font-size: 12px; margin-top: 8px; }

/* LES COUCHES DE LA PIÈCE N'ONT RIEN À FAIRE SUR L'ENTRÉE (30/07, retour
   utilisateur : « on dirait qu'apparaît le halo du fader horizontal de la mixette,
   un petit rectangle fantôme »). C'était bien lui : la touche du crossfader est une
   couche à part, posée sur TOUTE page à fond vivant — y compris l'accueil, où le
   décor est l'élévation frontale et où aucune mixette n'existe. Le plateau et le
   bras s'y ajoutaient de même, invisibles seulement parce que rien ne joue.
   Comme pour les images de repos, on agit sur `visibility` : leur opacité est posée
   en ligne par le script, et une règle d'opacité serait sans effet. */
body.intro-scene.entree-active #cw-fond-vivant .fv-spin,
body.intro-scene.entree-active #cw-fond-vivant .fv-bras,
body.intro-scene.entree-active #cw-fond-vivant .fv-fader,
body.intro-scene.entree-active #cw-fond-vivant .fv-label-zone { visibility: hidden; }


/* ═════ MODE EXPLORER : au plus près de la vue membre (30/07) ═════
   Demande de l'utilisateur : « mettre à jour le mode explorer pour qu'il se
   rapproche plus de l'interface utilisateur quand il log in ». Une cartographie des
   deux implémentations a mesuré l'écart ; ce qui suit corrige ce qu'elle a trouvé,
   sans ajouter une seule donnée au flux public. */

/* LE BANDEAU EN FLUX, avec sa propre boîte : il portait l'identifiant de la barre
   fixe du feuilletage, faite pour des icônes et haute de 50 px. */
#expl-entete { display: flex; align-items: center; flex-wrap: wrap; gap: 16px;
  margin: 0 0 14px; }

@media (min-width: 901px) {
  /* LA POCHETTE SE CALE EN HAUT, comme celle du feuilletage — c'était le symptôme
     numéro un du « ce n'est pas la même page » : le titre de la fiche démarrait de
     56 à 158 px au-dessus du haut de la pochette, l'écart croissant avec la hauteur
     de la fenêtre. */
  .expl-scene { align-items: flex-start; padding-top: 20px; }
  .expl-droite { padding-top: 20px; }
  /* LA COLONNE ÉPOUSE LE CARRÉ. Elle était figée à 42 % de la largeur tandis que la
     pochette, elle, est bornée aussi par la HAUTEUR : jusqu'à 88 px de vide mort
     restaient de chaque côté. Même formule que #fl-gauche. */
  .expl-gauche { flex: 0 0 auto;
    width: min(calc(100vh - 280px), 42%, 800px); }
  .expl-cover { width: min(calc(100vh - 280px), 100%, 800px);
    height: auto; aspect-ratio: 1 / 1; }
  /* LES FLÈCHES SUR LE BORD DU CARRÉ, et non sur celui de la colonne. */
  .expl-nav { left: auto; right: 4px; }
}


/* ═════ EXPLORER : les colonnes, les crédits et la rangée de visuels (31/07) ═════ */

/* LA ZONE BASSE, calquée sur #fd-bas-zone : mêmes proportions de colonnes, donc le
   même aplomb entre la fiche du visiteur et celle du membre. La tracklist occupe les
   deux premières colonnes, les crédits la troisième. */
@media (min-width: 901px) {
  .expl-bas { display: grid; grid-template-columns: 1fr 1fr 0.52fr;
              gap: 6px 18px; margin-top: 10px; align-items: start; }
  .expl-bas .expl-pistes { grid-column: 1 / 3; margin-top: 0; }
  .expl-bas .expl-credits { grid-column: 3; }
}
/* mobile : tout s'empile, comme chez le membre */
.expl-credits { display: grid; grid-template-columns: 1fr; gap: 0 18px;
                align-content: start; min-width: 0; font-size: 12px;
                line-height: 1.5; color: var(--texte); }
.expl-credits .fd-cred-bloc { min-width: 0; margin-bottom: 10px; }
.expl-credits .fd-notes-t { color: var(--sourd); }

/* LES AUTRES VISUELS SOUS LA POCHETTE, avec la rangée de la boutique : mêmes
   vignettes, même liseré sur celle qu'on regarde. */
.expl-vues { justify-content: flex-start; flex-wrap: wrap; margin-top: 10px; }


/* UNE IMAGE MASQUÉE SE RÉTABLIT AU CLIC (31/07) : le curseur le dit, et l'estompage
   s'atténue au survol — on voit ce qu'on s'apprête à faire revenir. */
.fd-galerie .bq-img.img-masquee { cursor: pointer; }
.fd-galerie .bq-img.img-masquee:hover { opacity: .72; filter: grayscale(.35); }

/* ═════ LE PRÉMIXAGE (31/07) ═════
   Le bouton vit À GAUCHE du lecteur, premier de la pilule : c'est un réglage de la
   façon d'écouter, il précède donc les commandes de ce qu'on écoute. Éteint, il est
   en sourdine comme les autres icônes ; allumé, il prend l'accent — un état qui dure
   doit se voir sans qu'on ait à survoler. */
.lect-premix { background: none; border: 0; padding: 0 2px; cursor: pointer;
  color: var(--sourd); font-size: 15px; line-height: 1; }
.lect-premix:hover { color: var(--texte); }
.lect-premix.actif { color: var(--accent); }

/* MIXAGE SEMI-MANUEL (01/08) : l'option M à côté du ∿ ; les phases 1-4 vivent
   dans #cw-mix, un conteneur À GAUCHE de la pilule du lecteur (dedans, elles
   rétrécissaient la barre d'avancement du morceau — retour utilisateur).
   Illumination : .fait = phase passée (plein accent), .pret = la prochaine à
   presser (contour accent) ; éteint = à venir. */
.lect-manuel { background: none; border: 0; padding: 0 2px; cursor: pointer;
  color: var(--sourd); font-size: 11.5px; font-weight: 700; line-height: 1; }
.lect-manuel:hover { color: var(--texte); }
.lect-manuel.actif { color: var(--accent); }
#cw-mix { display: inline-flex; gap: 4px; margin-right: 8px;
  align-items: center; }
.lect-mix-b { width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid var(--bord); background: transparent; color: var(--sourd);
  font-family: inherit; font-size: 10.5px; line-height: 1; padding: 0;
  cursor: pointer; display: inline-flex; align-items: center;
  justify-content: center; }
.lect-mix-b[disabled] { opacity: .4; cursor: default; }
.lect-mix-b.pret { border-color: var(--accent); color: var(--accent); opacity: 1; }
.lect-mix-b.fait { background: var(--accent); border-color: var(--accent);
  color: #16120f; opacity: 1; }
@media (max-width: 520px) {
  #cw-mix, #cw-lecteur .lect-manuel { display: none; }
}

/* ATELIER DU MIXAGE — page /mixage (01/08, demande utilisateur : « une page
   dédiée, les courbes en couleur, les paramètres à droite du graphique qui
   prendra plus de place, et le graphique interactif »). Le dessin tient la
   plus grande part ; les six réglages se rangent à sa droite. */
.mix-atelier { display: flex; gap: 26px; align-items: flex-start; margin-top: 10px; }
.mix-scene { flex: 1 1 auto; min-width: 0; }
.mix-reglages { flex: 0 0 268px; display: flex; flex-direction: column; gap: 2px; }
.mix-reglages label { display: block; font-size: 12.5px; color: var(--sourd);
  margin-bottom: 8px; }
.mix-reglages input { width: 100%; }
/* le réglage qu'on tient au doigt s'allume, pour qu'on sache ce qu'on change */
.mix-reglages label.tenu { color: var(--accent); }
.mix-reglages .bouton { margin-top: 12px; align-self: flex-start; }
/* le retour aux réglages d'origine se tient EN RETRAIT de l'enregistrement :
   c'est un geste rare, il ne doit pas se prendre pour le bouton principal */
.mix-reglages .mix-reset { margin-top: 6px; font-size: 12px; }
.mix-aide { margin-top: 8px; }
@media (max-width: 900px) {
  .mix-atelier { flex-direction: column; }
  .mix-reglages { flex: 1 1 auto; width: 100%;
    display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 0 18px; }
  .mix-reglages .bouton { grid-column: 1 / -1; }
}

#mixcfg-courbes { display: block; width: 100%; touch-action: none;
  background: rgba(22, 18, 15, .38); border-radius: 12px; }
#mixcfg-courbes .mxc-axe { stroke: var(--bord); stroke-width: 1; }
#mixcfg-courbes .mxc-tick { fill: var(--sourd); font-size: 11px; text-anchor: middle; }
/* les trois voix, chacune sa couleur : le sortant en ambre, sa traîne d'écho
   en violet, le morceau qui arrive en vert d'eau */
#mixcfg-courbes .mxc-sortant { fill: none; stroke: #e8a35c; stroke-width: 2.5;
  stroke-linejoin: round; }
#mixcfg-courbes .mxc-aire-s { fill: url(#mxc-gs); stroke: none; }
#mixcfg-courbes .mxc-entrant { fill: none; stroke: #6fc3a0; stroke-width: 2.5;
  stroke-linejoin: round; }
#mixcfg-courbes .mxc-aire-e { fill: url(#mxc-ge); stroke: none; }
#mixcfg-courbes .mxc-echo { fill: none; stroke: #b98fd6; stroke-width: 2.5; }
#mixcfg-courbes .mxc-echo-bloc { fill: #b98fd6; opacity: .16; }
/* la bande passante de l'écho, écrite au-dessus de sa première répétition */
#mixcfg-courbes .mxc-bande { fill: #b98fd6; font-size: 11px; opacity: .85; }
#mixcfg-courbes .mxc-marque { stroke: var(--sourd); stroke-width: 1;
  stroke-dasharray: 2 5; opacity: .5; }
#mixcfg-courbes .mxc-marque.tirable { stroke: var(--accent); opacity: .6; }
#mixcfg-courbes .mxc-rond { fill: rgba(22, 18, 15, .9); stroke: var(--accent);
  stroke-width: 1.5; }
#mixcfg-courbes .mxc-fixe .mxc-rond { stroke: var(--sourd); }
#mixcfg-courbes .mxc-num { fill: var(--accent); font-size: 13px; text-anchor: middle;
  font-weight: 700; }
#mixcfg-courbes .mxc-fixe .mxc-num { fill: var(--sourd); }
/* les poignées : on doit VOIR qu'elles se prennent */
#mixcfg-courbes .mxc-poignee { cursor: grab; }
#mixcfg-courbes .mxc-poignee:active { cursor: grabbing; }
#mixcfg-courbes .mxc-p-temps:hover .mxc-rond { fill: var(--accent); }
#mixcfg-courbes .mxc-p-temps:hover .mxc-num { fill: #16120f; }
#mixcfg-courbes .mxc-p-retour { fill: #b98fd6; stroke: rgba(22, 18, 15, .8);
  stroke-width: 2; }
#mixcfg-courbes .mxc-p-retour:hover { fill: #d3b3e8; }
#mixcfg-courbes .mxc-leg { font-size: 12px; fill: var(--sourd); }
#mixcfg-courbes .mxc-puce.mxc-leg-s { fill: #e8a35c; }
#mixcfg-courbes .mxc-puce.mxc-leg-h { fill: #b98fd6; }
#mixcfg-courbes .mxc-puce.mxc-leg-e { fill: #6fc3a0; }

/* UN DISQUE EN ATTENTE : la pilule le dit d'un liseré, sans rien ajouter à la
   barre — elle est déjà dense, et l'information est passagère. */
#cw-lecteur.a-la-suite { box-shadow: inset 0 0 0 1px var(--accent); }

/* LE ＋ « À LA SUITE », posé au survol d'un ▶ pendant qu'un morceau tourne. Il n'est
   inscrit dans aucun bouton : il y en a jusqu'à mille sur une page de collection, et
   neuf cent quatre-vingt-dix-neuf seraient inertes. */
/* LE ＋ RESTE DANS LA BOÎTE DU BOUTON (31/07). Il en débordait de sept pixels : son
   apparition et son retrait déplaçaient donc la zone survolée, et le curseur
   oscillait entre la main d'un parent glissable et le doigt du bouton. Dedans, il ne
   peut plus rien déplacer. */
.apercu-suite { position: absolute; top: 0; right: 0; width: 14px; height: 14px;
  border-radius: 50%; background: var(--accent); color: #141416;
  font-size: 10px; line-height: 14px; text-align: center; font-weight: 700;
  cursor: pointer; z-index: 3; }
/* le bouton et son ＋ imposent LEUR curseur : sans cela le `grab` d'un parent
   glissable — une ligne de morceau, une pochette — se disputait le survol avec eux. */
.apercu-btn, .apercu-btn * { cursor: pointer; }
.apercu-btn { position: relative; }


/* PRÉCÉDENT / SUIVANT : les doubles triangles sont DESSINÉS, le bouton n'a donc plus
   à corriger les métriques d'un caractère — il centre, et c'est tout. */
.lect-nav { display: inline-flex; align-items: center; justify-content: center;
  padding: 0 3px; }
.lect-nav svg { display: block; }


/* SUR UNE LIGNE DE MORCEAU, le ＋ vit DANS LE FLUX, collé au repère (31/07, demande
   utilisateur : « rapprocher la petite croix de queue vers le morceau »). En absolu
   il se calait sur le coin de la boîte du bouton, qui peut être plus large que son
   texte — le ＋ paraissait alors flotter loin du morceau survolé. Dans le flux, il
   suit le texte, où qu'il s'arrête. */
.fd-rep-jouer .apercu-suite { position: static; display: inline-block;
  margin-left: 3px; vertical-align: text-top; }


/* ---------- MODE SCAN (31/07) : caméra + code-barres en magasin ----------
   La caméra dit si le disque est déjà dans la collection : possédé → le
   feuilletage, absent → la fiche /d/{rid}. Mobile d'abord (c'est un geste de
   téléphone) — le bureau a droit à la même page, bornée en largeur. */
body.scan-page .conteneur { max-width: 640px; }
#scan-cam { position: relative; border-radius: 12px; overflow: hidden;
            background: #000; }
#scan-video { display: block; width: 100%; max-height: 52vh; min-height: 200px;
              object-fit: cover; }
/* cadre de visée CARRÉ (une pochette est carrée) : l'extérieur est assombri
   par une ombre géante — un seul élément, pas de voile à découper. Le côté
   exact est posé par scan.js (il correspond AU PIXEL au recadrage envoyé). */
#scan-cadre { position: absolute; left: 50%; top: 50%;
              transform: translate(-50%, -50%);
              width: min(74%, 42vh); aspect-ratio: 1 / 1;
              border: 2px solid rgba(242, 236, 223, .85); border-radius: 10px;
              pointer-events: none;
              box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .35); }
#scan-torche { position: absolute; right: 10px; bottom: 10px; z-index: 5;
               width: 42px; height: 42px; border-radius: 50%;
               border: 1px solid var(--bord); background: rgba(20, 20, 22, .55);
               color: var(--texte); font-size: 18px; cursor: pointer; }
#scan-torche.actif { background: var(--accent); }
#scan-etat { min-height: 22px; margin: 10px 2px; }
#scan-reprendre { width: auto; margin: 0 0 12px; padding: 6px 14px;
                  font-size: 13px; }
#scan-form { display: flex; gap: 8px; margin: 6px 0 18px; }
/* 16px : sous cette taille, iOS zoome la page à la prise de focus */
#scan-form input { flex: 1; min-width: 0; padding: 10px 12px; font-size: 16px;
                   border: 1px solid var(--bord); border-radius: 9px;
                   background: rgba(20, 20, 22, .6); color: var(--texte); }
#scan-form .bouton { width: auto; margin: 0; white-space: nowrap; }
.scan-oauth-lien { color: inherit; }
.scan-res { display: flex; gap: 12px; align-items: center; padding: 10px;
            border: 1px solid var(--bord); border-radius: 10px;
            margin-bottom: 10px; text-decoration: none; color: var(--texte);
            background: rgba(255, 255, 255, .03); }
.scan-res:hover { border-color: var(--accent); }
/* correspondance SÛRE (score haut + net écart avec le 2e) : liseré accent */
.scan-res-sur { border-color: rgba(242, 236, 223, .55); }
.scan-res img, .scan-res-vide { width: 58px; height: 58px; object-fit: cover;
                                border-radius: 6px; flex: none;
                                background: var(--carte); }
.scan-res-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.scan-res-titre { font-size: 14px; }
.scan-res-meta { font-size: 12px; }
.scan-res-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
/* badges d'état — les tons SOURDS de la barre have/want (jamais de vert/rouge
   vifs, décision du 23/07) */
.scan-b { font-size: 10.5px; padding: 2px 8px; border-radius: 999px;
          letter-spacing: .04em; text-transform: uppercase; }
.scan-b-oui { background: #55704f; color: var(--texte); }
.scan-b-non { border: 1px solid var(--bord); color: var(--sourd); }
.scan-b-ver { background: #6b5a3e; color: var(--texte); }
.scan-b-vendu { background: #83544e; color: var(--texte); }
.scan-b-want { border: 1px solid #83544e; color: var(--texte); }

/* fiche d'une release Discogs (/d/{rid}) — la destination du scan quand le
   disque n'est pas possédé */
.dsc-fiche { display: flex; gap: 26px; flex-wrap: wrap; margin-top: 8px; }
.dsc-poche { width: min(100%, 340px); aspect-ratio: 1 / 1; object-fit: cover;
             border-radius: 10px; background: var(--carte); }
.dsc-infos { flex: 1; min-width: 260px; }
.dsc-etat { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.dsc-titre { font-size: 21px; margin: 0 0 14px; }
.dsc-grille { display: grid; grid-template-columns: 110px 1fr; gap: 6px 12px;
              font-size: 14px; }
.dsc-l { color: var(--sourd); font-size: 11px; text-transform: uppercase;
         letter-spacing: .05em; align-self: center; }
.dsc-comm { margin: 14px 0; font-size: 13px; }
.dsc-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.dsc-actions form { margin: 0; }
.dsc-actions form .bouton, .dsc-actions .bouton { width: auto; margin: 0; }
.dsc-autres { margin-top: 16px; font-size: 13.5px; }
.dsc-autres a { color: var(--accent); margin-right: 12px; }
.dsc-pistes-t { margin-top: 30px; font-size: 16px; }
.dsc-pistes { list-style: none; padding: 0; margin: 8px 0 0;
              columns: 2 260px; column-gap: 40px; font-size: 14px; }
.dsc-pistes li { padding: 3px 0; break-inside: avoid; }
.dsc-rep { display: inline-block; min-width: 26px; }

/* --- téléphone en PAYSAGE : le site ne s'affiche qu'à la VERTICALE (31/07,
   demande utilisateur). Ciblé : écran TACTILE (pointer coarse) + hauteur
   ≤ 520px = un téléphone couché ; les tablettes (hauteur > 520px en paysage)
   et le bureau ne voient jamais ce voile. --- */
#verrou-paysage { display: none; }
@media (orientation: landscape) and (pointer: coarse) and (max-height: 520px) {
  #verrou-paysage { position: fixed; inset: 0; z-index: 2000; display: flex;
                    flex-direction: column; align-items: center;
                    justify-content: center; gap: 16px; background: var(--fond);
                    color: var(--sourd); text-align: center; padding: 24px; }
  #verrou-paysage svg { width: 46px; height: 46px; }
  #verrou-paysage p { margin: 0; font-size: 14px; max-width: 34ch; }
}
