/* =========================================================================
   CinePrompt Studio — feuille de style
   Theme sombre unique, assume : l'app est un outil d'image, l'interface
   doit disparaitre derriere les vignettes.
   ========================================================================= */

/* =========================================================================
   Butler Stencil — serif display ajouree de Fabian De Smet.
   Fichiers dans src/assets/fonts/ (voir le README du dossier).
   `font-display: swap` : le texte s'affiche tout de suite dans la serif de
   secours, puis bascule des que la police est chargee.

   ATTENTION a l'usage : les contre-formes ajourees cassent le dessin des
   lettres. C'est superbe en gros corps, illisible en petit. Cette famille
   est donc reservee au titre-heros de l'application (voir --font-stencil) ;
   tous les autres titres passent par --font-display, qui reste sur une
   serif classique.
   ========================================================================= */

@font-face {
  font-family: 'Butler Stencil';
  src: url('assets/fonts/ButlerStencil-Light.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Butler Stencil';
  src: url('assets/fonts/ButlerStencil-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Butler Stencil';
  src: url('assets/fonts/ButlerStencil-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Butler Stencil';
  src: url('assets/fonts/ButlerStencil-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Bruns neutres et froids pour les fonds — un brun qui tire sur le jaune
     devient sale dès qu'il est désaturé, on reste donc sur des gris chauds. */
  --bg:            #14100d;
  --bg-panel:      #1a1512;
  --bg-raised:     #221b16;
  --bg-input:      #261e18;
  --line:          #32271f;
  --line-strong:   #45362b;

  --text:          #f7f0e8;
  --text-soft:     #bfae9c;
  --text-faint:    #8a7767;

  /* L'orange, lui, reste franc et lumineux : c'est le contraste avec les
     bruns sourds qui rend l'ensemble net plutôt que terne. */
  --accent:        #e0763a;
  --accent-soft:   #f28f52;
  --accent-rgb:    224, 118, 58;
  --accent-glow:   rgba(224, 118, 58, 0.32);
  --accent-deep:   #b4541f;
  --gold:          #d8a253;
  --ok:            #7fa96a;

  /* ---------------------------------------------------------------------
     Echelle de rayons. Le principe : plus le conteneur est grand, plus le
     rayon est genereux. Les petits elements interactifs (boutons, chips,
     onglets, champs de recherche) passent en pilule complete.
     --------------------------------------------------------------------- */
  --r-xs:   8px;   /* pastilles, mini etiquettes imbriquees */
  --r-sm:  12px;   /* petits blocs : items de menu, encarts */
  --r-md:  18px;   /* champs, cartes moyennes, vignettes */
  --r-lg:  26px;   /* panneaux, plateau, modales */
  --r-xl:  32px;   /* grandes surfaces flottantes */
  --r-pill: 999px; /* boutons, chips, badges, onglets */

  /* Typographie -----------------------------------------------------------
     Deux piles distinctes, volontairement separees :

     --font-stencil : Butler Stencil, l'ajouree. Usage heros uniquement
       (titre de l'application). Trop typee pour du titrage courant.

     --font-display : les titres courants. Serif "old style" classique pour
       l'instant ; le jour ou le Butler classique est ajoute au dossier des
       polices, il suffira de le glisser en tete de cette pile.

     Le corps de texte et les champs de saisie restent en sans-serif.
     Le fallback est une chaine de serif presente de base sur
     macOS / Windows / Linux, donc le rendu tient meme sans fichier. */
  --font-stencil: 'Butler Stencil', "Iowan Old Style", "Palatino Linotype",
                  Palatino, Georgia, serif;
  --font-display: "Iowan Old Style", "Palatino Linotype", "Book Antiqua",
                  Palatino, Georgia, "Times New Roman", serif;
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
             "Segoe UI", Inter, Roboto, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  /* Verre optique ---------------------------------------------------------
     La saturation est ce qui distingue le verre Apple d'un simple flou :
     le fond garde ses couleurs au lieu de virer au gris.
     `--glass-edge` simule la refraction sur l'arete superieure. */
  --glass-blur:       blur(28px) saturate(180%);
  --glass-blur-soft:  blur(18px) saturate(160%);
  --glass-panel:  rgba(26, 21, 18, .62);
  /* Fenêtres d'outils (modales) : verre DÉPOLI, pas verre transparent.
     Le flou + la saturation restent, mais le fond est nettement plus opaque
     que `--glass-panel` pour que le texte soit lisible par-dessus n'importe
     quel contenu. */
  --glass-modal:  rgba(24, 19, 16, .94);
  --glass-raised: rgba(38, 30, 24, .58);
  --glass-input:  rgba(38, 30, 24, .45);
  --glass-border: rgba(255, 236, 214, .13);
  --glass-edge:   inset 0 1px 0 rgba(255, 255, 255, .12),
                  inset 0 -1px 0 rgba(0, 0, 0, .22);
  --glass-edge-strong: inset 0 1px 0 rgba(255, 255, 255, .2),
                       inset 0 0 0 1px rgba(255, 255, 255, .04),
                       inset 0 -1px 0 rgba(0, 0, 0, .3);

  --shadow-sm: 0 1px 2px rgba(0,0,0,.5);
  --shadow-md: 0 6px 20px rgba(0,0,0,.45);
  --shadow-lg: 0 18px 50px rgba(0,0,0,.6);

  --ease: cubic-bezier(.2, .8, .3, 1);
  --bounce: cubic-bezier(.34, 1.56, .64, 1);

  --titlebar-h: 46px;

  /* Ombres multi-couches pour un effet de flottement plus "materiel". */
  --shadow-float: 0 1px 2px rgba(0,0,0,.35), 0 8px 18px rgba(0,0,0,.35), 0 22px 46px rgba(0,0,0,.35);
  --shadow-float-lg: 0 2px 4px rgba(0,0,0,.4), 0 14px 30px rgba(0,0,0,.4), 0 34px 70px rgba(0,0,0,.5);
  --shadow-inset: inset 0 1px 0 rgba(255,255,255,.06), inset 0 -1px 0 rgba(0,0,0,.25);
}

* { box-sizing: border-box; }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  background: var(--bg);
  color: var(--text);
  font: 400 14px/1.5 var(--font-ui);
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

::selection { background: var(--accent-glow); }

/* Barres de defilement discretes ---------------------------------------- */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-radius: var(--r-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: #56422f; background-clip: content-box; }

/* ============================================================ barre haute */

.titlebar {
  height: var(--titlebar-h);
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 14px 0 18px;
  background: var(--glass-panel);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-edge), 0 4px 20px rgba(0,0,0,.3);
  border-bottom: 1px solid var(--line);
  -webkit-app-region: drag;
  z-index: 30;
}

.titlebar__brand { display: flex; align-items: center; gap: 10px; }

.titlebar__mark {
  width: 20px; height: 20px;
  border-radius: 50%;
  background: conic-gradient(from 200deg, #b4541f, #e0763a, #d8a253, #8a4a22, #b4541f);
  box-shadow: 0 0 14px var(--accent-glow);
}

.titlebar__name {
  font-size: 13px;
  letter-spacing: .3px;
  color: var(--text-soft);
  font-weight: 500;
}
.titlebar__name b { color: var(--text); font-weight: 600; }

.titlebar__tagline {
  font-size: 12px;
  color: var(--text-faint);
  padding-left: 10px;
  margin-left: 2px;
  border-left: 1px solid var(--line-strong);
}

.titlebar__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  -webkit-app-region: no-drag;
}

.titlebar__sep {
  width: 1px;
  height: 18px;
  background: var(--line-strong);
  margin: 0 2px;
}

/* Sélecteur de langue --------------------------------------------------- */
.langswitch {
  display: flex;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 2px;
  gap: 2px;
}
.langswitch__btn {
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  padding: 4px 10px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.langswitch__btn:hover { color: var(--text-soft); }
.langswitch__btn.is-active {
  background: var(--bg-raised);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

/* ====================================================== menus déroulants */

.menu { position: relative; }

.menu__trigger { display: inline-flex; align-items: center; gap: 7px; }
.menu__caret { font-size: 9px; opacity: .7; }

.menu__panel {
  position: absolute;
  top: calc(100% + 7px);
  right: 0;
  min-width: 288px;
  padding: 7px;
  background: var(--glass-raised);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
  box-shadow: var(--glass-edge-strong), var(--shadow-float-lg);
  z-index: 60;
  animation: menuIn .14s var(--ease);
}
.menu__panel[hidden] { display: none; }

@keyframes menuIn {
  from { opacity: 0; transform: translateY(-5px); }
  to   { opacity: 1; transform: none; }
}

.menu__item {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 9px 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  transition: background .13s var(--ease), color .13s var(--ease);
}
.menu__item:hover { background: rgba(var(--accent-rgb), .13); color: var(--text); }

.menu__icon {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--bg-input);
  border: 1px solid var(--line);
  color: var(--accent);
  font-size: 12px;
}
.menu__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.menu__label { font-size: 13px; color: var(--text); }
.menu__hint { font-size: 11.5px; color: var(--text-faint); line-height: 1.4; }
.menu__sep { height: 1px; background: var(--line); margin: 5px 8px; }

/* Sur macOS la barre systeme est masquee : on laisse la place aux pastilles. */
body.is-mac .titlebar { padding-left: 84px; }

/* ================================================================ boutons */

.btn {
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  padding: 7px 16px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .18s var(--ease), border-color .18s var(--ease),
              transform .16s var(--bounce), box-shadow .18s var(--ease), color .15s var(--ease);
  white-space: nowrap;
  will-change: transform;
}
.btn:active { transform: translateY(1px) scale(.97); }

.btn--ghost {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--text-soft);
}
.btn--ghost:hover { background: var(--bg-raised); color: var(--text); transform: translateY(-1px); }

.btn--primary {
  background: linear-gradient(160deg, var(--accent-soft), var(--accent));
  color: #fff;
  box-shadow: 0 2px 10px var(--accent-glow), var(--shadow-inset);
}
.btn--primary:hover {
  background: linear-gradient(160deg, #ff9f63, var(--accent-soft));
  transform: translateY(-1px);
  box-shadow: 0 4px 16px var(--accent-glow), var(--shadow-inset);
}
.btn--primary:active { box-shadow: 0 1px 6px var(--accent-glow); }

.btn--accent {
  background: linear-gradient(135deg, #a8641f, #7d4715);
  color: #fdf3e6;
  border-color: rgba(216, 162, 83, .38);
  box-shadow: var(--shadow-inset);
}
.btn--accent:hover {
  background: linear-gradient(135deg, #c47827, #a8641f);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(0,0,0,.35), var(--shadow-inset);
}
.btn--accent:disabled {
  background: transparent;
  border-color: var(--line);
  color: var(--text-faint);
  cursor: default;
  box-shadow: none;
  transform: none;
}

.btn.is-done {
  background: var(--ok);
  border-color: transparent;
  color: #12200c;
  box-shadow: none;
}

/* ================================================================= layout */

.layout {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: 288px minmax(0, 1fr) 306px;
  gap: 1px;
  background: var(--line);
}

.panel {
  background: var(--bg-panel);
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 16px 10px;
  flex: 0 0 auto;
}

.panel__title {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.badge {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 2px 9px;
}

/* =========================================================== bibliotheque */

.search {
  position: relative;
  margin: 0 16px 12px;
  flex: 0 0 auto;
}
.search__icon {
  position: absolute;
  left: 13px; top: 50%;
  transform: translateY(-50%);
  width: 14px; height: 14px;
  color: var(--text-faint);
  pointer-events: none;
}
.search input {
  width: 100%;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: 8px 14px 8px 33px;
  outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.search input::placeholder { color: var(--text-faint); }
.search input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}
.search input::-webkit-search-cancel-button { display: none; }

.catfilter {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  padding: 0 16px 12px;
  flex: 0 0 auto;
}

.catchip {
  font: inherit;
  font-size: 11px;
  padding: 4px 11px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: all .15s var(--ease);
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.catchip:hover { color: var(--text); border-color: var(--text-faint); transform: translateY(-1px); }
.catchip:active { transform: translateY(0) scale(.96); }
.catchip.is-active {
  color: #fff;
  border-color: transparent;
  background: var(--chip-color, var(--accent));
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
}
/* Categorie sans objet dans le mode courant (ex. mouvement de camera pour une
   image fixe) : grisee et non cliquable, mais toujours visible — l'utilisateur
   doit comprendre qu'elle existe et pourquoi elle est ecartee. */
.catchip:disabled {
  opacity: .38;
  cursor: not-allowed;
  text-decoration: line-through;
}
.catchip:disabled:hover { color: var(--text-faint); border-color: var(--line-strong); transform: none; }

.catchip__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--chip-color, var(--accent));
}
.catchip.is-active .catchip__dot { background: rgba(255,255,255,.85); }

/* Icones de categorie. Les traits noirs sur fond transparent seraient
   invisibles ici : on les inverse. Les icones en couleur gardent leurs
   teintes, seule leur opacite suit l'etat actif. */
.catchip__icon {
  width: 15px; height: 15px;
  object-fit: contain;
  flex: 0 0 auto;
  opacity: .72;
  transition: opacity .18s var(--ease), transform .18s var(--bounce);
}
.catchip__icon--mono { filter: invert(1); }
.catchip:hover .catchip__icon { opacity: 1; transform: scale(1.12); }
.catchip.is-active .catchip__icon { opacity: 1; }

.library {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0 10px 20px;
}

.libgroup { margin-bottom: 14px; }

.libgroup__head {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 6px 7px;
  position: sticky;
  top: 0;
  background: linear-gradient(var(--bg-panel) 70%, transparent);
  z-index: 2;
}
.libgroup__bar {
  width: 3px; height: 12px;
  border-radius: 2px;
  background: var(--cat-color);
}
.libgroup__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.libgroup__count { font-size: 10.5px; color: var(--text-faint); margin-left: auto; }

.libitem {
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 13px;
  color: var(--text-soft);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  padding: 7px 9px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 9px;
  transition: background .16s var(--ease), color .16s var(--ease),
              border-color .16s var(--ease), transform .16s var(--bounce), box-shadow .16s var(--ease);
}
.libitem:hover {
  background: var(--bg-raised);
  color: var(--text);
  border-color: var(--line);
  transform: translateX(2px);
  box-shadow: var(--shadow-sm);
}
.libitem:active { transform: translateX(2px) scale(.985); }
.libitem.is-used {
  color: var(--text);
  background: rgba(var(--accent-rgb), .12);
  border-color: rgba(var(--accent-rgb), .34);
}

.libitem__thumb {
  flex: 0 0 auto;
  width: 34px; height: 24px;
  border-radius: var(--r-xs);
  overflow: hidden;
  position: relative;
  border: 1px solid var(--cat-color);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .3);
  transition: transform .16s var(--bounce);
}
.libitem:hover .libitem__thumb { transform: scale(1.15); }
.libitem__thumb .visual { display: block; width: 100%; height: 100%; }
.libitem__thumb img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.libitem__label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.libitem__plus {
  font-size: 15px;
  line-height: 1;
  color: var(--text-faint);
  opacity: 0;
  transition: opacity .12s var(--ease);
}
.libitem:hover .libitem__plus { opacity: 1; }
.libitem.is-used .libitem__plus { opacity: 1; color: var(--accent-soft); }

.libempty {
  padding: 22px 12px;
  text-align: center;
  color: var(--text-faint);
  font-size: 12.5px;
}

/* =============================================================== composeur */

.panel--composer { background: var(--bg); }

.composer {
  flex: 0 0 auto;
  padding: 20px 24px 0;
}

.field { display: block; }

.field__label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 8px;
}

.field__box { position: relative; }

#promptInput {
  width: 100%;
  font: inherit;
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 14px 16px;
  resize: vertical;
  min-height: 92px;
  max-height: 220px;
  outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
#promptInput::placeholder { color: var(--text-faint); }
#promptInput:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

/* Autocompletion ------------------------------------------------------- */
.autocomplete {
  position: absolute;
  left: 0; right: 0;
  top: calc(100% + 6px);
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--glass-raised);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
  box-shadow: var(--glass-edge-strong), var(--shadow-float-lg);
  max-height: 246px;
  overflow-y: auto;
  z-index: 20;
}
.autocomplete[hidden] { display: none; }

.acitem {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: 13px;
  color: var(--text-soft);
}
.acitem.is-active { background: var(--accent); color: #fff; }
.acitem__dot { width: 5px; height: 5px; border-radius: 50%; background: var(--cat-color); }
.acitem.is-active .acitem__dot { background: rgba(255,255,255,.9); }
.acitem__label { flex: 1 1 auto; }
.acitem__cat { font-size: 10.5px; color: var(--text-faint); }
.acitem.is-active .acitem__cat { color: rgba(255,255,255,.75); }
.acitem__hint { font-size: 10px; color: rgba(255,255,255,.7); }
.acitem__lang {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .05em;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--line-strong);
  color: var(--text-soft);
}
.acitem.is-active .acitem__lang { background: rgba(255,255,255,.22); color: #fff; }

/* Barre de traduction ---------------------------------------------------- */
.translatebar {
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 30px;
  padding-top: 12px;
  flex-wrap: wrap;
}
.translatebar__hint {
  font-size: 12px;
  color: var(--text-faint);
}
.translatebar [hidden] { display: none; }

/* Gestionnaire de références ------------------------------------------- */
.refs {
  margin-top: 12px;
  padding: 12px 14px 13px;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
  background: var(--glass-input);
  backdrop-filter: var(--glass-blur-soft);
  -webkit-backdrop-filter: var(--glass-blur-soft);
  box-shadow: var(--glass-edge);
  transition: border-color .18s var(--ease), background .18s var(--ease),
              box-shadow .2s var(--ease);
}
.refs[open] { box-shadow: var(--glass-edge), var(--shadow-sm); }
.refs.is-over {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .09);
}

/* En-tete repliable, meme patron que .params__head : chevron en pseudo-element
   (le marqueur natif de <summary> n'est pas stylable de facon portable). */
.refs__head {
  display: flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
  list-style: none;
  user-select: none;
  border-radius: var(--r-md);
}
.refs__head::-webkit-details-marker { display: none; }
.refs__head::before {
  content: '▸';
  font-size: 10px;
  color: var(--text-faint);
  transition: transform .22s var(--bounce);
}
.refs[open] .refs__head::before { transform: rotate(90deg); }
.refs__head:hover .refs__title { color: var(--text); }

.refs__content {
  margin-top: 10px;
  animation: refsIn .22s var(--ease);
}
@keyframes refsIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}
.refs__title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.refs__empty {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-faint);
}
.refs__empty[hidden] { display: none; }

.refs__list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.refs__list:empty { display: none; }

.ref {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 7px 9px 7px 7px;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-pill);
  background: var(--glass-raised);
  box-shadow: var(--glass-edge);
  transition: border-color .16s var(--ease), transform .16s var(--bounce);
}
.ref:hover { border-color: rgba(var(--accent-rgb), .45); transform: translateY(-1px); }

.ref__thumb {
  flex: 0 0 auto;
  width: 52px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--bg-input);
  overflow: hidden;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: border-color .16s var(--ease);
}
.ref__thumb:hover { border-color: var(--accent); }
.ref__thumb img,
.ref__thumb video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ref__ph {
  font-size: 16px;
  color: var(--text-faint);
  line-height: 1;
}

.ref__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
}
.ref__name {
  flex: 1 1 auto;
  min-width: 0;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--glass-input);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease);
}
.ref__name:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .18);
}
.ref__token {
  flex: 0 0 auto;
  font-size: 12px;
  color: var(--gold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40%;
}

.ref__acts { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.ref__act {
  padding: 5px 13px;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .04);
  color: var(--text-soft);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: color .16s var(--ease), border-color .16s var(--ease), background .16s var(--ease);
}
.ref__act:hover {
  color: var(--text);
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .14);
}
.ref__act--del {
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
  font-size: 15px;
  line-height: 1;
  display: grid;
  place-items: center;
}

@media (max-width: 640px) {
  .ref { flex-wrap: wrap; border-radius: var(--r-lg); }
  .ref__body { flex-basis: 100%; order: 3; }
  .ref__token { max-width: 100%; }
}

.composer__generate {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  padding-top: 16px;
}

/* Bouton de génération + sa pastille de coût : un bloc qu'on montre ou cache
   d'un seul tenant selon le mode. */
.genopt {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  animation: tabIn .26s var(--ease);
}
.genopt[hidden] { display: none; }

.badge--cost {
  color: var(--text-soft);
  background: var(--glass-raised);
  border-color: var(--glass-border);
  box-shadow: var(--glass-edge);
  backdrop-filter: var(--glass-blur-soft);
  white-space: nowrap;
}

/* Bascule Image / Vidéo, au-dessus du champ de prompt. */
.composer__mode {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 14px;
}
.composer__modelabel {
  font-size: 10.5px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.imgresult {
  display: flex;
  justify-content: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  padding: 8px;
  background: var(--bg-raised);
  box-shadow: var(--shadow-float);
  animation: tabIn .3s var(--ease);
}
.imgresult__img {
  max-width: 100%;
  max-height: 420px;
  border-radius: var(--r-md);
  display: block;
}

.btn--mini { font-size: 11px; padding: 4px 12px; }

/* Paramètres prédéfinis -------------------------------------------------- */
.params {
  margin: 4px 0 20px;
  background: var(--glass-panel);
  backdrop-filter: var(--glass-blur-soft);
  -webkit-backdrop-filter: var(--glass-blur-soft);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
  box-shadow: var(--glass-edge), var(--shadow-sm);
  transition: box-shadow .2s var(--ease);
}
.params[open] { box-shadow: var(--glass-edge), var(--shadow-md); }

.params__head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 14px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.params__head::-webkit-details-marker { display: none; }
.params__head::before {
  content: '▸';
  font-size: 10px;
  color: var(--text-faint);
  transition: transform .18s var(--ease);
}
.params[open] .params__head::before { transform: rotate(90deg); }

.params__title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-faint);
  flex: 1 1 auto;
}

.params__groups {
  padding: 2px 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 11px;
}

.paramgroup__label {
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 6px;
}

.paramgroup__chips { display: flex; flex-wrap: wrap; gap: 6px; }

.paramchip {
  font: inherit;
  font-size: 12px;
  padding: 5px 13px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: all .14s var(--ease);
}
.paramchip:hover { color: var(--text); border-color: var(--text-faint); transform: translateY(-1px); }
.paramchip:active { transform: translateY(0) scale(.96); }
.paramchip.is-on {
  background: rgba(var(--accent-rgb), .16);
  border-color: var(--accent);
  color: var(--accent-soft);
  font-weight: 500;
}
.paramchip.is-on::before { content: '✓ '; opacity: .85; }

.params__preview {
  border-top: 1px solid var(--line);
  padding: 11px 14px 13px;
}
.params__previewhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
}
.params__previewhead .detail__key { margin: 0; }

.params__final {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--text-soft);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 9px 11px;
  max-height: 110px;
  overflow-y: auto;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
}

/* Référence image -------------------------------------------------------- */
.token__frame--ref { border-style: dashed; border-color: rgba(216, 162, 83, .5); }
.token--ref .token__label {
  color: var(--gold);
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  font-size: 12px;
}
.strip.is-text .token--ref .token__label {
  background: rgba(216, 162, 83, .18);
  border-bottom: 2px solid var(--gold);
  padding: 2px 8px;
  border-radius: var(--r-pill);
}

/* Metriques ------------------------------------------------------------ */
.metrics {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 14px 2px 18px;
  flex-wrap: wrap;
}

.metric { display: flex; flex-direction: column; gap: 3px; }
.metric__value {
  font-size: 17px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  line-height: 1;
}
.metric__label {
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.coverage {
  flex: 1 1 160px;
  min-width: 140px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.coverage__track {
  height: 4px;
  border-radius: 3px;
  background: var(--bg-input);
  overflow: hidden;
}
.coverage__fill {
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent-deep), var(--accent-soft), var(--gold));
  transition: width .35s var(--ease);
}

.gaps { display: flex; gap: 5px; flex-wrap: wrap; }
.gap {
  font-size: 10.5px;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  border: 1px dashed var(--line-strong);
  color: var(--text-faint);
}
/* Termes presents dans le prompt mais sans effet sur la cible choisie. Ils
   restent ecrits : c'est un signalement, pas une suppression. */
.gaps--ignored .metric__label { color: var(--accent-soft); }
.gap--ignored {
  border-style: solid;
  text-decoration: line-through;
  opacity: .8;
}

/* Plateau de decomposition --------------------------------------------- */
/* `min-height` plutot que 0 : dans un onglet qui defile, un enfant `flex: 1 1`
   se laisserait ecraser jusqu'a 0px au lieu de laisser apparaitre la barre de
   defilement. Le plateau garde donc un plancher lisible et c'est l'onglet qui
   defile. */
.board {
  flex: 1 1 auto;
  min-height: 300px;
  display: flex;
  flex-direction: column;
  margin: 0 24px 24px;
  background: var(--glass-panel);
  backdrop-filter: var(--glass-blur-soft);
  -webkit-backdrop-filter: var(--glass-blur-soft);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-xl);
  box-shadow: var(--glass-edge), var(--shadow-float);
  overflow: hidden;
  position: relative;
}

.board__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px 16px;
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}

.segmented {
  display: flex;
  background: var(--bg-input);
  border-radius: var(--r-pill);
  padding: 2px;
  gap: 2px;
}
.segmented__btn {
  font: inherit;
  font-size: 11.5px;
  padding: 4px 13px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.segmented__btn:hover { color: var(--text-soft); }
.segmented__btn.is-active { background: var(--bg-raised); color: var(--text); box-shadow: var(--shadow-sm); }

/* Variante compacte : barre de traduction, où la place est comptée. */
.segmented--mini { padding: 2px; align-self: center; }
.segmented--mini .segmented__btn { font-size: 10.5px; padding: 3px 9px; }

.strip {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 22px 18px;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 20px 12px;
  perspective: 900px;
}

.empty {
  position: absolute;
  inset: 44px 0 0 0;
  display: none;
  align-items: center;
  justify-content: center;
  margin: 0;
  color: var(--text-faint);
  font-size: 13px;
  pointer-events: none;
}
.board.is-empty .empty { display: flex; }

/* Blocs de mots -------------------------------------------------------- */
.token {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  border: 0;
  background: transparent;
  padding: 0;
  font: inherit;
  animation: pop .32s var(--ease) both;
}
.token--term { cursor: pointer; }

@keyframes pop {
  from { opacity: 0; transform: translateY(7px) scale(.965); }
  to   { opacity: 1; transform: none; }
}

.token__frame {
  position: relative;
  width: 148px;
  height: 99px;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid rgba(255, 236, 214, .12);
  box-shadow: var(--shadow-md);
  transition: transform .28s var(--bounce), box-shadow .28s var(--ease),
              border-color .2s var(--ease);
  transform-style: preserve-3d;
  will-change: transform;
}
.token--term:hover .token__frame {
  transform: translateY(-6px) scale(1.14) rotateX(4deg);
  box-shadow: var(--shadow-float-lg);
  border-color: rgba(255, 236, 214, .35);
  z-index: 5;
}
.token--term:hover .token__label {
  color: var(--accent-soft);
  transform: translateY(-2px);
}
.token.is-selected .token__frame {
  border-color: var(--accent-soft);
  box-shadow: 0 0 0 2px var(--accent-glow), var(--shadow-lg);
}

.token__frame .visual { display: block; width: 100%; height: 100%; }

.token__cat {
  position: absolute;
  top: 5px; left: 5px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--cat-color);
  box-shadow: 0 0 0 2px rgba(0,0,0,.45);
}

/* Marque un terme écrit en français : il sera réécrit par la traduction. */
.token__lang {
  position: absolute;
  top: 4px; right: 4px;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: .06em;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: rgba(180, 84, 31, .95);
  color: #fff2e2;
  box-shadow: 0 1px 3px rgba(0,0,0,.5);
}

.token__label {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-soft);
  max-width: 152px;
  text-align: center;
  line-height: 1.3;
  transition: color .18s var(--ease), transform .18s var(--ease);
}
.token--term .token__label { color: var(--text); }

/* Mot non reconnu : pas de vignette, il reste discret et aligne en bas. */
.token--plain {
  align-self: flex-end;
  padding-bottom: 3px;
}
.token--plain .token__label {
  color: var(--text-faint);
  font-size: 13.5px;
}

/* Mode texte ----------------------------------------------------------- */
.strip.is-text {
  display: block;
  font-size: 15px;
  line-height: 2.1;
  padding: 22px 20px;
}
.strip.is-text .token { display: inline; animation: none; }
.strip.is-text .token__frame, .strip.is-text .token__cat { display: none; }
.strip.is-text .token__label {
  display: inline;
  max-width: none;
  font-size: 15px;
}
.strip.is-text .token--term .token__label {
  color: #fff;
  background: color-mix(in srgb, var(--cat-color) 22%, transparent);
  border-bottom: 2px solid var(--cat-color);
  padding: 2px 8px;
  border-radius: var(--r-pill);
  margin: 0 1px;
}
.strip.is-text .token--plain { padding: 0; }

/* ================================================================= detail */

.panel--detail { display: flex; flex-direction: column; }

.detail {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 16px;
}

.detail__placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding: 46px 18px;
  color: var(--text-faint);
  font-size: 12.5px;
  line-height: 1.6;
}
.detail__placeholder svg { width: 34px; height: 34px; opacity: .45; }

.detail__hero {
  width: 100%;
  aspect-ratio: 3 / 2;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-md);
  margin-bottom: 14px;
  animation: tabIn .28s var(--ease);
}
.detail__section { animation: tabIn .3s var(--ease); }
.detail__hero .visual { display: block; width: 100%; height: 100%; }

.detail__cat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--cat-color);
  margin-bottom: 7px;
}

.detail__title {
  margin: 0 0 12px;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -.01em;
}

.detail__section { margin-bottom: 14px; }
.detail__key {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 4px;
}
.detail__text { margin: 0; font-size: 13px; line-height: 1.6; color: var(--text-soft); }

.detail__english {
  margin: 0;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text);
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 6px 9px;
}

.detail__aliases { display: flex; flex-wrap: wrap; gap: 5px; }
.alias {
  font-size: 11px;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  color: var(--text-faint);
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
}

.detail__actions { display: flex; gap: 8px; margin-top: 16px; }
.detail__actions .btn { flex: 1 1 auto; }

/* Utile seulement quand le panneau se superpose (voir media query plus bas). */
.detail__close { display: none; }

/* Presets --------------------------------------------------------------- */
.presets {
  flex: 0 0 auto;
  max-height: 40%;
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--line);
}
.presets__list {
  overflow-y: auto;
  padding: 0 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.preset {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  border-radius: var(--r-md);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  box-shadow: var(--glass-edge);
  cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease), transform .15s var(--bounce), box-shadow .15s var(--ease);
}
.preset:hover { border-color: var(--line-strong); background: #2a211a; transform: translateY(-1px); box-shadow: var(--shadow-sm); }

.preset__body { flex: 1 1 auto; min-width: 0; }
.preset__name {
  font-size: 12.5px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.preset__meta { font-size: 10.5px; color: var(--text-faint); }

.preset__del {
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 50%;
  opacity: 0;
  transition: opacity .12s var(--ease), color .12s var(--ease);
}
.preset:hover .preset__del { opacity: 1; }
.preset__del:hover { color: #e2705c; }

.presets__empty {
  padding: 4px 4px 12px;
  font-size: 12px;
  color: var(--text-faint);
}

/* =============================================================== responsive */

@media (max-width: 1240px) {
  .layout { grid-template-columns: 250px minmax(0, 1fr) 268px; }
}

@media (max-width: 1080px) {
  .layout { grid-template-columns: 232px minmax(0, 1fr); }
  .panel--detail {
    position: fixed;
    top: var(--titlebar-h); right: 0; bottom: 0;
    width: 300px;
    border-left: 1px solid var(--line);
    box-shadow: var(--shadow-lg);
    transform: translateX(100%);
    transition: transform .25s var(--ease);
    z-index: 25;
  }
  .panel--detail.is-open { transform: none; }
  .detail__close { display: block; }
}

/* Tablette et mobile : la bibliothèque passe sous le composeur, la page
   redevient scrollable verticalement. Utile surtout pour la version en ligne. */
@media (max-width: 820px) {
  html, body { overflow: auto; }
  body { height: auto; min-height: 100%; }

  .titlebar {
    position: sticky;
    top: 0;
    flex-wrap: wrap;
    height: auto;
    padding: 8px 12px;
    gap: 8px;
  }
  .titlebar__tagline { display: none; }
  .titlebar__actions { width: 100%; justify-content: flex-start; flex-wrap: wrap; }
  .titlebar__sep { display: none; }
  body.is-mac .titlebar { padding-left: 12px; }

  .layout {
    display: flex;
    flex-direction: column;
    gap: 1px;
  }
  .panel { overflow: visible; }

  .panel--composer { order: 1; }
  .panel--library  { order: 2; }

  .composer { padding: 16px 14px 0; }
  #promptInput { font-size: 16px; }  /* < 16px déclenche un zoom sur iOS */

  .board {
    margin: 0 14px 18px;
    min-height: 320px;
  }
  .strip { padding: 16px 12px; gap: 16px 10px; }
  .token__frame { width: 92px; height: 62px; }

  .library { max-height: none; }

  .panel--detail {
    top: 0;
    width: min(340px, 88vw);
  }
}

@media (max-width: 480px) {
  .metrics { gap: 14px; }
  .token__frame { width: 78px; height: 53px; }
  .token__label { font-size: 11.5px; max-width: 92px; }
  .board { margin: 0 10px 14px; }
  .composer { padding: 14px 10px 0; }
}

/* Respect des preferences systeme d'animation. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto; }
  .token--term:hover .token__frame { transform: none; box-shadow: var(--shadow-md); }
}

/* ========================================================================
   Fenêtres d'outils (réglages, amélioration, description d'image)
   ======================================================================== */

.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px;
}
.modal[hidden] { display: none; }

.modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(8, 5, 3, .74);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  animation: fadeIn .2s var(--ease);
}

.modal__box {
  position: relative;
  width: min(660px, 100%);
  max-height: min(86vh, 820px);
  display: flex;
  flex-direction: column;
  background: var(--glass-modal);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-xl);
  box-shadow: var(--glass-edge-strong), var(--shadow-float-lg);
  overflow: hidden;
  animation: modalIn .28s var(--bounce);
}
.modal__box[hidden] { display: none; }

@keyframes modalIn {
  from { opacity: 0; transform: translateY(16px) scale(.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, .035);
  flex: 0 0 auto;
}
.modal__title { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.01em; }

.modal__close {
  border: 0;
  background: transparent;
  color: var(--text-faint);
  font-size: 22px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
  border-radius: 50%;
  transition: color .13s var(--ease);
}
.modal__close:hover { color: var(--text); }

.modal__body {
  padding: 18px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.modal__actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Avertissement encadré (clé API) */
.notice {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-soft);
  background: rgba(216, 162, 83, .09);
  border: 1px solid rgba(216, 162, 83, .3);
  border-left: 3px solid var(--gold);
  border-radius: var(--r-md);
  padding: 12px 15px;
}

/* Champs de formulaire */
.formrow { display: flex; flex-direction: column; gap: 6px; }

.formrow__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.formrow__hint { font-size: 11.5px; color: var(--text-faint); line-height: 1.5; }

.formrow input,
.select {
  width: 100%;
  font: inherit;
  font-size: 13.5px;
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 9px 14px;
  outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.formrow input:focus,
.select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

/* La flèche native est illisible sur fond sombre : on la redessine. */
.select {
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-faint) 50%),
    linear-gradient(135deg, var(--text-faint) 50%, transparent 50%);
  background-position:
    calc(100% - 17px) calc(50% + 1px),
    calc(100% - 12px) calc(50% + 1px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 32px;
  cursor: pointer;
}
.select option { background: var(--bg-raised); color: var(--text); }

.status {
  margin: 0;
  font-size: 12.5px;
  color: var(--text-soft);
  min-height: 18px;
  display: flex;
  align-items: center;
  gap: 7px;
}
.status.is-loading::before {
  content: '';
  width: 12px; height: 12px;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
  border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.status--warn { color: var(--accent-soft); }

/* ------------------------------------------------ configuration vidéo */

.vidgen {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.vidgen__row {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.vidgen__row .segmented { align-self: flex-start; }
.vidgen__note {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-faint);
}
.vidgen__opts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.vidopt {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 8px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--bg-input);
  color: var(--text-soft);
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
  transition: transform .18s var(--bounce), border-color .15s var(--ease),
              background .15s var(--ease), color .15s var(--ease);
}
.vidopt:hover:not(:disabled) {
  transform: translateY(-1px);
  border-color: var(--accent-soft);
  color: var(--text);
}
.vidopt.is-active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), 0.16);
  color: var(--text);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 0 0 1px var(--accent-glow);
}
.vidopt:disabled {
  opacity: .38;
  cursor: not-allowed;
}
.vidopt__label { font-size: 13px; font-weight: 600; }
.vidopt__price { font-size: 11px; color: var(--text-faint); }
.vidopt.is-active .vidopt__price { color: var(--accent-soft); }

.vidgen__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: linear-gradient(160deg, rgba(var(--accent-rgb), 0.14), transparent 70%);
}
.vidgen__cost { display: flex; align-items: baseline; gap: 9px; }
.vidgen__costLabel {
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.vidgen__costValue {
  font-family: var(--font-display);
  font-size: 21px;
  color: var(--accent-soft);
}

/* --------------------------------------------- formats d'image (ratios)

   Pastille de verre avec une vignette AUX PROPORTIONS DU FORMAT : on lit
   16:9 contre 9:16 d'un coup d'oeil, sans avoir a decoder l'etiquette. Les
   dimensions de la vignette sont posees en JS (ratioThumb), normalisees sur
   18 px de cote long pour que toutes les pastilles gardent la meme hauteur.
   Aucun prix affiche ici : le format n'entre pas dans la grille tarifaire. */

.genopt__ratios,
#vidRatio {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.ratiopill {
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px 5px 9px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--bg-input);
  color: var(--text-faint);
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04);
  transition: transform .18s var(--bounce), border-color .15s var(--ease),
              background .15s var(--ease), color .15s var(--ease);
}
.ratiopill--lg { font-size: 13px; padding: 7px 15px 7px 11px; }
.ratiopill:hover {
  transform: translateY(-1px);
  border-color: var(--accent-soft);
  color: var(--text);
}
.ratiopill.is-active {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .16);
  color: var(--text);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 0 0 1px var(--accent-glow);
}

/* Boite de 18x18 : la vignette y flotte centree, quelles que soient ses
   proportions, donc les etiquettes restent alignees d'une pastille a l'autre. */
.ratiothumb {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
}
.ratiothumb__box {
  display: block;
  border: 1.5px solid currentColor;
  border-radius: 2px;
  opacity: .75;
}
.ratiopill.is-active .ratiothumb__box { opacity: 1; border-color: var(--accent); }

/* Comparaison avant / après */
.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }
.compare__col { display: flex; flex-direction: column; gap: 6px; min-width: 0; }

.compare__text {
  margin: 0;
  flex: 1 1 auto;
  min-height: 128px;
  max-height: 240px;
  overflow-y: auto;
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--text-soft);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 12px 14px;
  white-space: pre-wrap;
  word-break: break-word;
}
.compare__text--out {
  color: var(--text);
  border-color: rgba(var(--accent-rgb), .38);
  background: rgba(var(--accent-rgb), .06);
}

/* Zone de dépôt d'image */
.drop {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 190px;
  padding: 18px;
  border: 1.5px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: var(--bg-input);
  cursor: pointer;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
.drop:hover, .drop.is-over {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .07);
}

.drop__hint {
  font-size: 12.5px;
  color: var(--text-faint);
  text-align: center;
  max-width: 280px;
}

.drop__preview {
  max-width: 100%;
  max-height: 260px;
  border-radius: var(--r-sm);
  display: block;
  box-shadow: var(--shadow-md);
}

@media (max-width: 640px) {
  .modal { padding: 12px; }
  .compare { grid-template-columns: 1fr; }
  .menu__panel { min-width: 250px; }
}

/* Choix du mode d'appel IA -------------------------------------------- */
.modes { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }

.mode {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: left;
  font: inherit;
  padding: 12px 15px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--bg-input);
  box-shadow: var(--glass-edge);
  cursor: pointer;
  transition: border-color .16s var(--ease), background .16s var(--ease), transform .16s var(--bounce), box-shadow .16s var(--ease);
}
.mode:hover { border-color: var(--text-faint); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.mode.is-on {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .1);
  box-shadow: 0 0 0 2px var(--accent-glow);
}

.mode__title { font-size: 13px; font-weight: 500; color: var(--text); }
.mode.is-on .mode__title { color: var(--accent-soft); }
.mode__desc { font-size: 11.5px; line-height: 1.45; color: var(--text-faint); }

#modeKeyFields { display: flex; flex-direction: column; gap: 15px; }
#modeKeyFields[hidden], #modeProxyFields[hidden] { display: none; }

@media (max-width: 640px) {
  .modes { grid-template-columns: 1fr; }
}

/* ========================================================================
   Onglets du panneau central
   ======================================================================== */

.tabs {
  display: flex;
  gap: 4px;
  padding: 8px 24px;
  border-bottom: 1px solid var(--line);
  background: var(--glass-panel);
  backdrop-filter: var(--glass-blur-soft);
  -webkit-backdrop-filter: var(--glass-blur-soft);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
  flex: 0 0 auto;
}

.tab {
  position: relative;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  padding: 8px 18px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  transition: color .14s var(--ease), background .16s var(--ease),
              border-color .16s var(--ease), box-shadow .16s var(--ease),
              transform .16s var(--bounce);
}
.tab:hover { color: var(--text-soft); background: rgba(255, 255, 255, .04); }
.tab:active { transform: scale(.97); }

/* L'onglet actif devient une pastille de verre teintee : plus lisible qu'un
   simple trait, et coherent avec les autres formes ovales de l'interface. */
.tab.is-active {
  color: var(--text);
  background: linear-gradient(170deg,
              rgba(var(--accent-rgb), .26), rgba(var(--accent-rgb), .12));
  border-color: rgba(var(--accent-rgb), .42);
  box-shadow: var(--glass-edge), 0 2px 10px rgba(0, 0, 0, .3);
}

/* Compteur de l'onglet Galerie : dit qu'il y a quelque chose dedans sans
   forcer a l'ouvrir. Masque quand la galerie est vide. */
.tab__count {
  min-width: 18px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: rgba(var(--accent-rgb), .2);
  border: 1px solid rgba(var(--accent-rgb), .32);
  color: var(--accent-soft);
  font-size: 10.5px;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
}
.tab__count[hidden] { display: none; }

.tab__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 6px rgba(216, 162, 83, .7);
}
.tab__dot[hidden] { display: none; }

/* Signal « une generation tourne » sur l'onglet Galerie. Respiration lente et
   reguliere plutot que clignotement : visible du coin de l'oeil, jamais
   agressif, et sans jamais disparaitre completement. */
.tab__dot--busy {
  background: var(--accent);
  box-shadow: 0 0 7px rgba(var(--accent-rgb), .75);
  animation: genPulse 1.8s var(--ease) infinite;
}
@keyframes genPulse {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: .45; transform: scale(.7); }
}

/* Chaque onglet est SA propre zone de defilement.
   Sans `overflow-y: auto` ici, le composeur (`flex: 0 0 auto`, donc non
   compressible) poussait le plateau et les boutons de generation hors du
   `.panel--composer` en `overflow: hidden` : le bas de page devenait
   litteralement inatteignable des que le contenu grandissait (references
   ajoutees, panneau de parametres deplie, petite fenetre). */
.tabview {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: tabIn .22s var(--ease);
}
.tabview[hidden] { display: none; }

@keyframes tabIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ======================================================= outil Seedance */

/* Une seule zone de defilement par onglet : c'est `.tabview` qui defile
   desormais, `.sd` se contente de grandir avec son contenu. */
.sd {
  flex: 1 1 auto;
  overflow-y: visible;
  padding: 22px 24px 28px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.sd__head { display: flex; flex-direction: column; gap: 6px; }
.sd__title { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }
.sd__lead {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-soft);
  max-width: 68ch;
}

.sd__step { display: flex; gap: 14px; }

.sd__num {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--bg-input);
  border: 1px solid var(--line-strong);
  color: var(--accent);
  font-size: 11.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin-top: 1px;
}

.sd__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.sd__body .formrow__label { margin: 0; }
.sd__body .formrow__hint { max-width: 74ch; }

.sd__refrow { display: flex; gap: 8px; }
.sd__refrow input {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-size: 13.5px;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  color: var(--gold);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 9px 11px;
  outline: none;
}
.sd__refrow input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

/* Ce qui est conservé */
.sd__keep { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }

.keepchip {
  font: inherit;
  font-size: 12px;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: all .14s var(--ease);
}
.keepchip:hover { color: var(--text); border-color: var(--text-faint); transform: translateY(-1px); }
.keepchip:active { transform: translateY(0) scale(.96); }
.keepchip.is-on {
  background: rgba(127, 169, 106, .15);
  border-color: rgba(127, 169, 106, .55);
  color: #a8c893;
  font-weight: 500;
}
.keepchip.is-on::before { content: '🔒 '; font-size: 10px; }

/* Ce qui est remplacé */
.sd__swaps {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 2px;
}

.swaprow { display: flex; align-items: center; gap: 12px; }

.swaprow__label {
  flex: 0 0 150px;
  font-size: 12.5px;
  color: var(--text-soft);
  text-align: right;
}

.swaprow input {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 8px 11px;
  outline: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.swaprow input::placeholder { color: var(--text-faint); }
.swaprow input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

.sd__actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 4px; }

.sd #sdOut { min-height: 96px; max-height: 220px; }

@media (max-width: 900px) {
  .swaprow { flex-direction: column; align-items: stretch; gap: 4px; }
  .swaprow__label { flex: none; text-align: left; }
  .sd { padding: 18px 14px 24px; }
  .tabs { padding: 0 14px; }
}

/* ------------------------------------ bibliothèque de techniques Seedance */

.sdlib {
  border-top: 1px solid var(--line);
  padding-top: 16px;
}
.sdlib__head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  cursor: pointer;
  list-style: none;
  user-select: none;
  position: relative;
  padding-right: 22px;
}
.sdlib__head::-webkit-details-marker { display: none; }
.sdlib__head::after {
  content: '▸';
  position: absolute;
  top: 2px; right: 2px;
  font-size: 11px;
  color: var(--text-faint);
  transition: transform .18s var(--ease);
}
.sdlib[open] .sdlib__head::after { transform: rotate(90deg); }

.sdlib__content {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 14px;
}

.sdlib__groups { display: flex; flex-direction: column; gap: 14px; }

.techcat__head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}
.techcat__label { font-size: 13px; font-weight: 600; color: var(--gold); }
.techcat__count { font-size: 10.5px; color: var(--text-faint); }

.techcat__cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px;
}

.techcard {
  text-align: left;
  font: inherit;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 13px 15px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--bg-input);
  box-shadow: var(--glass-edge);
  cursor: pointer;
  transition: border-color .18s var(--ease), transform .18s var(--bounce), box-shadow .18s var(--ease);
}
.techcard:hover {
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: var(--shadow-float);
}
.techcard:active { transform: translateY(-1px) scale(.99); }
.techcard__title { font-size: 12.5px; font-weight: 600; color: var(--text); }
.techcard__why { font-size: 11.5px; line-height: 1.5; color: var(--text-soft); }
.techcard__tpl {
  font-size: 10.5px;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  color: var(--text-faint);
  white-space: pre-wrap;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

.sdlib__generic {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 12px;
  margin-top: 4px;
}
.sdlib__genericCol {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.sdlib__genericHead { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sdlib__pre {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.6;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  color: var(--text-soft);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  white-space: pre-wrap;
}

/* ------------------------------- plans du générateur de story-board */

.shotcard {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 13px 15px;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--bg-input);
  box-shadow: var(--glass-edge);
  transition: box-shadow .18s var(--ease), border-color .18s var(--ease);
}
.shotcard:hover { border-color: var(--line-strong); box-shadow: var(--shadow-sm); }
.shotcard__head {
  display: flex;
  align-items: center;
  gap: 10px;
}
/* Le bouton « retirer » reste plaque a droite comme avant l'arrivee du
   timecode : c'est lui qu'on pousse, pas le timecode qu'on centre. */
.shotcard__head > .btn { margin-left: auto; }
.shotcard__title { font-size: 12px; font-weight: 600; color: var(--gold); }

/* Timecode calcule — lecture chiffree, donc chasse fixe : les colonnes des
   cartes successives s'alignent a l'oeil et la cascade se verifie d'un coup. */
.shotcard__tc {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
  color: var(--gold);
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, .04);
  white-space: nowrap;
}
.shotcard__row { display: flex; align-items: center; gap: 12px; }
.shotcard__row .swaprow__label { flex: 0 0 130px; }
.shotcard__row input,
.shotcard__row select {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 7px 10px;
  outline: none;
}
.shotcard__row input:focus,
.shotcard__row select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow);
}

@media (max-width: 900px) {
  .shotcard__row { flex-direction: column; align-items: stretch; gap: 4px; }
  .shotcard__row .swaprow__label { flex: none; text-align: left; }
  .techcat__cards { grid-template-columns: 1fr; }
}

/* Rattachement des fiches au story-board ---------------------------------
   Rangées en pilule, dans le même verre que le reste : la case à cocher est
   un interrupteur dessiné à la main (accent-color suffit pour la coche, mais
   la pastille orange doit rester celle de la palette). */
.sblink { display: flex; flex-direction: column; gap: 8px; }
.sblink__row {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 11px 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--glass-border);
  background: var(--glass-input);
  box-shadow: var(--glass-edge);
  cursor: pointer;
  transition: border-color .18s var(--ease), background .18s var(--ease),
              transform .18s var(--bounce), opacity .18s var(--ease);
}
.sblink__row:hover { border-color: var(--accent); transform: translateY(-1px); }
.sblink__row.is-off { opacity: .5; cursor: not-allowed; }
.sblink__row.is-off:hover { border-color: var(--glass-border); transform: none; }
.sblink__row.is-on { border-color: var(--accent); background: rgba(var(--accent-rgb), .1); }
.sblink__row input[type="checkbox"] {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin: 2px 0 0;
  accent-color: var(--accent);
  cursor: inherit;
}
.sblink__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sblink__name { font-size: 13px; color: var(--text); }
.sblink__note { font-size: 11.5px; color: var(--text-faint); line-height: 1.35; }

/* Dépôt fichier de l'outil Seedance ------------------------------------- */
.drop--sd {
  position: relative;
  min-height: 130px;
  padding: 12px;
}

.drop--sd .drop__preview {
  max-height: 190px;
}

video.drop__preview {
  width: 100%;
  max-width: 260px;
  border-radius: var(--r-sm);
  display: block;
  box-shadow: var(--shadow-md);
  background: #000;
}

.drop__clear {
  position: absolute;
  top: 8px; right: 8px;
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: rgba(20, 16, 13, .85);
  color: var(--text-soft);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: color .13s var(--ease), border-color .13s var(--ease);
}
.drop__clear:hover { color: var(--text); border-color: var(--accent); }

/* Photo de référence, quand elle existe --------------------------------- */
.token__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Le SVG reste dessous : si la photo échoue à charger, il redevient visible
   dès que le script retire l'<img> (voir fillVisualFrame). */
.token__frame { position: relative; }
.detail__hero { position: relative; }

/* ========================================================================
   Carte flottante au survol — bibliothèque et décomposition
   ======================================================================== */

.hovercard {
  position: fixed;
  top: 0; left: 0;
  width: 320px;
  max-width: calc(100vw - 24px);
  max-height: 78vh;
  background: var(--glass-raised);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-xl);
  box-shadow: var(--glass-edge-strong), var(--shadow-float-lg);
  overflow: hidden;
  z-index: 200;
  pointer-events: none;
  opacity: 0;
  transform: translateY(10px) scale(.96);
  transition: opacity .18s var(--ease), transform .24s var(--bounce);
  display: flex;
  flex-direction: column;
}
.hovercard.is-visible { opacity: 1; transform: translateY(0) scale(1); }

.hovercard__media {
  flex: 0 0 auto;
  width: 100%;
  aspect-ratio: 3 / 2;
  position: relative;
  background: var(--bg-input);
  border-bottom: 1px solid var(--line);
}
.hovercard__media .visual,
.hovercard__media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

.hovercard__body {
  padding: 14px 16px 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.hovercard__head { display: flex; flex-direction: column; gap: 3px; }
.hovercard__cat {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--cat-color, var(--accent));
}
.hovercard__title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--text);
}

.hovercard__text { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--text-soft); }
.hovercard__text--effect { color: var(--text); }

.hovercard__en {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 2px;
}
.hovercard__enLabel {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.hovercard__enText {
  font-size: 12px;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  color: var(--gold);
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 5px 8px;
}

.hovercard__promptWrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
.hovercard__promptLabel {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.hovercard__promptText {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--text-soft);
  max-height: 90px;
  overflow-y: auto;
}

/* Portefeuille de crédits --------------------------------------------- */
.wallet {
  margin-top: 4px;
  padding: 12px 13px;
  background: var(--bg-input);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.wallet__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.wallet__balance { display: flex; align-items: baseline; gap: 6px; }
.wallet__count {
  font-size: 22px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--gold);
  transition: transform .18s var(--bounce);
}
.wallet__count.is-updated { transform: scale(1.18); }
.wallet__unit { font-size: 12px; color: var(--text-faint); }

/* ========================================================================
   Notifications (toasts)
   ======================================================================== */

.toasts {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 300;
  display: flex;
  flex-direction: column-reverse;
  gap: 8px;
  pointer-events: none;
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 220px;
  max-width: 360px;
  padding: 11px 14px 11px 16px;
  background: var(--glass-raised);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-pill);
  box-shadow: var(--glass-edge-strong), var(--shadow-float);
  font-size: 12.5px;
  color: var(--text);
  animation: toastIn .3s var(--bounce);
  transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}
.toast:hover { transform: translateY(-2px); box-shadow: var(--shadow-float-lg); }
.toast.is-leaving { animation: toastOut .2s var(--ease) forwards; }
.toast--ok { border-left-color: var(--ok); }
.toast--error { border-left-color: #e2705c; }

@keyframes toastIn {
  from { opacity: 0; transform: translateY(14px) scale(.94); }
  to   { opacity: 1; transform: none; }
}
@keyframes toastOut {
  to { opacity: 0; transform: translateY(6px) scale(.97); }
}

.toast__msg { flex: 1 1 auto; line-height: 1.4; }
.toast__action {
  flex: 0 0 auto;
  font: inherit;
  font-weight: 600;
  font-size: 12px;
  color: var(--accent-soft);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 2px 4px;
}
.toast__action:hover { color: var(--gold); }
.toast__close {
  flex: 0 0 auto;
  font-size: 15px;
  line-height: 1;
  color: var(--text-faint);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 0 2px;
}
.toast__close:hover { color: var(--text); }

/* ========================================================================
   État vide du plateau — invite à l'action plutôt qu'un simple message
   ======================================================================== */

.empty {
  position: absolute;
  inset: 44px 16px 16px;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin: 0;
  text-align: center;
  pointer-events: none;
}
.board.is-empty .empty { display: flex; }

.empty__text { margin: 0; color: var(--text-faint); font-size: 13px; }

.empty__chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: 520px;
  pointer-events: auto;
}

.emptychip {
  font: inherit;
  font-size: 12px;
  padding: 8px 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: var(--bg-input);
  color: var(--text-soft);
  cursor: pointer;
  transition: all .16s var(--ease);
}
.emptychip:hover {
  color: var(--text);
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .1);
  transform: translateY(-2px);
}

/* ========================================================================
   Indice de découverte (bibliothèque, premier lancement)
   ======================================================================== */

.tip {
  margin: 0 16px 12px;
  padding: 10px 12px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: rgba(var(--accent-rgb), .08);
  border: 1px solid rgba(var(--accent-rgb), .3);
  border-radius: var(--r-sm);
  animation: tabIn .25s var(--ease);
}
.tip__text { flex: 1 1 auto; margin: 0; font-size: 11.5px; line-height: 1.5; color: var(--text-soft); }
.tip__close {
  flex: 0 0 auto;
  font-size: 15px;
  line-height: 1;
  color: var(--text-faint);
  background: transparent;
  border: 0;
  cursor: pointer;
}
.tip__close:hover { color: var(--text); }

/* ========================================================================
   Panneau des raccourcis clavier
   ======================================================================== */

.modal__box--sm { width: min(420px, 100%); }

.kblist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.kblist li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 4px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--text-soft);
}
.kblist li:last-child { border-bottom: 0; }

.kbd-row { display: flex; gap: 4px; }
kbd {
  font: inherit;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  font-size: 11px;
  padding: 3px 7px;
  background: var(--bg-input);
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
  color: var(--text);
}

@media (max-width: 640px) {
  .toasts { left: 12px; right: 12px; bottom: 12px; }
  .toast { max-width: none; }
}

/* =========================================================================
   Typographie d'affichage
   -------------------------------------------------------------------------
   Une serif display est superbe en grand et illisible en petit corps dense.
   On la reserve donc aux titres, aux libelles de section et aux chiffres mis
   en avant, via --font-display. Le corps de texte, les champs de saisie, les
   descriptions et tout le monospace restent sur la pile sans-serif.

   Le Butler Stencil (--font-stencil) n'apparait qu'a un seul endroit, le
   titre-heros : voir la regle .titlebar__name plus bas.
   ========================================================================= */

h1, h2, h3, h4,
.panel__title,
.field__label,
.libgroup__label,
.detail__title,
.detail__cat,
.detail__key,
.modal__title,
.formrow__label,
.params__title,
.paramgroup__label,
.sd__title,
.techcat__label,
.shotcard__title,
.hovercard__title,
.hovercard__cat,
.hovercard__enLabel,
.hovercard__promptLabel,
.metric__value,
.metric__label,
.wallet__count,
.tab,
.empty__text {
  font-family: var(--font-display);
}

/* La serif est optiquement plus petite que la sans a taille egale : on
   compense sur les titres pour garder la meme presence visuelle. */
.detail__title  { font-size: 21px; font-weight: 700; letter-spacing: 0; }
.modal__title   { font-size: 18px; font-weight: 700; letter-spacing: 0; }
.sd__title      { font-size: 20px; font-weight: 700; letter-spacing: 0; }
.hovercard__title { font-size: 18px; font-weight: 700; letter-spacing: 0; }
.metric__value  { font-size: 20px; font-weight: 700; }
.wallet__count  { font-size: 25px; }
.techcat__label { font-size: 14.5px; font-weight: 700; }
.shotcard__title { font-size: 13px; font-weight: 700; }
.empty__text    { font-size: 15px; }

/* Titre-heros : le seul endroit ou le Stencil est employe. Les lettres
   ajourees ont besoin d'air pour que l'oeil recompose les contre-formes,
   d'ou la chasse elargie et le corps volontairement genereux. */
.titlebar__name {
  font-family: var(--font-stencil);
  font-size: 18px;
  font-weight: 400;
  letter-spacing: .07em;
  color: var(--text);
}
.titlebar__name b { font-weight: 700; letter-spacing: .07em; }
.tab            { font-size: 14px; font-weight: 500; letter-spacing: .01em; }

/* Les micro-libelles en capitales : la serif y gagne du caractere, mais il
   lui faut un poil plus de corps et de chasse pour rester nette. */
.panel__title,
.field__label,
.libgroup__label,
.detail__key,
.detail__cat,
.formrow__label,
.params__title,
.paramgroup__label,
.hovercard__cat,
.hovercard__enLabel,
.hovercard__promptLabel,
.metric__label {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .12em;
}
.paramgroup__label, .metric__label, .hovercard__enLabel, .hovercard__promptLabel {
  font-size: 11px;
}

/* Les titres de cartes de technique restent en sans : ils sont suivis d'un
   paragraphe dense, la coherence de lecture prime sur l'effet. */
.techcard__title { font-family: var(--font-ui); }

/* Tout ce qui est saisi, lu au long ou monospace garde la sans-serif. */
input, textarea, select, button.libitem, .acitem, .menu__label, .menu__hint,
.detail__text, .sd__lead, .formrow__hint, .techcard__why, .toast__msg,
.hovercard__text, .strip.is-text, .token__label, .kblist li {
  font-family: var(--font-ui);
}
.params__final, .detail__english, .alias, .sdlib__pre, .hovercard__enText,
.techcard__tpl, .sd__refrow input, kbd, .token--ref .token__label {
  font-family: var(--font-mono);
}

/* =========================================================================
   Verre optique — surfaces restantes
   -------------------------------------------------------------------------
   `backdrop-filter` est coûteux : il reste cantonne aux surfaces de premier
   plan et aux conteneurs (barre haute, onglets, plateau, panneaux, modales,
   toasts, menus). Les elements repetes en grille — vignettes de la
   bibliotheque, cartes de technique, blocs de mots — n'en portent pas ;
   ils recoivent seulement l'arete lumineuse, qui ne coute rien.
   ========================================================================= */

.panel--library,
.panel--detail {
  background: var(--glass-panel);
  backdrop-filter: var(--glass-blur-soft);
  -webkit-backdrop-filter: var(--glass-blur-soft);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .04);
}

/* Le degrade de fond donne au flou quelque chose a saturer : sans lui,
   le verre n'aurait rien a refracter sur un aplat uniforme. */
body {
  background:
    radial-gradient(1100px 620px at 12% -8%, rgba(224, 118, 58, .10), transparent 62%),
    radial-gradient(900px 560px at 92% 4%, rgba(216, 162, 83, .07), transparent 60%),
    radial-gradient(760px 700px at 60% 108%, rgba(180, 84, 31, .09), transparent 66%),
    var(--bg);
  background-attachment: fixed;
}
.panel--composer { background: transparent; }
.layout { background: rgba(255, 255, 255, .05); }

.sdlib__content,
.wallet,
.drop {
  box-shadow: var(--glass-edge);
}

.wallet {
  background: var(--glass-input);
  border-color: var(--glass-border);
  border-radius: var(--r-lg);
}

.drop { border-radius: var(--r-lg); }
.drop__preview, video.drop__preview { border-radius: var(--r-md); }

.detail__hero { border-radius: var(--r-lg); }

/* Arete lumineuse sur les elements repetes — pas de flou, donc gratuit.
   Chaque regle reprend l'ombre d'origine pour ne pas ecraser la profondeur
   ni l'anneau de selection deja definis plus haut. */
.paramchip,
.catchip,
.keepchip,
.emptychip,
.badge,
.alias,
.gap {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07);
}
.libitem__thumb {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .3), inset 0 1px 0 rgba(255, 255, 255, .12);
}
.token__frame {
  box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255, 255, 255, .1);
}
.token--term:hover .token__frame {
  box-shadow: var(--shadow-float-lg), inset 0 1px 0 rgba(255, 255, 255, .18);
}
.token.is-selected .token__frame {
  border-color: var(--accent-soft);
  box-shadow: 0 0 0 2px var(--accent-glow), var(--shadow-lg),
              inset 0 1px 0 rgba(255, 255, 255, .18);
}

/* Les champs de saisie : verre teinte plutot qu'aplat opaque. */
#promptInput,
.search input,
.formrow input,
.select,
.swaprow input,
.sd__refrow input,
.shotcard__row input,
.shotcard__row select {
  background: var(--glass-input);
  border-color: var(--glass-border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
#promptInput:focus,
.search input:focus,
.formrow input:focus,
.select:focus,
.swaprow input:focus,
.sd__refrow input:focus,
.shotcard__row input:focus,
.shotcard__row select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-glow), inset 0 1px 0 rgba(255, 255, 255, .08);
}

.swaprow input,
.sd__refrow input,
.shotcard__row input,
.shotcard__row select {
  border-radius: var(--r-md);
  padding-left: 14px;
  padding-right: 14px;
}

/* Les boutons gagnent l'arete lumineuse du verre sur leur bord superieur. */
.btn--ghost {
  background: rgba(255, 255, 255, .04);
  box-shadow: var(--glass-edge);
}
.btn--ghost:hover {
  background: rgba(255, 255, 255, .09);
  box-shadow: var(--glass-edge), var(--shadow-sm);
}

/* Chips actives : pastille de verre teintee plutot qu'aplat. */
.catchip.is-active {
  box-shadow: var(--glass-edge-strong), 0 2px 10px rgba(0, 0, 0, .4);
}

/* Pastilles rondes ------------------------------------------------------- */
.sd__num { box-shadow: var(--glass-edge); }

/* Les boutons de fermeture deviennent de vraies pastilles circulaires :
   sans dimensions fixes, `border-radius: 50%` sur une boite plus large que
   haute donne un ovale de travers plutot qu'un cercle. */
.modal__close,
.tip__close,
.toast__close {
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
  display: grid;
  place-items: center;
  transition: color .13s var(--ease), background .13s var(--ease);
}
.modal__close:hover,
.tip__close:hover,
.toast__close:hover { background: rgba(255, 255, 255, .09); }

.preset__del {
  width: 24px;
  height: 24px;
  padding: 0;
  display: grid;
  place-items: center;
}
.preset__del:hover { background: rgba(226, 112, 92, .15); }

.toast__action {
  border-radius: var(--r-pill);
  padding: 3px 11px;
  transition: background .13s var(--ease), color .13s var(--ease);
}
.toast__action:hover { background: rgba(var(--accent-rgb), .16); }
.drop__clear { backdrop-filter: blur(12px) saturate(160%); -webkit-backdrop-filter: blur(12px) saturate(160%); }

/* Le panneau de detail superpose (< 1080px) devient une plaque de verre. */
@media (max-width: 1080px) {
  .panel--detail {
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border-radius: var(--r-xl) 0 0 var(--r-xl);
    border-left: 1px solid var(--glass-border);
  }
}

/* En petite largeur, les grands rayons mangeraient le contenu. */
@media (max-width: 820px) {
  :root { --r-lg: 20px; --r-xl: 24px; }
  .board { border-radius: var(--r-lg); }
  .tabs { padding: 8px 14px; gap: 3px; }
  .tab { padding: 7px 14px; }
}

/* Nouvelles transitions couvertes par la preference systeme d'animation. */
@media (prefers-reduced-motion: reduce) {
  .tab:active { transform: none; }
  .libitem:hover .libitem__thumb { transform: none; }

  /* Galerie : tout ce qui boucle est neutralise. Le seul mouvement conserve
     est la rotation du spinner, fortement ralentie — le supprimer laisserait
     l'utilisateur sans aucun signe que la generation avance. */
  .gencard__media--busy { animation: none; }
  .gencard__media img { animation: none; }
  .gencard:hover { transform: none; }
  .tab__dot--busy { animation: none; }
  .genspin { animation-duration: 2.6s; }
}

/* ========================================================= onglet Galerie

   Grille d'apercus des generations. Meme vocabulaire visuel que le reste :
   cartes de verre, coins arrondis --r-*, arete lumineuse, accent orange.
   La carte survit a la disparition de son apercu : le cadre de remplacement
   (.gencard__ph) prend sa place et l'entree reste actionnable (prompt). */

.gal {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px 20px 26px;
}

.gal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}
.gal__headText { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.gal__headActions { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }

/* Cadres d'apercu carres : on resserre la colonne par rapport a l'ancienne
   grille (210px) pour garder la meme densite qu'avant, une vignette carree
   etant plus haute qu'une vignette 4/3 a largeur egale. */
.gal__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(192px, 1fr));
  gap: 13px;
  align-items: stretch;
}
.gal__grid:empty { display: none; }

/* Etat vide : conteneur propre a la galerie (voir index.html), centre dans le
   flux plutot qu'en position absolue, donc cliquable. */
.gal__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  text-align: center;
  padding: 34px 16px 42px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, .015);
}
.gal__empty[hidden] { display: none; }

.gencard {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
  background: var(--glass-raised);
  box-shadow: var(--glass-edge);
  overflow: hidden;
  transition: border-color .16s var(--ease), transform .16s var(--bounce);
}
.gencard:hover { border-color: rgba(var(--accent-rgb), .45); transform: translateY(-2px); }

/* CADRE D'APERCU CARRE — deux decisions liees, et une correction de fond.

   1. CORRECTION. L'`aspect-ratio` de ce cadre etait auparavant ignore : l'image
      etait un enfant de grille EN FLUX, sa hauteur intrinseque devenait donc le
      min-content de la ligne et etirait le cadre bien au-dela du ratio demande
      (un 9:16 de 241px de large imposait 363px de haut). D'ou des vignettes
      allongees, de hauteurs toutes differentes, et des cartes d'une meme rangee
      etirees par la plus grande. L'image passe en position absolue : elle ne
      participe plus au dimensionnement, et `aspect-ratio` gouverne enfin.

   2. CARRE (1 / 1) plutot que 4/3 : un cadre carre est neutre vis-a-vis des
      formats generes, qui vont du paysage au portrait. Aucun format n'est
      privilegie, et la grille est parfaitement reguliere.

   3. object-fit: CONTAIN, pas cover. Les generations couvrent 1:1, 16:9
      (1536x1024) et 9:16 (1024x1536) — et les entrees video ajouteront du 21:9.
      Dans un cadre carre, `cover` amputerait 43 % de la largeur d'un 16:9 et
      44 % de la hauteur d'un 9:16 : on masquerait justement ce que
      l'utilisateur vient inspecter, et un cadrage vertical deviendrait
      illisible. `contain` laisse des bandes, mais elles se fondent dans le fond
      sombre du cadre (--bg-input) et aucune generation n'est mutilee. */
.gencard__media {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--bg-input);
  display: grid;
  place-items: center;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.gencard__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  /* Apparition douce : quand une carte « en cours » devient une vraie entree,
     l'apercu se fond au lieu de surgir. La carte ne bouge pas de place. */
  animation: genReveal .28s var(--ease) both;
}
@keyframes genReveal {
  from { opacity: 0; transform: scale(.985); }
  to   { opacity: 1; transform: none; }
}
.gencard__ph {
  font-size: 11.5px;
  color: var(--text-faint);
  text-align: center;
  padding: 0 12px;
}

/* Type de generation, pose sur l'apercu : lisible sur n'importe quelle image
   grace au fond sombre translucide. */
.gencard__kind {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(255, 255, 255, .16);
  background: rgba(10, 8, 7, .66);
  color: var(--text-soft);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.gencard__kind--video { color: var(--accent-soft); border-color: rgba(var(--accent-rgb), .45); }

/* ------------------------------------- carte « en cours » et carte en echec

   Meme vocabulaire visuel que `.status.is-loading` (meme keyframe `spin`, meme
   accent) : l'utilisateur reconnait l'attente sans avoir a l'apprendre. */
.gencard--pending { border-color: rgba(var(--accent-rgb), .38); }
.gencard--error   { border-color: rgba(207, 92, 66, .5); }

/* Squelette pulsant : une onde chaude qui balaie le cadre vide. */
.gencard__media--busy {
  background:
    linear-gradient(115deg,
      rgba(255, 255, 255, .015) 0%,
      rgba(var(--accent-rgb), .13) 45%,
      rgba(255, 255, 255, .015) 90%) no-repeat 0 0 / 250% 100%,
    var(--bg-input);
  animation: genSkel 1.7s var(--ease) infinite;
}
@keyframes genSkel {
  from { background-position: 150% 0; }
  to   { background-position: -50% 0; }
}

.genspin {
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
  border-top-color: var(--accent);
  animation: spin .7s linear infinite;
}

/* Glyphe d'echec : pastille, pas une icone importee (CSP : rien d'externe). */
.gencard__fail {
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(207, 92, 66, .55);
  background: rgba(207, 92, 66, .16);
  color: #e8a48f;
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
}

/* Libelle d'etat pose en bas du cadre, sur deux lignes au plus. */
.gencard__state {
  position: absolute;
  left: 0; right: 0; bottom: 9px;
  padding: 0 11px;
  text-align: center;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--text-faint);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.gencard--error .gencard__state { color: var(--accent-soft); }

.gencard__body {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 10px 12px 12px;
  /* Le corps occupe la place restante : les actions se posent en bas, donc
     toutes les cartes d'une meme rangee alignent leurs boutons. */
  flex: 1 1 auto;
}
.gencard__date { font-size: 11px; color: var(--text-faint); }

/* Prompt tronque a trois lignes ; un clic bascule .is-open et le deplie. */
.gencard__prompt {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-soft);
  cursor: pointer;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.gencard__prompt.is-open { -webkit-line-clamp: unset; overflow: visible; }
.gencard__prompt:hover { color: var(--text); }

.gencard__tags { display: flex; flex-wrap: wrap; gap: 5px; }
.gencard__tag {
  padding: 2px 9px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .04);
  color: var(--text-faint);
  font-size: 10.5px;
}

.gencard__acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: auto;
  padding-top: 2px;
}
.gencard__acts .ref__act { font-size: 11.5px; padding: 4px 11px; text-decoration: none; }
.gencard__acts .ref__act--del { margin-left: auto; }
.gencard__acts .ref__act:disabled { opacity: .4; cursor: not-allowed; }

@media (max-width: 640px) {
  .gal { padding: 14px 13px 22px; }
  .gal__grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}
