/* =============================================================================
   listen.noxelstudio.com — feuille unique
   -----------------------------------------------------------------------------
   Meme famille que noxelstudio.com, send et image : encre noire sur papier,
   Space Grotesk pour le texte, DM Mono pour tout ce qui se lit comme une
   donnee — minutages, codes, numeros, noms de destinataires — et pour TOUS les
   controles, en capitales espacees. Un seul accent, le rouge d'enregistrement,
   reserve a l'action et aux reperes vivants, jamais a une phrase.

   Deux pages, deux temperaments :

     LE PANNEAU   dense, tabulaire, fait pour surveiller. On y voit d'un coup
                  d'œil qui ecoute en ce moment et ou il en est.
     L'ECOUTE     une seule chose a l'ecran, le morceau. Rien a cliquer sauf
                  lire, rien a emporter. C'est une page de salle d'ecoute, pas
                  un lecteur de bureau.

   La page s'inverse toute seule en theme sombre : on fait ecouter une maquette
   le soir, et un rectangle blanc en pleine nuit n'est pas un choix de design.

   -----------------------------------------------------------------------------
   L'ADAPTATION AUX ECRANS

   Quatre familles de regles, en fin de fichier, dans cet ordre — il compte, la
   derniere gagne :

     largeur   760 / 640 / 600 / 420 / 360 px
     toucher   `pointer:coarse` — cibles a quarante-quatre pixels, controles a
               16 px, sous quoi iOS zoome la page sans revenir
     survol    `hover:hover` — tout effet de survol y est enferme, sinon un
               bouton reste allume apres une tape sur ecran tactile

   REGLE : aucune couleur en dur hors du bloc de variables.
   ============================================================================= */
/* ---------- polices, hebergees ici ---------- */
@font-face { font-family:'DM Mono'; font-style:normal; font-weight:400; font-display:swap;
  src:url('/fonts/dm-mono-400-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:'DM Mono'; font-style:normal; font-weight:400; font-display:swap;
  src:url('/fonts/dm-mono-400-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:'DM Mono'; font-style:normal; font-weight:500; font-display:swap;
  src:url('/fonts/dm-mono-500-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:'DM Mono'; font-style:normal; font-weight:500; font-display:swap;
  src:url('/fonts/dm-mono-500-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:'Space Grotesk'; font-style:normal; font-weight:400; font-display:swap;
  src:url('/fonts/space-grotesk-400-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:'Space Grotesk'; font-style:normal; font-weight:400; font-display:swap;
  src:url('/fonts/space-grotesk-400-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:'Space Grotesk'; font-style:normal; font-weight:500; font-display:swap;
  src:url('/fonts/space-grotesk-500-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:'Space Grotesk'; font-style:normal; font-weight:500; font-display:swap;
  src:url('/fonts/space-grotesk-500-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family:'Space Grotesk'; font-style:normal; font-weight:700; font-display:swap;
  src:url('/fonts/space-grotesk-700-latin.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family:'Space Grotesk'; font-style:normal; font-weight:700; font-display:swap;
  src:url('/fonts/space-grotesk-700-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }

/* ---------- variables ---------- */
:root {
  /* ---------------------------------------------------------------------------
     BLANC ET BLEU
     ---------------------------------------------------------------------------
     Reprise de la palette du back-office, à la demande de Noxel le 2026-08-28 :
     surfaces BLANCHES posées sur un fond gris très clair, et un seul bleu franc
     pour l'action. La DA papier crème et rouge d'origine appartenait à send ;
     elle isolait les outils du reste, alors qu'ils s'ouvrent désormais depuis le
     même back-office.

     ⚠️ LE BLEU EST L'ACTION, PAS L'ALERTE. Le rouge d'avant portait les deux à
     la fois — bouton principal ET message d'erreur — ce qui passait tant que
     tout était rouge. Séparé ici : `--acc` pour ce qu'on peut faire, `--danger`
     pour ce qui a échoué. Ne jamais reprendre l'un pour l'autre.

     ⚠️ Les angles sont VIFS. `--r:0;            /* controles : rectangulaires, sans exception */
  --paper-2:#e9ebee;
  --wash:#ffffff;
  --ink:#14171a;
  --ink-2:#3d444b;
  --ink-3:#6b737b;
  --rule:#e0e3e7;
  --rule-2:#eef0f2;
  --field:#ffffff;
  --acc:#1d4ed8;
  --acc-ink:#ffffff;
  --acc-soft:#eaf0fd;
  --danger:#b42318;
  --danger-soft:#fdecea;
  --ok:#1d6b3f;
  --shadow:0 1px 2px rgba(20,23,26,.04), 0 10px 30px -18px rgba(20,23,26,.22);
  --lift:0 6px 22px -14px rgba(20,23,26,.30);
  /* Le grain venait du papier. Sur du blanc il salit au lieu de texturer. */
  --grain-o:0;

  --sans:'Space Grotesk',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'DM Mono',ui-monospace,'SF Mono',Menlo,monospace;

  /* La colonne est volontairement etroite : c'est un outil, pas un magazine.
     Le panneau d'usage, plus dense, la relargue avec `body.wide`. */
  --col:min(760px,100% - 2.4rem);
  --r:0;            /* controles : rectangulaires, sans exception */          /* controles : angles quasi vifs, comme un tampon */
  --r-lg:2px;       /* grandes surfaces : deux pixels, pas plus */      /* cartes et scenes : a peine adouci */
  --ease:cubic-bezier(.2,.7,.3,1);
  --pop:cubic-bezier(.16,1.1,.3,1);
}

@media (prefers-color-scheme:dark) {
  :root {
    --paper:#0c0d0f;
    --paper-2:#23262a;
    --wash:#141618;
    --ink:#f4f5f6;
    --ink-2:#c9ced3;
    --ink-3:#8f969d;
    --rule:#24272b;
    --rule-2:#1c1f22;
    --field:#1a1d20;
    --acc:#7aa2ff;
    --acc-ink:#0c0d0f;
    --acc-soft:#151d2e;
    --danger:#e5645c;
    --danger-soft:#2a1614;
    --ok:#4cc17d;
    --shadow:0 1px 2px rgba(0,0,0,.5), 0 18px 44px -24px rgba(0,0,0,.9);
    --lift:0 12px 32px -18px rgba(0,0,0,.8);
    --grain-o:0;
  }
}

.wide { --col:min(980px,100% - 2.4rem); }

/* ---------- socle ---------- */
*,*::before,*::after { box-sizing:border-box; }
html { -webkit-text-size-adjust:100%; }

/* ⚠️ RÈGLE INDISPENSABLE, ET PIÈGE CLASSIQUE.
   L'attribut `hidden` ne vaut qu'un `display:none` de feuille par défaut : la
   moindre règle qui pose un `display` explicite — et il y en a partout ici,
   flex et grid — l'emporte sur lui, et l'élément reste visible. En production
   le 2026-08-12, la boîte « CODE » s'affichait avec six zéros sur des envois
   qui n'avaient pas de code, et le bouton « Partager » apparaissait là où le
   système ne sait pas partager. */
[hidden] { display:none !important; }

body {
  margin:0; color:var(--ink);
  min-height:100vh;                      /* voie de secours : Safari < 15.4 */
  min-height:100svh;
  background-color:var(--paper);
  /* Une lumiere douce tombe du haut de la page : le noir plein ecran de la
     v1 se lisait comme une page eteinte. */
  background-image:radial-gradient(1100px 640px at 50% -160px, var(--wash), transparent 72%);
  background-repeat:no-repeat;
  font:400 16px/1.55 var(--sans);
  -webkit-font-smoothing:antialiased;
  display:flex; flex-direction:column;
  /* ⚠️ Les encoches se prennent ICI, pas dans `.wrap`. Un telephone couche
     glisse son objectif dans la marge gauche : sans ces deux lignes, le titre
     et le pied passent dessous et deviennent illisibles. La colonne se calcule
     ensuite sur la largeur restante, donc tout suit. */
  padding-left:env(safe-area-inset-left);
  padding-right:env(safe-area-inset-right);
  padding-bottom:env(safe-area-inset-bottom);
}
img,svg { display:block; max-width:100%; }
button,input,select,textarea { font:inherit; color:inherit; }
a { color:inherit; }
h1,h2,h3,h4 { overflow-wrap:break-word; }   /* un nom de fichier ne deborde pas */
::selection { background:var(--acc); color:var(--acc-ink); }
:focus-visible { outline:2px solid var(--acc); outline-offset:3px; }

/* Un liseré rouge en haut de page : le seul aplat de couleur du site. */
body::before {
  content:''; position:fixed; inset:0 0 auto 0; height:2px;
  background:var(--acc); z-index:60;
}

/* Le grain de pellicule : un bruit SVG minuscule, répété, fixe, sous les
   dialogues et le toast. C'est lui qui fait tenir les grands vides de la page.
   (`body::after` est pris par le cadre rouge du survol de fichier.) */
html::after {
  content:''; position:fixed; inset:0; z-index:55; pointer-events:none;
  opacity:var(--grain-o);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.wrap { width:var(--col); margin:0 auto; }
main { flex:1 1 auto; }

/* ---------- micro-etiquettes ---------- */
.etiquette {
  font:500 10.5px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-3);
}
.mono { font-family:var(--mono); font-variant-numeric:tabular-nums; }
.dim  { color:var(--ink-2); }
.tiny { font-size:13px; }
.spacer { flex:1 1 auto; }

/* ---------- en-tete : un cartouche de une ---------- */
.tete-page {
  display:flex; align-items:center; gap:1rem; flex-wrap:wrap;
  padding:1.9rem 0 1.2rem; margin-bottom:.4rem;
  border-bottom:1px solid var(--rule-2);
  animation:rise .5s var(--pop) both;
}
.mark {
  font:700 clamp(24px,5vw,30px)/1 var(--sans); letter-spacing:-.04em; margin:0;
  display:flex; align-items:baseline; gap:.05em;
}
.mark span { color:var(--acc); }
.tete-page .home {
  position:relative;
  font:400 10.5px/1 var(--mono); letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-3); text-decoration:none; border-bottom:1px solid transparent;
  padding-bottom:2px;
}

/* ---------- boutons ---------- */
/* Tous les controles parlent en capitales mono espacees : ce qui se lit est en
   Space Grotesk, ce qui se presse est en DM Mono. */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:.5rem;
  min-height:46px; padding:.7rem 1.35rem; border-radius:var(--r);
  border:1px solid var(--ink); background:transparent; color:var(--ink);
  font:500 12px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  cursor:pointer; text-decoration:none; white-space:nowrap;
  transition:background .16s var(--ease), color .16s var(--ease),
             border-color .16s var(--ease), transform .12s var(--ease),
             box-shadow .16s var(--ease), opacity .16s;
}
.btn:active { transform:translateY(1px); box-shadow:none; }
.btn:disabled { opacity:.32; cursor:not-allowed; transform:none; box-shadow:none; }
.btn--acc { background:var(--acc); border-color:var(--acc); color:var(--acc-ink); }
.btn--ghost { border-color:var(--rule); color:var(--ink-2); }
.btn--sm { min-height:36px; padding:.45rem .85rem; font-size:10.5px; }

/* ---------- cartes ---------- */
.card {
  border:1px solid var(--rule-2); border-radius:calc(var(--r-lg) - 3px);
  background:linear-gradient(180deg, var(--field), transparent 90%);
  padding:1.3rem; margin:1.3rem 0;
  animation:rise .35s var(--pop) both;
}
.card h3 { margin:0 0 .7rem; font:500 16px/1.3 var(--sans); letter-spacing:-.01em; }

/* ⚠️ Les cartes de transfert du mode direct portent en sous-ligne la LISTE DES
   NOMS de fichiers, fabriquee par direct.js. Un nom sans espace n'a aucun
   endroit ou se couper : sans cette regle il sortait de la carte et faisait
   defiler toute la page en largeur sur un telephone. La classe sert aussi au
   panneau d'usage, ou le probleme est le meme. */
.sub { overflow-wrap:anywhere; }
.card .hd > strong { min-width:0; overflow-wrap:anywhere; }

.bar { position:relative; height:2px; background:var(--rule-2); overflow:hidden; }
.bar > i {
  position:absolute; inset:0 auto 0 0; width:0; background:var(--acc);
  transition:width .25s linear;
}

.pill {
  display:inline-flex; align-items:center; gap:.4rem; white-space:nowrap;
  font:500 10px/1 var(--mono); letter-spacing:.11em; text-transform:uppercase;
  padding:.32rem .5rem; border:1px solid var(--rule); border-radius:99px;
  color:var(--ink-2);
}
.pill::before { content:''; width:5px; height:5px; border-radius:50%; background:currentColor; }
.pill--live { color:var(--ok); border-color:currentColor; }
.pill--warn { color:var(--danger); border-color:currentColor; }

/* ---------- messages ---------- */
/* `anywhere` : un message d'expediteur peut contenir une adresse sans espace,
   qui pousserait la page en largeur. */
.msg {
  padding:.8rem 1rem; border-left:2px solid var(--acc);
  background:var(--field); font-size:14px; margin:1.1rem 0;
  border-radius:0 var(--r) var(--r) 0; overflow-wrap:anywhere;
}
.msg--ok  { border-left-color:var(--ok); }
/* Le message d'erreur porte deja le rouge par defaut de `.msg` ; la classe
   existe pour le dire dans le balisage plutot que de le laisser deviner. */
.msg--err { border-left-color:var(--danger); color:var(--ink); }


/* ---------- pied ---------- */
/* ⚠️ `auto` sur les cotes, et surtout PAS `0`. Le pied porte AUSSI la classe
   `.wrap`, qui le centre par `margin:0 auto` — mais ce raccourci-ci est
   declare plus bas, a specificite egale, et remplacait les `auto` par des
   zeros : le pied gardait la bonne largeur, colle au bord gauche de la
   fenetre. Vu en production le 2026-08-13. Toute regle qui touche au `margin`
   d'un element `.wrap` doit passer par les longhands verticaux. */
.pied {
  margin:3rem auto 2rem; padding-top:1.1rem; border-top:1px solid var(--rule-2);
  display:flex; gap:1rem; flex-wrap:wrap; align-items:baseline;
  font:400 10.5px/1.6 var(--mono); letter-spacing:.08em; color:var(--ink-3);
}
.pied a { position:relative; text-decoration:none; border-bottom:1px solid var(--rule); }

/* ---------- le champ de mot de passe ---------- */
.champ-mdp {
  width:100%; min-height:46px; padding:.6rem .8rem; margin:1rem 0;
  background:var(--field); color:var(--ink);
  border:1px solid var(--rule); border-radius:var(--r); outline:none;
  transition:border-color .16s var(--ease);
}
.champ-mdp:focus { border-color:var(--ink); }
/* =============================================================================
   LA FORME D'ONDE
   -----------------------------------------------------------------------------
   Le meme dessin sert des deux cotes — la page d'ecoute pour lire, le panneau
   pour montrer ce qui a ete reecoute. Il est peint sur un canvas et non
   compose de mille elements : mille barres en DOM se redessinent mal a
   soixante images par seconde, et il faut que la tete de lecture avance sans
   accroc pendant qu'une carte de chaleur se met a jour dessous.
   ============================================================================= */
.onde--carte   { height:74px; }

/* La tete de lecture. Un filet, pas une poignee : on ne la saisit pas, on
   clique dans l'onde. */

/* Le survol de l'onde annonce ou l'on tomberait. */
.onde--lecture:hover .repere { opacity:1; }

/* =============================================================================
   LE LECTEUR
   ============================================================================= */


/* Le bouton de lecture. Rond, plein, unique — c'est la seule chose a faire sur
   cette page. */


/* Le mot laisse au destinataire. */

/* =============================================================================
   LA MENTION DE SUIVI
   -----------------------------------------------------------------------------
   ⚠️ Elle ne se retire pas en faisant le menage. Le destinataire est une
   personne nommee, son ecoute est suivie a la seconde, et le service n'a pas
   de page de confidentialite : le lui dire en clair est le minimum. Elle est
   discrete, pas cachee — sous le lecteur, lisible, jamais en gris pale sur
   gris pale.
   ============================================================================= */

/* =============================================================================
   LA PORTE : le code a six chiffres
   ============================================================================= */

.code-champ {
  width:100%; text-align:center;
  font:500 clamp(26px, 8vw, 34px)/1 var(--mono); letter-spacing:.34em;
  text-indent:.34em;                       /* recentre : l'interlettrage pousse a droite */
  padding:.9rem .6rem; color:var(--ink);
  border:1px solid var(--rule); border-radius:var(--r);
  background:var(--field);
}
.code-champ:focus { outline:none; border-color:var(--ink); }

/* =============================================================================
   LE PANNEAU : les tracks et leurs liens
   ============================================================================= */
.piste { border:1px solid var(--rule-2); border-radius:var(--r-lg); margin:1.1rem 0; overflow:hidden; }
.piste__hd {
  display:flex; align-items:baseline; gap:.8rem; flex-wrap:wrap;
  padding:1rem 1.1rem; background:linear-gradient(180deg, var(--field), transparent);
}
.piste__hd h3 { margin:0; font:600 17px/1.2 var(--sans); letter-spacing:-.01em; }
.piste__meta { margin-left:auto; display:flex; align-items:center; gap:.5rem; flex-wrap:wrap; }

/* Une ligne de lien. Tabulaire : on lit une colonne, pas une phrase. */
.lien {
  display:grid; gap:.2rem .9rem; align-items:center;
  grid-template-columns:minmax(8rem,1.4fr) auto auto auto;
  padding:.75rem 1.1rem; border-top:1px solid var(--rule-2);
}
.lien__nom { font:500 14px/1.3 var(--sans); overflow-wrap:anywhere; }
.lien__etat, .lien__chiffre {
  font:500 11px/1 var(--mono); letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-2); font-variant-numeric:tabular-nums; white-space:nowrap;
}
.lien__actions { display:flex; gap:.4rem; justify-self:end; }
.lien--mort .lien__nom { color:var(--ink-3); text-decoration:line-through; }

/* La ligne d'un destinataire en train d'ecouter. Le seul endroit du panneau
   qui bouge tout seul, donc le seul qui merite l'accent. */
.lien--direct { background:color-mix(in srgb, var(--acc) 5%, transparent); }
.lien--direct .lien__nom { color:var(--acc); }

.point-direct {
  display:inline-block; width:6px; height:6px; border-radius:50%;
  background:var(--acc); margin-right:.4rem; vertical-align:middle;
  animation:battement 1.6s var(--ease) infinite;
}
@keyframes battement { 0%,100% { opacity:1; } 50% { opacity:.25; } }

/* La barre d'avancement d'une ecoute en cours, sous la ligne du lien. */
.avance { grid-column:1/-1; height:2px; background:var(--rule-2); margin-top:.5rem; }
.avance > i { display:block; height:100%; background:var(--acc); transition:width .4s linear; }

/* Le code, montre UNE FOIS a la creation. */
.code-neuf {
  font:500 22px/1 var(--mono); letter-spacing:.28em;
  padding:.7rem .9rem; border:1px dashed var(--rule); border-radius:var(--r);
  background:var(--field); display:inline-block;
}

/* =============================================================================
   LE DEPOT
   ============================================================================= */
.cible {
  border:1px dashed var(--rule); border-radius:var(--r-lg);
  padding:2.4rem 1.4rem; text-align:center; cursor:pointer;
  transition:border-color .18s var(--ease), background .18s var(--ease);
}
.cible:hover, .cible--survol { border-color:var(--ink); background:var(--field); }
.cible p { margin:.4rem 0 0; color:var(--ink-2); font:400 14px/1.5 var(--sans); }
.cible strong { font:500 16px/1.3 var(--sans); }

.champs { display:grid; gap:.8rem; margin:1.1rem 0; }
.champ { display:grid; gap:.35rem; }
.champ > span { font:500 10px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase; color:var(--ink-2); }
.champ input, .champ textarea, .champ select {
  font:400 15px/1.4 var(--sans); color:var(--ink);
  padding:.6rem .7rem; border:1px solid var(--rule); border-radius:var(--r);
  background:var(--field); width:100%;
}
.champ textarea { resize:vertical; min-height:4.5rem; }
.champ input:focus, .champ textarea:focus, .champ select:focus { outline:none; border-color:var(--ink); }

.rangee { display:flex; gap:.7rem; flex-wrap:wrap; align-items:flex-end; }
.rangee > * { flex:1 1 8rem; }

/* =============================================================================
   SURVOL
   -----------------------------------------------------------------------------
   ⚠️ TOUT effet de survol vit ici, et nulle part ailleurs. Sur un ecran
   tactile, un `:hover` non garde reste ALLUME apres la tape : sur send, le
   bouton « Copier » gardait son fond d'encre jusqu'a ce qu'on touche autre
   chose, ce qui se lit comme un bouton bloque. `:active`, lui, reste dehors :
   il marche au doigt et se relache tout seul.
   ============================================================================= */
@media (hover:hover) {
  .btn:hover { background:var(--ink); color:var(--paper); box-shadow:var(--lift); }
  .btn:disabled:hover { background:transparent; color:var(--ink); box-shadow:none; }
  .btn--acc:hover { background:var(--acc); border-color:var(--acc); color:var(--acc-ink); filter:brightness(1.08); }
  .pied a:hover { color:var(--ink); border-bottom-color:var(--ink); }
  .lien:hover { background:var(--field); }
  .lire:hover { box-shadow:var(--lift); }
}

/* =============================================================================
   LE DETAIL D'UN LIEN
   -----------------------------------------------------------------------------
   Une fenetre modale native : c'est le seul endroit du service ou l'on
   superpose quelque chose, et `<dialog>` apporte seul la pile de focus, la
   fermeture par Echap et le fond inerte.
   ============================================================================= */
dialog#detail {
  width:min(680px, calc(100% - 2rem)); max-height:82vh; max-height:82svh;
  padding:1.5rem; border:1px solid var(--rule); border-radius:var(--r-lg);
  background:var(--paper); color:var(--ink); box-shadow:var(--shadow);
}
dialog#detail::backdrop { background:color-mix(in srgb, var(--ink) 42%, transparent); }

.detail__hd {
  display:flex; align-items:baseline; gap:1rem;
  padding-bottom:.9rem; margin-bottom:1.1rem; border-bottom:1px solid var(--rule-2);
}
.detail__hd h3 { margin:0; flex:1; font:600 17px/1.25 var(--sans); letter-spacing:-.01em; overflow-wrap:anywhere; }

/* =============================================================================
   LES ECRANS
   -----------------------------------------------------------------------------
   Quatre largeurs, du plus large au plus etroit — l'ordre compte, la derniere
   gagne. Le panneau est un outil de bureau ; la page d'ecoute, elle, s'ouvre
   surtout depuis un telephone, sur un lien recu par message. C'est elle qui
   dicte les ruptures.
   ============================================================================= */

@media (max-width:760px) {
  .tete-page { padding:1.3rem 0 .9rem; gap:.6rem; }
  .card { padding:1rem; }
  .scene { padding:1.15rem; }

  /* La ligne d'un lien passe de quatre colonnes a deux : cote a cote, le nom
     du destinataire et ses trois compteurs se reduisaient chacun a une bouillie
     de six caracteres. */
  .lien { grid-template-columns:1fr auto; row-gap:.45rem; padding:.85rem .9rem; }
  .lien__nom { grid-column:1/-1; }
  .lien__actions { grid-column:2; }
  .piste__hd { padding:.9rem; }
  .piste__meta { margin-left:0; width:100%; }
}

@media (max-width:600px) {
  .tete-page { padding:1.1rem 0 .8rem; }
  .pied { margin:2rem auto 1.4rem; }
  .cible { padding:1.8rem 1.1rem; }

  /* Le transport s'empile : le minutage tenait sur la meme ligne que le bouton
     de lecture au prix de deux caracteres par champ. */
  .transport { flex-wrap:wrap; }
  .minutage { margin-left:0; width:100%; order:3; }

  .rangee > * { flex:1 1 100%; }
  dialog#detail { padding:1.1rem; }
}

@media (max-width:420px) {
  .onde--lecture { height:clamp(96px, 22vh, 140px); }
  .lire { width:50px; height:50px; }
  .lien__actions { flex-wrap:wrap; }
}

/* =============================================================================
   LE TOUCHER
   -----------------------------------------------------------------------------
   ⚠️ 16 px sur les champs, pas moins : sous cette taille, iOS zoome la page a
   la mise au point et ne revient jamais en arriere. La page d'ecoute est
   surtout ouverte au telephone, et son champ de code est la premiere chose
   qu'on y touche.
   ============================================================================= */
@media (pointer:coarse) {
  .btn { min-height:44px; }
  .btn--sm { min-height:38px; }
  .champ input, .champ textarea, .champ select, .champ-mdp { font-size:16px; }

  /* L'onde se pointe au doigt : le repere de survol n'a pas de sens, et la
     cible de saut merite d'etre haute. */
  .repere { display:none; }
  .onde--lecture { touch-action:manipulation; }
}


/* ⚠️ La langue se devine, elle ne se demande pas — mais elle doit rester
   corrigeable : un francophone dont le système est en anglais ne doit pas
   rester coincé. D'où ce bouton, discret et sans drapeau (un drapeau désigne
   un pays, pas une langue). */

/* =============================================================================
   LA COUVERTURE
   -----------------------------------------------------------------------------
   Même squelette que les deux pages d'atterrissage de noxelstudio.com : un
   bandeau de mentions sur un filet, le sujet au centre, un pied sur un second
   filet, des repères verticaux aux extrémités. Ce que voit un label qui reçoit
   un lien, c'est cet écran — il est la seule vitrine du service.
   ============================================================================= */
.couv {
  position:relative;
  min-height:100vh; min-height:100svh;
  display:grid; grid-template-rows:auto 1fr auto;
  width:min(940px, 100% - 3rem); margin:0 auto;
  padding:1.4rem 0;
}

/* Les repères verticaux : deux filets qui tiennent la page par les côtés, comme
   les marges d'une couverture imprimée. */
.couv-repere {
  position:absolute; top:1.4rem; bottom:1.4rem; width:1px;
  background:var(--rule-2); pointer-events:none;
}
.couv-repere--g { left:-1.5rem; }
.couv-repere--d { right:-1.5rem; }

.couv-haut, .couv-pied {
  display:flex; align-items:center; gap:1.1rem; flex-wrap:wrap;
  font:500 10.5px/1 var(--mono); letter-spacing:.15em; text-transform:uppercase;
  color:var(--ink-3);
}
.couv-haut { padding-bottom:1rem; border-bottom:1px solid var(--rule-2); }
.couv-pied { padding-top:1rem; border-top:1px solid var(--rule-2); }

/* Une mention de couverture : le texte des deux bandeaux, qui hérite déjà de
   la casse et de l'interlettrage de son parent. La classe existe pour le dire
   dans le balisage plutôt que de le laisser deviner. */
.couv-mention { color:inherit; }

.couv-marque { display:inline-flex; align-items:center; gap:.5rem; color:var(--ink-2); }
.couv-marque img { display:block; width:18px; height:18px; object-fit:contain; }
.couv-pour { margin-left:auto; color:var(--ink-2); }
.couv-langue {
  margin-left:auto; background:none; border:0; padding:0; cursor:pointer;
  font:inherit; color:var(--ink-3); letter-spacing:.15em;
  border-bottom:1px solid var(--rule);
}
.couv-langue:hover { color:var(--ink); }


/* ---------- la porte ---------- */
.porte { max-width:23rem; margin:0 auto; text-align:center; }
.porte-t { margin:0 0 .5rem; font:600 clamp(20px,3.4vw,26px)/1.2 var(--sans); letter-spacing:-.02em; }
.porte-p { margin:0 0 1.6rem; color:var(--ink-2); font:400 14.5px/1.55 var(--sans); }

/* ---------- le transport ---------- */

/* Reculer et avancer : secondaires, donc plus petits et sans fond. Le seul
   bouton plein de la page est celui qui lance le morceau. */
.rond {
  width:38px; height:38px; flex:none; display:grid; place-items:center;
  border:1px solid var(--rule); border-radius:var(--r);
  background:transparent; color:var(--ink-2); cursor:pointer;
  transition:border-color .16s var(--ease), color .16s var(--ease);
}
.rond svg { width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; }
.rond:hover { border-color:var(--ink); color:var(--ink); }

.minutage {
  margin-left:auto; background:none; border:0; padding:.3rem .1rem; cursor:pointer;
  font:500 13px/1 var(--mono); letter-spacing:.06em; color:var(--ink-3);
  font-variant-numeric:tabular-nums;
}
.minutage b { color:var(--ink); font-weight:500; }
.minutage:hover { color:var(--ink-2); }

/* ---------- le volume ---------- */
.volume { display:flex; align-items:center; gap:.5rem; color:var(--ink-3); }
.volume svg { width:17px; height:17px; flex:none; fill:none; stroke:currentColor;
  stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.volume input {
  width:82px; height:2px; -webkit-appearance:none; appearance:none;
  background:var(--rule); cursor:pointer;
}
/* ⚠️ Les deux sélecteurs de curseur ne se factorisent PAS. Un navigateur qui
   ne comprend pas `::-webkit-slider-thumb` jette la règle ENTIÈRE si les deux
   sont dans la même liste — et le curseur redevient celui du système. */
.volume input::-webkit-slider-thumb {
  -webkit-appearance:none; width:11px; height:11px; border-radius:50%;
  background:var(--ink); cursor:pointer;
}
.volume input::-moz-range-thumb {
  width:11px; height:11px; border:0; border-radius:50%;
  background:var(--ink); cursor:pointer;
}

/* ---------- les raccourcis ---------- */
/* Ils n'existent que s'ils s'affichent : personne n'essaie la barre d'espace
   sur une page qu'il ne connaît pas. */

.btn--large { width:100%; min-height:46px; margin-top:1rem; }

@media (max-width:640px) {
  .couv { width:calc(100% - 2rem); }
  .couv-repere { display:none; }
  /* Le volume passe sous la ligne : au doigt, un curseur de 82 px coincé entre
     trois boutons ne se saisit pas. */
  .volume { order:5; width:100%; margin-top:.4rem; }
  .volume input { flex:1; width:auto; }
  .minutage { margin-left:auto; }
  .touches { display:none; }
}


/* =============================================================================
   LA SCÈNE — une pochette, pas un lecteur
   -----------------------------------------------------------------------------
   C'est l'écran qu'un label ouvre en cliquant sur un lien reçu par message. Il
   n'a que quelques secondes pour décider si ce qu'on lui envoie a été soigné.

   Le geste : le morceau OCCUPE la page. Titre en grand, onde en grand, et rien
   d'autre au même niveau — le transport, les mentions et les raccourcis se
   rangent sous eux, en retrait. Une carte posée au milieu d'un écran vide, comme
   dans la première version, dit « formulaire » ; ceci dit « disque ».
   ============================================================================= */
.couv-corps { display:grid; align-content:center; padding:3vh 0; }

.scene { max-width:64rem; margin:0 auto; width:100%; }

/* Le titre porte la page. Il descend jusqu'à 30 px sur un téléphone et monte à
   68 sur un écran large : c'est la seule chose qui change vraiment de taille. */
.scene__titre {
  margin:0; font:600 clamp(30px, 6.4vw, 68px)/1.02 var(--sans);
  letter-spacing:-.04em; overflow-wrap:anywhere;
}
.scene__artiste {
  margin:.5rem 0 0; color:var(--ink-3);
  font:500 12px/1 var(--mono); letter-spacing:.18em; text-transform:uppercase;
}

/* ---------- l'onde ---------- */
.onde {
  position:relative; width:100%;
  margin:clamp(1.6rem, 4vh, 3rem) 0 0;
}
.onde canvas { display:block; width:100%; height:100%; }
.onde--lecture { height:clamp(140px, 30vh, 260px); cursor:pointer; }

/* La tête de lecture : un filet et rien de plus. Une poignée inviterait à la
   saisir, alors qu'on se déplace en cliquant dans l'onde. */
.tete {
  position:absolute; top:0; bottom:0; width:1px;
  background:var(--acc); pointer-events:none; transform:translateX(-.5px);
  box-shadow:0 0 12px 1px var(--acc);
}
.repere {
  position:absolute; top:0; bottom:0; width:1px; background:var(--ink-3);
  pointer-events:none; opacity:0; transition:opacity .14s var(--ease);
}
.onde--lecture:hover .repere { opacity:.5; }

/* ---------- le transport ---------- */
.transport {
  display:flex; align-items:center; gap:.9rem; flex-wrap:wrap;
  margin-top:clamp(1.2rem, 3vh, 2rem);
}

/* Le seul objet plein de la page. Tout le reste est en trait : c'est ce qui
   fait qu'on sait où cliquer sans avoir à chercher. */
.lire {
  width:clamp(56px, 8vw, 68px); height:clamp(56px, 8vw, 68px);
  flex:none; border-radius:50%;
  border:0; background:var(--ink); color:var(--paper);
  display:grid; place-items:center; cursor:pointer;
  transition:transform .18s var(--pop), opacity .18s var(--ease);
}
.lire:active { transform:scale(.95); }
.lire:disabled { opacity:.3; cursor:default; }
.lire svg { width:22px; height:22px; fill:currentColor; }

.mot {
  margin:clamp(1.4rem, 3vh, 2.2rem) 0 0; padding-top:1.2rem;
  border-top:1px solid var(--rule-2);
  color:var(--ink-2); font:400 15px/1.6 var(--sans);
  white-space:pre-wrap; overflow-wrap:anywhere; max-width:44rem;
}

/* ⚠️ Cette mention ne se retire pas : elle dit au destinataire ce qu'il a entre
   les mains. Discrète, jamais cachée. */
.suivi {
  display:flex; align-items:flex-start; gap:.6rem;
  margin:clamp(1.4rem, 3vh, 2.2rem) 0 0; padding-top:1.2rem;
  border-top:1px solid var(--rule-2);
  color:var(--ink-3); font:400 13px/1.55 var(--sans); max-width:44rem;
}
.suivi svg { flex:none; width:15px; height:15px; margin-top:.1rem;
  stroke:currentColor; fill:none; stroke-width:1.5; }

/* Les raccourcis existent parce qu'ils sont écrits, mais ils ne disputent rien
   à personne : ils s'éclairent quand on les regarde. */
.touches {
  display:flex; align-items:center; gap:.35rem; flex-wrap:wrap;
  margin:1.4rem 0 0; font:400 11px/1 var(--sans); color:var(--ink-3);
  opacity:.45; transition:opacity .2s var(--ease);
}
.touches:hover { opacity:1; }
.touches kbd {
  font:500 10px/1 var(--mono); padding:.3rem .42rem;
  border:1px solid var(--rule); color:var(--ink-2);
}
.touches span { margin-right:.9rem; }

/* Un halo très bas sous la scène : il donne de la profondeur au fond sans
   qu'on puisse le nommer. Assez faible pour ne jamais se voir comme un effet. */
body::before {
  content:''; position:fixed; inset:0; pointer-events:none; z-index:-1;
  background:radial-gradient(120% 70% at 50% 42%,
    color-mix(in srgb, var(--acc) 7%, transparent), transparent 62%);
}

@media (max-width:640px) {
  .transport { gap:.6rem; }
  .scene__artiste { letter-spacing:.14em; }
}
