/* Charte Bassignac Studio, version outils internes.
   Fond sombre, panneaux à peine détachés, un seul accent doré. Les couleurs de
   locuteur (bleu, rose) ne sont pas décoratives : ce sont exactement celles que
   la vidéo incruste, l'éditeur montre donc déjà le rendu. */

@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('figtree-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: 'Figtree';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('figtree-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;
}
/* La graisse 700 est celle que la vidéo grave dans l'image. */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('figtree-bold.ttf') format('truetype');
}

:root {
  --ink: #0e0e10;
  --panel: #17171a;
  --raise: #1f1f24;
  --line: rgba(255, 255, 255, .09);
  --line-2: rgba(255, 255, 255, .18);
  --text: #edecea;
  --mute: #8d8d95;
  --faint: #5d5d66;
  --gold: #d4a259;
  --gold-soft: rgba(212, 162, 89, .13);
  /* Le vert-jaune des plans, la teinte Higgsfield. Elle n'a rien à voir avec
     l'or du lab : la piste des SHOTS décrit le MONTAGE, pas le son, et se lit
     d'un coup d'œil comme une couche à part. */
  --shot: #c9f24c;
  --shot-soft: rgba(201, 242, 76, .14);
  /* Le rouge du panneau gravé dans la vidéo. Tenu en phase avec `SHOT_COLOR`
     de src/lab/card.js : la pastille de l'écran annonce la couleur du fichier. */
  --shot-ink: #ff2a2a;
  /* Le montage du son : la timeline commande le fichier au lieu de le décrire. */
  --cut: #7be0ad;
  --cut-soft: rgba(123, 224, 173, .12);
  --boy: #4da6ff;
  --girl: #ff7eb6;
  --ok: #7be0ad;
  --warn: #ffb454;
  --bad: #ff6b6b;
  --r-s: 8px;
  --r-m: 14px;
  --r-l: 22px;
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }

/* Toute règle `display` d'une classe l'emporte sur le `display: none` que le
   navigateur applique à l'attribut `hidden`. Sans ce rappel, un panneau masqué
   par le script reste à l'écran. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--ink);
  color: var(--text);
  font: 400 16px/1.5 'Figtree', ui-sans-serif, system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  border-radius: 4px;
}

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ── Barre de tête ─────────────────────────────────────────────── */

.bar {
  display: flex; align-items: center; gap: 14px;
  padding: 14px clamp(16px, 4vw, 34px);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--ink) 88%, transparent);
  backdrop-filter: blur(14px);
}
.bar__mark { width: 22px; height: 22px; opacity: .9; flex: none; }
.bar__name {
  font-weight: 700; font-size: 13px; letter-spacing: .16em; text-transform: uppercase;
  white-space: nowrap;
}
.bar__name em { font-style: normal; color: var(--gold); }
.bar__spacer { flex: 1; }
.bar__who { color: var(--faint); font-size: 13px; }
.bar__link {
  color: var(--mute); font-size: 13px; text-decoration: none; white-space: nowrap;
  border-bottom: 1px solid transparent; padding-bottom: 1px;
}
.bar__link:hover { color: var(--text); border-bottom-color: var(--line-2); }

/* Sortie vers le choix des applications. Même grille de neuf points que dans
   Atlas : d'une application à l'autre, le geste pour remonter est le même. */
.bar__switch {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  padding: 7px 12px; border-radius: 7px; text-decoration: none;
  border: 1px solid var(--line); color: var(--mute); font-size: 13px;
  transition: color .18s ease, border-color .18s ease, background .18s ease;
}
.bar__switch:hover, .bar__switch:focus-visible {
  color: var(--gold); border-color: rgba(212, 162, 89, .45); background: var(--gold-soft);
}
.bar__switch svg { flex: none; }

@media (max-width: 560px) { .bar__who { display: none; } }
/* L'icône seule suffit quand la place manque : la grille de neuf points et la
   maison se lisent sans mot, et la barre tient sur une ligne. */
@media (max-width: 620px) { .bar__switch span { display: none; } }
@media (max-width: 430px) {
  .bar { gap: 10px; padding-inline: 14px; }
  .bar__name { font-size: 12px; letter-spacing: .12em; }
  .bar__link { font-size: 12.5px; }
  .bar__switch { padding: 7px 9px; }
}

/* ── Boutons ───────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 12px 20px; border-radius: var(--r-s);
  border: 1px solid var(--line-2); background: var(--raise); color: var(--text);
  font-weight: 500; font-size: 15px; line-height: 1;
  transition: background .18s ease, border-color .18s ease, transform .12s ease, opacity .18s ease;
}
.btn:hover:not(:disabled) { background: #2a2a30; border-color: rgba(255, 255, 255, .3); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: .42; cursor: not-allowed; }
.btn--gold {
  background: var(--gold); border-color: var(--gold); color: #14100a; font-weight: 700;
}
.btn--gold:hover:not(:disabled) { background: #e0b571; border-color: #e0b571; }
.btn--quiet { background: transparent; border-color: var(--line); color: var(--mute); }
.btn--quiet:hover:not(:disabled) { color: var(--text); background: var(--raise); }
.btn--small { padding: 8px 13px; font-size: 13px; border-radius: 7px; }
.btn--bad { border-color: rgba(255, 107, 107, .45); color: var(--bad); }
.btn--bad:hover:not(:disabled) { background: rgba(255, 107, 107, .12); border-color: var(--bad); }

/* ── Une porte, un bouton ──────────────────────────────────────── */

.door {
  min-height: 100dvh; display: grid; place-items: center;
  padding: 24px; position: relative; overflow: hidden;
}
/* Le halo : une ampoule au-dessus d'une entrée de service, qui respire.
   Seul geste décoratif de la page, et le seul indice qu'il y a quelqu'un. */
.door::before {
  content: ''; position: absolute; inset: auto; width: min(120vw, 900px); aspect-ratio: 1;
  background: radial-gradient(circle, rgba(212, 162, 89, .16), transparent 62%);
  animation: breathe 7s ease-in-out infinite; pointer-events: none;
}
@keyframes breathe {
  0%, 100% { opacity: .34; transform: scale(.9); }
  50% { opacity: .82; transform: scale(1.06); }
}
.door__inner { position: relative; text-align: center; display: grid; gap: 40px; justify-items: center; }

/* La marque, à sa vraie taille. Elle était à 46 px et à moitié effacée : sur la
   seule page que voit quelqu'un qui n'est pas encore entré, la maison doit se
   reconnaître avant le bouton. Le trait du logo est fin, il ne supporte pas
   d'être réduit — d'où une taille qui suit l'écran plutôt qu'un chiffre fixe. */
.door__brand { display: grid; gap: 20px; justify-items: center; }
.door__mark { width: clamp(104px, 22vw, 148px); height: auto; }
.door__word { width: clamp(160px, 34vw, 216px); height: auto; opacity: .92; }
.door__step { display: grid; gap: 18px; justify-items: center; }

.door__google {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 14px 24px; border-radius: 999px; text-decoration: none;
  border: 1px solid var(--line-2); background: var(--panel); color: var(--text);
  font-weight: 500; transition: background .2s ease, border-color .2s ease;
}
.door__google:hover { background: var(--raise); border-color: rgba(255, 255, 255, .32); }
.door__note { color: var(--faint); font-size: 12.5px; margin: 0; }
.door__note b { color: var(--mute); font-weight: 500; }
.door__error {
  margin: 0; color: var(--warn); font-size: 13px; line-height: 1.6;
  max-width: 54ch; text-align: left; overflow-wrap: anywhere;
  border: 1px solid rgba(255, 180, 84, .3); background: rgba(255, 180, 84, .07);
  padding: 12px 16px; border-radius: var(--r-s);
}
.door__foot {
  position: absolute; bottom: 22px; left: 50%; transform: translateX(-50%);
  color: var(--faint); font-size: 11px; letter-spacing: .22em; text-transform: uppercase;
  text-decoration: none; opacity: .55; transition: opacity .2s ease;
}
.door__foot:hover { opacity: 1; }

/* ── Choix d'une application ───────────────────────────────────── */

/* Le bloc est centré dans ce qui reste de l'écran sous la barre, comme un
   écran de choix d'appareil : rien d'autre à faire sur cette page. */
.picker {
  min-height: calc(100dvh - 54px); display: grid; align-content: center;
  padding: 40px 20px 70px; text-align: center;
}
.picker__eyebrow {
  color: var(--faint); font-size: 11.5px; letter-spacing: .3em; text-transform: uppercase; margin: 0 0 46px;
}
.grid {
  display: grid; gap: clamp(26px, 5vw, 52px);
  grid-template-columns: repeat(auto-fit, minmax(150px, 168px));
  justify-content: center; max-width: 900px; margin: 0 auto;
}
/* `align-content: start` n'est pas un détail : les tuiles d'une même rangée
   sont étirées à la hauteur de la plus grande, et sans cette ligne l'espace en
   trop est redistribué DANS les rangs de chaque tuile. Une description qui tient
   sur une ligne de moins décale alors son nom de six pixels — mesuré sur Suno,
   dont la phrase est plus courte que les autres. */
.app {
  text-decoration: none; color: inherit; display: grid; gap: 15px;
  justify-items: center; align-content: start;
}
.app__tile {
  width: clamp(120px, 34vw, 152px); aspect-ratio: 1; border-radius: 27%;
  display: grid; place-items: center;
  background: var(--panel); border: 1px solid var(--line);
  box-shadow: 0 16px 34px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .05);
  transition: transform .22s cubic-bezier(.2, .8, .3, 1), box-shadow .22s ease, border-color .22s ease;
}
.app__tile svg { width: 46%; height: 46%; }

/* Une application extérieure garde SA marque : le fond est sa couleur, posée
   en style plutôt qu'en image, et seul le glyphe vient du fichier — l'icône
   reste donc nette quelle que soit la définition de l'écran. */
.app__tile--brand { background: var(--brand); border-color: transparent; }
/* Un logo déjà en couleur garde la tuile ordinaire : c'est lui qui porte la
   marque, la tuile n'a qu'à l'encadrer. */
.app__tile img { width: var(--logo, 62%); height: auto; }
.app:hover .app__tile, .app:focus-visible .app__tile {
  transform: translateY(-6px) scale(1.045);
  border-color: rgba(212, 162, 89, .55);
  box-shadow: 0 22px 48px rgba(0, 0, 0, .62), 0 0 0 4px rgba(212, 162, 89, .12);
}
.app:focus-visible { outline: none; }
.app__name { font-weight: 700; font-size: 15px; letter-spacing: .01em; }
.app__what { color: var(--faint); font-size: 12.5px; margin-top: -9px; max-width: 19ch; line-height: 1.4; }

/* Un compte tout neuf n'a encore aucune application : il doit lire pourquoi
   son écran est vide, et à qui s'adresser. */
.picker__none {
  color: var(--mute); font-size: 14px; line-height: 1.7; max-width: 40ch;
  margin: 0 auto; padding: 20px 22px; border-radius: var(--r-m);
  border: 1px solid var(--line); background: var(--panel);
}

/* ── L'écran des accès ─────────────────────────────────────────── */

.admin { max-width: 940px; margin: 0 auto; padding: 34px clamp(14px, 3.5vw, 30px) 90px; display: grid; gap: 24px; }
.admin__head { display: grid; gap: 8px; }
.admin__title { margin: 0; font-size: 21px; font-weight: 700; letter-spacing: .01em; }
.admin__lead { margin: 0; color: var(--mute); font-size: 13.5px; line-height: 1.6; max-width: 62ch; }
/* La grille peut dépasser en largeur sur un téléphone : elle défile dans son
   propre cadre, la page ne défile jamais de côté. */
.admin__scroll { overflow-x: auto; border-radius: var(--r-m); border: 1px solid var(--line); background: var(--panel); }

.rights { border-collapse: collapse; width: 100%; font-size: 13.5px; }
.rights th, .rights td { padding: 12px 14px; text-align: center; border-bottom: 1px solid var(--line); }
.rights thead th { color: var(--mute); font-weight: 500; font-size: 12.5px; white-space: nowrap; }
.rights__app { display: block; color: var(--text); font-weight: 700; font-size: 13px; }
.rights__ext { display: block; color: var(--faint); font-size: 11px; margin-top: 2px; }
.rights__who { text-align: left; white-space: nowrap; }
.rights__mail { color: var(--text); }
.rights__note { display: block; color: var(--faint); font-size: 11.5px; }
.rights__tag {
  display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px;
  font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--gold); border: 1px solid rgba(212, 162, 89, .4); background: var(--gold-soft);
}
/* « Tout le monde » n'est pas un compte : la ligne est détachée des autres pour
   qu'on ne coche pas l'une en croyant cocher l'autre. */
.rights__row--all { background: rgba(255, 255, 255, .025); }
.rights__row--all td { border-bottom: 2px solid var(--line-2); }
.rights__box { display: inline-grid; place-items: center; cursor: pointer; }
.rights__box input { width: 18px; height: 18px; accent-color: var(--gold); cursor: pointer; }
.rights__box input:disabled { opacity: .4; cursor: progress; }
.rights tbody tr:last-child td { border-bottom: 0; }
.rights__end { width: 42px; padding-left: 0; }
/* La croix de retrait n'existe que sur les lignes qui ne tiennent à rien : ni
   accès coché, ni connexion passée. Discrète au repos, rouge au survol — c'est
   un retrait, pas une case à cocher. */
.rights__drop {
  width: 24px; height: 24px; border-radius: 6px; line-height: 1; font-size: 15px;
  border: 1px solid var(--line); background: transparent; color: var(--faint);
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.rights__drop:hover:not(:disabled) { color: var(--bad); border-color: rgba(255, 107, 107, .45); background: rgba(255, 107, 107, .1); }
.rights__drop:disabled { opacity: .4; cursor: progress; }

/* La grille et le formulaire sont dans un même bloc : sans cette grille, le
   `gap` du panneau ne s'applique pas entre eux et le tableau colle au champ. */
.admin__body { display: grid; gap: 22px; }
.admin__add { display: grid; gap: 9px; }
.admin__label { color: var(--mute); font-size: 13px; }
.admin__addRow { display: flex; gap: 10px; flex-wrap: wrap; }
.admin__input {
  flex: 1; min-width: 240px; padding: 9px 12px; border-radius: 7px;
  border: 1px solid var(--line); background: var(--raise); color: var(--text); font-size: 14px;
}
.admin__input:focus { outline: none; border-color: var(--gold); }
.admin__hint { margin: 0; color: var(--faint); font-size: 12px; }

/* ── Le lab ────────────────────────────────────────────────────── */

.lab { max-width: 1080px; margin: 0 auto; padding: 24px clamp(14px, 3.5vw, 30px) 90px; display: grid; gap: 20px; }

/* ── L'étagère : les projets, comme des mémos vocaux ───────────── */

.shelf__title {
  margin: 30px 0 12px; font-size: 12px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--faint); font-weight: 700;
}
.shelf { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.shelf__item {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--line); border-radius: var(--r-m); background: var(--panel);
  transition: border-color .18s ease, background .18s ease;
}
.shelf__item:hover { border-color: var(--line-2); background: var(--raise); }
.shelf__open {
  flex: 1; min-width: 0; display: grid; gap: 4px;
  padding: 15px 4px 15px 18px; text-decoration: none; color: inherit;
}
.shelf__name {
  font-weight: 700; font-size: 15.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.shelf__meta { color: var(--faint); font-size: 12.5px; }
.shelf__tools { display: flex; gap: 2px; padding-right: 10px; }
.shelf__tools button, .shelf__tools a {
  display: grid; place-items: center; width: 36px; height: 36px;
  border: none; background: transparent; color: var(--faint); border-radius: 7px;
  transition: color .15s ease, background .15s ease;
}
.shelf__tools button:hover, .shelf__tools a:hover { color: var(--text); background: rgba(255, 255, 255, .07); }
.shelf__tools [data-act='delete']:hover { color: var(--bad); background: rgba(255, 107, 107, .1); }
.shelf__empty { color: var(--faint); font-size: 14px; text-align: center; padding: 26px 0; }

/* ── L'en-tête de l'éditeur ────────────────────────────────────── */

.editor__head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 4px; }
.editor__name {
  flex: 1; min-width: 190px;
  background: transparent; border: 1px solid transparent; border-radius: var(--r-s);
  padding: 8px 10px; font-size: 20px; font-weight: 700; letter-spacing: -.01em;
}
.editor__name:hover { border-color: var(--line); }
.editor__name:focus { outline: none; border-color: var(--gold); background: var(--panel); }
.editor__state { color: var(--faint); font-size: 12.5px; white-space: nowrap; }
.editor__state.is-dirty { color: var(--warn); }

.blank { display: grid; gap: 14px; justify-items: center; padding: 22px 0; text-align: center; }
.blank p { margin: 0; color: var(--mute); }

/* ── Les fenêtres de confirmation ──────────────────────────────── */

.ask {
  max-width: 440px; width: calc(100vw - 32px);
  border: 1px solid var(--line-2); border-radius: var(--r-m);
  background: var(--panel); color: var(--text); padding: 22px;
}
.ask::backdrop { background: rgba(0, 0, 0, .62); backdrop-filter: blur(3px); }
.ask__title { margin: 0 0 10px; font-size: 17px; font-weight: 700; }
.ask__text { margin: 0 0 20px; color: var(--mute); font-size: 14px; line-height: 1.55; }
.ask__actions { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
.ask--wide { max-width: 640px; }

/* Le compteur de coût, dans l'en-tête du projet. Discret tant qu'il est à zéro :
   un projet qui n'a rien coûté n'a pas à porter une alarme. */
.cost {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  padding: 6px 11px; border-radius: 7px; font-size: 13px;
  border: 1px solid var(--line); background: transparent; color: var(--mute);
  font-variant-numeric: tabular-nums;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.cost:hover { color: var(--text); border-color: var(--line-2); background: var(--raise); }
.cost__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--faint); }
.cost.is-spent { color: var(--gold); border-color: rgba(212, 162, 89, .38); }
.cost.is-spent .cost__dot { background: var(--gold); }

/* Le détail : une ligne par dépense, telle qu'elle a eu lieu. */
.spend { list-style: none; margin: 0 0 18px; padding: 0; display: grid; gap: 8px; max-height: 46vh; overflow: auto; }
.spend__l {
  display: grid; grid-template-columns: 1fr auto; gap: 3px 14px; align-items: baseline;
  padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--r-s); background: var(--raise);
}
.spend__k { font-weight: 700; font-size: 13.5px; }
.spend__n { font-variant-numeric: tabular-nums; color: var(--gold); font-weight: 700; font-size: 13.5px; }
.spend__d { grid-column: 1 / -1; font-size: 12.5px; color: var(--faint); }
.spend__empty { color: var(--mute); font-size: 13.5px; padding: 4px 0; }

/* Dans la liste des projets : le montant à la suite des autres repères. */
.shelf__cost { color: var(--gold); }
.shelf__cost.is-free { color: inherit; }

/* Un choix entre deux façons de faire la même chose, dont une est payante : les
   deux sont posées côte à côte, avec ce qu'elles coûtent et ce qu'elles valent.
   Aucune n'est présélectionnée — c'est le clic qui engage, jamais le défaut. */
.pick { display: grid; gap: 12px; margin: 0 0 20px; grid-template-columns: 1fr 1fr; }
@media (max-width: 560px) { .pick { grid-template-columns: 1fr; } }
.pick__opt {
  display: grid; gap: 7px; text-align: left; align-content: start;
  padding: 15px 16px; border-radius: var(--r-s);
  border: 1px solid var(--line-2); background: var(--raise); color: var(--text);
  transition: border-color .18s ease, background .18s ease;
}
.pick__opt:hover { border-color: var(--gold); background: #26262c; }
.pick__name { font-weight: 700; font-size: 15px; }
.pick__tag {
  justify-self: start; font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--gold); background: var(--gold-soft); border-radius: 5px; padding: 3px 8px;
}
.pick__tag--free { color: var(--ok); background: rgba(123, 224, 173, .12); }
.pick__why { font-size: 13px; line-height: 1.5; color: var(--mute); }

.step { border: 1px solid var(--line); border-radius: var(--r-m); background: var(--panel); overflow: hidden; }
.step[aria-disabled='true'] { opacity: .42; pointer-events: none; }
.step__head {
  display: flex; align-items: center; gap: 11px;
  padding: 14px 18px; border-bottom: 1px solid var(--line);
}
.step__n {
  width: 21px; height: 21px; flex: none; border-radius: 50%;
  border: 1px solid rgba(212, 162, 89, .45); color: var(--gold);
  font-size: 11px; font-weight: 700; display: grid; place-items: center;
}
.step__title { font-weight: 700; font-size: 12.5px; letter-spacing: .17em; text-transform: uppercase; }
.step__meta { margin-left: auto; color: var(--faint); font-size: 12.5px; text-align: right; }
.step__body { padding: 18px; }
/* Sur un téléphone, le détail passe sous le titre plutôt que de l'écraser. */
@media (max-width: 620px) {
  .step__head { flex-wrap: wrap; }
  .step__meta { margin-left: 0; flex-basis: 100%; text-align: left; padding-left: 32px; }
}

/* Dépôt du fichier */
.drop {
  border: 1.5px dashed var(--line-2); border-radius: var(--r-m);
  padding: clamp(26px, 7vw, 46px) 20px; text-align: center;
  display: grid; gap: 13px; justify-items: center;
  transition: border-color .2s ease, background .2s ease;
}
.drop.is-over { border-color: var(--gold); background: var(--gold-soft); }
.drop__hint { color: var(--faint); font-size: 12.5px; margin: 0; }
.drop__title { margin: 0; font-weight: 700; font-size: 17px; }

.file {
  display: grid; gap: 14px; border-radius: var(--r-s);
  transition: outline-color .2s ease, background .2s ease;
  outline: 1.5px dashed transparent; outline-offset: 10px;
}
/* Un fichier traîné jusqu'ici prend la place de celui qui est en écoute : le
   bloc entier s'allume, pour qu'on voie où on lâche. */
.file.is-over { outline-color: var(--gold); background: var(--gold-soft); }
.file__row { display: flex; align-items: center; gap: 13px; flex-wrap: wrap; }
.file__name { font-weight: 700; word-break: break-all; flex: 1; min-width: 150px; }
.file__facts { color: var(--faint); font-size: 13px; font-variant-numeric: tabular-nums; }
.file__hint { color: var(--faint); font-size: 12.5px; margin: 14px 0 0; line-height: 1.5; }
.file__hint + .working { margin-top: 14px; }
.wave { width: 100%; height: 68px; display: block; border-radius: var(--r-s); background: #0b0b0d; }
.play {
  width: 42px; height: 42px; flex: none; border-radius: 50%;
  border: 1px solid var(--line-2); background: var(--raise);
  display: grid; place-items: center;
}
.play svg { width: 15px; height: 15px; fill: var(--text); }

/* ── La piste des plans ─────────────────────────────────────────
   Plus étroite que la timeline, posée juste au-dessus et EXACTEMENT alignée sur
   elle : les deux décrivent le même fichier, et une frontière de plan doit se
   lire à la verticale du bloc de MAP qu'elle coupe. D'où la largeur pleine,
   sans marge propre, et les commandes rejetées sur une ligne au-dessus. */
.track { margin-bottom: 6px; }
.track__head {
  display: flex; align-items: center; gap: 12px; margin-bottom: 5px;
}
.track__name { font-size: 11.5px; letter-spacing: 1.6px; font-weight: 700; }
.track__hint { color: var(--faint); font-size: 12px; }
.track__spacer { flex: 1; }

.shots {
  position: relative; height: 30px; border-radius: var(--r-s);
  background: #08080a; border: 1px solid var(--line); overflow: hidden;
  touch-action: pan-y; user-select: none; -webkit-user-select: none;
}

/* Les repères chiffrés, juste au-dessus de la piste. Deux rangées : les durées
   de plan en haut, centrées sur leur plan ; les instants de coupe en bas, sur
   la frontière qu'ils désignent. Mélangées, elles se chevaucheraient sur un
   découpage serré et aucun des deux nombres ne se lirait.
   La bande ne reçoit aucun clic : la piste est juste dessous, et un nombre qui
   avale le geste de la souris empêcherait de saisir une frontière. */
.shots__marks {
  position: relative; height: 32px; margin-bottom: 3px;
  pointer-events: none; font-variant-numeric: tabular-nums;
}
.shots__len {
  position: absolute; top: 0; transform: translateX(-50%);
  font-size: 11.5px; font-weight: 700; color: var(--shot);
  white-space: nowrap; letter-spacing: .01em;
}
/* Le rouge est celui du panneau gravé dans la vidéo (`--shot-ink`) : à l'écran
   comme à l'image, la coupe se reconnaît à la même couleur. */
.shots__at {
  position: absolute; bottom: 0; transform: translateX(-50%);
  font-size: 11px; font-weight: 700; color: var(--shot-ink);
  white-space: nowrap; letter-spacing: .01em;
  padding: 0 3px; border-radius: 3px; background: #08080a;
}
.shots__at--haut { bottom: 15px; }
/* Décochée, la piste est éteinte : ses chiffres le sont avec elle. */
.track.is-off .shots__marks { opacity: .3; filter: saturate(.25); }
/* Décochée, la piste reste VISIBLE mais éteinte : masquer la bande ferait
   sauter la page à chaque clic sur la case, et on ne verrait plus ce que la
   case commande. */
.track.is-off .shots { opacity: .3; filter: saturate(.25); pointer-events: none; }
/* Le compteur reste ACTIF décoché : cliquer « + » est le geste par lequel on
   enclenche les scènes, et un bouton inerte ne mènerait nulle part. */
.track.is-off .stepper { opacity: .55; }

.shots__bar {
  position: absolute; top: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--shot); color: #14180a;
  font-size: 11px; font-weight: 700; letter-spacing: .8px;
  border-right: 1px solid var(--ink); overflow: hidden; white-space: nowrap;
}
/* Un plan sur deux légèrement assombri : sans cette alternance, deux plans
   voisins de même teinte ne se distinguent que par un trait d'un pixel. */
.shots__bar:nth-child(even) { background: #a8d43a; }
.shots__bar span { padding: 0 6px; }

/* La frontière entre deux plans, à cheval sur les deux : c'est elle qu'on tire.
   Le plan 1 n'en a pas à gauche — son début est 0,0 et ne se déplace pas. */
.shots__cut {
  position: absolute; top: 0; bottom: 0; width: 18px; margin-left: -9px;
  cursor: ew-resize; z-index: 3; display: grid; place-items: center;
}
/* La poignée se voit de loin : sur du vert-jaune, un trait sombre disparaît.
   Elle est donc claire, cernée de noir, et occupe presque toute la hauteur —
   c'est un élément qu'on doit attraper, pas seulement un séparateur. */
.shots__cut::after {
  content: ''; width: 5px; height: 22px; border-radius: 3px;
  background: #fff; border: 1px solid var(--ink);
  transition: height .12s ease, width .12s ease, background .12s ease;
}
.shots__cut:hover::after, .shots__cut.is-dragging::after {
  width: 7px; height: 26px; background: var(--gold);
}

/* La timeline : la MAP vue comme une bande de temps, et manipulable comme
   telle. Assez haute pour qu'un bloc s'attrape au doigt. */
.ribbon {
  position: relative; height: 56px; border-radius: var(--r-s);
  background: #08080a; border: 1px solid var(--line); overflow: hidden;
  margin-bottom: 6px; cursor: pointer; touch-action: pan-y;
  user-select: none; -webkit-user-select: none;
}
.tl__seg {
  position: absolute; top: 0; bottom: 0; border-right: 1px solid var(--ink);
  cursor: grab; box-sizing: border-box;
}
.tl__seg[data-kind='silence'] { background: rgba(255, 255, 255, .05); }
/* Le VIDE : la place qu'un bloc déplacé a quittée, et qui ne porte plus aucun
   son. Hachurée, pour qu'on ne la confonde pas d'un coup d'œil avec un silence
   du fichier — celui-là porte encore l'ambiance, celui-ci ne porte rien. */
.tl__seg[data-kind='void'] {
  background: repeating-linear-gradient(135deg,
    rgba(255, 255, 255, .02) 0 5px, rgba(255, 255, 255, .07) 5px 10px);
}
.tl__seg:hover { filter: brightness(1.14); }
.tl__seg:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
/* Le bloc sélectionné : contour doré épais, au-dessus des autres pour que ses
   poignées restent attrapables même quand il touche ses voisins. */
.tl__seg.is-picked {
  z-index: 2; box-shadow: inset 0 0 0 3px var(--gold), 0 0 0 1px rgba(0, 0, 0, .5);
  cursor: grab;
}
.tl__seg.is-picked[data-kind='silence'] { background: rgba(212, 162, 89, .12); }
.tl__seg.is-picked[data-kind='void'] {
  background: repeating-linear-gradient(135deg,
    rgba(212, 162, 89, .06) 0 5px, rgba(212, 162, 89, .18) 5px 10px);
}
.tl__seg.is-dragging, .tl__seg.is-dragging:hover { cursor: grabbing; filter: brightness(1.14); }
/* Les poignées débordent un peu du bloc : sur un bloc de 0,4 s, une poignée
   strictement intérieure serait plus étroite qu'un doigt. */
.tl__grip {
  position: absolute; top: 0; bottom: 0; cursor: ew-resize;
  background: var(--gold); border-radius: 3px; z-index: 3;
}
.tl__grip::after {
  content: ''; position: absolute; top: 50%; left: 50%; width: 2px; height: 16px;
  transform: translate(-50%, -50%); background: rgba(0, 0, 0, .55); border-radius: 2px;
}
/* La largeur et le décalage sont posés par le script : ils dépendent de la
   largeur réelle du bloc, pour qu'une poignée n'avale jamais son corps. */
.ribbon__head { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--gold); opacity: 0; z-index: 4; }
.ribbon__head.is-on { opacity: 1; }
/* La règle de temps sous la timeline : un point par seconde, un chiffre toutes
   les cinq. Les graduations sont posées en pourcentage par le script, donc
   elles restent alignées sur les blocs quelle que soit la largeur de l écran. */
.scale {
  position: relative; height: 22px; margin-bottom: 10px;
  color: var(--faint); font-size: 10.5px; font-variant-numeric: tabular-nums;
}
.scale__tick { position: absolute; top: 0; width: 1px; height: 3px; background: var(--line-2); }
/* Une graduation sur cinq est plus haute et porte son chiffre : l œil compte
   les points entre deux repères sans avoir à lire. */
.scale__tick--big { height: 6px; background: rgba(255, 255, 255, .32); }
.scale__label { position: absolute; top: 8px; transform: translateX(-50%); white-space: nowrap; }
/* Le premier et le dernier chiffre se collent au bord plutôt que de déborder. */
.scale__label--first { transform: none; left: 0; }
.scale__label--last { transform: none; right: 0; left: auto; }

/* Le menu des voix : mêmes bords que les champs voisins, plus la flèche qui
   annonce une liste. Sans elle, rien ne dirait qu on peut en changer. */
.row__voice {
  width: 100%; padding: 8px 26px 8px 10px; border-radius: 7px;
  border: 1px solid var(--line); background: var(--raise); color: var(--text);
  font-size: 13.5px; appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238d8d95' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; background-size: 10px;
}
.row__voice:focus { outline: none; border-color: var(--gold); }
.row__voice option { background: var(--panel); color: var(--text); }

/* La piste audio porte la MÊME tête de lecture que la timeline : on suit
   l'écoute sur l'onde comme sur les blocs, sans chercher des yeux. */
.wave__zone { position: relative; }
.wave__head {
  position: absolute; top: 0; bottom: 0; width: 2px; background: var(--gold);
  opacity: 0; pointer-events: none;
}
.wave__head.is-on { opacity: 1; }

/* ── Le pied de page ──────────────────────────────────────────── */
.foot {
  color: var(--faint); font-size: 11.5px; text-align: center;
  padding: 26px 20px 34px; border-top: 1px solid var(--line); margin-top: 30px;
}
.foot a { color: var(--mute); text-decoration: none; border-bottom: 1px solid transparent; }
.foot a:hover { color: var(--gold); border-bottom-color: rgba(212, 162, 89, .45); }
/* Sur la porte, le pied de page ne doit pas pousser le halo hors de l écran. */
.door + .foot { border-top: 0; margin-top: 0; }

/* La barre de transport, sous la timeline. */
.transport { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.transport__keys { display: flex; align-items: center; gap: 5px; }
.transport__spacer { flex: 1; }
.transport__what { color: var(--faint); font-size: 12.5px; }
.tp {
  width: 34px; height: 32px; border-radius: 7px; display: grid; place-items: center;
  border: 1px solid var(--line); background: transparent; color: var(--mute);
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.tp svg { width: 16px; height: 16px; fill: currentColor; }
.tp:hover { color: var(--gold); border-color: rgba(212, 162, 89, .45); background: var(--gold-soft); }
.tp--main { width: 42px; color: var(--text); border-color: var(--line-2); }

.switch { display: flex; align-items: center; gap: 7px; color: var(--mute); font-size: 12.5px; cursor: pointer; }
.switch input { accent-color: var(--gold); width: 15px; height: 15px; }

/* Annuler et rétablir, à côté du nom du projet : le raccourci ⌘Z est le geste
   courant, mais un raccourci ne se découvre pas — les deux flèches disent qu'il
   existe, et leur état dit s'il y a quelque chose à défaire. */
.undo { display: flex; align-items: center; gap: 3px; flex: none; }
.undo__btn {
  width: 30px; height: 28px; border-radius: 7px; display: grid; place-items: center;
  border: 1px solid var(--line); background: transparent; color: var(--mute);
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.undo__btn svg { width: 17px; height: 17px; }
.undo__btn:hover:not(:disabled) { color: var(--gold); border-color: rgba(212, 162, 89, .45); background: var(--gold-soft); }
.undo__btn:disabled { opacity: .3; cursor: not-allowed; }

/* Le compteur de plans, au bout de la piste. */
.stepper { display: flex; align-items: center; gap: 2px; }
.stepper__btn {
  width: 26px; height: 24px; border-radius: 6px; line-height: 1;
  border: 1px solid var(--line); background: transparent; color: var(--mute);
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.stepper__btn:hover:not(:disabled) { color: var(--shot); border-color: rgba(201, 242, 76, .45); background: var(--shot-soft); }
.stepper__btn:disabled { opacity: .35; cursor: not-allowed; }
.stepper__n {
  min-width: 30px; text-align: center; font-variant-numeric: tabular-nums;
  font-size: 13px; font-weight: 700; color: var(--text);
}

/* L'edit map : un aperçu du texte qui sortira, tel qu'il sortira. */
.edit {
  margin-top: 14px; padding: 12px; border-radius: var(--r-s);
  background: var(--raise); border: 1px solid var(--line);
}
.edit__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.edit__title {
  font-size: 11.5px; letter-spacing: 1.6px; font-weight: 700; color: var(--shot);
}
.edit__hint { color: var(--faint); font-size: 12px; }
/* Éditable, parce qu'on y COLLE : une edit map écrite ailleurs revient ici et
   replace les barres. D'où un vrai champ de saisie, pas un aperçu. */
.edit__text {
  display: block; width: 100%; margin: 0; padding: 10px 12px; border-radius: 6px;
  background: #08080a; border: 1px solid var(--line); color: var(--text);
  font: 400 12.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; resize: vertical; min-height: 150px; max-height: 60vh;
  overflow-y: auto;
}
.edit__text:focus { outline: none; border-color: var(--shot); }

/* La timeline quand elle COMMANDE le son : un liseré vert, visible sans être
   criard, pour qu'on sache d'un coup d'œil que déplacer un bloc déplace la voix. */
.ribbon.is-cut { border-color: rgba(123, 224, 173, .5); box-shadow: inset 0 0 0 1px rgba(123, 224, 173, .18); }
.note--cut { color: var(--cut); background: var(--cut-soft); border-color: rgba(123, 224, 173, .3); }

/* Les lignes de la MAP */
.rows { display: grid; gap: 7px; }
.row {
  display: grid; gap: 8px; align-items: center;
  grid-template-columns: 92px 92px 104px 1fr auto;
  padding: 8px; border-radius: var(--r-s);
  background: var(--raise); border: 1px solid transparent;
}
/* La ligne dont le bloc est sélectionné sur la timeline : même contour doré,
   pour qu'on voie d'un coup d'œil de quel bloc on parle. */
.row.is-picked { border-color: var(--gold); background: var(--gold-soft); }

/* Un temps, et les deux flèches qui le bougent d'un dixième. Collées au nombre :
   impossible de les confondre avec les flèches de déplacement du texte, qui
   vivent tout à droite de la ligne. */
.row__time { display: flex; align-items: stretch; gap: 3px; min-width: 0; }
.row__time .row__t { flex: 1; min-width: 0; }
.row__step { display: grid; grid-template-rows: 1fr 1fr; gap: 2px; width: 17px; flex: none; }
.row__step button {
  border: 1px solid var(--line); background: transparent; color: var(--mute);
  border-radius: 4px; line-height: 1; font-size: 8px; padding: 0;
  transition: color .15s ease, border-color .15s ease;
}
.row__step button:hover { color: var(--gold); border-color: rgba(212, 162, 89, .45); }

/* Les flèches réarrangent le TEXTE, pas les fenêtres de temps : celles-ci
   appartiennent au son. Toujours visibles, parce que réarranger est le geste
   courant une fois la transcription revenue de travers. */
.row__move { display: flex; gap: 3px; align-items: center; }
/* Le bouton qui va chercher le bloc sur la timeline : séparé des flèches, il ne
   modifie rien, il désigne. */
.row__move .is-pick { margin-right: 6px; }
.row__move .is-pick svg { display: block; margin: 0 auto; }
.row__move .is-pick.is-on { color: var(--gold); border-color: rgba(212, 162, 89, .45); background: var(--gold-soft); }
.row__move button {
  width: 30px; height: 32px; border-radius: 6px; line-height: 1;
  border: 1px solid var(--line); background: transparent; color: var(--mute); font-size: 14px;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.row__move button:hover:not(:disabled) { color: var(--gold); border-color: rgba(212, 162, 89, .45); background: var(--gold-soft); }
.row__move button:disabled { opacity: .3; cursor: not-allowed; }
.row:focus-within { border-color: var(--line-2); }
.row.is-silence { background: transparent; border-color: var(--line); }
.row input, .row textarea {
  background: #131316; border: 1px solid var(--line); border-radius: 6px;
  padding: 9px 10px; width: 100%; min-width: 0;
}
.row input:focus, .row textarea:focus { outline: none; border-color: var(--gold); }
.row__t { font-variant-numeric: tabular-nums; text-align: center; font-size: 13.5px; }
.row__t.is-bad { border-color: var(--bad); color: var(--bad); }
/* La zone reste TOUJOURS déployée : sa hauteur est celle de son texte, posée
   sans détour ni animation (voir `grow()` dans lab.js). Corriger un mot suppose
   de voir la phrase entière, tout de suite. */
.row__text {
  font-weight: 700; letter-spacing: .012em; line-height: 1.45;
  resize: none; overflow: hidden; font-family: inherit;
}
.row__text::placeholder { font-weight: 400; color: var(--faint); letter-spacing: 0; }
/* `--voice` est posée par le script à partir de la règle partagée : la couleur
   affichée ici est exactement celle que la vidéo gravera. */
.row__text { color: var(--voice, var(--text)); }
/* Les outils n'appartiennent qu'à la ligne qu'on est en train de travailler :
   affichés partout, ils quadruplent la hauteur de la MAP et noient le texte,
   qui est la seule chose à lire ici. */
.row__tools { display: none; grid-column: 1 / -1; gap: 6px; flex-wrap: wrap; padding-top: 2px; }
.row:hover .row__tools, .row:focus-within .row__tools { display: flex; }
.row__tools button {
  border: 1px solid var(--line); background: transparent; color: var(--mute);
  border-radius: 6px; padding: 5px 10px; font-size: 12px;
}
.row__tools button:hover { color: var(--text); border-color: var(--line-2); background: var(--raise); }
@media (max-width: 760px) {
  .row { grid-template-columns: 1fr 1fr 1fr auto; }
  .row__text { grid-column: 1 / -1; }
}
@media (max-width: 460px) {
  .row { grid-template-columns: 1fr 1fr auto; }
  .row [data-f='speaker'] { grid-column: 1 / 3; }
}

.raw { width: 100%; min-height: 320px; resize: vertical; font-variant-numeric: tabular-nums;
  background: #131316; border: 1px solid var(--line); border-radius: var(--r-s); padding: 14px;
  font-family: ui-monospace, 'SF Mono', Menlo, monospace; font-size: 13px; line-height: 1.75; }
.raw:focus { outline: none; border-color: var(--gold); }
.actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-top: 18px; }
.actions__spacer { flex: 1; }

.note { margin: 12px 0 0; font-size: 13px; color: var(--mute); }
.note--ok { color: var(--ok); }
.note--warn { color: var(--warn); }
.note--bad { color: var(--bad); }

.result { display: grid; gap: 14px; }
.result video { width: 100%; border-radius: var(--r-s); background: #000; display: block; }
.checks { display: grid; gap: 7px; margin: 0; padding: 0; list-style: none; font-size: 13.5px; }
.checks li { display: flex; gap: 9px; align-items: baseline; color: var(--mute); }
.checks li::before { content: '✓'; color: var(--ok); font-weight: 700; }
.checks li.is-bad::before { content: '✕'; color: var(--bad); }
/* Une mesure ne se coupe pas en deux : « 15,0 s » sur une seule ligne. */
.checks b { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Barre d'état du travail en cours */
.working { display: flex; align-items: center; gap: 12px; color: var(--mute); font-size: 14px; }
.spin {
  width: 15px; height: 15px; flex: none; border-radius: 50%;
  border: 2px solid rgba(212, 162, 89, .25); border-top-color: var(--gold);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ── Les infobulles ────────────────────────────────────────────
   Celles du navigateur ne se règlent pas : ni leur délai, ni leur apparence, et
   elles ignorent le clavier. Voir public/assets/tips.js. */
.tip {
  position: fixed; z-index: 60; max-width: 34ch; pointer-events: none;
  padding: 9px 12px; border-radius: 8px;
  background: #26262c; color: var(--text); border: 1px solid var(--line-2);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
  font-size: 12.5px; line-height: 1.5; text-align: left;
  opacity: 0; transform: translateY(-3px);
  transition: opacity .12s ease, transform .12s ease;
}
/* L'état visible est posé par le script APRÈS la mise en place : une bulle qui
   apparaîtrait avant d'être placée se verrait sauter d'un coin à l'autre. */
.tip.is-on { opacity: 1; transform: translateY(0); }
