/* AudioKit — Vocal Studio : styles de l'outil, partagés par les pages EN et FR
   (extraits des <style> inline le 21/10/2026, Lot C). Ordre d'origine conservé. */

    /* ------------------------------------------------------------
       Styles spécifiques à Vocal Studio. Couleurs / rayons / fontes
       héritées de /socle/layout.css.
       Cette version utilise un moteur Web Audio temps réel — pas
       de waveform : un simple transport (Play/Pause + barre de
       position) suffit, l'expérience est centrée sur les sliders
       qui sonnent EN DIRECT.
       ------------------------------------------------------------ */

    /* ============================================================
       SOURCE VOCALE (en tête de l'outil)
       ─────────────────────────────────────────────────────────────
       Brique répliquée depuis l'outil Podcast : toggle Upload/Record,
       enregistrement micro complet, Clean up voice (gratuit, local
       ffmpeg.wasm) et Enhance with AI (premium, /api/enhance-voice).
       Préfixe `vfx-src-` pour éviter tout conflit avec le reste de
       l'outil. Toute prise / fichier nettoyé / résultat enhance
       alimente la chaîne d'effets via le MÊME point d'entrée que
       l'upload original (handleFile dans vocal-studio.js). ============ */


    /* ── Bloc « Calez votre voix » (proéminent) ── */
    .cw-align {
      margin: 12px 0 4px; padding: 14px;
      background: var(--surface);
      border: 1.5px solid var(--accent);
      border-radius: 10px;
    }
    .cw-align__title { margin: 0 0 8px; font-size: 13.5px; font-weight: 600; color: var(--text); }
    .cw-align__value { font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }
    .cw-align__row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
    .cw-align__nudges { display: flex; gap: 6px; }
    .cw-align__nudge {
      font-family: inherit; font-size: 12px; font-weight: 500;
      min-height: 40px; min-width: 52px; padding: 6px 8px;
      color: var(--text-soft); background: var(--bg);
      border: 1px solid var(--border-strong); border-radius: 8px;
      cursor: pointer; touch-action: manipulation;
      font-variant-numeric: tabular-nums;
    }
    .cw-align__loop {
      font-family: inherit; font-size: 12.5px; font-weight: 500;
      min-height: 40px; padding: 6px 12px; margin-left: auto;
      color: var(--accent); background: var(--surface);
      border: 1px solid var(--accent); border-radius: 8px;
      cursor: pointer; touch-action: manipulation;
    }
    .cw-align__loop.is-on { background: var(--accent); color: #fff; }

    /* ── Écran d'intention (pattern deux-intentions de Cover video) ── */
    .vfx-intent { display: flex; flex-direction: column; gap: 10px; margin-bottom: 6px; }
    .vfx-intent__card {
      display: flex; gap: 12px; align-items: flex-start; text-align: left;
      font-family: inherit; cursor: pointer; touch-action: manipulation;
      border: 1.5px solid var(--border-strong); border-radius: 12px;
      background: var(--surface); padding: 14px;
    }
    .vfx-intent__card--primary { border-color: var(--accent); background: var(--accent-tint, #eceefc); }
    .vfx-intent__icon { font-size: 22px; line-height: 1; }
    .vfx-intent__card b { font-size: 14px; display: block; color: var(--text); }
    .vfx-intent__desc { font-size: 12px; color: var(--text-soft); display: block; margin-top: 2px; }
    .vfx-intent-back { margin: 0 0 12px; font-size: 12px; }
    .vfx-intent-back__btn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 4px; border: 0; background: none; color: var(--accent); font: inherit; font-size: 13.5px; cursor: pointer; }
    .vfx-intent-back__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

    /* ── Wizard du parcours cover ── */
    .cw-step { border: 1px solid var(--border); border-radius: 12px; margin-bottom: 10px; background: var(--surface); }
    .cw-head {
      display: flex; align-items: center; gap: 8px; width: 100%;
      font-family: inherit; font-size: 13px; font-weight: 600; color: var(--text);
      background: none; border: 0; padding: 11px 12px; text-align: left; cursor: default;
    }
    .cw-step.is-done .cw-head { cursor: pointer; }
    .cw-step.is-closed .cw-head { color: var(--text-soft); }
    .cw-n {
      width: 20px; height: 20px; border-radius: 50%; background: var(--accent); color: #fff;
      font-size: 11px; display: inline-flex; align-items: center; justify-content: center; flex: none;
    }
    .cw-step.is-done .cw-n { background: var(--state-good); }
    .cw-sum { margin-left: auto; font-weight: 400; font-size: 11.5px; color: var(--text-soft); }
    .cw-body { padding: 0 12px 14px; }
    .cw-step.is-closed .cw-body, .cw-step.is-done .cw-body { display: none; }
    .cw-actions { margin-top: 12px; }
    .cw-actions .btn { width: 100%; min-height: 44px; }
    .cw-note { font-size: 11.5px; color: var(--text-soft); margin: 8px 0 0; }
    /* En mode cover : la tête/toggle de la section instru est superflue
       (l'instru est la fondation, toujours active). */
    .is-cover .vfx-instrumental__head { display: none; }
    .is-cover #instru-section { border: 0; padding: 0; margin: 0; }
    /* Presets d'effets (chips) + repli des réglages détaillés. */
    .cw-presets { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 2px; }
    .cw-preset {
      font-family: inherit; font-size: 12.5px; font-weight: 500;
      min-height: 40px; padding: 6px 12px; cursor: pointer;
      color: var(--text-soft); background: var(--bg);
      border: 1px solid var(--border-strong); border-radius: 8px;
    }
    .cw-preset.is-selected { color: var(--accent); border-color: var(--accent); background: var(--surface); }
    .cw-fx-fold {
      display: flex; justify-content: space-between; width: 100%;
      font-family: inherit; font-size: 12.5px; color: var(--text-soft);
      border: 1px solid var(--border); border-radius: 8px; background: var(--surface);
      padding: 9px 12px; margin-top: 10px; cursor: pointer;
    }
    .is-cover.cw-fx-folded #vfx-rack, .is-cover.cw-fx-folded #vfx-panel { display: none; }

    .vfx-src {
      margin-bottom: 18px;
    }

    /* ─── Segmented control Upload / Record ─── */
    .vfx-src__switch {
      display: inline-flex;
      background: var(--bg-warm);
      border: 1px solid var(--border);
      border-radius: var(--radius-btn);
      padding: 3px;
      gap: 2px;
      margin-bottom: 12px;
    }
    .vfx-src__switch-btn {
      border: 0;
      background: transparent;
      color: var(--text-soft);
      font-size: 13px;
      font-weight: 500;
      padding: 6px 14px;
      border-radius: 6px;
      cursor: pointer;
      font-family: inherit;
      transition: background .12s var(--ease-out), color .12s var(--ease-out);
    }
    .vfx-src__switch-btn:hover { color: var(--text); }
    .vfx-src__switch-btn.is-active {
      background: var(--surface);
      color: var(--text);
      box-shadow: var(--shadow-1);
    }
    .vfx-src__switch-btn:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }
    .vfx-src__switch-btn[disabled] { opacity: 0.55; cursor: not-allowed; }

    .vfx-src__pane[hidden] { display: none !important; }

    /* ─── Recorder (4 états via data-state) ───
       idle      → bouton REC + hint
       recording → Pause + Stop, chrono, point rouge clignote, waveform
       paused    → Resume + Stop, chrono figé
       recorded  → take audible + Re-record / Use this take */
    .vfx-src-rec {
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      background: var(--surface);
      padding: 16px;
      display: flex;
      flex-direction: column;
      gap: 14px;
    }
    .vfx-src-rec[data-state="recording"] { border-color: var(--accent); }

    .vfx-src-rec__bar {
      display: flex;
      align-items: center;
      gap: 10px;
      font-size: 13px;
      color: var(--text-soft);
    }
    .vfx-src-rec__dot {
      width: 10px; height: 10px;
      border-radius: 50%;
      background: var(--border-strong);
      flex-shrink: 0;
    }
    .vfx-src-rec[data-state="recording"] .vfx-src-rec__dot {
      background: var(--state-bad);
      animation: vfx-src-rec-pulse 1s ease-in-out infinite;
    }
    .vfx-src-rec[data-state="paused"] .vfx-src-rec__dot {
      background: var(--state-bad);
      opacity: 0.5;
    }
    .vfx-src-rec[data-state="recorded"] .vfx-src-rec__dot {
      background: var(--accent);
    }
    @keyframes vfx-src-rec-pulse {
      0%, 100% { opacity: 1; transform: scale(1); }
      50%      { opacity: 0.45; transform: scale(0.85); }
    }
    .vfx-src-rec__status {
      font-weight: 500;
      color: var(--text);
    }
    .vfx-src-rec__chrono {
      margin-left: auto;
      font-variant-numeric: tabular-nums;
      font-size: 18px;
      font-weight: 600;
      color: var(--text);
    }

    .vfx-src-rec__controls {
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
    }
    .vfx-src-rec__btn {
      min-width: 110px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
    }
    .vfx-src-rec__btn--rec .vfx-src-rec__btn-dot {
      width: 10px; height: 10px;
      border-radius: 50%;
      background: currentColor;
      display: inline-block;
    }
    .vfx-src-rec__btn--stop { color: var(--danger-text); }

    /* Affichage conditionnel par état (CSS only). */
    .vfx-src-rec[data-state="idle"]      #src-rec-pause,
    .vfx-src-rec[data-state="idle"]      #src-rec-resume,
    .vfx-src-rec[data-state="idle"]      #src-rec-stop,
    .vfx-src-rec[data-state="recording"] #src-rec-start,
    .vfx-src-rec[data-state="recording"] #src-rec-resume,
    .vfx-src-rec[data-state="paused"]    #src-rec-start,
    .vfx-src-rec[data-state="paused"]    #src-rec-pause,
    .vfx-src-rec[data-state="recorded"]  #src-rec-start,
    .vfx-src-rec[data-state="recorded"]  #src-rec-pause,
    .vfx-src-rec[data-state="recorded"]  #src-rec-resume,
    .vfx-src-rec[data-state="recorded"]  #src-rec-stop {
      display: none;
    }

    .vfx-src-rec__headphones {
      margin: 10px 0 0; padding: 8px 12px;
      font-size: 12.5px; line-height: 1.5;
      background: var(--warn-bg); color: var(--warn-text);
      border-radius: 8px;
    }
    .vfx-src-rec__hint {
      font-size: 12px;
      color: var(--text-soft);
      margin: 0;
      line-height: 1.45;
    }

    /* Sélecteur de micro — désactivé pendant la prise. */
    .vfx-src-rec__device {
      display: flex;
      align-items: center;
      gap: 10px;
      flex-wrap: wrap;
    }
    .vfx-src-rec__device.is-hidden { display: none; }
    .vfx-src-rec__device-label {
      font-size: 12.5px;
      font-weight: 500;
      color: var(--text-soft);
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }
    .vfx-src-rec__device-select {
      flex: 1;
      min-width: 0;
      padding: 7px 10px;
      font-family: inherit;
      font-size: 13px;
      color: var(--text);
      background: var(--surface);
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-btn);
      cursor: pointer;
    }
    .vfx-src-rec__device-select:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }
    .vfx-src-rec__device-select:disabled {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* Waveform défilante (visible uniquement en recording). */
    .vfx-src-rec__wave {
      display: block;
      width: 100%;
      height: 64px;
      border: 1px solid var(--border);
      border-radius: var(--radius-btn);
      background: var(--bg-warm);
    }
    .vfx-src-rec[data-state="idle"]     .vfx-src-rec__wave,
    .vfx-src-rec[data-state="recorded"] .vfx-src-rec__wave { display: none; }
    .vfx-src-rec[data-state="paused"]   .vfx-src-rec__wave { opacity: 0.55; }

    /* Take preview + actions. */
    .vfx-src-rec__take {
      border-top: 1px dashed var(--border);
      padding-top: 12px;
      display: flex;
      flex-direction: column;
      gap: 10px;
    }
    .vfx-src-rec__take[hidden] { display: none; }
    .vfx-src-rec__take-actions {
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
    }
    .vfx-src-rec__take-status {
      margin: 0;
      font-size: 12px;
      color: var(--text-soft);
    }
    .vfx-src-rec__take-status.is-success {
      color: var(--success-text, #1b7a39);
      font-weight: 500;
    }
    .vfx-src-rec__audio {
      width: 100%;
    }

    /* ─── Clean up voice (gratuit, one-shot via ffmpeg.wasm) ───
       Adaptation Vocal Studio : podcast applique le filtre AU BOUNCE.
       Ici la chaîne est temps réel + export offline distinct, on
       PRÉ-TRAITE donc la source : clic → ffmpeg.wasm produit une
       voix nettoyée → handleFile la charge comme nouvelle source.
       Cohérent avec « Use this take » et Enhance qui remplacent
       aussi voiceFile. Pour revenir à l'original, l'utilisateur
       recharge le fichier (Load another file). */
    .vfx-src-cleanup {
      position: relative;
      margin-top: 12px;
      padding: 14px 14px 12px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      display: flex;
      flex-direction: column;
      gap: 10px;
    }
    .vfx-src-cleanup__head {
      display: flex;
      align-items: center;
      gap: 8px;
      flex-wrap: wrap;
    }
    .vfx-src-cleanup__title {
      font-size: 13px;
      font-weight: 600;
      color: var(--text);
    }
    .vfx-src-cleanup__hint {
      margin: 0;
      font-size: 12px;
      color: var(--text-soft);
      line-height: 1.45;
    }
    .vfx-src-cleanup__row {
      display: flex;
      align-items: center;
      gap: 12px;
      flex-wrap: wrap;
    }
    .vfx-src-cleanup__btn[disabled] {
      opacity: 0.55;
      cursor: not-allowed;
    }
    .vfx-src-cleanup__status {
      margin: 0;
      font-size: 12px;
      color: var(--text-soft);
      line-height: 1.45;
    }
    .vfx-src-cleanup__status.hidden { display: none; }
    .vfx-src-cleanup__status.is-success {
      color: var(--success-text, #1b7a39);
      font-weight: 500;
    }
    .vfx-src-cleanup__status.is-error { color: var(--danger-text); }
    .vfx-src-cleanup__status.is-info  { color: var(--accent); }
    .vfx-src-cleanup.hidden { display: none; }

    /* ─── Enhance with AI (premium) ─── */
    .vfx-src-enhance {
      position: relative;
      margin-top: 12px;
      padding: 14px 14px 12px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      display: flex;
      flex-direction: column;
      gap: 10px;
    }
    .vfx-src-enhance__head {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 10px;
      flex-wrap: wrap;
    }
    .vfx-src-enhance__title-wrap {
      display: flex;
      align-items: center;
      gap: 8px;
      flex-wrap: wrap;
    }
    .vfx-src-enhance__title {
      font-size: 13px;
      font-weight: 600;
      color: var(--text);
    }
    .vfx-src-enhance__badge {
      display: inline-flex;
      align-items: center;
      padding: 2px 8px;
      font-size: 10.5px;
      font-weight: 700;
      letter-spacing: 0.4px;
      text-transform: uppercase;
      background: var(--warn-bg, #faeeda);
      color: var(--warn-text, #854f0b);
      border-radius: var(--radius-pill, 999px);
    }
    .vfx-src-enhance__hint {
      margin: 0;
      font-size: 12px;
      color: var(--text-soft);
      line-height: 1.45;
    }
    .vfx-src-enhance__row {
      display: flex;
      align-items: center;
      gap: 12px;
      flex-wrap: wrap;
    }
    .vfx-src-enhance__btn {
      display: inline-flex;
      align-items: center;
      gap: 8px;
    }
    .vfx-src-enhance__btn[disabled] {
      opacity: 0.55;
      cursor: not-allowed;
    }
    .vfx-src-enhance__quota {
      font-size: 12.5px;
      color: var(--text-soft);
      line-height: 1.4;
    }
    .vfx-src-enhance__quota.hidden { display: none; }
    .vfx-src-enhance__quota--exhausted {
      color: var(--warn-text, #854f0b);
      font-weight: 600;
    }
    .vfx-src-enhance__status {
      margin: 0;
      font-size: 12px;
      color: var(--text-soft);
      line-height: 1.45;
    }
    .vfx-src-enhance__status.hidden { display: none; }
    .vfx-src-enhance__status.is-success {
      color: var(--success-text, #1b7a39);
      font-weight: 500;
    }
    .vfx-src-enhance__status.is-error { color: var(--danger-text); }
    .vfx-src-enhance__status.is-info  { color: var(--accent); }

    /* État verrouillé : non-premium (clic = upgrade) ou quota épuisé.
       Le contenu est visuellement atténué pour signaler l'indispo. */
    .vfx-src-enhance.is-locked .vfx-src-enhance__title,
    .vfx-src-enhance.is-locked .vfx-src-enhance__hint {
      opacity: 0.7;
    }
    .vfx-src-enhance.is-locked .vfx-src-enhance__btn:not([disabled]) {
      opacity: 0.55;
    }
    /* ============================================================ */

    .vfx-stage {
      position: relative;
      margin-top: 18px;
      background: var(--bg);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      padding: 16px;
      overflow: hidden;
    }
    .vfx-stage.is-loading { opacity: 0.55; pointer-events: none; }

    /* ─── Transport (Play + position + A/B) ─────────────────── */

    .vfx-transport {
      padding: 14px 16px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
    }
    .vfx-transport__row {
      display: flex;
      align-items: center;
      gap: 14px;
      flex-wrap: wrap;
    }
    .vfx-play {
      width: 44px;
      height: 44px;
      padding: 0;
      border-radius: 50%;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      flex-shrink: 0;
    }
    .vfx-play svg { width: 18px; height: 18px; }

    .vfx-times {
      display: flex;
      gap: 6px;
      font-variant-numeric: tabular-nums;
      font-size: 12.5px;
      color: var(--text-soft);
    }
    .vfx-times span { color: var(--text); font-weight: 500; }

    .vfx-ab {
      margin-left: auto;
      display: inline-flex;
      padding: 3px;
      gap: 2px;
      background: var(--bg-warm);
      border: 1px solid var(--border);
      border-radius: var(--radius-pill);
    }
    .vfx-ab__btn {
      appearance: none;
      border: 0;
      background: transparent;
      font-family: inherit;
      font-size: 12.5px;
      font-weight: 500;
      color: var(--text-soft);
      padding: 5px 12px;
      border-radius: var(--radius-pill);
      cursor: pointer;
      transition: background .15s var(--ease-out),
                  color .15s var(--ease-out);
    }
    .vfx-ab__btn:hover { color: var(--text); }
    .vfx-ab__btn[aria-pressed="true"] {
      background: var(--surface);
      color: var(--accent-deep);
      box-shadow: 0 1px 2px rgba(44, 44, 42, 0.08);
    }
    .vfx-ab__btn:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }

    /* Barre de position : fine, cliquable pour seek. */
    .vfx-pos {
      position: relative;
      margin-top: 12px;
      height: 6px;
      background: var(--border);
      border-radius: 999px;
      cursor: pointer;
    }
    .vfx-pos__fill {
      position: absolute;
      top: 0; bottom: 0; left: 0;
      width: 0%;
      background: var(--accent);
      border-radius: inherit;
      pointer-events: none;
    }
    .vfx-pos[aria-disabled="true"] { cursor: not-allowed; opacity: 0.5; }

    /* ─── Rack de tuiles + panneau de réglages ───────────────── */
    /*
       Refonte de PRÉSENTATION (le moteur audio n'a pas changé) :
       à la place d'une colonne de grandes cartes une-par-effet, on
       montre une grille de TUILES COMPACTES (un effet = une tuile)
       à côté d'un PANNEAU qui affiche les sliders de l'effet
       actuellement SÉLECTIONNÉ pour édition.

       Deux états visuels distincts par tuile :
         - .is-active   → toggle on/off de l'effet (effet en train de
                          sonner). Halo accent.
         - .is-selected → tuile dont les réglages sont affichés dans
                          le panneau. Anneau d'outline accent.
       Les deux peuvent se cumuler (active ET selected).
    */

    .vfx-rack-layout {
      display: grid;
      grid-template-columns: minmax(320px, 1fr) minmax(280px, 1fr);
      gap: 14px;
      margin-top: 14px;
      align-items: start;
    }
    @media (max-width: 800px) {
      .vfx-rack-layout {
        grid-template-columns: 1fr;
      }
    }

    /* Grille des 6 tuiles. Ordre d'affichage = ordre de la chaîne. */
    .vfx-rack {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
      align-content: start;
    }
    @media (max-width: 480px) {
      .vfx-rack { grid-template-columns: 1fr; }
    }

    /* Tuile : conteneur compact « nom + toggle ». Cliquer le CORPS
       sélectionne (ouvre le panneau), cliquer le toggle active. */
    .vfx-tile {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
      padding: 12px 14px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      cursor: pointer;
      user-select: none;
      transition: border-color .15s var(--ease-out),
                  background .15s var(--ease-out),
                  box-shadow .15s var(--ease-out),
                  transform .12s var(--ease-out);
    }
    .vfx-tile:hover { border-color: var(--border-strong); }
    .vfx-tile:active { transform: translateY(1px); }

    /* État "effet allumé" : la tuile "s'allume" comme une pédale. */
    .vfx-tile.is-active {
      border-color: var(--accent);
      background: linear-gradient(180deg,
                                  var(--accent-tint),
                                  var(--surface) 70%);
    }
    .vfx-tile.is-active .vfx-tile__name {
      color: var(--accent-deep);
    }

    /* État "en cours d'édition" : anneau d'outline accent.
       Distinct visuellement de "is-active" (couleur intérieure). */
    .vfx-tile.is-selected {
      box-shadow: 0 0 0 2px var(--accent-ring),
                  var(--shadow-1);
    }

    /* Focus clavier (Tab) sur la tuile. */
    .vfx-tile:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }

    .vfx-tile__name {
      font-size: 12.5px;
      font-weight: 600;
      letter-spacing: 0.3px;
      text-transform: uppercase;
      color: var(--text);
    }

    /* Le toggle hérite des styles .vfx-toggle ; on annule le
       margin-left:auto pour le laisser à droite naturellement (flex). */
    .vfx-tile__toggle { margin-left: 0; }

    /* Petite LED en haut à droite de la tuile (renforce l'état actif).
       Reste discrète quand l'effet est OFF. */
    .vfx-tile__dot {
      position: absolute;
      top: 8px;
      right: 8px;
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: var(--border-strong);
      transition: background .15s var(--ease-out),
                  box-shadow .15s var(--ease-out);
      pointer-events: none;
    }
    .vfx-tile.is-active .vfx-tile__dot {
      background: var(--accent);
      box-shadow: 0 0 6px var(--accent);
    }

    /* Panneau de réglages : affiche les sliders de l'effet sélectionné.
       Les sliders sont les MÊMES <input> qu'avant — seul leur
       emplacement change (de la carte vers le panneau). */
    .vfx-panel {
      padding: 16px 18px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      min-height: 200px;
    }
    .vfx-panel__head {
      display: flex;
      align-items: baseline;
      gap: 10px;
      flex-wrap: wrap;
      margin-bottom: 14px;
      padding-bottom: 10px;
      border-bottom: 1px solid var(--border);
    }
    .vfx-panel__title {
      font-size: 13px;
      font-weight: 600;
      letter-spacing: 0.3px;
      text-transform: uppercase;
      color: var(--text);
      margin: 0;
    }
    .vfx-panel__sub {
      font-size: 12px;
      color: var(--text-soft);
    }

    /* Section par effet : un seul est visible à la fois.
       L'attribut [hidden] suffit (display:none). */
    .vfx-panel__section {
      display: grid;
      gap: 10px;
    }
    .vfx-panel__section[hidden] { display: none; }

    /* Indicateur discret de chargement d'IR (reverb à convolution).
       Vit désormais dans l'en-tête du panneau. */
    .vfx-loading {
      font-size: 12px;
      color: var(--text-soft);
      font-style: italic;
      margin-left: 8px;
    }

    /* Select pour le choix du lieu de la reverb. Réutilise la palette
       du select d'export, mais s'intègre dans la colonne médiane d'une
       .vfx-row (height aligné sur les sliders). */
    .vfx-select {
      width: 100%;
      height: 32px;
      padding: 0 32px 0 10px;
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-btn);
      background: var(--surface);
      color: var(--text);
      font-family: inherit;
      font-size: 13px;
      cursor: pointer;
    }
    .vfx-select:focus { outline: none; border-color: var(--accent); }

    /* Toggle switch (pill). */
    .vfx-toggle {
      position: relative;
      display: inline-flex;
      align-items: center;
      margin-left: auto;
      cursor: pointer;
      user-select: none;
    }
    .vfx-toggle input {
      position: absolute;
      opacity: 0;
      width: 1px;
      height: 1px;
      pointer-events: none;
    }
    .vfx-toggle__track {
      width: 36px;
      height: 20px;
      background: var(--border-strong);
      border-radius: 999px;
      position: relative;
      transition: background .15s var(--ease-out);
      flex-shrink: 0;
    }
    .vfx-toggle__track::after {
      content: "";
      position: absolute;
      top: 2px;
      left: 2px;
      width: 16px;
      height: 16px;
      border-radius: 50%;
      background: var(--surface);
      box-shadow: 0 1px 3px rgba(44, 44, 42, 0.18);
      transition: transform .15s var(--ease-out);
    }
    .vfx-toggle input:checked + .vfx-toggle__track {
      background: var(--accent);
    }
    .vfx-toggle input:checked + .vfx-toggle__track::after {
      transform: translateX(16px);
    }
    .vfx-toggle input:focus-visible + .vfx-toggle__track {
      outline: 2px solid var(--accent-ring);
      outline-offset: 2px;
    }

    /* Sliders dans le panneau : légèrement grisés quand l'effet
       sélectionné est OFF — MAIS pas pointer-events:none : on veut
       pouvoir pré-régler les valeurs avant d'activer le toggle.
       Le visuel "grisé" suffit comme indicateur. */
    .vfx-panel__section.is-effect-off {
      opacity: 0.55;
    }

    .vfx-row {
      display: grid;
      grid-template-columns: 88px 1fr 72px;
      align-items: center;
      gap: 12px;
    }
    .vfx-row__label {
      font-size: 12.5px;
      color: var(--text-soft);
      font-weight: 500;
    }
    .vfx-row__value {
      font-size: 12.5px;
      color: var(--text);
      font-variant-numeric: tabular-nums;
      text-align: right;
    }
    .vfx-slider {
      width: 100%;
      height: 6px;
      -webkit-appearance: none;
      appearance: none;
      background: var(--border);
      border-radius: 999px;
      outline: none;
    }
    .vfx-slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 16px;
      height: 16px;
      border-radius: 50%;
      background: var(--accent);
      border: 2px solid var(--surface);
      box-shadow: 0 1px 4px var(--accent-ring);
      cursor: pointer;
    }
    .vfx-slider::-moz-range-thumb {
      width: 16px;
      height: 16px;
      border-radius: 50%;
      background: var(--accent);
      border: 2px solid var(--surface);
      box-shadow: 0 1px 4px var(--accent-ring);
      cursor: pointer;
    }
    .vfx-slider:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 3px;
    }

    /* ─── Section Instrumental (optionnel, repliable) ────────── */
    /*
       Fonction SECONDAIRE : repliée derrière un toggle « Add a backing
       track » (off par défaut). Le cœur de l'outil reste le rack
       d'effets. Quand le toggle est OFF → seul l'en-tête (titre + sous-
       titre + interrupteur) est visible, et l'instrumental ne compte PAS
       dans le mix. Quand le toggle est ON → le corps se déplie : dropzone
       puis, dès qu'un fichier est chargé, les 2 sliders Voice/Instru.
    */
    .vfx-instrumental {
      margin-top: 14px;
      padding: 16px 18px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
    }
    .vfx-instrumental__head {
      display: flex;
      align-items: center;
      gap: 14px;
    }
    .vfx-instrumental__head-text {
      display: flex;
      flex-direction: column;
      gap: 3px;
      min-width: 0;
    }
    .vfx-instrumental__title {
      font-size: 14px;
      font-weight: 600;
      color: var(--text);
      margin: 0;
    }
    .vfx-instrumental__sub {
      font-size: 12.5px;
      line-height: 1.45;
      color: var(--text-soft);
    }
    /* Interrupteur de section : réutilise le toggle pill du rack d'effets
       (.vfx-toggle), poussé à droite de l'en-tête. */
    .vfx-instrumental__switch {
      margin-left: auto;
      flex-shrink: 0;
    }
    /* Corps repliable : dropzone + sliders. Caché quand le toggle est OFF
       (attribut [hidden] piloté par vocal-studio.js). */
    .vfx-instrumental__body {
      margin-top: 14px;
      padding-top: 14px;
      border-top: 1px solid var(--border);
    }
    /* Marges verticales entre l'uploader interne et les sliders. */
    .vfx-instrumental__levels {
      display: grid;
      gap: 10px;
      margin-top: 14px;
      padding-top: 14px;
      border-top: 1px dashed var(--border);
    }

    /* ─── Bandeau info + actions ─────────────────────────────── */

    .vfx-hint {
      margin-top: 14px;
      padding: 10px 12px;
      background: var(--info-bg);
      border: 1px solid var(--info-bg);
      border-radius: var(--radius-btn);
      font-size: 12.5px;
      line-height: 1.5;
      color: var(--info-text);
    }

    .vfx-export {
      margin-top: 18px;
      padding: 14px 16px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      display: flex;
      align-items: center;
      gap: 12px;
      flex-wrap: wrap;
    }
    .vfx-export__field {
      display: flex;
      align-items: center;
      gap: 8px;
    }
    .vfx-export__field label {
      font-size: 12.5px;
      color: var(--text-soft);
      font-weight: 500;
    }
    .vfx-export__select {
      height: 36px;
      padding: 0 32px 0 12px;
      border: 1px solid var(--border-strong);
      border-radius: var(--radius-btn);
      background: var(--surface);
      color: var(--text);
      font-family: inherit;
      font-size: 13px;
      cursor: pointer;
    }
    .vfx-export__select:focus { outline: none; border-color: var(--accent); }

    .vfx-actions {
      margin-left: auto;
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
    }

    .vfx-result {
      margin-top: 14px;
      padding: 12px 14px;
      background: var(--success-bg);
      border: 1px solid var(--success-text);
      border-radius: var(--radius-card);
      color: var(--success-text);
      font-size: 13px;
    }

    /* ------------------------------------------------------------
       Bandeau de réception d'un fichier transféré (handoff) depuis le
       Gate de silence. Discret et positif, tokens uniquement
       (theme-aware). Masqué tant qu'aucun handoff n'est consommé.
       ------------------------------------------------------------ */
    .vfx-handoff {
      margin-bottom: 14px;
      padding: 10px 14px;
      background: var(--accent-tint);
      border: 1px solid var(--border);
      border-radius: var(--radius-card);
      color: var(--text-soft);
      font-size: 12.5px;
    }

    /* ------------------------------------------------------------
       Quota d'utilisation (badge + bloc bloquant) — mêmes tokens
       et même hiérarchie visuelle que les autres outils AudioKit.
       ------------------------------------------------------------ */
    .ak-usage-wrap { display: flex; justify-content: center; }
    .ak-usage {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      margin: 14px auto 0;
      padding: 4px 12px;
      border-radius: var(--radius-pill);
      background: var(--accent-tint);
      color: var(--accent);
      font-size: 12.5px;
      font-weight: 500;
      letter-spacing: 0.1px;
    }
    .ak-usage--premium { background: var(--warn-bg); color: var(--warn-text); }
    .ak-usage--low     { background: var(--warn-bg); color: var(--warn-text); }

    .ak-quota {
      margin-top: 18px;
      padding: 18px;
      background: var(--accent-tint);
      border: 1px solid var(--accent);
      border-radius: var(--radius-card);
      text-align: center;
    }
    .ak-quota__title {
      font-size: 15px;
      font-weight: 600;
      color: var(--text);
      margin: 0 0 6px;
    }
    .ak-quota__text {
      font-size: 13px;
      line-height: 1.5;
      color: var(--text-soft);
      margin: 0 0 14px;
    }

    /* ------------------------------------------------------------
       Contenu éditorial SEO (sections sous l'outil). Couleurs et
       rayons via les variables du socle — suit le dark mode.
       ------------------------------------------------------------ */
    .seo { margin-top: 48px; }
    .seo section + section { margin-top: 36px; }
    .seo h2 { font-size: 18px; font-weight: 600; color: var(--text); margin: 0 0 14px; }
    .seo p, .seo li { font-size: 14px; line-height: 1.6; color: var(--text-soft); }
    .seo strong { color: var(--text); font-weight: 600; }
    .seo-steps { margin: 0; padding: 0; list-style: none; counter-reset: step;
                 display: flex; flex-direction: column; gap: 12px; }
    .seo-steps li { counter-increment: step; position: relative; padding-left: 40px; }
    .seo-steps li::before { content: counter(step); position: absolute; left: 0; top: 0;
                            width: 26px; height: 26px; border-radius: 50%;
                            background: var(--accent); color: var(--surface);
                            font-size: 13px; font-weight: 600;
                            display: flex; align-items: center; justify-content: center; }
    .seo-features { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 10px; }
    .seo-faq { display: flex; flex-direction: column; gap: 10px; }
    .seo-faq details { background: var(--surface); border: 1px solid var(--border);
                       border-radius: 12px; padding: 14px 16px; }
    .seo-faq summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--text); }
    .seo-faq details p { margin: 10px 0 0; }
    .seo-related { margin: 0; padding: 0; list-style: none; display: grid;
                   grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
    .seo-related a { display: block; background: var(--surface); border: 1px solid var(--border);
                     border-radius: 12px; padding: 12px 14px; text-decoration: none; height: 100%; }
    .seo-related a:hover { border-color: var(--accent); }
    .seo-related .seo-related__title { display: block; font-size: 14px; font-weight: 600;
                                       color: var(--accent); margin-bottom: 4px; }
    .seo-related .seo-related__desc { display: block; font-size: 12.5px; line-height: 1.5;
                                      color: var(--text-soft); }

    /* ── Lot S3 (gestes tactiles, sept. 2026) — surcharges posées en fin
       de cascade (même spécificité → dernière règle gagne). Pourquoi :
       mobile-audit.md §P5/P6 + backlog B2. pan-y = le geste horizontal
       sert le composant, le vertical rend le scroll de page. ── */
    .vfx-pos { touch-action: pan-y; }                /* tap = seek ; vertical = scroll page */
    @media (pointer: coarse) {
      .vfx-pos { height: 44px; padding: 19px 0; background-clip: content-box; }
      .vfx-pos__fill { top: 19px; bottom: 19px; }    /* la barre visible reste 6px, la boîte tactile fait 44px */
    }


/* ── Lot C (21/10/2026) — refonte sur le kit « résultat » ─────────────
   Parcours « traiter une voix » numéroté, sons nommés, réglages fins
   repliables, cibles tactiles 44 px, carte résultat. Maquette :
   mockups/vocal-studio/. Les titres d'étape sont propres au parcours
   « traiter » : le wizard cover a déjà ses propres étapes. ── */
.vs-step { margin: 18px 0 8px; font-size: 12px; font-weight: 700; letter-spacing: 1.1px; text-transform: uppercase; color: var(--accent); }
.vs-sub { margin: -2px 0 10px; font-size: 12.5px; color: var(--text-soft); }
body.is-cover .vs-step, body.is-cover .vs-sub, body.is-cover .vs-sounds, body.is-cover .vs-fold { display: none; }
.vs-prep { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; align-items: stretch; }
.vs-prep > * { margin: 0; }
@media (max-width: 640px) { .vs-prep { grid-template-columns: 1fr; } }
.vs-sounds { display: flex; flex-wrap: wrap; gap: 8px; }
.vs-sound { display: flex; flex-direction: column; align-items: flex-start; min-height: 56px; padding: 8px 14px; border: 1px solid var(--border-strong); border-radius: 12px; background: var(--surface); color: var(--text); font: inherit; text-align: left; cursor: pointer; }
.vs-sound b { font-size: 14px; font-weight: 600; }
.vs-sound small { font-size: 12px; color: var(--text-soft); }
.vs-sound:hover { border-color: var(--accent); }
.vs-sound[aria-checked="true"] { border-color: var(--accent); background: var(--accent-tint); box-shadow: inset 0 0 0 1px var(--accent); }
.vs-sound:focus-visible, .vs-fold:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vs-fold { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; min-height: 48px; margin-top: 12px; padding: 0 2px; border: 0; border-top: 1px solid var(--border); background: none; color: var(--text); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; }
body.vs-fx-folded:not(.is-cover) .vfx-rack-layout { display: none; }
/* Cibles tactiles (mobile-audit : Dry/Wet 25 px ; la barre de position
   est déjà à 44 px au doigt — Lot S3 plus haut). */
.vfx-ab__btn { min-height: 44px; min-width: 72px; font-size: 13.5px; }
.vfx-export .btn, .vfx-actions .btn { min-height: 44px; }
.vfx-export__select { min-height: 44px; }
/* Carte résultat. */
.vs-result { margin-top: 18px; }
.vs-result > * + * { margin-top: 16px; }
.vs-result .ak-r-summary { margin-bottom: 0; }
.vs-result audio { display: block; width: 100%; margin-top: 12px; }
.vs-result__actions { display: flex; flex-wrap: wrap; gap: 10px; }
.vs-result__actions .btn { min-height: 44px; }
/* Nom de tuile = bouton de sélection (Lot C, plus de contrôles imbriqués). */
button.vfx-tile__name { flex: 1; min-height: 44px; margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
button.vfx-tile__name:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
/* Textes d'aide lisibles (--text-faint < 4,5:1) ; cibles tactiles 44 px. */
.vfx-src-enhance__hint, .vfx-src-cleanup__hint { color: var(--text-soft); }
.vfx-src-cleanup__btn, .vfx-src-enhance__btn { min-height: 44px; }
@media (pointer: coarse), (max-width: 640px) {
  .vfx-src__switch-btn { min-height: 44px; }
}
.vfx-src-enhance.is-locked .vfx-src-enhance__title,
.vfx-src-enhance.is-locked .vfx-src-enhance__hint { opacity: 1; }   /* verrou dit par le badge et le bouton */
.tool-card .ak-save__btn { min-height: 44px; }
/* Verrouillé (non Premium) : le bouton reste lisible — il ouvre l'offre Premium. */
.vfx-src-enhance.is-locked .vfx-src-enhance__btn:not([disabled]) { opacity: 1; }

/* Limiteur de sortie (V2, 22/10/2026) : état discret sous le mixage. */
.vfx-limiter {
  margin: 14px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}
.vfx-limiter::before {
  content: "";
  display: inline-block;
  width: 8px; height: 8px;
  margin-right: 8px;
  border-radius: 50%;
  background: var(--border-strong);
  vertical-align: 1px;
}
.vfx-limiter.is-active::before { background: var(--accent); }

/* 7 tuiles (dé-esseur V2) : la dernière occupe toute la ligne. */
.vfx-rack > .vfx-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* Afficheur de réduction du compresseur (V2 #4) : barre qui pousse vers la gauche. */
.vfx-gr__bar {
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: var(--border);
  overflow: hidden;
}
.vfx-gr__fill {
  position: absolute; right: 0; top: 0; bottom: 0;
  width: 0;
  background: var(--accent);
}
