﻿@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);
                  /* ⚠️ ANCRAGE LOGIQUE, pas `right` (09/08, arabe) : le bouton ⋮
                     passe a gauche en ecriture de droite a gauche, et le menu
                     ancre a droite sortait de l'ecran — mesure a x = -105 px. */
                  inset-inline-end: 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; }
/* ⚠️ DEUX FONDS DIFFERENTS ONT ETE CONFONDUS, ET C'EST MOI QUI LES AI CONFONDUS
   (11/08). Le « remplissage noir » qu'il fallait enlever etait le BANDEAU pose
   sous chaque titre — un aplat presque opaque (rgba(20,20,22,.93)) peint sur un
   decor vivant. J'avais retire en meme temps le PANNEAU translucide de la carte,
   qui n'a jamais rien masque : il pose juste assez de matiere pour qu'une liste
   se lise sur le decor. Il revient donc ici (« replacer le fond translucide
   precedent »), et le cadre, lui, reste supprime.
   La regle est posee HORS du regime bureau : elle vaut aussi sur tablette, ou il
   regarde le plus souvent. */
body.tableau-plein .dash-col .carte-info { background: rgba(255, 255, 255, .03); }
/* ⚠️ ET PLUS DE CADRE NON PLUS (11/08, capture : une croix sur chaque
   encadrement). Il ne reste que le texte sur le decor — c'est ce qui etait
   demande, et le fondu du haut comme du bas suffit desormais a dire ou la
   colonne commence et ou elle finit. */
body.tableau-plein .dash-col .carte-info { border: none; }
body.tableau-plein .dash-grandes .tuile { border: none; background: none; }
/* ⚠️ ET PLUS DE TRAIT ENTRE LES LIGNES des deux colonnes de droite (11/08,
   demande utilisateur). Le trait etait la separation d'une liste ENCADREE ; le
   cadre parti, il ne separait plus rien — il quadrillait. Le rythme des lignes
   (leur pas vertical) suffit a les distinguer. Portee au tableau de bord
   seulement : `.alerte` n'existe nulle part ailleurs aujourd'hui, mais la regle
   dit explicitement ou elle s'applique plutot que de compter la-dessus. */
body.tableau-plein .dash-col .alerte { border-bottom: none; }
body.tableau-plein .dash-grandes .tuile:hover { background: rgba(255, 255, 255, .05); }
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: rgba(19, 19, 19, .72); 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: rgba(255, 255, 255, .05);
             border: 1px solid transparent; border-radius: 10px; 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: rgba(19, 19, 19, .72);
           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: rgba(19, 19, 19, .72); 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 transparent; border-radius: 10px; margin-bottom: 6px;
             background: rgba(255, 255, 255, .05); 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: rgba(19, 19, 19, .5);
                                 flex: none; }
.set-txt { flex: 1; min-width: 0; }
/* UNE SEULE LIGNE par entree (12/08, demande utilisateur) : titre + format +
   morceau choisi en TEXTE (le selecteur ne subsiste que tant que le choix
   n'est pas fait, ou au clic sur le texte pour changer) */
.set-ligne-info { display: flex; align-items: center; gap: 10px; min-width: 0; }
.set-titre { display: block; white-space: nowrap; overflow: hidden;
             text-overflow: ellipsis; font-size: 14px; flex: 0 1 auto; min-width: 60px; }
.set-meta { display: block; font-size: 12px; flex: none; }
.set-piste-texte { flex: 0 1 auto; min-width: 40px; overflow: hidden;
                   text-overflow: ellipsis; white-space: nowrap;
                   background: none; border: none; padding: 0; cursor: pointer;
                   font: inherit; font-size: 12px; color: var(--sourd);
                   text-align: left; }
.set-piste-texte:hover { color: var(--accent); }
.set-piste { display: block; width: auto; flex: 1 1 160px; min-width: 120px;
             max-width: 440px; margin: 0; background: rgba(19, 19, 19, .72);
             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); }
@media (max-width: 900px) { .set-ligne-info { flex-wrap: wrap; } }
/* `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: rgba(19, 19, 19, .72);
                 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 transparent; border-radius: 10px;
                 background: rgba(255, 255, 255, .05); }
.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: rgba(255, 255, 255, .07); }
.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 */
    /* ⚠️ LA HAUTEUR DE LA BARRE, PAS 50 px (11/08, demande utilisateur : « centrer
     Dashboard par rapport a Crucial wax »). La barre fait `--entete-h` = 56 px et
     son centre tombe donc a 28 ; cale sur 50, le titre se centrait a 25 — trois
     pixels trop haut, ce qui se voit quand les deux mots sont cote a cote.
     On prend la variable et non un nombre : elle est deja la mesure de la barre,
     et deux nombres pour une meme hauteur finiraient par diverger. */
#fl-entete { position: fixed; top: 0; height: var(--entete-h, 56px); 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,
#bq-filtres .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,
#bq-filtres .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,
#bq-filtres .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,
#bq-filtres .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; }
/* les actions que l'appelant pose dans l'en-tete de la grille (le bac lie y remet
   « ouvrir le set » et « detacher ») : discretes, a hauteur de la chip. */
.flg-action { background: none; border: 1px solid var(--bord); color: var(--sourd);
  border-radius: 999px; font: inherit; font-size: 11.5px; padding: 2px 10px;
  cursor: pointer; }
.flg-action:hover { color: var(--texte); border-color: var(--texte); }
#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; }
/* AIMANTATION DU DEFILEMENT (03/08, demande utilisateur : « aimanter la position
   des disques apres scroll pour en avoir toujours des complets visibles »).
   Cette grille montre EXACTEMENT trois rangees -- `feuilletage.js` calcule leur
   hauteur pour cela -- mais rien n'empechait de s'arreter entre deux : on voyait
   alors deux rangees entieres et deux moities. L'aimantation est FERME ici
   (`mandatory`) : la hauteur des rangees etant constante et le cadre en montrant
   un nombre entier, chaque point d'arret tombe forcement juste.
   ⚠️ MAIS DOUCE, PAS FERME (03/08, 2e retour : « faire que l'aimantation soit plus
   naturelle »). En `mandatory`, le cadre reprend la main a CHAQUE cran de molette :
   le geste n'aboutit jamais ou on l'a laisse, et cela se sent comme une main qui
   tire. `proximity` ne rattrape que la fin de course, et seulement si elle tombe
   deja pres d'une rangee -- on garde des disques entiers sans jamais lutter contre
   le defilement. Meme reglage que la collection, donc : une seule regle a retenir.
   ⚠️ `scroll-snap-align` va sur les CASES, pas sur le conteneur : c'est l'element
   qui vient se caler, pas la boite qui le porte.
   ⚠️ Et `scroll-padding` sur le cadre plutot qu'une marge sur chaque case : la
   rangee doit se caler sous le bord haut, pas sur ses 2 px de padding. */
/* ⚠️ ET LA MEME PRUDENCE ICI (09/08). Cette aimantation-la n'a jamais ete
   signalee — elle porte sur un CONTENEUR, pas sur la page — mais c'est la meme
   mecanique, et elle se disputerait le meme geste au doigt. On la garde a la
   molette, ou elle fait ce qu'on lui demande. */
#fl-grille-cases { scroll-padding-top: 2px; }
@media (pointer: fine) {
  #fl-grille-cases { scroll-snap-type: y proximity; }
}
.flg-case { scroll-snap-align: start; }
.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; }
/* ⚠️ UNE ETIQUETTE DECOUPEE N'A PAS DE FOND (03/08, demande utilisateur : « fond
   transparent pour les labels decoupes »). La decoupe rend un PNG a canal alpha,
   rond, dont les coins sont vides -- et la case leur donnait son fond de carte, son
   cadre et son ombre : le macaron se retrouvait pose sur un carre gris, exactement
   ce qu'on avait pris soin de decouper. On efface donc les trois : le decor passe a
   travers, et l'etiquette se decoupe sur la piece comme un vrai disque pose.
   `object-fit: contain` par-dessus : un macaron rond ne se recadre pas, il se
   montre en entier. */
.flg-case.flg-decoupe { background: none; border-color: transparent;
                        box-shadow: none; }
.flg-case.flg-decoupe img { object-fit: contain; }
@media (hover: hover) {
  .flg-case.flg-decoupe:hover { border-color: var(--accent); }
}
.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 */
/* ⚠️ EN ARABE, LE BAC PASSE DU COTE DE LA BANDE (09/08). La bande de chips suit
   le texte et s'en va a droite ; le bac, ancre en `left`, restait a gauche, sous
   la fiche. Ils sont censes partager un bord — c'est la regle du 21/07. On le
   RETOURNE donc, sans toucher au decor : `aligner()` pose ensuite la valeur fine
   sur la bonne propriete. */
[dir="rtl"] #bac-set { left: auto; right: 18px; }
[dir="rtl"] #bac-set-n { right: auto; left: -9px; }
[dir="rtl"] #bac-set-nomlie { left: auto; right: 0; }
/* 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; }
/* ⚠️ LE LABEL A SA PROPRE LIGNE (11/08). Mis a la suite du titre, il etait le
   PREMIER a se faire couper par l'ellipse — donc invisible exactement quand
   c'est lui qui avait repondu a la recherche. Mesure : jusqu'a 255 px perdus sur
   une boite de 277. Sur deux lignes, le titre garde la sienne et le label la
   sienne ; chacune s'ellipse pour son compte.
   `min-width: 0` reste indispensable : sans lui la largeur minimale d'un element
   flexible vaut son contenu, et une ligne longue pousserait la vignette. */
/* ⚠️ LA CROIX DES CHAMPS DE RECHERCHE EST LA NOTRE, PLUS CELLE DE CHROME
   (11/08, demande utilisateur : « remplacer partout la croix blanche pour
   effacer dans la loupe par une croix blanche en PIX100 »). Celle du navigateur
   est grise, dessinee par lui, et c'est la seule chose de la page qui ne soit
   pas de la maison — on la masque. La notre est posee par effacer.js et vaut
   pour les CINQ champs du site, dont celui de la boutique, cree par script. */
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none; appearance: none; display: none; }
/* 11/08, 2e passe (demande utilisateur) : la croix grandit — 17 -> 24 px de
   glyphe dans un bouton de 28. Le rembourrage droit du champ suit, sinon le
   texte saisi passerait dessous. */
/* ⚠️ PAS DE `padding-right` ICI : chacun des cinq champs porte une regle visee
   par son ID (`#recherche`, `#voile-rech-champ`, `#set-recherche`…), et un
   selecteur d'ID bat toute regle de classe — mesure : 12 px effectifs pour 34
   demandes. C'est effacer.js qui pose la reserve, en ligne, avec le seul
   argument valable : il connait la largeur reelle du bouton. */
.champ-eff { position: absolute; z-index: 2; width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  padding: 0; border: 0; background: none; cursor: pointer;
  font-family: "PIX Dot", var(--titres); font-size: 24px; line-height: 1;
  color: #fff; opacity: .72; }
.champ-eff:hover { opacity: 1; color: var(--accent); }

.rech-texte { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.rech-l1, .rech-lab { white-space: nowrap; overflow: hidden;
                      text-overflow: ellipsis; }
.rech-lab { font-size: 11.5px; }
#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; }
/* 12/08 (demande utilisateur) : le graphe INSCRIT dans le carre de la pochette
   (bureau) — le popover prend exactement la geometrie du carre mesuree par le
   JS, contenu centre verticalement ; le corps epouse la largeur du carre.
   Centrage par MARGES AUTO et pas justify-content:center : centre quand ca
   tient, cale en haut et ENTIEREMENT defilable quand ca deborde (fenetre
   basse + mode edition) — justify-content:center rendrait le HAUT du
   debordement inatteignable (lecon .article-note, entree 209). */
.fd-bpm-pop.fd-bpm-carre { box-sizing: border-box; display: flex;
  flex-direction: column; overflow: auto;
  /* 12/08 (demande utilisateur) : plus de carte grise — seulement un VOILE
     leger et neutre pour la lisibilite (« opacifier un peu »), sans trait ni
     ombre : le fond vivant reste present derriere le graphe */
  background: rgba(19, 19, 19, .5); border: none; box-shadow: none; }
.fd-bpm-pop.fd-bpm-carre > :first-child { margin-top: auto; }
.fd-bpm-pop.fd-bpm-carre > :last-child { margin-bottom: auto; }
.fd-bpm-pop.fd-bpm-carre .fd-bpm-pop-corps { width: 100%; max-width: none; }
/* les specs respirent sous le graphe (le padding de base n'a pas de haut) et
   s'alignent sur sa marge gauche interne */
.fd-bpm-pop.fd-bpm-carre .fd-bpm-specs { padding: 14px 16px 0; }
.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; }
/* le monteur d'extrait, dans le popover d'un morceau (08/08) : la ligne qui
   PRÉVIENT que le résultat sera public, et celle du résultat avec son ▶. */
.fd-extrait-note { font-size: 10.5px; line-height: 1.45; color: var(--sourd);
                   margin: 5px 0 0; max-width: 260px; }
.fd-extrait-fait { color: var(--accent); }
/* TAP TEMPO du popover (12/08, demande utilisateur) : battre la mesure au
   clic, l'enregistrement marque le tempo VERIFIE a l'oreille */
.fd-bpm-tap-zone { display: flex; gap: 10px; align-items: center;
                   margin-top: 10px; flex-wrap: wrap; }
.fd-bpm-tap { width: 58px; height: 36px; border-radius: 9px; cursor: pointer;
              font: inherit; font-size: 12.5px; font-weight: 700;
              letter-spacing: .5px; background: rgba(255, 255, 255, .08);
              color: var(--texte); border: 1px solid var(--bord); }
.fd-bpm-tap:active { background: var(--accent); color: #141416; }
.fd-bpm-tap-lu { font-size: 12px; min-width: 90px; }
.fd-bpm-tap-ok { 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-tap-ok:hover { background: var(--accent); color: #141416; }
.fd-bpm-verifie { font-size: 11.5px; color: #7ac074; }
/* 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 (≥901px, POINTEUR FIN) tout tient dans la fenêtre — les listes
   (registre, signaux, achats) deviennent des COLONNES à défilement INTERNE.
   ⚠️ ET SEULEMENT AU POINTEUR FIN (09/08, retour utilisateur : « le scroll n'est
   pas possible dans ces colonnes sur iPad Safari, et le bandeau sombre sous les
   intitulés empêche la bonne lecture »). Un iPad en paysage fait 1024 px : il
   entrait donc dans ce régime, avec des colonnes à défilement interne que le
   doigt n'arrive pas à saisir de façon fiable, et des intitulés posés EN ABSOLU
   par-dessus leur liste — un bandeau opaque qui mange la première ligne dès que
   rien ne défile. `pointer: fine` retire d'un coup les deux défauts : sur une
   tablette, la page redevient une page, elle défile en entier, et les intitulés
   reprennent leur place dans le flux. Mobile : inchangé. --- */
@media (min-width: 901px) and (pointer: fine) {
  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;
  /* la largeur de lecture (860 px) convient à un texte, pas à quatre
     colonnes : à un quart de 860, une tuile ne tiendrait plus son titre. */
  /* ⚠️ ET IL PREND CETTE LARGEUR (11/08). Sans `width: 100%` il ne la prenait
     PAS : `margin: 0 auto` en axe transverse annule l'etirement d'un enfant de
     boite flexible, si bien que le conteneur EPOUSAIT son contenu — mesure a
     1920 : 1199 px pour un plafond de 1440. C'etait la vraie cause des mots
     serres, et j'ai d'abord cherche du cote de la police. */
                                  width: 100%;
                                  max-width: min(1440px, 96vw); }
  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; }
  /* ⚠️ ELLES DEFILENT SANS BARRE (08/08, capture annotee de l'utilisateur : deux
     croix sur les ascenseurs). Le defilement reste, seul l'ascenseur disparait --
     meme geste que sur le feuilletage et les stats, ou la barre coupait le decor.
     La molette et le doigt continuent d'agir. */
  body.tableau-plein .dash-col .carte-info { flex: 1 1 auto; min-height: 0;
    overflow-y: auto; scrollbar-width: none; margin-bottom: 10px; }
  body.tableau-plein .dash-col .carte-info::-webkit-scrollbar { display: none; }
  /* ⚠️ LE FONDU SE POSE SUR LA FENETRE, PAS SUR LA LISTE (11/08, capture de
     l'utilisateur : le texte defilant passait EN TOUTES LETTRES sous le titre).
     Deux defauts, mesures, et le meme correctif les prend tous les deux.

     1. IL ETAIT ANCRE SUR LE CONTENU. Un `mask-image` se cale sur la boite de
        l'element ; pose sur la liste, il DEFILE AVEC ELLE. Mesure a 1280 : au
        repos le fondu devenait opaque a y=182 pour un titre finissant a 144
        (protege) ; defile de 150 px, l'opacite pleine remontait a y=32, soit
        112 px de texte NU sous le titre ; a 400 px, 362 px. Pose sur
        `.carte-info` — la fenetre qui decoupe — il ne bouge plus, quoi que fasse
        le contenu.

     2. SON INTERRUPTEUR ETAIT LE MAUVAIS. `dash-deborde` dit « il en reste
        DESSOUS » : il s'eteint quand on arrive au bas de la liste, c'est-a-dire
        au moment ou le chevauchement du HAUT est le plus fort. Le haut a
        desormais le sien, `dash-defile` (« on a fait defiler »).

     ⚠️ Le fondu du haut vaut 52 px, un peu PLUS que la hauteur du titre (48 px
     mesures) : un fondu plus court laisserait les jambages du titre sur du texte
     encore lisible. Et il n'existe qu'une fois qu'on defile — au repos, la
     premiere ligne ne doit pas palir sans raison.
     ⚠️ Le masque prend aussi le fond translucide de la carte, mais a 3 % de blanc
     la difference est invisible : c'est le prix, minime, d'un fondu qui ne peint
     rien. */
  /* ⚠️ LE FONDU NE DOIT PAS *TRAVERSER* LE TITRE, IL DOIT LE COUVRIR (11/08,
     capture VIDEO de l'utilisateur — le seul document qui pouvait le montrer).
     Mon degrade montait de transparent a opaque DES le haut de la carte : au
     milieu du titre, le texte etait donc a moitie opaque, et « € (vous : 96 €) »
     se lisait en travers de « Recent signals ». Le fondu marchait, il etait juste
     construit a l'envers.
     Il tient desormais DEUX bornes : transparent PLEIN sur toute la hauteur du
     titre (`--fondu-clair`), puis remontee vers l'opaque APRES lui
     (`--fondu-haut`). Sous le titre : plus rien. Apres : le texte revient.
     A l'arret les deux bornes valent 0 — trois arrets a la meme position, donc
     une carte opaque des son premier pixel. */
  body.tableau-plein .dash-col .carte-info {
    --fondu-clair: 0px; --fondu-haut: 0px; --fondu-bas: 0px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0,
      transparent var(--fondu-clair), #000 var(--fondu-haut),
      #000 calc(100% - var(--fondu-bas)), transparent);
    mask-image: linear-gradient(to bottom, transparent 0,
      transparent var(--fondu-clair), #000 var(--fondu-haut),
      #000 calc(100% - var(--fondu-bas)), transparent); }
  /* transparent sur TOUTE la hauteur du titre, puis 16 px pour revenir au
     texte plein — deux bornes mesurees sur le titre, jamais choisies a la main. */
  body.tableau-plein .dash-col.dash-defile .carte-info {
    --fondu-clair: var(--titre-h);
    --fondu-haut: calc(var(--titre-h) + 16px); }
  body.tableau-plein .dash-col.dash-deborde .carte-info { --fondu-bas: 34px; }
  /* 03/08 (demande utilisateur) : QUATRE colonnes, dans cet ordre — les
     chiffres, les trois portes, les signaux, le registre. Quatre pistes
     ÉGALES et non un auto-fit : l'ordre demandé est un ordre de lecture, il
     ne doit pas se réarranger selon la largeur disponible. */
  body.tableau-plein .dash-listes.dash-quatre {
    grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0 24px; }
  /* ⚠️ TROIS COLONNES, ET LES PORTES GARDENT LA LEUR (11/08, correction de
     l'utilisateur : « ce n'etait pas la consigne d'agrandir les encadrements ni
     changer la diagrammation… juste les textes grands sur une seule colonne
     comme avant, mais donnant plus de largeur aux autres deux colonnes »).
     J'avais fait une rangee pleine largeur et grossi les boites : ni l'un ni
     l'autre n'etait demande. Les chiffres ayant rejoint le ＋ de la tuile, leur
     colonne est rendue — les portes restent etroites, les deux listes prennent
     tout le reste. */
  body.tableau-plein .dash-listes.dash-quatre {
    /* ⚠️ .95 ET NON .72 (11/08, « agrandir encore les textes ») : c'est la
       LARGEUR qui plafonnait la police, pas la fonte. Mesure : l'allemand
       « Sammlung(en) », le plus long des neuf, interdisait de depasser 28,4 px
       dans une colonne de 278. Les deux listes n'y perdent rien de ce qu'elles
       ont gagne — elles avaient 270 px quand les colonnes etaient quatre. */
    grid-template-columns: minmax(0, .95fr) minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr); }
  /* les portes s'empilent DANS leur colonne, comme avant */
  .dash-quatre .dash-tuiles { grid-template-columns: 1fr; max-width: none;
    margin: 0; gap: 12px; align-content: start; }
  .dash-quatre .dash-col-portes .dash-tuiles {
    flex: 1 1 auto; min-height: 0; margin-bottom: 0;
    grid-auto-rows: minmax(0, 1fr); align-content: stretch; }
  /* ⚠️ SEUL LE TEXTE GRANDIT — l'encadrement garde ses cotes d'avant (22/18/18).
     C'est ce qui etait demande, et c'est ce qui permet a la colonne de rester
     etroite : ce sont les MOTS qu'on veut voir de loin, pas les cadres.
     11/08 : en PIX 140, la fonte du logo — les trois portes deviennent alors la
     signature du site, pas trois libelles. Elle est LARGE : la taille est celle
     que la colonne accepte sans couper le plus long des trois mots. */
  /* ⚠️ PIX 100, ET NON 140 (11/08, demande utilisateur) : la 140 est tres large et
     obligeait a descendre a 21 px pour que l'allemand tienne. La 100 est bien plus
     etroite — a taille EGALE elle occupe un quart de moins. Mesure DANS la tuile,
     avec la vraie fonte (une sonde a part ou un canevas rendent les chiffres d'une
     AUTRE fonte, ce qui m'a fait conclure deux fois de travers) : dans 260 px
     utiles, « Sammlung(en) » avec son ＋ vaut 258 px a 28 et 272 a 30. 28 px est
     donc le plafond des neuf langues, et le francais y garde 22 px d'air — les
     « trois caracteres de place restante » qu'il voyait. Le rembourrage descend a
     12 px pour rendre six pixels de plus au texte. */
  /* ⚠️ PAS DE `container-type` SUR LA COLONNE : mesure, il la fait tomber a 0 px
     de large. `container-type: inline-size` pose `contain: layout inline-size`,
     et une piste de grille en `minmax(0, .95fr)` n'a alors plus rien pour se
     dimensionner. La taille suit donc la FENETRE, dont la colonne depend
     directement depuis que le conteneur s'etire : elle en vaut 30,9 %. Le
     plafond de 48 px est celui du conteneur (1440 px) — au-dela, la colonne ne
     grandit plus et une police qui monterait encore couperait l'allemand. */
  .dash-quatre .dash-grandes .tuile { padding: 22px 6px 18px;
    /* ⚠️ ET LE PLAFOND EST A 32 px, PAS PLUS HAUT : au-dela de ~1200 px de
       fenetre le conteneur du tableau de bord est BORNE (mesure : 1146 px a
       1920), donc la colonne cesse de grandir — 312 px — et un `vw` qui continue
       de monter ferait deborder. A 32 px l'allemand occupe 275 px sur 288
       utiles. En dessous, la taille suit la fenetre : 27,5 px a 1280, ou la
       colonne n'a que 260 px utiles. */
    /* 2,85 vw et non 3 : a 3, l'allemand tombait a ZERO pixel pres du bord dans
       une fenetre de 1024 (mesure). Une fonte qui rendrait un cheveu plus large
       ailleurs ferait alors passer le mot a la ligne. */
    font-size: clamp(20px, 2.85vw, 48px);
    font-family: "PIX Dot", var(--titres); letter-spacing: 0;
    line-height: 1.25; }
  /* ⚠️ LE NOMBRE EST EN PIX 100 ET PLUS GRAND (11/08, demande utilisateur :
     « agrandir un peu ces trois sous-titres et remplacer par PIX100 »). Il ne
     porte plus qu'un nombre depuis que les phrases sont tombees, si bien qu'il
     peut grandir sans risquer la ligne suivante. `"PIX Dot"` EST la 100 —
     PIX-DOT-1-100.ttf ; la 140 porte son chiffre dans son nom. */
  .dash-quatre .dash-grandes .tuile-note { margin-top: 10px; font-size: 19px;
    font-family: "PIX Dot", var(--titres); letter-spacing: .02em; }
  /* le « + » vert de la capture : le bloc de chiffres est ce qu'on lit en
     premier le matin, il ne peut pas etre le plus petit texte de la page. */
  .dash-quatre .dash-chiffres .dash-vie { font-size: 13px; line-height: 1.8;
    margin: 0; }
  .dash-quatre .dash-col-chiffres .ligne-sync { margin-top: 16px;
    flex-wrap: wrap; gap: 8px; }
  /* deux listes dans la même colonne (signaux puis achats) : chacune prend
     sa part, aucune n'écrase l'autre. */
  .dash-quatre .dash-col .carte-info { flex: 1 1 auto; }
}
.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 { max-width: 960px; gap: 16px; }
/* ⚠️ TROIS OU UNE, JAMAIS DEUX PUIS UNE (15/08, demande utilisateur : « soit les
   trois titres sont horizontaux, soit verticaux, mais pas de decoupage
   intermediaire deux et un ou un et deux »).
   L'auto-fill herite de `.dash-tuiles` produisait exactement ce qu'il ne fallait
   pas : en retrecissant, la troisieme porte tombait seule sous les deux autres —
   une rangee bancale que l'oeil lit comme une erreur, alors que ces trois portes
   sont un ensemble. Le nombre de colonnes devient donc une DECISION : trois tant
   qu'elles tiennent, une des qu'elles ne tiennent plus.
   ⚠️ SEULEMENT EN FLUX, SOUS 901 px. Au-dessus, le tableau de bord met les portes
   dans une COLONNE etroite a cote de deux listes, et elles y sont verticales par
   dessein (`.dash-quatre .dash-tuiles`) : une regle non bornee l'aurait defait,
   sa specificite etant egale et sa place plus basse dans le fichier.
   ⚠️ ET IL FAUT LES DEUX CLASSES : `.dash-grandes` seule perd contre
   `.dash-tuiles` — mesure, quatre colonnes de 170,5 px la ou la regle en
   demandait trois. */
@media (max-width: 900px) and (min-width: 700px) {
  .dash-tuiles.dash-grandes { grid-template-columns: repeat(3, 1fr); }
  /* trois de front dans cette largeur : les cadres se resserrent, les MOTS
     restent lisibles — c'est eux qu'on vient lire. */
  .dash-tuiles.dash-grandes .tuile { padding: 26px 12px 20px; font-size: 19px; }
}
@media (max-width: 699px) {
  .dash-tuiles.dash-grandes { grid-template-columns: 1fr;
    /* ⚠️ ET SERREES (15/08, demande utilisateur : « dans la version verticale du
       dashboard, diminuer l'interligne entre les titres collection, wantlist et
       shop »). Empilees, elles heritaient d'un ecart de 16 px et d'un rembourrage
       de 42/34 px pense pour trois cases COTE A COTE : la colonne devenait longue
       et l'oeil devait descendre pour voir les trois portes, alors qu'elles sont
       un ensemble et doivent se lire d'un coup. */
    gap: 8px; }
  .dash-tuiles.dash-grandes .tuile { padding: 18px 18px 14px; }
  .dash-tuiles.dash-grandes .tuile-note { margin-top: 4px; }
}
.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; }
/* LE ＋ EN EXPOSANT SUR « Collection(s) » (11/08, capture annotee) : un appel de
   note, pas un bouton — il ne doit pas peser autant que le mot qu'il suit. */
/* ⚠️ UNE TAILLE A LUI, PAS UN `em` : accroche a la taille du titre, le ＋
   retrecissait chaque fois que le titre retrecissait — alors qu'on le voulait
   PLUS GROS. 18 px, en PIX comme le reste : mesure, le pire cas des neuf langues
   passe de 246 a 242 px dans 254 px utiles, il reste donc de la place. */
/* ⚠️ LE ＋ SE MESURE EN `em`, PAS EN PIXELS (11/08) : le mot qui le porte va
   desormais de 28 a 48 px selon la fenetre ; a taille fixe, le ＋ paraissait
   juste a 1280 et minuscule a 1920. En `em` il garde son rapport partout. */
.tuile-plus { background: none; border: 0; padding: 0 0 0 5px; cursor: pointer;
              color: var(--sourd); font-family: "PIX Dot", var(--titres);
              font-size: .58em; line-height: 1; vertical-align: super; }
.tuile-plus:hover, .tuile-plus.ouvert { color: var(--accent); }
.tuile-plus.ouvert { transform: rotate(45deg); display: inline-block; }
/* les chiffres deplies : sous les portes, dans leur colonne */
.dash-chiffres { margin-top: 10px; padding: 10px 12px;
                 background: rgba(255, 255, 255, .03);
                 border: 1px solid var(--bord); border-radius: 10px; }
.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; }
/* ═══════ LA REGLETTE DE COULEUR (10/08, 2e passe) ═══════════════════════════
   Le glisser-deposer est retire : deux bacs sont a des centaines de pixels l'un
   de l'autre dans une page qui defile. La reglette se deploie SOUS la pochette
   cliquee, en pleine largeur de son bac — rien a traverser.
   Sobre : un trait d'arc-en-ciel, un curseur, deux mots. */
.ch-reglette { grid-column: 1 / -1; margin: 6px 0 10px;
               background: rgba(255, 255, 255, .04);
               border: 1px solid var(--bord); border-radius: 8px;
               padding: 10px 12px 11px; }
.ch-reg-titre { margin: 0 0 9px; font-size: 12.5px; line-height: 1.35; }
.ch-reg-titre .sourd { font-size: 11.5px; }
/* L'ARC-EN-CIEL EST L'ORDRE DU TRI LUI-MEME : teintes croissantes, puis le noir
   et blanc au bout — on montre la couleur au lieu de demander un nombre. */
.ch-reg-barre { position: relative; height: 16px; border-radius: 8px;
                cursor: pointer; touch-action: none;
                background: linear-gradient(to right,
                  hsl(0 46% 58%), hsl(60 46% 58%), hsl(120 46% 58%),
                  hsl(180 46% 58%), hsl(240 46% 58%), hsl(300 46% 58%),
                  hsl(360 46% 58%) 87.5%, #8b8177 87.5%, #6f665e 100%); }
.ch-reg-nb { position: absolute; left: 87.5%; top: -2px; bottom: -2px; width: 1px;
             background: var(--fond); opacity: .55; }
.ch-reg-curseur { position: absolute; top: -3px; width: 14px; height: 22px;
                  margin-left: -7px; border: 2px solid #fff; border-radius: 4px;
                  background: rgba(19, 19, 19, .35); pointer-events: none;
                  box-shadow: 0 1px 4px rgba(0, 0, 0, .5); }
.ch-reg-barre:focus { outline: 1px solid var(--accent); outline-offset: 3px; }
.ch-reg-pied { display: flex; align-items: center; gap: 9px; margin-top: 10px; }
.ch-reg-apercu { width: 15px; height: 15px; border-radius: 50%;
                 border: 1px solid var(--bord); }
.ch-reg-valeur { font-size: 11.5px; font-variant-numeric: tabular-nums;
                 min-width: 42px; }
.ch-reg-pied button { margin-left: auto; background: none; color: var(--sourd);
                      border: 1px solid var(--bord); border-radius: 13px;
                      padding: 3px 13px; font-size: 12.5px; cursor: pointer; }
.ch-reg-ok { color: var(--texte) !important; border-color: var(--texte) !important; }
.ch-reg-ok:hover { background: var(--texte); color: var(--fond) !important; }
.ch-reg-non { margin-left: 0 !important; }
.ch-reg-non:hover { color: var(--texte); }
.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; }
/* MEME AIMANTATION POUR LA COLLECTION, mais DOUCE. Ici c'est la PAGE qui defile,
   sur des centaines de rangees entrecoupees de titres de bacs : une aimantation
   ferme reprendrait la main a chaque geste, y compris quand on cherche seulement a
   parcourir. `proximity` ne rattrape que ce qui est deja presque en place -- on
   arrive donc sur des disques entiers sans jamais se sentir retenu.
   ⚠️ ET LE CALAGE TIENT COMPTE DE L'EN-TETE : sans `scroll-margin-top`, la rangee
   aimantee se rangeait SOUS la barre superieure, qui est fixe. On lui rend sa
   hauteur, exposee par base.html en --entete-h. */
/* ⚠️ PLUS D'AIMANTATION DU TOUT SUR CETTE PAGE (09/08, demande utilisateur :
   « enlever toute aimantation qui produise des bugs »). Elle avait ete posee pour
   arriver sur des rangees entieres a la molette ; au doigt elle se disputait le
   geste avec l'inertie — on remontait vers la barre de filtres, l'elan s'eteignait
   et l'aimantation redescendait a la rangee la plus proche. Un premier correctif
   la reservait au pointeur fin ; l'utilisateur a tranche plus court, et il a
   raison : un confort qui casse un geste n'est pas un confort.
   ⚠️ `scroll-margin-top` reste sur les cases : il ne sert plus l'aimantation mais
   les ancres (#a-… , « voir ce disque »), qui sinon se rangeraient SOUS la barre
   superieure, qui est fixe. */
.ch-case { scroll-margin-top: calc(var(--entete-h, 56px) + 12px); }
.ch-case img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* ⚠️ UNE ETIQUETTE DECOUPEE N'A PAS DE FOND ICI NON PLUS (03/08, meme demande que
   pour la grille du feuilletage). Le PNG de la decoupe est rond et ses coins sont
   vides : la case leur donnait son fond de carte, son cadre et son ombre, et le
   macaron se retrouvait pose sur un carre gris. On efface les trois, et l'image
   passe en `contain` -- un macaron rond ne se recadre pas, il se montre entier. */
.ch-case.ch-decoupe { background: none; border-color: transparent;
                      box-shadow: none; }
.ch-case.ch-decoupe img { object-fit: contain; }
.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) */
/* 08/08 (demande utilisateur) : titre et artiste des cartes en PIX. C'est la fonte
   des TITRES du site (logo, sections magazine) ; elle est a chasse pixelisee, donc
   moins dense qu'une grotesque — on remonte legerement la taille pour garder la
   meme presence, et l'interlettrage d'un demi-pixel l'aere. */
.article-titre { white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
                 font-family: "PIX Dot", var(--titres); font-size: 17px;
                 letter-spacing: .5px; }
.article-titre a { color: var(--texte); text-decoration: none; font-weight: 700; }
.article-titre a:hover { color: var(--accent); }
/* 08/08 : l'ARTISTE passe SOUS le titre, en retrait de ton — le titre porte le
   nom du disque, l'artiste le signe. Meme ellipse, chacun sur sa ligne. */
.article-artiste { color: var(--sourd); font-size: 15px; margin-top: 3px;
                   font-family: "PIX Dot", var(--titres); letter-spacing: .4px;
                   white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 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; min-width: 0;
                /* 08/08 : la ligne S'ENROULE au lieu de rogner — l'annee et l'etat
                   ne descendent que si le label leur a pris la place. */
                flex-wrap: wrap; column-gap: 4px; row-gap: 2px; }
.article-meta-an { flex: none; }
.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; }
/* ⚠️ LE SIGNAL SE LIT SUR DEUX LIGNES (11/08, demande utilisateur) : le disque
   d'abord, son motif dessous. `align-items: baseline` sur la ligne aligne alors
   le picto et la date sur la PREMIERE ligne du corps, c'est-a-dire sur le titre
   du disque — la date reste donc exactement ou elle etait.
   ⚠️ `min-width: 0` est indispensable : sans lui, un titre long refuserait de se
   comprimer (la largeur minimale d'un element flexible vaut son contenu) et
   pousserait la date hors de la carte. */
.alerte-corps { flex: 1; min-width: 0; display: flex; flex-direction: column;
                gap: 1px; }
.alerte-corps > a { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.alerte-corps .alerte-detail { flex: none; font-size: 12.5px; line-height: 1.35; }
.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 --- */
/* LE COMPTE DISCOGS SUR /compte (11/08) : la ligne vient du tableau de bord,
   elle en garde la sobriete — un fait et un bouton. */
.compte-discogs { display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
                  color: var(--sourd); font-size: 13.5px; margin: 0 0 22px; }
.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. */
/* ═══ LE PALIER INTERMEDIAIRE : UNE SEULE COLONNE, MAIS ENCORE A COTE DE
   L'IMAGE (15/08, demande utilisateur : « quand la fenetre se retrecit, d'abord
   mettre toutes les informations a droite de l'image en une seule colonne, puis
   passer a la configuration verticale ; cela empechera le chevauchement des
   trois colonnes »).
   Il manquait une marche. Entre 901 et 1279 px la fiche gardait ses TROIS
   colonnes dans une largeur qui n'en portait plus trois : les libelles et les
   valeurs se tassaient les uns sur les autres. On passe donc a UNE colonne — le
   texte respire, l'image garde sa place —, et ce n'est qu'en dessous de 901 px
   que tout se met a la verticale.
   ⚠️ LES CALAGES A HAUTEUR CONSTANTE DOIVENT SAUTER ICI. Ils existent pour le
   feuilletage a trois colonnes : la tracklist doit demarrer au meme Y d'un
   disque a l'autre. Empilee, une colonne capee a 210 px ROGNERAIT ses notes
   derriere une barre invisible. La fiche entiere defile a la place — une seule
   barre, cachee, comme sur fenetre basse. */
@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; }
  /* une seule colonne, en haut comme en bas */
  #fd-colonnes { grid-template-columns: 1fr; gap: 10px 0; }
  #fd-bas-zone { grid-template-columns: 1fr; grid-template-rows: auto auto; }
  #fd-bas-tete   { grid-column: 1; grid-row: 1; }
  #fd-bas-gauche { grid-column: 1; grid-row: 2; overflow-y: visible; }
  /* plus rien n'est cape : c'est la fiche qui defile */
  #fl-detail:not(.edition) #fd-colonnes { min-height: 0; align-items: start; }
  #fl-detail:not(.edition) #fd-extra,
  #fl-detail:not(.edition) #fd-notes-col { max-height: none; }
  #fl-detail:not(.edition) #fd-notes { max-height: none; }
  #fl-detail { overflow-y: auto; scrollbar-width: none; }
  #fl-detail::-webkit-scrollbar { display: none; }
  /* les credits reviennent sur une colonne : deux dans cette largeur se
     serreraient exactement comme les trois qu'on vient de defaire. */
  #fd-credits { grid-template-columns: 1fr; }
}
/* 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; }
  /* ⚠️ SAUF SUR LA FICHE D'UN DISQUE EN VENTE (09/08, capture utilisateur : « le
     chevauchement des notes vendeur et de l'invite de texte »). Ce calage à 210 px
     existe pour le FEUILLETAGE : on y passe d'un disque à l'autre, et la tracklist
     ne doit pas danser. Sur une fiche de vente on arrive UNE fois — rien à caler —
     et la note de vente, elle, peut faire dix lignes : capée, elle débordait par
     -dessus l'invite qui la suit (mesuré : zone figée à 210 px, note à 146 px et
     `overflow: visible`). La note pousse donc ce qui suit, et la page défile. */
  body.boutique-vitrine #fl-detail:not(.edition) #fd-colonnes { min-height: 0; }
  body.boutique-vitrine #fl-detail:not(.edition) #fd-extra,
  body.boutique-vitrine #fl-detail:not(.edition) #fd-notes-col { max-height: none; }
}
/* 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)); }
/* LES LISTES VOIENT MIEUX LEUR DECOR (09/08, demande utilisateur : « enlever de
   10 % le voile noir transparent du fond vivant des SETS »). Un dixieme de moins
   sur les deux extremites du degrade, pas une valeur plate : le voile est plus
   dense en bas qu'en haut, et l'aplatir changerait le modele de la piece. */
body.sets-decor #cw-fond-vivant .fv-voile {
  background: linear-gradient(rgba(16, 16, 18, 0.72), rgba(16, 16, 18, 0.81)); }
/* 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; }
/* la boucle du psyduck EST un plateau : meme etage que lui. */
#cw-fond-vivant .fv-canard { 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; }
/* L'ADAPTATEUR DU REPLI SANS VIDEO (10/08) : une fenetre de la taille d'UNE
   cellule, dans laquelle glisse la planche des 90 positions.
   ⚠️ z-index 2 — LA PLACE DE LA VIDEO DU PLATEAU, donc SOUS l'enveloppe du
   macaron (3) : c'est le trou de serrure de l'etiquette qui le decoupe a sa
   silhouette. Le poser au-dessus obligerait a le detourer soi-meme, et la
   consigne etait de ne pas compromettre sa qualite. */
/* ⚠️ LE CALQUE EST PLEIN CADRE ET MASQUE PAR LA SERRURE. Il l'a ete des le
   deuxieme jour : pose en rectangle, il DEBORDAIT de l'etiquette — qui est un
   disque (`border-radius: 50%`) — et l'on voyait ses coins. En v3, ou la camera
   est presque au-dessus du plateau, l'etiquette ne fait que 90 x 31 px et le
   debordement etait franc. Le masque vient de `poserLabel`, dans le meme repere
   plein cadre : c'est le complementaire exact du trou perce dans l'etiquette. */
#cw-fond-vivant .fv-adapt { z-index: 2; pointer-events: none; }
/* la FENETRE : une cellule de la planche, et rien d'autre */
#cw-fond-vivant .fv-adapt-fen { position: absolute; overflow: hidden; }
/* ⚠️ la planche N'EST PAS soumise a la regle `> *` du conteneur (inset:0,
   width/height 100 %) : c'est un petit-enfant. Ses cotes sont poses en ligne par
   `calerAdapt`, a l'echelle `cover`, et `max-width:none` empeche une feuille de
   style generique de la retrecir. */
#cw-fond-vivant .fv-adapt img { position: absolute; left: 0; top: 0;
                                max-width: none; will-change: transform; }
#cw-fond-vivant .fv-bras  { z-index: 4; }
#cw-fond-vivant .fv-fader { z-index: 4; }
/* ── LA LUMIERE DU JOUR (13/08) ─────────────────────────────────────────────
   Un filtre commun aux couches DIFFUSES (pose par fond-vivant.js dans la
   variable --fv-jour : luminosite + saturation selon l'heure locale). Le
   vumetre — emissif — et les voiles de teinte n'en sont pas. */
#cw-fond-vivant .fv-fond, #cw-fond-vivant .fv-lumieres,
#cw-fond-vivant .fv-spin, #cw-fond-vivant .fv-canard,
#cw-fond-vivant .fv-adapt, #cw-fond-vivant .fv-label-zone,
#cw-fond-vivant .fv-bras, #cw-fond-vivant .fv-fader,
#cw-fond-vivant .fv-entree { filter: var(--fv-jour, none); }
/* les teintes : l'or du soleil bas (fusion douce, venu du cote de la baie),
   le bleu de la nuit (multiplie), et la LAMPE artificielle du soir — un halo
   chaud en fusion `screen` sur le meuble. Opacites posees par majJour(). */
#cw-fond-vivant .fv-teinte-chaude { z-index: 5; pointer-events: none; opacity: 0;
  background: linear-gradient(115deg, rgba(255, 186, 100, 0.95) 0%,
              rgba(255, 158, 66, 0.55) 45%, rgba(140, 84, 36, 0.30) 100%);
  mix-blend-mode: soft-light; }
#cw-fond-vivant .fv-teinte-froide { z-index: 5; pointer-events: none; opacity: 0;
  background: rgb(58, 78, 134); mix-blend-mode: multiply; }
#cw-fond-vivant .fv-lampe { z-index: 5; pointer-events: none; opacity: 0;
  background: radial-gradient(ellipse 46% 38% at 63% 56%,
              rgba(255, 192, 112, 0.50), rgba(255, 172, 84, 0.16) 55%,
              rgba(0, 0, 0, 0) 76%);
  mix-blend-mode: screen; }
/* la toile du vumetre : posee sur la fenetre de la mixette — EMISSIVE, donc
   AU-DESSUS des teintes du jour (une diode perce la nuit) ; le bras et le
   fader ne traversent jamais sa fenetre. Ses cotes sont poses en ligne par
   calerVu, a l'echelle `cover` du cadre. */
#cw-fond-vivant .fv-vu    { z-index: 6; pointer-events: none; }
#cw-fond-vivant .fv-voile { z-index: 7; }   /* au-dessus des teintes ET du vumetre */
/* 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: row; }
/* LES COMMANDES VIVENT À DROITE (02/08, capture annotée : « déplacer les
   informations trop petites et tassées en partie basse sur le côté droit »).
   Le plan de travail est un CARRÉ : dans un panneau large, il laisse forcément
   deux marges vides sur les côtés, pendant que les commandes s'écrasaient sur
   une bande de trente pixels en bas. On rend cette marge utile — la colonne
   gagne de la place sans rien prendre au carré, qui n'aurait de toute façon
   pas grandi (c'est la HAUTEUR qui le borne). */
.cal-cote { flex: 0 0 366px; display: flex; flex-direction: column; gap: 14px;
  padding: 12px; overflow-y: auto; background: rgba(20, 20, 22, .92);
  border-left: 1px solid var(--bord); }
.cal-scene { position: relative; flex: 1 1 auto; min-width: 0; 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; }
/* LA TRAME DE REPÈRES (02/08) : le calque qu'on allume pour juger une rotation.
   ⚠️ `pointer-events: none` est load-bearing — sans lui la trame volerait le
   glisser destiné au plan, et le geste principal de l'atelier serait mort. */
.cal-trame { position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; }
.cal-trame-btn { flex: none; }
.cal-defaut-btn { flex: none; position: relative; }
.cal-defaut-n { position: absolute; top: -5px; right: -5px; min-width: 13px;
  height: 13px; line-height: 13px; padding: 0 2px; border-radius: 7px;
  background: var(--accent); color: #16120f; font-size: 9px; text-align: center; }
.cal-defaut-n:empty { display: none; }
/* LE PANNEAU DES DOUZE MOTS — EN COLONNE À DROITE (02/08, capture utilisateur :
   « déplacer les informations trop petites et tassées en partie basse sur le côté
   droit »). En bandeau bas, les deux familles se disputaient une seule ligne et
   les chips, faute de largeur, se comprimaient jusqu'à casser les mots au milieu.
   ⚠️ LA CAUSE PROFONDE ÉTAIT LE FLEX : un enfant flex peut rétrécir SOUS son
   contenu. `flex: none` + `white-space: nowrap` sur les chips l'interdit — sans
   ces deux-là, le même écrasement reviendrait dans n'importe quelle disposition.
   Le plan de travail est un CARRÉ centré dans une boîte bien plus large : la
   colonne se loge dans la marge de droite sans jamais le recouvrir. */
.cal-defauts { flex: none; display: flex; flex-direction: column; gap: 16px;
  padding-top: 12px; border-top: 1px solid var(--bord); }
.cal-def-fam { display: flex; flex-wrap: wrap; gap: 6px; min-width: 0; }
.cal-def-titre { flex-basis: 100%; font-size: 10.5px; color: var(--sourd);
  text-transform: uppercase; letter-spacing: .07em; margin-bottom: 3px; }
/* ⚠️ `flex: none` + `white-space: nowrap` sont load-bearing : un enfant flex
   peut rétrécir SOUS son contenu, et c'est ce qui cassait les mots au milieu
   dans le bandeau bas (capture du 02/08). Sans ces deux-là, le même écrasement
   reviendrait dans n'importe quelle disposition. */
/* ⚠️ TROIS CLASSES, ET C'EST OBLIGATOIRE : `.cal-boite button` plus bas impose
   à TOUS les boutons de l'atelier une pastille ronde de 22 px — c'est ce qui
   convient aux ⟲ ⦿ ✓ ✕, et c'est ce qui écrasait les douze mots en petits
   ronds illisibles (mesuré : 22 px de large pour « resolución insuficiente »).
   Un sélecteur à deux classes perdrait contre (0,2,1) ; il en faut trois. */
.cal-boite .cal-defauts .cal-def { flex: none; width: auto; height: auto;
  white-space: nowrap; font-size: 12px; padding: 4px 10px; line-height: 1.35;
  border-radius: 12px; background: transparent; color: var(--texte);
  border: 1px solid var(--bord); cursor: pointer; }
.cal-boite .cal-defauts .cal-def:hover { color: var(--texte);
  border-color: var(--accent); }
.cal-boite .cal-defauts .cal-def.actif { background: var(--accent);
  color: #16120f; border-color: var(--accent); }
/* écran étroit : plus de marge à droite du carré, la colonne repasse en bas */
@media (max-width: 1023px) {
  .cal-boite { flex-direction: column; }
  .cal-cote { flex: none; max-height: 42vh; border-left: none;
    border-top: 1px solid var(--bord); }
}
/* une image signalée se voit dans la galerie sans qu'on rouvre l'atelier */
.bq-img.img-defaut { outline: 1px dashed rgba(232, 80, 60, .85);
  outline-offset: -1px; }
.cal-barre button.actif { background: var(--accent); color: #16120f;
  border-color: var(--accent); }
/* LA GRILLE DES GABARITS (02/08) : trois vignettes par rangée, dessinées aux
   vraies cotes. Une liste déroulante obligeait à lire sept intitulés proches
   (« A Side - Label LP / Maxi »…) pour un choix qui se fait à l'œil ; le dessin
   le rend immédiat, et le rapport trou/extérieur distingue les deux 45 tours. */
.cal-gabarits { flex: none; display: grid; gap: 8px;
  grid-template-columns: repeat(3, 1fr); }
.cal-boite .cal-gabarits .cal-gab { width: auto; height: auto; display: flex;
  align-items: center; justify-content: center; padding: 7px;
  border: 1px solid var(--bord); border-radius: 8px; background: transparent;
  color: var(--sourd); cursor: pointer; }
.cal-boite .cal-gabarits .cal-gab svg { width: 100%; height: auto;
  aspect-ratio: 1 / 1; display: block; }
.cal-boite .cal-gabarits .cal-gab:hover { color: var(--texte);
  border-color: var(--accent); }
.cal-boite .cal-gabarits .cal-gab.actif { color: #16120f; background: var(--accent);
  border-color: var(--accent); }
.cal-boite .cal-gabarits .cal-gab-aucun { font-size: 30px; line-height: 1; }
.cal-barre { flex: none; display: flex; align-items: center; flex-wrap: wrap;
  gap: 10px; padding: 0; background: transparent; border-top: none; }
/* LES BOUTONS D'ACTION, PLUS GRANDS (« on n'y voit pas assez ») : 22 px de
   pastille étaient lisibles dans un bandeau, pas dans une colonne où l'œil
   revient de vignettes de 58 px. */
.cal-boite .cal-barre button { width: 34px; height: 34px; font-size: 15px; }
.cal-boite .cal-barre .cal-defaut-n { top: -3px; right: -3px; min-width: 15px;
  height: 15px; line-height: 15px; font-size: 10px; }
.cal-choix { flex-basis: 100%; min-width: 0; font-size: 12px; padding: 5px 6px;
  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: 78px; font-size: 13px; padding: 6px 6px; 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: 12px; 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(19, 19, 19, .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(19, 19, 19, .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(19, 19, 19, .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; }
}

/* --- LA PLANCHE DE REVUE DES ETIQUETTES (03/08) -------------------------------
   Le cadrage est previsualise en CSS : l'image porte la transformation exacte de
   la decoupe, et le plan est masque d'un disque de 80 % -- le meme rapport que
   DECOUPE_PART, sans quoi l'apercu mentirait sur ce qu'on obtiendra. */
/* LE TRAIT AU-DESSUS DES TITRES DISPARAIT DU TABLEAU DE BORD (03/08, demande
   utilisateur). Il separait des sections empilees ; depuis que les listes sont
   des COLONNES cote a cote, il ne separe plus rien -- il barre le haut d'une
   colonne. Ailleurs sur le site, ou les sections se suivent, il reste utile. */
@media (min-width: 901px) and (pointer: fine) {
  body.tableau-plein .titre-section { border-top: none; padding-top: 0;
    margin-top: 0; }
  /* LE TITRE RENTRE DANS SON ENCADREMENT (03/08, demande utilisateur) : il flottait
     au-dessus de la carte, si bien qu'une colonne montrait un mot suspendu puis un
     cadre. Dedans, chaque colonne devient un seul objet. On le remonte par une marge
     negative egale au padding de la carte, plutot que de deplacer le balisage : le
     titre reste un h2 avant sa section, ce que lisent les liseuses d'ecran. */
  /* ⚠️ ET ELLES COMMENCENT A LA MEME LIGNE QUE LES AUTRES (08/08, fleches rouges
     de la capture). Les colonnes SANS titre -- les chiffres, les portes -- partent
     du haut du conteneur ; celles a titre partaient 16 px plus bas, a cause du
     rembourrage haut du titre. On le retire, et l'on retire d'autant celui que la
     carte posait pour compenser : le texte garde sa place DANS la carte, c'est
     l'ensemble qui remonte. */
  /* ⚠️ LE TITRE NE DOIT OCCUPER AUCUNE HAUTEUR (08/08, 2e passe). Un premier
     correctif retirait son rembourrage haut pour remonter la colonne : il a sorti
     les titres de leur cadre au lieu de remonter les cadres -- le titre restait
     DANS le flux, et la marge negative ne suffisait plus a le rattraper.
     On le sort donc du flux : pose en absolu sur la colonne, il ne pousse plus
     rien. Le cadre part alors du HAUT de la colonne, exactement comme les tuiles
     voisines, et le titre se dessine dedans, dans le rembourrage que la carte lui
     reserve.
     ⚠️ ET CETTE MESURE N'EST PLUS DEVINEE (11/08 — « les textes chevauchent
     toujours avec les titres »). Elle valait 42 px en dur pour un titre qui en
     fait 48 en francais, 41 en espagnol, et DAVANTAGE des qu'il passe a la ligne
     (une colonne etroite, une langue plus longue). Le contenu commencait donc
     6 px DANS le titre, et bien plus quand il se repliait. La hauteur reelle est
     desormais mesuree par le script de la page et posee ici en `--titre-h` ; la
     valeur ci-dessous n'est qu'un repli avant que le script ne passe. */
  body.tableau-plein .dash-col { position: relative; --titre-h: 48px; }
  body.tableau-plein .dash-col .titre-section {
    position: absolute; top: 0; left: 0; right: 0; z-index: 1;
    margin: 0; padding: 14px 18px 10px;
    /* ⚠️ PLUS D'APLAT SOUS LE TITRE (11/08, capture annotee). Il avait ete pose le
       08/08 pour une vraie raison — la liste defilait A TRAVERS ses lettres — et
       le retirer seul ramenerait ce defaut. Le remede est celui du bas de colonne,
       applique en haut : la liste s'efface AVANT d'atteindre le titre (voir le
       masque ci-dessous). Rien n'est peint, et rien ne traverse. */
    pointer-events: none;
}
  body.tableau-plein .dash-col .carte-info {
    padding-top: calc(var(--titre-h) + 8px); }
  /* ⚠️ ET LA PREMIERE CARTE D'UNE COLONNE N'A PAS DE MARGE HAUTE (08/08, 3e passe —
     MESURE : les colonnes partent toutes de 96 px, mais `.carte-info` porte un
     `margin-top: 20px` general qui poussait le cadre a 116, quand la tuile voisine
     restait a 96. C'etait cela, le desalignement, et ni le titre ni le rembourrage
     n'y etaient pour rien. Les cartes SUIVANTES d'une meme colonne (les achats sous
     les signaux) gardent la leur : c'est un ecart entre deux cartes, pas un retrait
     du haut. */
  body.tableau-plein .dash-col > .carte-info:first-of-type { margin-top: 0; }
}
/* LE « + » DE LA DERNIERE LIGNE : derouler les plus anciens sans quitter la
   page. Les lignes au-dela des premieres sont posees mais cachees -- tout est
   deja la, le geste ne coute aucun aller-retour. */
.dash-plus { list-style: none; }
.dash-plus button { width: 100%; text-align: left; background: transparent;
  border: none; border-top: 1px dashed var(--bord); color: var(--sourd);
  font-size: 11.5px; padding: 7px 2px 3px; cursor: pointer; }
.dash-plus button:hover { color: var(--accent); border-top-color: var(--accent); }
.alerte.dash-vieille { display: none; }
.liste-alertes.deplie .alerte.dash-vieille { display: flex; }

.masse-intro { margin: 2px 0 10px; font-size: 13px; }
.masse-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 6px 0 18px; }
.masse-actions .bouton { width: auto; margin: 0; }
.masse-actions .bouton.actif { background: var(--accent); color: #16120f;
  border-color: var(--accent); }
.masse-compte { margin-left: auto; font-size: 12.5px; }
.masse-planche { display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); }
.masse-vign { margin: 0; position: relative; }
/* LES DEUX OUTILS D'UNE VIGNETTE vivent HORS du plan : le clip-path qui y
   dessine le disque rognerait tout ce qu'on y mettrait, boutons compris. */
.masse-outils { position: absolute; top: 5px; right: 5px; display: flex; gap: 4px;
  opacity: 0; transition: opacity .15s; }
.masse-vign:hover .masse-outils, .masse-vign.avant .masse-outils,
.masse-vign.masse-touche .masse-outils { opacity: 1; }
.masse-outils button { width: 24px; height: 24px; border-radius: 50%;
  background: rgba(20, 20, 22, .82); border: 1px solid var(--bord);
  color: var(--texte); font-size: 12px; line-height: 1; cursor: pointer; }
.masse-outils button:hover { border-color: var(--accent); color: var(--accent); }
/* une vignette RETOUCHEE se signale : c'est le geste de la main, il doit se voir
   dans la planche sans qu'on ait a se souvenir de ce qu'on a fait. */
.masse-vign.masse-touche .masse-plan { border-color: var(--accent); }
.masse-plan { position: relative; width: 100%; aspect-ratio: 1 / 1;
  overflow: hidden; border-radius: 10px; background: rgba(255, 255, 255, .03);
  border: 1px solid var(--bord); cursor: grab; touch-action: none;
  /* ⚠️ PAS DE radial-gradient ICI, ET C'EST UNE ERREUR PAYEE : dans un gradient
     radial sans taille explicite, un pourcentage se rapporte a la distance
     centre -> COIN LE PLUS ELOIGNE, soit cote x racine(2)/2. Un masque « 39,6 % »
     donnait donc un disque 29 % trop petit, et TOUS les macarons proposes
     arrivaient rognes. `clip-path: circle(r%)` sur une boite CARREE, lui, resout
     le pourcentage sur le cote : 39,6 % = le rayon voulu, exactement. Et il
     decoupe aussi le pointeur, ce qui le rend MESURABLE (elementFromPoint). */
  clip-path: circle(39.6%); }
.masse-plan img { position: absolute; left: 50%; top: 50%;
  transform-origin: center center; user-select: none; -webkit-user-drag: none; }
.masse-cercle { position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; opacity: 0; }
.masse-planche.avant .masse-plan, .masse-vign.avant .masse-plan {
  clip-path: none; }
.masse-planche.avant .masse-cercle, .masse-vign.avant .masse-cercle { opacity: 1; }
.masse-vign figcaption { display: flex; align-items: flex-start; gap: 6px;
  margin-top: 6px; }
.masse-oui { display: flex; align-items: flex-start; gap: 6px; flex: 1 1 auto;
  min-width: 0; font-size: 11.5px; color: var(--sourd); cursor: pointer; }
.masse-oui input { margin: 2px 0 0; flex: none; }
.masse-oui span { display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden; }
.masse-non { flex: none; width: 22px; height: 22px; border-radius: 50%;
  background: transparent; border: 1px solid var(--bord); color: var(--sourd);
  font-size: 11px; line-height: 1; cursor: pointer; }
.masse-non:hover { border-color: var(--rouge); color: var(--rouge); }
.masse-plan:active { cursor: grabbing; }
.masse-vign.masse-envoi { opacity: .45; }
.masse-vign.masse-partie { opacity: .25; }
.masse-vign.masse-rate .masse-plan { border-color: var(--rouge); }

/* --- « À PROPOS » : LE DÉCOR ENTRE DEUX BLOCS (03/08) ------------------------
   L'image du dehors a une limite d'ombre nette à 63 % de sa largeur — mesurée sur
   le rendu : au-delà c'est le mur noir. Les informations d'identité s'y posent
   sans voile ; l'avancement occupe le quart gauche, sur le corps sombre de
   Pikachu. Entre les deux, on laisse voir la scène : c'est elle le sujet. */
body.apropos-scene .conteneur { max-width: none; padding: 0; }
/* UNE SEULE COLONNE, A GAUCHE, ET ELLE SEULE DEFILE (08/08, demande utilisateur :
   « n'utiliser que la partie gauche de l'ecran avec un scroll des informations
   uniquement ; une seule colonne d'information »).
   La page est tenue dans la fenetre par `body.plein` ; la colonne prend la hauteur
   restante et defile en interne, barre masquee comme partout ailleurs sur le site.
   Le decor reste donc entier et immobile a droite pendant qu'on lit -- c'etait le
   sens de la demande : la scene est le sujet, le texte se pose dessus. */
/* LE TEXTE À GAUCHE, LES MESURES À DROITE (09/08) : deux colonnes aux deux bords,
   la scène entre elles. Seule celle de gauche défile — c'est elle qui porte le
   texte ; les mesures tiennent d'un coup d'œil et restent en place. */
/* ⚠️ LE DÉCOR EST EN « COVER » : SON MONTANT NE TOMBE PAS À UNE POSITION FIXE
   (09/08, demande utilisateur : « aligner avancement et les textes à 3 mm à droite
   du trait de la fenêtre du fond qui sépare la partie noire »). L'image de fond
   fait 1668 × 943 et `object-fit: cover` la met à l'échelle du PLUS GRAND des deux
   rapports, puis la centre : l'arête se déplace donc avec la fenêtre, et une
   valeur en dur dériverait au premier redimensionnement.
   Le même calcul existe déjà DEUX fois en JavaScript (`calerCouches` et
   `poserLabel`, dans fond-vivant.js) mais n'est pas exporté ; il est ici en CSS
   pur — donc sans écouteur de redimensionnement à poser ni à démonter.
   ⚠️ LA FRACTION EST MESURÉE SUR L'IMAGE RÉELLEMENT SERVIE, pas sur la copie de
   l'arbre local : les deux diffèrent (0,733 en production contre 0,622 ici).
   Méthode : pour chaque ligne, la colonne où la moyenne des 40 px de droite tombe
   sous 12/255 avec une chute d'au moins 25 — 340 lignes sur 463 se groupent à
   x = 1223 (écart-type 3,6 px), sur 76 % de la hauteur. À refaire si le fond est
   re-rendu. */
body.apropos-scene {
  --fv-ech: max(calc(100vw / 1668), calc(100vh / 943));
  --fv-dx: calc((100vw - 1668 * var(--fv-ech)) / 2);
  --fv-arete: calc(var(--fv-dx) + 1223 * var(--fv-ech));
  --ap-haut: 34px; }
/* ⚠️ ET LE VISITEUR NON CONNECTÉ NE VOIT PAS LA MÊME IMAGE. /a-propos est une
   page PUBLIQUE : sans session, `base.html` pose `entree-fond` et le décor joue
   `v4-entree.webm` EN BOUCLE et PLEIN CADRE par-dessus la pièce — un autre plan,
   donc un autre montant. Mesuré sur deux images du film (t = 0,2 s et 3,2 s) par
   le même critère, sur le fichier DE PRODUCTION : x = 903-904 sur 1668, soit
   0,5420, stable sur trois images (t = 0,2 / 2 / 3,6 s). Sans cette ligne, le
   bloc se serait posé au milieu de rien pour tout visiteur — c'est-à-dire pour
   tous ceux à qui cette page est destinée.
   ⚠️ SIGNAL FAIBLE, ASSUMÉ : ce montant ne se lit que sur ~10 % de la hauteur
   (24 lignes retenues contre 340 pour la pièce). Le film d'entrée est sombre ;
   l'alignement y est une approximation honnête, pas une mesure franche. */
body.apropos-scene.entree-fond { --fv-arete: calc(var(--fv-dx) + 904 * var(--fv-ech)); }
/* et le titre ne colle plus à la barre supérieure. ⚠️ EN PADDING, JAMAIS EN
   MARGE : `.conteneur` est en `overflow: hidden` et la hauteur de la colonne se
   résout en `height: 100%` — une marge la pousse sans la rétracter et lui coupe
   le bas (mesuré : 40 px rognés). Le padding, lui, entre dans la boîte. */
.ap-plan { display: flex; justify-content: space-between; align-items: flex-start;
           height: 100%; gap: 24px; position: relative;
           padding-top: var(--ap-haut); }
.ap-mesures { width: min(34%, 460px); flex: none; padding: 6px 24px 0 0;
              align-self: flex-start; }
@media (min-width: 901px) {
  /* le bord gauche du bloc EST l'arête du décor, plus 3 mm. Sorti du flux : sa
     place ne dépend plus de la largeur de la colonne de texte, seulement du
     décor. ⚠️ UN PLANCHER TOUT DE MÊME (`min`) : sur une fenêtre haute et étroite
     le « cover » pousse l'arête très à droite, et le bloc n'aurait plus de quoi
     écrire ses libellés — on lui garde 330 px. */
  /* ⚠️ EN `fixed`, PAS EN `absolute` : l'arête est exprimée en unités de FENÊTRE
     (vw/vh), comme le décor lui-même, qui est en `position: fixed; inset: 0`. La
     caler sur un ancêtre supposerait que celui-ci commence au bord de la fenêtre
     — MESURÉ FAUX (le corps de page démarre à 15 px dans le panneau d'essai), et
     l'alignement aurait dérivé d'autant. La page ne défile pas à cette largeur
     (`body.plein` est en `overflow: hidden`), donc `fixed` ne fige rien qui
     devrait bouger. */
  .ap-mesures { position: fixed; padding: 0; width: auto;
    top: calc(var(--entete-h, 56px) + var(--ap-haut));
    left: min(calc(var(--fv-arete) + 3mm), calc(100vw - 330px));
    right: 24px;
    max-height: calc(100vh - var(--entete-h, 56px) - var(--ap-haut) - 24px);
    overflow-y: auto; scrollbar-width: none; }
}
.ap-mesures .ap-h2 { margin-top: 0; }
@media (max-width: 900px) {
  .ap-plan { display: block; height: auto; }
  /* ⚠️ PLUS DE VOILE DERRIÈRE LE TEXTE (09/08, retour utilisateur : « sur A
     PROPOS dans iPad iOS et mobile, enlever le voile noir derrière le texte qui
     empêche la lecture du fond »). Il avait été posé pour la lisibilité, et il la
     payait trop cher : un rectangle opaque sur une pièce en trois dimensions, la
     seule page où le décor est le sujet. L'ombre portée fait le même travail —
     elle détache les lettres de ce qu'il y a derrière SANS rien masquer. */
  .ap-mesures { width: auto; padding: 16px 16px 0; margin: 0 0 14px;
                background: none; }
}
/* L'ESSENTIEL, EN QUATRE LIGNES (09/08) : la seule liste que l'on lit vraiment.
   Le nom de la famille en tete de ligne fait le relief — on trouve « la boutique »
   d'un coup d'oeil sans lire les quatre. */
.ap-quoi { list-style: none; padding: 0; margin: 10px 0 4px; }
.ap-quoi li { margin: 0 0 11px; font-size: 14px; line-height: 1.62;
              color: var(--texte); }
.ap-quoi strong { font-weight: 600; }
/* la liste exhaustive se deplie : elle repond a une question qu'on ne pose pas
   toujours, et elle ne doit pas se lire en travers du reste */
.ap-detail { margin: 18px 0 4px; }
.ap-detail summary { cursor: pointer; color: var(--sourd); font-size: 13px;
                     padding: 4px 0; }
.ap-detail summary:hover { color: var(--accent); }
.ap-colonne { width: min(46%, 640px); height: 100%; overflow-y: auto;
  padding: 6px 30px 40px 24px; scrollbar-width: none; }
.ap-colonne::-webkit-scrollbar { display: none; }
.ap-titre { font-size: 34px; margin: 0 0 4px; line-height: 1.1; }
.ap-version { font-size: 13px; color: var(--sourd); margin: 0 0 18px; }
.ap-h2 { font-size: 15px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--texte); margin: 30px 0 4px; font-weight: 400; }
.ap-note { font-size: 12px; margin: 0 0 10px; }
.ap-desc { font-size: 13.5px; line-height: 1.65; margin: 0 0 12px; max-width: 52ch; }
/* LES GRAPHIQUES SONT CEUX DE /stats (memes fonctions serveur) : ici on ne fait
   que les laisser respirer et suivre la largeur de la colonne. */
.ap-graphe { margin: 0 0 8px; }
.ap-graphe svg { width: 100%; height: auto; display: block; }
.ap-contact { font-size: 13px; margin: 0 0 14px; }
.ap-contact a { color: var(--accent); text-decoration: none; }
.ap-contact a:hover { text-decoration: underline; }
/* MOBILE : la colonne prend toute la largeur, sur un voile qui la rend lisible ;
   la page redevient defilante (body.plein ne s'applique qu'au-dela de 900 px). */
@media (max-width: 900px) {
  .ap-colonne { width: auto; height: auto; overflow: visible; margin: 0 0 14px;
    padding: 16px; background: none; }
  .ap-titre { font-size: 26px; }
  /* la lisibilité sans le voile : une ombre serrée, deux fois — la première
     détache la lettre, la seconde éteint un fond clair sous elle. */
  body.apropos-scene .ap-colonne, body.apropos-scene .ap-mesures {
    text-shadow: 0 1px 2px rgba(0, 0, 0, .95), 0 0 10px rgba(0, 0, 0, .8); }
  /* les barres et la jauge restent lisibles : elles ont leur propre encre */
  body.apropos-scene .ap-graphe { text-shadow: none; }
}

/* ═══════ LA FICHE PUBLIQUE D'UN ARTICLE (08/08) ═══════════════════════════
   Une page de VENTE, pas une fiche de collection : la pochette en grand a gauche,
   ce qu'il faut pour se decider a droite. Rien du dossier prive n'y entre (voir
   article.html). */
/* 08/08 (capture annotee) : le retour a la boutique quitte sa ligne propre pour
   le BOUT DE LA LIGNE DU TITRE -- la tete de fiche porte alors le disque a
   gauche et la sortie a droite, au lieu de deux lignes pour une seule idee. */
.art-tete { display: flex; align-items: flex-start; gap: 24px; }
.art-tete #fd-titre { flex: 1 1 auto; min-width: 0; }
.art-retour { margin: 0; flex: none; padding-top: 8px; white-space: nowrap; }
.art-retour a { color: var(--sourd); text-decoration: none; font-size: 13px; }
.art-retour a:hover { color: var(--texte); }
/* ⚠️ LES MEMES MESURES QUE LA PAGE FEUILLETAGE (08/08, demande utilisateur :
   « respecter les tailles et la diagrammation de la page feuilletage afin que les
   elements soient poses identiquement »). On reprend les VALEURS de #fl-split /
   #fl-gauche : gouttiere de 38 px, colonne de gauche a min(100vh-280px, 42%,
   800px), la fiche prenant le reste.
   On ne reprend PAS les regles elles-memes : la fiche du feuilletage vit dans une
   page SANS defilement (body.plein) -- sa pochette y est absolue dans une scene a
   `inset: 0`, et #fl-droite y est en `overflow: hidden`. Poser cela sur une page
   qui defile rognerait la fiche. Memes tailles, donc, dans une page normale. */
.art-fiche { display: flex; gap: 38px; align-items: flex-start; }
/* la NOTE DE VENTE, éditable par le vendeur seul (09/08) : elle se donne comme
   un texte, pas comme un formulaire — c'est le clic qui ouvre le champ. */
/* ⚠️ LA NOTE PREND LA COLONNE VIDE (09/08, retour utilisateur : « l'espace de
   lecture et d'écriture des notes de vente est dérisoire »). Sur la fiche d'un
   disque en vente, la colonne du milieu ne porte rien — la fiche de collection y
   met Net Cost / Net Price / vendeur, qui n'ont pas leur place dans une boutique.
   La note s'y étend donc : de 159 px on passe à toute la largeur des deux
   dernières colonnes, et le texte se lit enfin. Les trois colonnes du feuilletage
   restent celles qu'elles étaient — c'est une colonne inoccupée qu'on emploie,
   pas une géométrie qu'on change. */
body.boutique-vitrine #fd-notes-col { grid-column: 2 / -1; }
.art-note-l { display: block; margin: 0 0 6px; }
.art-note { font-size: 13px; line-height: 1.6; white-space: pre-wrap;
            overflow-wrap: anywhere; min-height: 4.8em; }
.art-note-editable { cursor: text; }
.art-note-editable:hover { outline: 1px dashed var(--bord); outline-offset: 3px; }
.art-note-champ { width: 100%; box-sizing: border-box; font: inherit;
  font-size: 13px; line-height: 1.6; color: var(--texte); resize: vertical;
  min-height: 7em;
  background: rgba(19, 19, 19, .72); border: 1px solid var(--bord);
  border-radius: 7px; padding: 6px 8px; }
.art-note-aide { font-size: 10.5px; line-height: 1.45; margin: 8px 0 0;
                 max-width: 52ch; }
.art-note-etat { font-size: 11px; margin: 4px 0 0; min-height: 14px; }
/* sur la fiche, les chips sont des LIENS : on leur ote le soulignement par defaut
   (le trait ne doit dire qu'une chose, la selection). */
#bq-filtres.art-filtres .fl-chip { display: block; }
/* ⚠️ `:not(.actif)` : sans lui, oter le soulignement des LIENS effacait aussi le
   TRAIT DE SELECTION (meme specificite, regle plus loin dans le fichier --
   mesure : la chip de la famille du disque n'etait plus soulignee). */
#bq-filtres.art-filtres .fl-chip:not(.actif) { text-decoration: none; }
.art-gauche { flex: 0 0 42%; }
@media (min-width: 901px) {
  .art-gauche { flex: 0 0 auto; width: min(calc(100vh - 280px), 42%, 800px); }
}
.art-droite { flex: 1 1 0; min-width: 0; }
/* la pochette porte l'icone du panier dans son coin : d'ou le position relative */
/* LA CARTE DE GAUCHE : c'est une fiche de vitrine (.article), posee dans la
   colonne du feuilletage. Elle en garde donc le fond, le cadre et les deux traits
   du pied ; on ne lui donne que sa largeur. */
/* la page de detail prend la largeur du feuilletage (1500 px) : ses trois colonnes
   ont alors les memes proportions ET la meme place qu'a la collection. */
body.article-large .conteneur { max-width: 1500px; }
.art-carte { width: 100%; }
/* la fiche de boutique reprend les conteneurs du feuilletage : ses proportions
   viennent donc des memes declarations. Deux reserves, parce que cette page
   DEFILE alors que le feuilletage tient dans l'ecran : la zone basse n'a pas a
   remplir une hauteur, et la tracklist occupe les deux premieres colonnes comme
   la-bas (grid-column 1 / span 2). */
.art-droite #fd-bas-zone { flex: none; min-height: 0; }
.art-droite #fd-colonnes { align-items: start; }
.art-carte .article-image { aspect-ratio: 1 / 1; }
.art-poche img { width: 100%; height: 100%; object-fit: cover; display: block; }
.art-poche-vide { width: 100%; height: 100%; }
.art-vignettes { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.art-vignette { width: 54px; height: 54px; padding: 0; border-radius: 3px;
                border: 1px solid var(--bord); background: none; cursor: pointer;
                overflow: hidden; opacity: .6; }
.art-vignette.actif, .art-vignette:hover { opacity: 1; border-color: var(--texte); }
.art-vignette img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* titre et artiste en PIX, comme sur les cartes de la vitrine */
.art-titre { font-family: "PIX Dot", var(--titres); font-size: 27px;
             letter-spacing: .5px; margin: 0; line-height: 1.25; }
.art-artiste { font-family: "PIX Dot", var(--titres); font-size: 18px;
               letter-spacing: .4px; color: var(--sourd); margin: 6px 0 0; }
.art-meta { color: var(--sourd); font-size: 13px; display: flex; flex-wrap: wrap;
            align-items: center; column-gap: 6px; row-gap: 3px; margin: 16px 0 0; }
.art-sous-titre { display: block; color: var(--sourd); font-size: 11px;
                  letter-spacing: .08em; text-transform: uppercase; margin-bottom: 6px; }
.art-note { margin-top: 26px; }
.art-note p { margin: 0; white-space: pre-wrap; line-height: 1.6; }
.art-pistes { margin-top: 26px; }
.art-pistes ol { list-style: none; margin: 0; padding: 0; }
.art-pistes li { display: flex; align-items: baseline; gap: 10px; padding: 3px 0;
                 font-size: 13.5px; }
.art-repere { color: var(--sourd); font-size: 12px; min-width: 30px; }
.art-piste-titre { flex: 1 1 auto; min-width: 0; }
.art-duree { color: var(--sourd); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.art-discogs { margin-top: 26px; }
.art-discogs a { color: var(--sourd); font-size: 13px; }
@media (max-width: 900px) {
  .art-fiche { display: block; }
  .art-gauche { width: 100%; }
  .art-droite { margin-top: 20px; }
  .art-titre { font-size: 22px; }
}

/* ═══════ LA LOUPE DE LA VITRINE (08/08) ══════════════════════════════════
   Elle vit dans la rangee des vues, avec les chips : c'est la barre d'outils de
   la boutique. Le champ n'apparait qu'au clic — une vitrine n'a pas a montrer un
   formulaire tant qu'on ne cherche rien. */
/* elle vit dans la BARRE SUPERIEURE : meme gabarit que la loupe du membre
   (.entete-loupe), dont elle reprend la classe — recopier des valeurs, c'est
   accepter qu'elles divergent. */
.bq-loupe { cursor: pointer; }
.bq-loupe.actif { color: var(--accent); }
.bq-q { background: rgba(19, 19, 19,.72); border: 1px solid var(--bord);
        color: var(--texte); border-radius: 999px; padding: 3px 12px;
        font: inherit; font-size: 13px; width: min(210px, 34vw); }
.bq-q:focus { outline: none; border-color: var(--texte); }
.bq-resultats { font-size: 12.5px; }
/* ⚠️ !important : la pagination pose un `display` EN LIGNE sur les fiches hors
   page ; sans cela, une fiche ecartee par la recherche mais gardee par la
   pagination resterait visible. */
/* « Terminer » occupe la place du crayon dans la rangée des vues (09/08) :
   même gabarit de chip, l'accent pour dire que c'est l'action qui clôt. */
.bq-fin-chip { color: var(--accent); border-color: var(--accent); cursor: pointer; }
.bq-fin-chip:hover { background: var(--accent); color: #16120f; }
/* LES BLOCS DE SECTION (09/08) : un intitulé et ses disques, d'un seul tenant.
   Le bloc occupe `--bq-col` colonnes de la grille de page et range ses disques
   sur autant de colonnes : deux blocs de 2 côte à côte font donc une ligne de
   deux intitulés et quatre pochettes, ce qui était la demande. */
.bq-bloc { grid-column: span var(--bq-col, 2); min-width: 0; }
.bq-bloc-tete { display: flex; align-items: center; gap: 8px; margin: 0 0 10px;
                border-bottom: 1px solid var(--bord); padding-bottom: 6px; }
.bq-bloc-nom, .bq-bloc-titre { font-family: "PIX Dot 100", var(--titres);
  font-size: 17px; letter-spacing: .02em; margin: 0; flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bq-bloc-titre { background: none; border: none; color: var(--texte); padding: 2px 0; }
.bq-bloc-titre:focus { outline: 1px dashed var(--bord); outline-offset: 2px; }
.bq-bloc-texte { width: 100%; box-sizing: border-box; font: inherit; font-size: 12px;
  color: var(--texte); background: rgba(19, 19, 19,.6); border: 1px solid var(--bord);
  border-radius: 7px; padding: 4px 7px; margin: 0 0 8px; resize: vertical; }
.bq-bloc-desc { font-size: 12.5px; line-height: 1.5; color: var(--sourd);
                margin: 0 0 10px; max-width: 60ch; }
.bq-bloc-grille { display: grid; gap: 16px;
                  grid-template-columns: repeat(var(--bq-col, 2), minmax(0, 1fr)); }
/* le bloc SAISI se soulève, comme une fiche qu'on déplace */
.bq-bloc.en-deplacement { opacity: .45; }

/* ═══ LE PANNEAU DE FACETTES (09/08) ═══════════════════════════════════════
   « Comme sur Discogs pour les filtres » : une colonne à gauche, la vitrine à
   droite. Le panneau se lit d'un coup d'œil — un titre par famille, une valeur
   par ligne avec son compte — et il se ferme sur petit écran, où la vitrine a
   besoin de toute la largeur. */
.bq-plan { display: flex; align-items: flex-start; gap: 26px; }
.bq-corps { flex: 1 1 auto; min-width: 0; }
.bq-facettes { flex: 0 0 226px; width: 226px;
  position: sticky; top: calc(var(--entete-h, 56px) + 12px);
  max-height: calc(100vh - var(--entete-h, 56px) - 32px);
  overflow-y: auto; scrollbar-width: none;
  padding: 2px 10px 14px 0; }
.bq-facettes::-webkit-scrollbar { display: none; }
.bq-facettes-btn { display: none; }

.bqf-tete { display: flex; align-items: center; justify-content: space-between; }
.bqf-tete h2 { font-family: var(--titres); font-size: 15px; font-weight: 400;
  margin: 0 0 8px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--sourd); }
.bqf-fermer { display: none; background: none; border: none; color: var(--sourd);
  font-size: 17px; cursor: pointer; padding: 0 2px; }

.bqf-q { width: 100%; box-sizing: border-box; margin: 0 0 14px;
  background: rgba(19, 19, 19, .72); border: 1px solid var(--bord);
  border-radius: 8px; color: var(--texte); font: inherit; font-size: 13px;
  padding: 7px 10px; }
.bqf-q:focus { outline: none; border-color: var(--accent); }

/* les filtres actifs : ce qu'on a fait, et comment le défaire — en tête, parce
   qu'on les cherche du regard avant tout le reste */
.bqf-actifs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; }
.bqf-chip { background: var(--accent); color: #16120f; border: none;
  border-radius: 11px; font: inherit; font-size: 11.5px; padding: 3px 9px;
  cursor: pointer; }
.bqf-chip:hover { opacity: .82; }
.bqf-effacer { background: none; border: none; color: var(--sourd);
  font: inherit; font-size: 11.5px; text-decoration: underline; cursor: pointer;
  padding: 3px 2px; }
.bqf-effacer:hover { color: var(--accent); }

.bqf-groupe { margin: 0 0 15px; }
.bqf-groupe h3 { font-size: 11px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--sourd); font-weight: 600; margin: 0 0 5px; }
.bqf-groupe ul { list-style: none; margin: 0; padding: 0; }
/* ⚠️ UNE VALEUR EST UN BOUTON PLEINE LARGEUR, pas un lien : on la coche et on la
   décoche, et la cible doit être grande — au doigt comme à la souris. */
.bqf-val { display: flex; align-items: center; gap: 7px; width: 100%;
  background: none; border: none; color: var(--texte); font: inherit;
  font-size: 12.5px; text-align: left; padding: 3px 4px; border-radius: 6px;
  cursor: pointer; }
.bqf-val:hover:not([disabled]) { background: rgba(255, 255, 255, .06); }
.bqf-val[disabled] { opacity: .35; cursor: default; }
.bqf-case { flex: none; width: 13px; height: 13px; border: 1px solid var(--bord);
  border-radius: 3px; font-size: 10px; line-height: 12px; text-align: center; }
.bqf-val.on .bqf-case { background: var(--accent); border-color: var(--accent);
  color: #16120f; }
.bqf-val.on { color: var(--accent); }
.bqf-nom { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.bqf-n { flex: none; color: var(--sourd); font-size: 11px; font-variant-numeric: tabular-nums; }
.bqf-plus { background: none; border: none; color: var(--sourd); font: inherit;
  font-size: 11.5px; padding: 3px 4px; cursor: pointer; }
.bqf-plus:hover { color: var(--accent); }

@media (max-width: 900px) {
  /* le panneau se replie : sur un téléphone la vitrine a besoin de tout */
  .bq-plan { display: block; }
  .bq-facettes-btn { display: inline-block; margin: 0 0 12px; }
  .bq-facettes { display: none; position: static; width: auto; max-height: none;
    padding: 0 0 10px; }
  body.bq-facettes-ouvert .bq-facettes { display: block; }
  .bqf-fermer { display: block; }
}
/* ⚠️ LE DÉCOR DE COMPOSITION NE VIT QUE PENDANT L'ÉDITION (09/08, demande
   utilisateur : « le mode composition est perpétuel »). Le propriétaire reçoit
   les deux états dans la page ; c'est ici qu'on choisit lequel se voit. `revert`
   et non une valeur en dur : ces éléments n'ont pas le même display naturel
   (span, input, bouton, textarea) et figer le mauvais les casserait. */
.bq-bloc-edit { display: none; }
body.bq-edition .bq-bloc-edit { display: revert; }
body.bq-edition .bq-bloc-vue { display: none; }
/* la vue acheteur : une pastille qui se distingue des vues sans crier */
.bq-acheteur-chip { text-decoration: none; }
@media (max-width: 900px) {
  /* un écran étroit ne tient qu'une colonne : le bloc prend la largeur et ses
     disques se rangent en une colonne, l'intitulé au-dessus. */
  .bq-bloc { grid-column: 1 / -1; }
  .bq-bloc-grille { grid-template-columns: 1fr; }
}
.bq-hors { display: none !important; }
/* LES FILTRES À GAUCHE DE LA VITRINE (08/08, demande utilisateur) : la bande
   verticale du feuilletage, mais DANS le flux — la vitrine occupe déjà toute la
   largeur du conteneur (le feuilletage, lui, a de la marge où faire flotter la
   sienne). Les chips reprennent `.fl-chip` : mêmes règles, même aspect que dans
   la collection. Elle colle au défilement pour rester à portée sur les longues
   pages. */
/* ⚠️ LA MEME FONTE ET LES MEMES COULEURS QUE LA BANDE DE LA COLLECTION (08/08,
   demande utilisateur) : elles viennent des MEMES declarations que #fl-formats --
   leurs selecteurs portent les deux id -- si bien que les deux bandes ne peuvent
   pas diverger. Il ne reste ici que la mise en place, et elle differe selon la
   page : EN LIGNE sur la vitrine (dans la rangee des vues, capture du 08/08),
   EN COLONNE sur la fiche d'un disque (ou le feuilletage met la sienne). */
#bq-filtres { display: flex; }
#bq-filtres select.fl-chip { appearance: none; -webkit-appearance: none; }
/* la vitrine : a l'horizontale, au corps de la bande horizontale du feuilletage */
.vues-boutique #bq-filtres { flex-flow: row wrap; align-items: center; gap: 14px;
  margin-left: 18px; }
.vues-boutique #bq-filtres .fl-chip { font-size: 14.5px; padding: 0;
  white-space: nowrap; }
/* la fiche : en colonne, aux chiffres du feuilletage (104 px, 22 px, 18,75 px).
   ⚠️ L'ID FIGURE DANS LE SELECTEUR : la regle de base est portee par
   `#bq-filtres .fl-chip`, qu'un selecteur a deux classes ne bat pas -- mesure, le
   corps restait a 14,5 px au lieu de 18,75. */
#bq-filtres.art-filtres { flex-direction: column; flex: 0 0 104px; width: 104px;
                          gap: 22px; padding-top: 2px; }
#bq-filtres.art-filtres .fl-chip { width: 100%; box-sizing: border-box;
  text-align: left; font-size: 18.75px; padding: 0; white-space: nowrap;
  overflow: hidden; }
/* mobile : la bande repasse À L'HORIZONTALE au-dessus des fiches (une colonne de
   78px y prendrait un cinquième de l'écran). */
/* mobile : la bande de la FICHE repasse a l'horizontale au-dessus de la pochette
   (une colonne de 104 px y prendrait plus du quart de l'ecran). */
@media (max-width: 900px) {
  #bq-filtres.art-filtres { width: auto; flex: none; flex-flow: row wrap;
                            gap: 12px; margin-bottom: 12px; }
  #bq-filtres.art-filtres .fl-chip { width: auto; font-size: 14.5px; }
}


/* ═══════ LA CARTE DES RÉCURRENCES (10/08, 2e passe) ════════════════════════
   « Un graphique ultra parlant… une visualisation plus amiable » : la carte
   occupe la page, le panneau lui répond à droite, et la saisie vient après —
   on épingle une racine quand on a vu la carte, pas avant. */
.rec-chiffres { font-size: 14px; color: var(--sourd); margin: 2px 0 16px; }
.rec-chiffres strong { color: var(--texte); font-weight: 600; }
.rec-scene { display: flex; gap: 26px; align-items: flex-start; }
.rec-nuage-boite { flex: 1 1 auto; min-width: 0; }
/* ⚠️ UNE LARGEUR, pas seulement un maximum : le SVG ne porte qu'un `viewBox`,
   et sans width il s'effondre à 0 px (leçon du 22/07, repayée le 10/08). */
.rec-nuage { width: 100%; height: auto; display: block; }
.rec-bulle { cursor: pointer; outline: none; }
.rec-bulle circle { transition: fill-opacity .15s, stroke-width .15s; }
.rec-bulle:hover circle, .rec-bulle:focus circle { fill-opacity: .34; }
.rec-bulle.actif circle { fill-opacity: .42; stroke-width: 2.6; }
.rec-bulle text { pointer-events: none; user-select: none; }
/* une racine épinglée porte un anneau plus franc : c'est SA carte dans la carte */
.rec-epingle circle { stroke-dasharray: 3 2.4; }

.rec-panneau { flex: 0 0 310px; border-left: 1px solid var(--bord);
               padding-left: 20px; min-height: 320px; }
.rec-invite { font-size: 13px; }
#rec-mot { font-size: 22px; margin: 0 0 2px; }
.rec-compte { margin: 0 0 2px; font-size: 15px; }
.rec-compte .sourd { font-size: 12.5px; }
#rec-style { font-size: 12.5px; margin: 0 0 14px; }
#rec-formes { font-size: 12px; margin: 12px 0 8px; line-height: 1.5; }

/* les décennies : six barres, pas une courbe — six points ne font pas une
   tendance, ils font six chiffres. */
.rec-dec { display: flex; align-items: flex-end; gap: 5px; height: 62px;
           margin: 4px 0 6px; }
.rec-dec-col { flex: 1; display: flex; flex-direction: column;
               justify-content: flex-end; height: 100%; }
.rec-dec-barre { display: block; width: 100%; min-height: 1px; border-radius: 2px 2px 0 0;
                 opacity: .8; }
.rec-dec-nom { font-size: 9.5px; color: var(--sourd); text-align: center;
               margin-top: 3px; }

.rec-morceaux { list-style: none; margin: 0; padding: 0;
                max-height: 34vh; overflow-y: auto; }
.rec-morceaux li a { display: flex; gap: 9px; align-items: baseline; padding: 2px 0;
                     color: var(--texte); text-decoration: none; font-size: 13px; }
.rec-morceaux li a:hover .rec-piste { color: var(--accent); }
.rec-rep { min-width: 26px; font-size: 11.5px; }
.rec-de { font-size: 11.5px; margin-left: auto; }

.rec-ajout { display: flex; gap: 8px; align-items: center; margin: 24px 0 10px;
             flex-wrap: wrap; }
.rec-ajout input { flex: 0 1 260px; }
.rec-aide-courte { margin: 0; }
.rec-epingles { display: flex; flex-wrap: wrap; gap: 7px; }
.rec-epingle-chip { display: inline-flex; align-items: center; gap: 6px;
                    background: rgba(255, 255, 255, .05);
                    border: 1px dashed var(--bord); border-radius: 13px;
                    padding: 2px 6px 2px 11px; font-size: 12.5px; }
.rec-epingle-chip button { background: none; border: none; color: var(--sourd);
                           cursor: pointer; font-size: 12px; padding: 0 2px; }
.rec-epingle-chip button:hover { color: var(--texte); }

@media (max-width: 900px) {
  /* le panneau passe SOUS la carte : à 390 px, deux colonnes ne tiennent pas */
  .rec-scene { flex-direction: column; gap: 14px; }
  /* ⚠️ 46 bulles dans 300 px sont illisibles — mesuré. La carte garde donc une
     largeur de travail et DÉFILE dans sa boîte, comme les tableaux larges du
     site : mieux vaut faire glisser une carte lisible que tout voir en illisible. */
  .rec-nuage-boite { overflow-x: auto; width: 100%; }
  .rec-nuage { min-width: 520px; }
  .rec-panneau { flex: none; width: 100%; border-left: none; padding-left: 0;
                 border-top: 1px solid var(--bord); padding-top: 14px;
                 min-height: 0; }
  .rec-de { display: none; }
}

/* 12/08 (demande utilisateur) : les CHIFFRES des trois portes du tableau
   (Collection / Wantlist / Shop) en vert menthe tres tres clair */
.dash-grandes .tuile-note { color: #d9f5e7; }

/* PLAGE DE BPM (12/08, demande utilisateur) : deux champs nombre dans la
   barre d'outils de la Liste et de la Grille — filtre 120-128 par ex. */
.filtre-bpm { display: inline-flex; align-items: center; gap: 5px;
  color: var(--sourd); font-size: 12px; }
.filtre-bpm input { width: 62px; font: inherit; font-size: 13px; padding: 5px 7px;
  background: rgba(19, 19, 19,.72); color: var(--texte);
  border: 1px solid var(--bord); border-radius: 8px; }
.filtre-bpm input::-webkit-outer-spin-button,
.filtre-bpm input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ═══ LA BARRE SUPERIEURE SUR MOBILE : DEUX BOUTONS, PAS DAVANTAGE ══════════
   (15/08, demandes utilisateur : « permettre la fonction de mixage sur bureau et
   non sur les versions mobiles, trop peu de place » ; « reduire le reproducteur a
   un bouton qui le deploie avec ses options d'ecoute, et un deuxieme pour couper
   le volume ».)
   La barre supérieure porte le logo, la loupe, la langue, le menu ET le lecteur.
   Sur un telephone il n'y a pas de place pour tout : on garde ce qui sert a
   chaque instant — deplier, et couper le son — et l'on range le reste derriere
   le premier bouton. */
#cw-lecteur .lect-plier { display: none; }
/* ⚠️ AVANT la media query, et non apres : a specificite egale c'est la DERNIERE
   regle qui gagne — ecrite plus bas, celle-ci masquait la langue du menu jusque
   sur mobile, ou elle doit justement paraitre (mesure : « masque » menu ouvert).
   Hors mobile le doublon n'a pas lieu d'etre : c'est celui de la barre qui sert. */
.menu-nav-langue { display: none; }
@media (max-width: 900px) {
  /* LE MIXAGE EST UNE AFFAIRE DE BUREAU. ⚠️ `display: none` et non une classe
     d'opacite : un bouton ainsi masque sort AUSSI du parcours de tabulation, ce
     qu'un simple masquage visuel n'aurait pas fait. */
  #cw-lecteur .lect-premix, #cw-lecteur .lect-manuel, #cw-mix { display: none; }
  #cw-lecteur .lect-plier { display: inline-flex; align-items: center;
    justify-content: center; background: none; border: none; padding: 0 2px;
    color: var(--texte); font-size: 15px; line-height: 1; cursor: pointer; }
  #cw-lecteur .lect-plier:hover { color: var(--accent); }
  /* REPLIE : il ne reste que le depli et la sourdine — donc `.lect-mute` n'est
     PAS dans cette liste, et la passe compacte de 520 px qui la masquait est
     annulee juste en dessous. Couper le son est le geste qu'on veut a portee
     sans rien deplier. */
  #cw-lecteur:not(.deplie) .lect-pp,
  #cw-lecteur:not(.deplie) .lect-nav,
  #cw-lecteur:not(.deplie) .lect-titre,
  #cw-lecteur:not(.deplie) .lect-liste-btn,
  #cw-lecteur:not(.deplie) .lect-fermer,
  #cw-lecteur:not(.deplie) .lect-pistes { display: none; }
  /* DEPLIE : la sourdine revient (elle est masquee sous 520 px par la passe
     compacte du 18/07), et le titre reste hors jeu — il n'y a pas la largeur ;
     c'est la liste des pistes qui dit ce qui joue. */
  #cw-lecteur .lect-mute { display: inline-flex; }
  #cw-lecteur.deplie .lect-pp, #cw-lecteur.deplie .lect-nav,
  #cw-lecteur.deplie .lect-liste-btn, #cw-lecteur.deplie .lect-fermer {
    display: inline-flex; }
  /* LA LANGUE QUITTE LA BARRE POUR LE MENU (voir base.html) : c'est le dernier
     element qu'on peut ranger sans rien perdre — on change de langue une fois,
     pas a chaque page. */
  .entete .nav-droite > .selecteur-langue.langue-repliable { display: none; }
  .menu-nav-langue { display: flex; align-items: center; gap: 10px;
    padding: 9px 14px; }
  .menu-nav-langue svg { width: 16px; height: 16px; flex: none; color: var(--sourd); }
  .menu-nav-langue .selecteur-langue { flex: 1; min-width: 0; }
}

