/* v06a — Generate page styles.
   Reuses the cream/forest design language from the rest of the tracker.
   Two-column layout on desktop: shot picker (320px) + builder (1fr).
   The page itself sits inside the standard .view-page glass shell. */

.gen-page {
  padding: 0;
}
.gen-shell {
  display: grid;
  /* v07zz156 — Shots picker drawer must EXACTLY match the Assets workbench
     drawer (.ga-shell first column = 300px) so the left panel never changes
     width when toggling Shots ⇄ Assets. (v154 bumped this to 344 to fit the
     pills, but the pills live in .ga-shell and fit via nowrap, so the bump
     only widened the Shots drawer — reverted to 300 to match.) */
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 16px;
  align-items: stretch;
  flex: 1;
  min-height: 0;
  /* v07zz400 — Shot picker | builder | Generations drawer. The 3rd track
     (~336px) only appears via the .gen-shell--with-drawer modifier so batch /
     VO mode keep the original 2-up grid (no empty track, no shift). */
  /* v06c — Padding-top moved OFF the shell. The previous global
     padding-top: 16px pushed both columns down equally, which left
     a weird empty gap above the shot picker's "SHOTS" header. Now
     the picker reaches all the way up to align with where the
     builder's "CREATE A PROMPT" eyebrow sits, and the builder's own
     padding handles its breathing room (see .gen-builder below). */
}
/* v07zz401 — 3-column layout when the Generations drawer is shown. The drawer
   track is fixed-width (340px) so it never shrinks or overlaps the References
   panel — the builder (track 2) absorbs the slack. The drawer itself reuses the
   asset-gen page's .ga-preview.ga-drawer styling verbatim; the only adapter we
   need is to let it sit + scroll inside the grid track. */
.gen-shell--with-drawer {
  grid-template-columns: 300px minmax(0, 1fr) 340px;
}
/* The shot drawer is the SAME .ga-preview.ga-drawer panel the asset page uses;
   .gen-gens-drawer just pins it to its grid track + caps its height so the inner
   RECENT GENERATIONS list scrolls (the .ga-preview > .ga-recent rules already
   make the list absorb the slack). No bespoke card/badge styling — it's all
   inherited from ga-*. */
.gen-gens-drawer.ga-preview.ga-drawer {
  align-self: stretch;
  min-height: 0;
  max-height: 100%;
}
/* v07zz402 — discard button in the preview tools row: same shape as the other
   .ga-preview-tools buttons (base styling inherited), red on hover/active. */
.ga-preview-tools .ga-preview-tool--discard:hover:not(:disabled) {
  background: color-mix(in srgb, var(--danger-soft) 12%, transparent);
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger-soft) 50%, transparent);
}

/* ─── Gallery drawer (v07zz403 — restored big-thumbnail view) ──────────── */
/* Container rules are scoped with :not(.ga-preview) so they apply ONLY to the
   Gallery aside, never to the Panel aside (which also carries .gen-gens-drawer
   but must keep .ga-drawer's overflow-y:auto scroll). The inner card classes
   below are Gallery-only markup, so they don't need the guard. */
.gen-gens-drawer:not(.ga-preview) {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-card);
  overflow: hidden;
}
.gen-gens-head {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 14px 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, color-mix(in srgb, var(--gold-2) 26%, var(--mix-light)) 85%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-8) 31%, var(--mix-light)) 65%, transparent));
}
.gen-gens-title {
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-18);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.gen-gens-spin {
  width: 12px; height: 12px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--gold-5) 30%, transparent);
  border-top-color: color-mix(in srgb, var(--gold-5) 90%, transparent);
  animation: gen-gens-spin 0.7s linear infinite;
}
@keyframes gen-gens-spin { to { transform: rotate(360deg); } }
.gen-gens-err {
  flex-shrink: 0;
  margin: 8px 12px 0;
  font-size: var(--fs-11-5);
  line-height: 1.4;
  color: var(--danger);
  background: color-mix(in srgb, var(--danger-soft) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger-soft) 35%, transparent);
  border-radius: var(--r-sm);
  padding: 7px 10px;
}
.gen-gens-empty {
  padding: 24px 16px;
  font-size: var(--fs-12);
  font-style: italic;
  line-height: 1.5;
  color: var(--ink-muted);
  text-align: center;
}
.gen-gens-list {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.gen-gens-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 8px;
  border-radius: var(--r-panel);
  border: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  background: color-mix(in srgb, var(--cream) 55%, transparent);
}
.gen-gens-card.is-current {
  border-color: color-mix(in srgb, var(--gold-3) 95%, transparent);
  box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--gold-3) 30%, transparent), inset 0 0 6px color-mix(in srgb, var(--gold-3) 10%, transparent);
  background: color-mix(in srgb, var(--hi) 70%, transparent);
}
.gen-gens-thumb {
  position: relative;
  width: 100%;
  aspect-ratio: var(--project-aspect, 21 / 9);
  border-radius: var(--r-7);
  overflow: hidden;
  background: var(--parchment);
  cursor: zoom-in;
}
.gen-gens-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gen-gens-thumb-ph { display: block; width: 100%; height: 100%; }
.gen-gens-badge {
  position: absolute;
  top: 6px;
  font-size: var(--fs-9);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-08);
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 5px;
  pointer-events: none;
}
.gen-gens-badge--grid {
  left: 6px;
  background: color-mix(in srgb, var(--shade-23) 78%, transparent);
  color: color-mix(in srgb, var(--gold-10) 24%, var(--mix-light));
}
.gen-gens-badge--current {
  right: 6px;
  background: color-mix(in srgb, var(--gold-3) 95%, transparent);
  color: color-mix(in srgb, var(--ink-deep) 91%, var(--mix-dark));
}
/* v07zz570 — Grid indicator = a clean 2×2 grid ICON, no text (Hugo: "give me a
   nice big grid icon and no text"). Top-left overlay on any grid thumbnail /
   preview. Default = gallery / general; --lg = the big GENERATED PREVIEW; --sm =
   the 52px Panel recent thumb. */
.gen-grid-badge {
  position: absolute;
  top: 6px; left: 6px;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--shade-24) 72%, transparent);
  color: color-mix(in srgb, var(--gold-10) 24%, var(--mix-light));
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.30);
  pointer-events: none;
  z-index: 3;
}
.gen-grid-badge svg { width: 66%; height: 66%; display: block; }
.gen-grid-badge--lg { top: 12px; left: 12px; width: 46px; height: 46px; border-radius: var(--r-md); }
.gen-grid-badge--sm { top: 4px; left: 4px; width: 22px; height: 22px; border-radius: var(--r-xs); }
/* v07zz403 — per-card discard ✕, bottom-right of the thumbnail. Visible on card
   hover/focus (always visible on touch). Neutral → red on hover. */
.gen-gens-discard {
  position: absolute;
  bottom: 6px; right: 6px;
  width: 24px; height: 24px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  background: color-mix(in srgb, var(--mix-light) 82%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  display: grid; place-items: center;
  opacity: 0;
  transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-gens-card:hover .gen-gens-discard,
.gen-gens-card:focus-within .gen-gens-discard { opacity: 1; }
.gen-gens-discard:hover { background: color-mix(in srgb, var(--danger-soft) 14%, transparent); color: var(--danger); border-color: color-mix(in srgb, var(--danger-soft) 50%, transparent); }
/* v07zz461 — A/B compare button on a gallery gen card (bottom-LEFT, mirrors the discard ✕). */
.gen-gens-cmp {
  position: absolute;
  bottom: 6px; left: 6px;
  width: 24px; height: 24px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  background: color-mix(in srgb, var(--mix-light) 82%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; z-index: 2;
  transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-gens-card:hover .gen-gens-cmp,
.gen-gens-card:focus-within .gen-gens-cmp { opacity: 1; }
.gen-gens-cmp:hover { background: color-mix(in srgb, var(--gold-4) 16%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
/* v07zz470 — Reuse-prompt button on a gallery gen card (next to the compare button). */
.gen-gens-reuse {
  position: absolute;
  bottom: 6px; left: 36px;
  width: 24px; height: 24px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  background: color-mix(in srgb, var(--mix-light) 82%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; z-index: 2;
  transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-gens-card:hover .gen-gens-reuse,
.gen-gens-card:focus-within .gen-gens-reuse { opacity: 1; }
.gen-gens-reuse:hover { background: color-mix(in srgb, var(--gold-4) 16%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
/* v07zz471 — Use-as-reference (iterate) button on a gallery gen card (3rd in the bottom-left row). */
.gen-gens-useref {
  position: absolute;
  bottom: 6px; left: 66px;
  width: 24px; height: 24px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  background: color-mix(in srgb, var(--mix-light) 82%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; z-index: 2;
  transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-gens-card:hover .gen-gens-useref,
.gen-gens-card:focus-within .gen-gens-useref { opacity: 1; }
.gen-gens-useref:hover { background: color-mix(in srgb, var(--gold-4) 16%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
/* v07zz511 — Copy-prompt button on a gallery gen card (4th slot in the bottom-left row). */
.gen-gens-copy { left: 96px; }
/* v07zz595 — Depth-map button (5th slot in the bottom-left row). Same circle as its siblings. */
.gen-gens-depth {
  position: absolute;
  bottom: 6px; left: 126px;
  width: 24px; height: 24px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 82%, transparent);
  color: var(--ink-muted); cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; z-index: 2;
  transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-gens-card:hover .gen-gens-depth,
.gen-gens-card:focus-within .gen-gens-depth { opacity: 1; }
.gen-gens-depth:hover { background: color-mix(in srgb, var(--gold-4) 16%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
.gen-gens-copy.is-copied { opacity: 1; background: color-mix(in srgb, var(--ok) 90%, transparent); color: var(--white); border-color: color-mix(in srgb, color-mix(in srgb, var(--leaf) 84%, var(--mix-dark)) 90%, transparent); }
/* v07zz539 — Crop button on a gallery gen card (TOP-left corner, kept clear of the
   bottom action row). Non-grid cards only. Neutral → gold on hover, like the others. */
.gen-gens-crop {
  position: absolute;
  top: 6px; left: 6px;
  width: 24px; height: 24px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  background: color-mix(in srgb, var(--mix-light) 82%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; z-index: 2;
  transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-gens-card:hover .gen-gens-crop,
.gen-gens-card:focus-within .gen-gens-crop { opacity: 1; }
.gen-gens-crop:hover { background: color-mix(in srgb, var(--gold-4) 16%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
/* v07zz472 — Grid slicing Auto|Manual toggle (Mode card, grid/batch modes). */
.gen-slicemode-row { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
/* v07zz489 — Mode header row: "Mode" label left, Grid-slicing toggle right, on
   one line. min-height reserves the toggle's height so switching modes (which
   shows/hides the toggle) never shifts the mode buttons below. */
.gen-setting-labelrow { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 22px; margin-bottom: 4px; }
.gen-setting-labelrow .gen-setting-label { margin: 0; }
.gen-slicemode--brow { display: flex; align-items: center; gap: 8px; }
.gen-slicemode--brow .gen-slicemode-label { font-size: var(--fs-9-5); }
.gen-slicemode-label { font-size: var(--fs-10-5); font-weight: var(--fw-bold); letter-spacing: var(--track-05); text-transform: uppercase; color: var(--ink-muted); }
.gen-slicemode-btns { display: inline-flex; gap: 2px; background: color-mix(in srgb, var(--umber-2) 8%, transparent); border: 1px solid var(--card-border); border-radius: var(--r-round); padding: 2px; }
.gen-slicemode-btn {
  border: none; background: transparent; cursor: pointer;
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-bold); letter-spacing: var(--track-04);
  color: var(--ink-muted); padding: 3px 12px; border-radius: var(--r-round); line-height: 1.5;
  transition: background var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-slicemode-btn:hover { color: var(--ink); }
.gen-slicemode-btn.is-active { background: color-mix(in srgb, var(--amber) 85%, transparent); color: var(--ink-on-accent); }
/* v07zz471 — ARCHIVE-FOOTAGE placeholder rows in the shot picker: visible but dimmed +
   tagged (they're excluded from generation server-side). */
.gen-shot-row.is-archive-footage { opacity: 0.45; }
.gen-shot-row.is-archive-footage:hover { opacity: 0.7; }
.gen-shot-archtag {
  position: absolute; top: 4px; left: 4px; z-index: 2;
  font-size: var(--fs-8-5); font-weight: var(--fw-heavy); letter-spacing: var(--track-06);
  padding: 1px 6px; border-radius: var(--r-round);
  background: color-mix(in srgb, var(--shade-62) 72%, transparent); color: color-mix(in srgb, var(--white) 88%, transparent);
  pointer-events: none;
}
.gen-gens-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}
.gen-gens-label {
  font-size: var(--fs-12);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-03);
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gen-gens-model {
  font-size: var(--fs-10);
  color: var(--ink-muted);
  white-space: nowrap;
  flex-shrink: 0;
}
.gen-gens-act {
  font: inherit;
  font-size: var(--fs-12);
  font-weight: var(--fw-semi);
  padding: 8px 10px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  cursor: pointer;
  text-align: center;
  transition: filter var(--dur-1) ease, background var(--dur-1) ease;
}
.gen-gens-act:disabled { opacity: 0.5; cursor: default; }
.gen-gens-act--approve {
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--leaf-bright) 54%, var(--mix-light)) 95%, transparent), color-mix(in srgb, var(--pale-green) 90%, transparent));
  color: color-mix(in srgb, var(--leaf-bright) 32%, var(--mix-dark));
  border-color: color-mix(in srgb, var(--ok) 60%, transparent);
}
.gen-gens-act--approve:hover:not(:disabled) { filter: brightness(1.05); }
.gen-gens-act--promote {
  background: color-mix(in srgb, var(--cream) 80%, transparent);
  color: var(--ink);
  border-color: color-mix(in srgb, var(--card-border) 60%, transparent);
}
.gen-gens-act--promote:hover:not(:disabled) { background: color-mix(in srgb, color-mix(in srgb, var(--paper-2) 61%, var(--mix-light)) 95%, transparent); }
.gen-gens-act--promote.is-current {
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--gold-13) 46%, var(--mix-light)) 90%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-17) 75%, var(--mix-light)) 85%, transparent));
  color: color-mix(in srgb, var(--ink-tan-deep) 67%, var(--mix-dark));
  border-color: color-mix(in srgb, var(--gold-4) 60%, transparent);
}
/* v07zz440 — action row: Set-as-frame (flex) + compact re-render icon button.
   Fixed one-line height so toggling nothing shifts the card below. */
.gen-gens-actrow { display: flex; align-items: stretch; gap: 6px; flex-wrap: wrap; }
.gen-gens-actrow .gen-gens-act--promote,
.gen-gens-actrow .gen-gens-act--push { flex: 1 1 auto; min-width: 0; }
/* v07zz462 — "Push to shot": green + prominent when the gen is still a candidate; neutral
   "In shot ✓" once pushed. Only pushed frames appear in the shot modal's FRAMES strip. */
.gen-gens-act--push {
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--leaf-bright) 54%, var(--mix-light)) 95%, transparent), color-mix(in srgb, var(--pale-green) 90%, transparent));
  color: color-mix(in srgb, var(--leaf-bright) 32%, var(--mix-dark)); border-color: color-mix(in srgb, var(--ok) 60%, transparent);
}
.gen-gens-act--push:hover:not(:disabled) { filter: brightness(1.05); }
.gen-gens-act--push.is-pushed {
  background: color-mix(in srgb, var(--cream) 80%, transparent); color: var(--ink-muted); border-color: color-mix(in srgb, var(--card-border) 60%, transparent);
}
.gen-gens-act--restyle {
  flex: 0 0 auto;
  width: 34px;
  padding: 8px 0;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--cream) 80%, transparent);
  color: var(--ink-muted);
  border-color: color-mix(in srgb, var(--card-border) 60%, transparent);
}
.gen-gens-act--restyle:hover:not(:disabled) {
  background: linear-gradient(135deg, color-mix(in srgb, var(--blue-12) 90%, transparent), color-mix(in srgb, var(--blue-13) 85%, transparent));
  color: var(--ink-blue-7);
  border-color: color-mix(in srgb, var(--blue-6) 60%, transparent);
}
.gen-gens-restyle-spin {
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--blue-6) 35%, transparent);
  border-top-color: var(--blue-8);
  animation: gen-gens-restyle-spin 0.7s linear infinite;
}
@keyframes gen-gens-restyle-spin { to { transform: rotate(360deg); } }
/* v07zz440 — Gallery drawer tools-row re-render button: same base as the other
   .ga-preview-tools buttons, blue accent on hover so it reads as "re-render". */
.ga-preview-tools .ga-preview-tool--restyle:hover:not(:disabled) {
  background: color-mix(in srgb, var(--blue-6) 14%, transparent);
  color: var(--ink-blue-7);
  border-color: color-mix(in srgb, var(--blue-6) 50%, transparent);
}

/* ─── Gallery|Panel toggle (v07zz403) — segmented control in the drawer header.
   Lives in the (fixed-height) header so switching modes never shifts content. */
.gen-gens-modetoggle {
  margin-left: auto;
  flex-shrink: 0;
  display: inline-flex;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: color-mix(in srgb, var(--cream) 50%, transparent);
}
.gen-gens-modebtn {
  font: inherit;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-04);
  padding: 4px 9px;
  border: none;
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  transition: background var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-gens-modebtn + .gen-gens-modebtn { border-left: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent); }
.gen-gens-modebtn:hover { background: color-mix(in srgb, var(--hi-2) 70%, transparent); color: var(--ink); }
.gen-gens-modebtn.is-active {
  background: color-mix(in srgb, var(--leaf) 16%, transparent);
  color: var(--ink-forest-4);
}
/* Panel mode: the toggle sits in its own fixed-height header row above the
   GENERATED PREVIEW eyebrow (no layout shift). */
.gen-gens-toggle-row {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 10px;
}

/* At narrow widths the drawer drops below the builder (full width) rather than
   squeezing the 2-col content. Matches the .gen-row-2col collapse breakpoint. */
@media (max-width: 1100px) {
  .gen-shell--with-drawer {
    grid-template-columns: 300px minmax(0, 1fr);
  }
  .gen-gens-drawer.ga-preview.ga-drawer {
    grid-column: 1 / -1;
    max-height: 520px;
  }
  .gen-gens-drawer:not(.ga-preview) {
    grid-column: 1 / -1;
    max-height: 460px;
  }
  .gen-gens-list {
    flex-direction: row;
    flex-wrap: wrap;
  }
  .gen-gens-card { width: 220px; }
}
@media (max-width: 720px) {
  .gen-shell--with-drawer { grid-template-columns: 1fr; }
  .gen-gens-card { width: 100%; }
}
.gen-empty {
  padding: 60px 20px;
  text-align: center;
  color: var(--ink-muted);
  font-style: italic;
}

/* v06p — Slide-down panel animation was here; reverted on request
   (felt jittery, not what Hugo had in mind). Panels appear
   instantly again, like before. */

/* ─── Shot picker (left column) ─────────────────────────────────── */
.gen-shotpicker {
  display: flex;
  flex-direction: column;
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-card);
  overflow: hidden;
  min-height: 0;
}
.gen-shotpicker-head {
  padding: 14px 14px 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: linear-gradient(180deg, color-mix(in srgb, color-mix(in srgb, var(--gold-2) 26%, var(--mix-light)) 85%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-8) 31%, var(--mix-light)) 65%, transparent));
}
.gen-shotpicker-title {
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-18);
  text-transform: uppercase;
  color: var(--ink-muted);
}
/* v07zz86 — Shots ⟷ Assets switch reuses the global .tabs/.tab
   underline style (identical to the Shots/Sequences panel). This
   wrapper just adds a divider + bottom spacing inside the picker. */
.gen-picker-tabwrap {
  border-bottom: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  padding-bottom: 8px;
  margin-bottom: 2px;
}
.gen-shotpicker-search {
  width: 100%;
  font: inherit;
  font-size: var(--fs-12-5);
  padding: 6px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent);
  color: var(--ink);
}
.gen-shotpicker-search:focus {
  outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent);
  outline-offset: 1px;
}
.gen-shotpicker-count {
  font-size: var(--fs-10);
  color: var(--ink-muted);
  letter-spacing: var(--track-04);
}
.gen-shotpicker-list {
  flex: 1;
  overflow-y: auto;
  padding: 4px;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.gen-shotpicker-empty {
  padding: 20px 14px;
  font-size: var(--fs-12);
  font-style: italic;
  color: var(--ink-muted);
  text-align: center;
}
.gen-shot-row {
  /* v07zw — Bigger thumbs in the left drawer with the project's
     actual aspect ratio (21:9 for Paradise Found, set via the
     --project-aspect CSS token). Two-column grid: thumb fills
     most of the row + shot id on the right with bigger type. */
  display: grid;
  grid-template-columns: 170px minmax(0, 1fr);
  gap: 12px;
  align-items: center;
  padding: 6px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  cursor: pointer;
  font: inherit;
  text-align: left;
  width: 100%;
  transition: background var(--dur-0) ease, border-color var(--dur-0) ease;
}
.gen-shot-row:hover { background: color-mix(in srgb, var(--hi) 55%, transparent); }
.gen-shot-row.is-active {
  /* v07perf (round 4) — Hugo: "put a gold foil outline around the
     selected shot, this is a bit faint at the moment." Swapped the
     muted green tint for a punchier gold ring: solid 1.5px gold
     border + a soft outer glow + a subtle warm background tint. The
     row reads as "you're here" at a glance from anywhere in the
     drawer. */
  background: color-mix(in srgb, var(--gold-3) 14%, transparent);
  border-color: color-mix(in srgb, var(--gold-3) 95%, transparent);
  border-width: 1.5px;
  box-shadow:
    0 0 0 var(--hairline-w) color-mix(in srgb, var(--gold-3) 35%, transparent),
    0 0 12px color-mix(in srgb, var(--gold-3) 30%, transparent),
    inset 0 0 6px color-mix(in srgb, var(--gold-3) 12%, transparent);
}
.gen-shot-thumb {
  width: 170px;
  /* v07zw — Inherit the project aspect (21:9 for Paradise Found) so
     shot thumbs don't get letterboxed. Falls back to 21:9 when the
     token isn't set. */
  aspect-ratio: var(--project-aspect, 21 / 9);
  border-radius: 5px;
  background: color-mix(in srgb, color-mix(in srgb, var(--umber-4) 67%, var(--mix-dark)) 18%, transparent);
  background-size: cover;
  background-position: center;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  position: relative;   /* v07zz471 — anchors the ARCHIVE tag */
}
.gen-shot-thumb-glyph {
  font-size: var(--fs-18);
  color: color-mix(in srgb, color-mix(in srgb, var(--ink-umber-4) 67%, var(--mix-dark)) 40%, transparent);
}
.gen-shot-meta { min-width: 0; }
.gen-shot-id {
  /* v07zw — Bigger + heavier shot number now that it's the only
     text in the row. */
  font-size: var(--fs-15);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-04);
  color: var(--ink);
}
.gen-shot-title {
  font-size: var(--fs-11);
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ─── Builder (right column) ────────────────────────────────────── */
.gen-builder {
  display: flex;
  flex-direction: column;
  /* v06j — Tighter gap so more fits above the fold. */
  gap: 10px;
  min-height: 0;
  min-width: 0;
  overflow-y: auto;
  /* v06n — `scrollbar-gutter: stable` reserves the scrollbar width
     ALWAYS, whether or not there's actual overflow. Otherwise modes
     with shorter content (Single Image, Upscale) have no scrollbar
     and end up wider than modes with overflow (Grid) — causing the
     References panel + everything else to shift left/right when
     toggling between sub-modes. */
  scrollbar-gutter: stable;
  /* v06c — Padding lives here (not on .gen-shell) so the builder
     gets its top breathing room but the shot picker still reaches
     all the way up. */
  padding: 14px 6px 0 0;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
  position: relative;  /* anchor for sticky footer */
}
.gen-header {
  padding: 4px 4px 8px;
  border-bottom: 1px solid color-mix(in srgb, var(--card-border) 35%, transparent);
}
.gen-eyebrow {
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-18);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 4px;
}
.gen-title {
  font-family: var(--font-display, "Bebas Neue"), sans-serif;
  font-size: var(--fs-32);
  letter-spacing: var(--track-005);
  color: var(--ink);
  margin: 0;
  line-height: 1.05;
}
.gen-subtitle {
  font-size: var(--fs-11-5);
  color: var(--ink-muted);
  letter-spacing: var(--track-04);
  margin-top: 4px;
  text-transform: uppercase;
}

.gen-section {
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-md);
  padding: 10px 12px;
}

/* v07zz374 — Camera & Style preset chips (Generate page, frame + video). Single-
   select pills; the active one fills green and weaves a [Style …] clause into the
   prompt. */
.gen-camstyle { margin-bottom: 10px; }
.gen-camstyle-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 8px; }
/* v07zz377 — match the REFERENCES tab pills (.gen-refs-tab): uppercase, small,
   cream outline with a tan/gold active fill (was a green pill that didn't match). */
.gen-camstyle-chip {
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-semi); letter-spacing: var(--track-04);
  text-transform: uppercase; line-height: 1.1;
  color: var(--ink-muted); background: color-mix(in srgb, var(--cream) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-round); padding: 5px 9px; cursor: pointer; white-space: nowrap;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-camstyle-chip:hover { color: var(--ink); }
.gen-camstyle-chip.is-active {
  background: linear-gradient(180deg, color-mix(in srgb, var(--nav-active) 65%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold) 75%, var(--mix-light)) 55%, transparent));
  border-color: color-mix(in srgb, var(--gold-9) 65%, transparent); color: var(--ink);
}
/* v07zz528 — camera-MOVEMENT preset DROPDOWN (video Camera movement box). Replaced the pill
   wall Hugo hated. Compact select between the label and the textarea; picking a move appends
   its phrase to the box. */
.gen-cammove-select {
  font: inherit; font-size: var(--fs-11); font-weight: var(--fw-semi); letter-spacing: var(--track-02);
  color: var(--ink-muted); background: color-mix(in srgb, var(--cream) 75%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-7); padding: 5px 26px 5px 9px; margin: 6px 0 8px;
  width: 100%; cursor: pointer; appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%238a7b53' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center;
  transition: border-color var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-cammove-select:hover { border-color: color-mix(in srgb, var(--gold-9) 70%, transparent); color: var(--ink); }
.gen-cammove-select:focus { outline: none; border-color: color-mix(in srgb, var(--gold-9) 85%, transparent); }
/* v07zz377 — toggle for the "Blue chip cinematic color grading …" prompt line.
   Same pill family; a filled dot indicates the line is included. */
.gen-camstyle-grade {
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-semi); letter-spacing: var(--track-04);
  text-transform: uppercase; line-height: 1.1; margin-top: 8px;
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--ink-muted); background: color-mix(in srgb, var(--cream) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-round); padding: 5px 11px 5px 8px; cursor: pointer; white-space: nowrap;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-camstyle-grade:hover { color: var(--ink); }
.gen-camstyle-grade .gen-camstyle-grade-dot {
  width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid color-mix(in srgb, var(--gold-9) 55%, transparent); background: transparent;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-camstyle-grade.is-on {
  background: linear-gradient(180deg, color-mix(in srgb, var(--nav-active) 65%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold) 75%, var(--mix-light)) 55%, transparent));
  border-color: color-mix(in srgb, var(--gold-9) 65%, transparent); color: var(--ink);
}
.gen-camstyle-grade.is-on .gen-camstyle-grade-dot {
  background: color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 93%, var(--mix-light)) 90%, transparent); border-color: color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 93%, var(--mix-light)) 90%, transparent);
}
/* v06k — Reference / Source-frame sections lock to a fixed total
   height (including the tabs row + grid + "Show more" footer
   button). This removes ALL jitter when:
   – switching tabs (Archival 137 items → Characters 5 items)
   – switching shots (frame counts vary)
   – the pagination "Show 40 more" button appears or disappears
   The grid inside flex-fills the remaining space and scrolls
   internally. */
.gen-section--refs {
  /* v07zz386 — fill the (now stretched) column instead of a fixed 380px, so the
     refs panel matches the right column's height. min-height keeps it from
     collapsing if the right column is ever shorter. */
  flex: 1 1 auto;
  min-height: 380px;
  display: flex;
  flex-direction: column;
}
.gen-section--refs .gen-section-head,
.gen-section--refs .gen-section-sub,
.gen-section--refs .gen-refs-tabs,
.gen-section--refs .gen-refs-upload-row,
.gen-section--refs .gen-refs-loadmore,
.gen-section--refs .gen-refs-selected-bar {
  flex-shrink: 0;
}
.gen-section--refs .gen-refs-grid {
  flex: 1 1 0;
  min-height: 0;
}

/* v06m — Selected-refs footer inside .gen-section--refs. Fixed height
   so picking / unpicking refs never changes the section's outer size.
   Empty state shows a muted hint. */
.gen-refs-selected-bar {
  margin-top: 8px;
  /* v07zz384 — vertical padding + taller min-height so the chips (and the Swap
     source chip's green glow + SRC badge) are never clipped by overflow-y: hidden.
     overflow-y must stay non-visible because overflow-x: auto needs the pair. */
  padding: 9px 2px 11px 0;
  border-top: 1px dashed color-mix(in srgb, var(--card-border) 45%, transparent);
  min-height: 52px;
  display: flex;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.gen-refs-selected-empty {
  font-size: var(--fs-10-5);
  font-style: italic;
  letter-spacing: var(--track-04);
  color: var(--ink-muted);
}
.gen-refs-selected-chips {
  display: flex;
  gap: 6px;
  flex-wrap: nowrap;
}
/* v06l — Right-column sections (Direction / Video inputs / Upscale)
   match the References / Source Frame panel height so the 2-column
   row stays balanced regardless of mode. Internal textareas flex to
   fill so there's never dead space. */
.gen-section--match-refs {
  height: 380px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* v06p — VO mode needs more vertical room: the Voice + Settings
   panel holds Character avatars + Voice + Model + up to three
   v2 sliders (Stability + Similarity + Style). Bump the height
   on both left + right cards in VO mode so they stay matched and
   nothing gets clipped. The `.gen-row-2col--vo` modifier is
   applied to the 2-col row when in VO mode. */
.gen-row-2col--vo .gen-section--match-refs {
  /* v07zz552 — Hugo: "the panel is too short and it's cropping the settings." The fixed
     460px + overflow:hidden clipped the Model row once the character grid wrapped to
     several rows. Keep 460 as the reserved FLOOR (so model/voice toggles never shift
     the rows below — invariant #20) but let the card GROW when the content needs it. */
  height: auto;
  min-height: 460px;
}
.gen-section--match-refs .gen-section-head,
.gen-section--match-refs .gen-section-sub,
.gen-section--match-refs .gen-upscale-actions,
.gen-section--match-refs .gen-upscale-advanced-toggle {
  flex-shrink: 0;
}
.gen-section--match-refs .gen-video-inputs--compact {
  flex: 1 1 0;
  min-height: 0;
}
.gen-section--match-refs .gen-video-inputs--compact .gen-direction {
  flex: 1 1 0;
  min-height: 0;
  resize: none;
}
.gen-section--match-refs .gen-video-inputs--compact .gen-video-field {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
/* v07zz412 — Direction panel: Direction | Latest edit tabs + reserved body. The panel
   itself is a fixed 380px (.gen-section--match-refs) so swapping tabs never shifts the
   MODE/MODEL row below it; the body just flexes to fill. */
.gen-section--match-refs .gen-dir-head {
  display: flex; gap: 16px; align-items: baseline; flex-shrink: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--card-border) 40%, transparent); margin-bottom: 12px;
}
.gen-dir-tab {
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-bold); letter-spacing: var(--track-16); text-transform: uppercase;
  color: color-mix(in srgb, var(--ink-muted) 45%, transparent); background: none; border: none; padding: 0 0 8px; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color var(--dur-1) ease;
}
.gen-dir-tab:hover { color: color-mix(in srgb, var(--ink-muted) 75%, transparent); }
.gen-dir-tab.is-on { color: var(--ink, var(--ink-3)); border-bottom-color: var(--accent, color-mix(in srgb, var(--moss) 81%, var(--mix-light))); }
.gen-section--match-refs .gen-dir-tabbody { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.gen-dir-editwrap { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
.gen-dir-video {
  width: 100%; flex: 1 1 0; min-height: 0;
  background: var(--ied-bg-6); border-radius: var(--r-sm); object-fit: contain;
  border: 1px solid color-mix(in srgb, var(--card-border) 35%, transparent);
}
.gen-dir-edit-title {
  font-size: var(--fs-11); color: color-mix(in srgb, var(--ink-muted) 72%, transparent); flex-shrink: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gen-dir-edit-msg {
  flex: 1 1 0; display: flex; align-items: center; justify-content: center;
  color: color-mix(in srgb, var(--ink-muted) 50%, transparent); font-size: var(--fs-12); font-style: italic;
}
/* v07zz492 — shot-gen edit player: the stage is 16:9 (matches the edit's own aspect) with
   object-fit:contain so the video is NEVER cropped top/bottom (the old 21:9 cover clipped
   the top/bottom of every 16:9 edit). The transport bar is an OVERLAY across the bottom of
   the video (over a dark scrim), so it costs zero extra vertical space. The right column is
   fixed-width ("never shrink References" — see .gen-row-2col), so the 16:9 frame is width-
   bound: it fills the column width and centres vertically in the panel. */
.gen-edit-player { flex: 1 1 auto; min-height: 0; gap: 6px; display: flex; align-items: center; justify-content: center; container-type: size; }
/* v07zz503 — the stage must be EXACTLY 16:9 in BOTH regimes. The old width:100% +
   max-height pair let flexbox squeeze the stage's height when the panel was tight while
   the width stayed full, so the box went ~2.1:1 and the (object-fit:cover) poster cropped
   the burn-ins. Fix: the column is a size container; the stage width is the SMALLEST of
   (a) full column width, (b) the 336px-tall cap, (c) what fits the column height minus the
   30px transport bar+gap — and the height always follows from aspect-ratio. */
.gen-edit-player .review-stage {
  flex: 0 0 auto;
  width: min(100%, calc(336px * 16 / 9), calc((100cqh - 30px) * 16 / 9));
  aspect-ratio: 16 / 9;
  margin: 0 auto;
}
.gen-edit-player .review-video { object-fit: contain; background: var(--ied-bg-6); }
.gen-edit-player .review-stage-play, .gen-edit-play { width: 46px; height: 46px; }
.gen-edit-play svg { width: 20px; height: 20px; }
/* v07zz503 — transport bar BELOW the 16:9 stage (an overlay covered the shot-number
   burn-ins along the bottom of the edit). Capped to the stage's max-width so the bar's
   edges line up with the video's. */
.gen-editbar { display: flex; align-items: center; gap: 8px; padding: 0 2px; width: 100%; margin: 0 auto; }
/* Bar width mirrors the stage's three-way min() so its edges always line up with the video. */
.gen-edit-player .gen-editbar { flex: 0 0 auto; width: min(100%, calc(336px * 16 / 9), calc((100cqh - 30px) * 16 / 9)); }
.gen-editbar-btn {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: var(--r-xs); padding: 0;
  display: grid; place-items: center; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--card-border) 55%, transparent); background: color-mix(in srgb, var(--cream) 72%, transparent); color: var(--ink);
}
.gen-editbar-btn:hover { background: color-mix(in srgb, var(--leaf) 18%, transparent); }
.gen-editbar-tc {
  flex: 0 0 auto; font-family: var(--font-mono, monospace); font-size: var(--fs-10); font-weight: var(--fw-semi);
  color: var(--ink-muted); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.gen-editbar-scrub { flex: 1 1 auto; min-width: 0; height: 14px; position: relative; display: flex; align-items: center; cursor: pointer; }
.gen-editbar-scrub::before {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
  height: 4px; border-radius: var(--r-round); background: color-mix(in srgb, var(--tan-deep) 22%, transparent);
}
.gen-editbar-scrub-fill {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  height: 4px; max-width: 100%; border-radius: var(--r-round);
  background: linear-gradient(90deg, color-mix(in srgb, var(--leaf) 95%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-5) 86%, var(--mix-light)) 90%, transparent));
}
.gen-editbar-scrub.is-scrubbing .gen-editbar-scrub-fill { background: linear-gradient(90deg, var(--leaf), color-mix(in srgb, var(--gold-17) 87%, var(--mix-light))); }
/* Compact edit picker row above the player. */
.gen-edit-pickrow { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.gen-edit-picklabel { font-size: var(--fs-9); font-weight: var(--fw-bold); letter-spacing: var(--track-08); color: var(--ink-muted); flex-shrink: 0; }
.gen-edit-select {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: var(--fs-11);
  padding: 3px 6px; border-radius: var(--r-xs);
  border: 1px solid color-mix(in srgb, var(--card-border) 55%, transparent); background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink);
  cursor: pointer;
}
/* v07zz449 — edit picker sitting inline with the DIRECTION / LATEST EDIT tabs (right-aligned),
   so it no longer eats a body row that would clip the transport bar under the 21:9 stage. */
.gen-edit-select--inline {
  flex: 0 1 auto; width: auto; max-width: 58%;
  margin-left: auto; align-self: center; margin-bottom: 6px;
  font-size: var(--fs-10-5); padding: 3px 8px;
}
.gen-section-head {
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-16);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.gen-section-head--toggle {
  cursor: pointer;
  background: transparent;
  border: none;
  padding: 0;
  width: 100%;
  font: inherit;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-16);
  text-transform: uppercase;
  color: var(--ink-muted);
  justify-content: space-between;
  margin-bottom: 0;
}
.gen-section-head--toggle:hover { color: var(--ink); }
.gen-section-head-chev { font-size: var(--fs-12); }

/* v06b — Mode toggle (Grid vs Single image). Sits at the very top of
   the builder, two big chunky buttons. The active mode gets a leaf-
   green border + soft tint, mirroring the .gen-model-btn.is-active
   styling so the page feels consistent. */
.gen-mode-row {
  display: grid;
  /* v06o — Three top-level tabs now (Image / Video / Voice Over). */
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
}
@media (max-width: 900px) {
  .gen-mode-row { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 600px) {
  .gen-mode-row { grid-template-columns: 1fr; }
}

/* v06h — Image sub-toggle (Grid / Single / Upscale). Renders below the
   top-level Image tab when Image is active. Smaller pill buttons —
   secondary to the big Image/Video decision above. */
.gen-submode-row {
  display: flex;
  gap: 6px;
  padding: 4px 4px 0;
}
.gen-submode-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font: inherit;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-04);
  border-radius: var(--r-round);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 55%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-submode-btn:hover { background: color-mix(in srgb, var(--cream) 95%, transparent); color: var(--ink); }
.gen-submode-btn.is-active {
  background: linear-gradient(180deg, color-mix(in srgb, var(--leaf) 20%, transparent), color-mix(in srgb, var(--olive-2) 16%, transparent));
  border-color: color-mix(in srgb, var(--leaf) 65%, transparent);
  color: var(--ink);
  box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 30%, transparent);
}
.gen-submode-glyph { display: inline-grid; place-items: center; }
.gen-mode-btn {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  font: inherit;
  border-radius: var(--r-md);
  border: 1.5px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 65%, transparent);
  color: var(--ink);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--dur-1) ease, background var(--dur-1) ease, transform var(--dur-1) ease;
}
.gen-mode-btn:hover { background: color-mix(in srgb, var(--cream) 95%, transparent); }
.gen-mode-btn.is-active {
  border-color: color-mix(in srgb, var(--leaf) 75%, transparent);
  background: color-mix(in srgb, var(--leaf) 14%, transparent);
  box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 35%, transparent);
}
.gen-mode-icon {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  color: var(--ink);
}
.gen-mode-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.gen-mode-title {
  font-size: var(--fs-13-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-02);
}
.gen-mode-sub {
  font-size: var(--fs-10-5);
  color: var(--ink-muted);
  letter-spacing: var(--track-02);
  line-height: 1.3;
}

/* Section sub-text — small italic helper line under a section head. */
.gen-section-sub {
  font-size: var(--fs-11-5);
  color: var(--ink-muted);
  font-style: italic;
  line-height: 1.4;
  margin: -4px 0 10px;
}

/* v06b — Per-quadrant grid input. 2×2 grid of textareas matching the
   spatial layout of the final image grid (so Frame 1 = top-left, etc).
   Each cell has a numbered label + position tag. */
.gen-quad-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
/* v776 — 3×3 grids show their 9 panel boxes in three columns, mirroring the sheet. */
.gen-quad-grid--3 { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 720px) {
  .gen-quad-grid, .gen-quad-grid--3 { grid-template-columns: 1fr; }
}
.gen-quad-cell {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  border-radius: var(--r-panel);
  border: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  background: color-mix(in srgb, var(--cream) 55%, transparent);
}
.gen-quad-label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: var(--fs-10-5);
  letter-spacing: var(--track-10);
  text-transform: uppercase;
}
.gen-quad-num {
  font-weight: var(--fw-bold);
  color: var(--ink);
}
.gen-quad-pos {
  font-weight: var(--fw-semi);
  color: var(--ink-muted);
}
.gen-quad-input {
  width: 100%;
  font: inherit;
  font-size: var(--fs-12-5);
  line-height: 1.4;
  padding: 8px 10px;
  border-radius: var(--r-xs);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent);
  color: var(--ink);
  resize: vertical;
  min-height: 70px;
}
.gen-quad-input:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }

/* v06d/v06j — Video inputs default layout is column-stacked (used
   inside the upscale panel). The .gen-video-inputs--compact variant
   used inside the right column of the 2-col layout switches to a
   2x2 grid so the 4 fields fit in the same vertical space as the
   refs panel on the left. */
.gen-video-inputs {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.gen-video-inputs--compact {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
/* v06k/v06l — "Overall direction" is 3 ROWS stacked vertically. The
   parent section is locked at the same height as the References /
   Source Frame panel (380px) so the right column never has dead
   space below it. The 3 textareas flex-fill the available vertical
   space, splitting it ~equally. */
.gen-dir-3col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1;
  min-height: 0;
}
.gen-dir-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1 1 0;
  min-height: 0;
}
.gen-dir-cell textarea {
  flex: 1 1 0;
  min-height: 0;
  resize: none;
}
/* v07zz550 — tiny "overrides shotlist" hint on the Direction labels whose box
   REPLACES an auto shotlist-derived prompt line when filled. */
.gen-dir-ovr {
  font-size: var(--fs-8-5); font-weight: var(--fw-semi); letter-spacing: var(--track-06); text-transform: uppercase;
  opacity: .48; margin-left: 6px;
}
.gen-video-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.gen-video-label {
  font-size: var(--fs-10);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-10);
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* v06j — 2-column row: references / source-frames on the left,
   direction or mode-specific inputs on the right. Aligns at top so
   short content (the textarea on the right) doesn't get stretched
   to match the taller refs panel on the left. */
.gen-row-2col {
  display: grid;
  /* v07zz400 — the Generations drawer takes width off the builder, so the
     right column (Direction / Composition / Subject) is SQUISHED (0.8fr) while
     the References panel (left) KEEPS / gains room (1.2fr) — Hugo's rule: never
     shrink References. Reverts to 1:1 below 1100px where the drawer drops away. */
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  gap: 12px;
  /* v07zz386 — stretch so the References panel (left) grows to the height of the
     right column (Camera & Style + Direction), killing the dead space under refs.
     The right column's own sections are fixed-height so they never over-stretch. */
  align-items: stretch;
}
.gen-col { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* v07zz461 — Upscale: three EQUAL columns (Source Frame | References | Upscale prompt). */
.gen-row-2col.gen-row--up3 { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); }
@media (max-width: 1100px) {
  .gen-row-2col { grid-template-columns: 1fr; }
  .gen-row-2col.gen-row--up3 { grid-template-columns: 1fr; }
}

/* v06p — Duration slider. Value chip now reads at 18px (Bebas Neue
   is condensed so 14 felt tiny), and the 3 / 9 / 15 second ticks
   are visible under the slider again. */
.gen-setting--duration .gen-setting-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
.gen-duration-value {
  font-family: var(--font-display, "Bebas Neue"), sans-serif;
  font-size: var(--fs-18);
  letter-spacing: var(--track-04);
  color: var(--ink);
  text-transform: none;
}
.gen-duration-slider {
  width: 100%;
  margin: 6px 0 0;
  accent-color: var(--olive-7);
}
.gen-duration-ticks {
  display: flex;
  justify-content: space-between;
  margin-top: 2px;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-med);
  color: var(--ink-muted);
  letter-spacing: var(--track-04);
}
.gen-duration-ticks span {
  flex: 0 0 auto;
}

/* Shot context card.
   v06e — Always renders 3 rows so the card has a stable height. The
   surrounding panels (References / Direction / Settings) no longer
   jump up and down when Hugo switches between shots with different
   amounts of shotlist data. Missing fields show "—" instead of
   collapsing the row. */
.gen-context-card {
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-md);
  padding: 10px 12px;
}
.gen-context-grid {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.gen-context-row {
  display: grid;
  grid-template-columns: 90px minmax(0, 1fr);
  gap: 10px;
  align-items: baseline;
  padding: 3px 0;
  /* v06j — Compact + still-stable: fixed min-height keeps the card
     the same shape across shots whether values are present or "—". */
  min-height: 18px;
  border-bottom: 1px dashed color-mix(in srgb, var(--card-border) 30%, transparent);
}
.gen-context-row:last-child { border-bottom: none; }
.gen-context-value--empty {
  color: var(--ink-soft, color-mix(in srgb, color-mix(in srgb, var(--ink-umber-4) 67%, var(--mix-dark)) 45%, transparent));
  font-style: italic;
}
.gen-context-label {
  font-size: var(--fs-10);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-10);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.gen-context-value {
  font-size: var(--fs-13);
  color: var(--ink);
  line-height: 1.4;
}
/* v07zz390 — editable per-quadrant ACTION in the Combined Grid frame cards. */
.gen-context-action-edit {
  width: 100%; box-sizing: border-box;
  font: inherit; font-size: var(--fs-13); line-height: 1.4; color: var(--ink);
  background: color-mix(in srgb, var(--cream) 90%, transparent);
  border: 1px solid var(--card-border); border-radius: 5px;
  padding: 5px 7px; resize: vertical; min-height: 38px;
}
.gen-context-action-edit:focus { outline: none; border-color: var(--tan, color-mix(in srgb, var(--gold-7) 54%, var(--mix-light))); background: var(--cream-12); }
.gen-context-empty {
  font-size: var(--fs-12);
  font-style: italic;
  color: var(--ink-muted);
  text-align: center;
  padding: 10px;
}

/* References picker */
.gen-refs-tabs {
  display: flex;
  gap: 4px;
  align-items: center;
  margin-bottom: 8px;
  /* v07zz59 — Hugo: "i dont want a stupid scroll bar, i want a drag
     scroll behaviour". Hidden scrollbar entirely; the row scrolls
     horizontally via mouse drag (wired in GeneratePage.jsx with
     pointer events on the container, mirroring useDragScroll). */
  flex-wrap: nowrap;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
  user-select: none;
  padding-right: 4px;
}
.gen-refs-tabs::-webkit-scrollbar { display: none; }
.gen-refs-tabs.is-dragging { cursor: grabbing; }
.gen-refs-tabs.is-dragging .gen-refs-tab { pointer-events: none; }
.gen-refs-tab {
  font: inherit;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-04);
  text-transform: uppercase;
  padding: 5px 9px;
  border-radius: var(--r-round);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 65%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}
.gen-refs-tab:hover { color: var(--ink); }
.gen-refs-tab.is-active {
  background: linear-gradient(180deg, color-mix(in srgb, var(--nav-active) 65%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold) 75%, var(--mix-light)) 55%, transparent));
  border-color: color-mix(in srgb, var(--gold-9) 65%, transparent);
  color: var(--ink);
}
.gen-refs-search {
  margin-left: auto;
  font: inherit;
  font-size: var(--fs-11-5);
  padding: 5px 8px;
  border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent);
  color: var(--ink);
  /* v06m — Search shrinks first when there's no room for both tabs +
     a wide search field. Tabs always stay legible. */
  min-width: 60px;
  flex-shrink: 1;
  min-width: 0;
}
.gen-refs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 160px));
  gap: 8px;
  /* v06k — Flexible inside a fixed-height section. The grid now
     flex-fills so the "Show more" button below it doesn't add to
     the section's total height. */
  flex: 1;
  min-height: 0;
  align-content: start;
  overflow-y: auto;
  padding: 2px;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.gen-refs-grid--source {
  /* Source-frame grid: same flex-fill behaviour. The fixed height is
     enforced by the parent .gen-section--refs. */
}
/* v07zz494 — "pick one quadrant & upscale": the grid-quadrant section under the source
   frames. Sub-label gets a little breathing room; each tile shows a cropped quadrant. */
.gen-src-quad-sub { margin-top: 10px; padding-top: 8px; border-top: 1px dashed color-mix(in srgb, var(--card-border) 40%, transparent); }
/* v07zz523 — "show all frames" pill under the source-frame grid: reveals WIP candidates. */
.gen-src-morepill {
  align-self: flex-start;
  margin-top: 10px;
  padding: 5px 12px;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-02);
  color: var(--ink-soft, var(--ink-taupe-3));
  background: color-mix(in srgb, var(--card-border) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  border-radius: var(--r-round);
  cursor: pointer;
  transition: background var(--dur-2) ease, border-color var(--dur-2) ease, color var(--dur-2) ease;
}
.gen-src-morepill:hover { background: color-mix(in srgb, var(--card-border) 26%, transparent); border-color: color-mix(in srgb, var(--card-border) 70%, transparent); color: var(--ink, var(--ink-umber)); }
.gen-ref-tile--quad .gen-ref-tile-img { background-repeat: no-repeat; }
.gen-refs-empty {
  grid-column: 1 / -1;
  text-align: center;
  font-size: var(--fs-12);
  font-style: italic;
  color: var(--ink-muted);
  padding: 20px;
}
.gen-refs-overflow {
  margin-top: 6px;
  font-size: var(--fs-11);
  color: var(--ink-muted);
  font-style: italic;
  text-align: center;
}
/* v06b — Load-more button under the ref grid. Replaces the old
   silent overflow text — now Hugo can actually load the rest of the
   archival batch instead of being told to refine the filter. */
.gen-refs-loadmore {
  margin-top: 8px;
  width: 100%;
  font: inherit;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-06);
  text-transform: uppercase;
  padding: 8px 14px;
  border-radius: var(--r-sm);
  border: 1px dashed var(--card-border);
  background: color-mix(in srgb, var(--cream) 45%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  transition: background var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-refs-loadmore:hover {
  background: color-mix(in srgb, var(--cream) 85%, transparent);
  color: var(--ink);
}

/* v06b — External-refs upload row. Single button + inline error msg. */
.gen-refs-upload-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.gen-refs-upload-btn {
  font: inherit;
  font-size: var(--fs-12);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-04);
  padding: 8px 14px;
  border-radius: var(--r-round);
  border: 1px solid color-mix(in srgb, var(--leaf) 55%, transparent);
  background: color-mix(in srgb, var(--leaf) 12%, transparent);
  color: var(--ink);
  cursor: pointer;
}
.gen-refs-upload-btn:hover:not(:disabled) {
  background: color-mix(in srgb, var(--leaf) 22%, transparent);
  border-color: color-mix(in srgb, var(--leaf) 75%, transparent);
}
.gen-refs-upload-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
/* v07zz296 — "Reload last setup" button (This Shot tab). */
.gen-refs-reload-row { display: flex; align-items: center; margin-bottom: 10px; }
.gen-refs-reload-btn {
  font: inherit; font-size: var(--fs-12); font-weight: var(--fw-bold); letter-spacing: var(--track-03);
  padding: 8px 14px; border-radius: var(--r-round);
  border: 1px solid color-mix(in srgb, var(--leaf) 55%, transparent);
  background: color-mix(in srgb, var(--leaf) 14%, transparent); color: var(--ink); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.gen-refs-reload-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 24%, transparent); border-color: color-mix(in srgb, var(--leaf) 80%, transparent); }
.gen-refs-reload-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.gen-refs-upload-err {
  font-size: var(--fs-11-5);
  color: var(--danger-ink);
  font-style: italic;
}
.gen-ref-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px;
  border: 2px solid transparent;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--cream) 45%, transparent);
  cursor: pointer;
  font: inherit;
  text-align: left;
  transition: border-color var(--dur-0) ease, background var(--dur-0) ease, transform var(--dur-1) ease;
  /* v808 — the tile is draggable now (drag the full-res file straight out without
     attaching it first), so kill text selection: a drag that starts on the label
     would otherwise drag selected TEXT instead of the image. */
  user-select: none;
  -webkit-user-select: none;
}
.gen-ref-tile:hover { transform: translateY(-1px); background: color-mix(in srgb, var(--cream) 85%, transparent); }
.gen-ref-tile.is-selected {
  border-color: color-mix(in srgb, var(--leaf) 75%, transparent);
  background: color-mix(in srgb, var(--leaf) 12%, transparent);
}
.gen-ref-tile-img {
  width: 100%;
  /* v06b — Aspect ratio driven by the parent .gen-refs-grid's
     --gen-tile-aspect CSS variable. Characters use 3/4 (matches the
     Assets page); everything else stays 16/9 cinema crop. */
  aspect-ratio: var(--gen-tile-aspect, 16 / 9);
  border-radius: 5px;
  /* v07zz212 — solid cream placeholder so a loading reference reveals onto the
     panel, not a dark flash. */
  background-color: color-mix(in srgb, var(--paper) 97%, var(--mix-dark));
  background-size: cover;
  background-position: center top;
  /* v07zw — Centred initials inside when the asset has no image. */
  display: grid;
  place-items: center;
}
/* v07zz348 — reference thumb fade. On a COLD load the thumb starts hidden and fades in over
   the gradient/initials placeholder (320ms, matching the shot-modal hero + frames strip).
   A thumb already loaded this session gets .gen-ref-img--warm = instant, no fade, so a cached
   tab-switch-back never re-fades. */
.gen-ref-tile-img .gen-ref-img { opacity: 0; }
.gen-ref-tile-img .gen-ref-img.gen-ref-img--loaded { animation: genRefFadeIn var(--dur-6) ease-out forwards; }
.gen-ref-tile-img .gen-ref-img.gen-ref-img--warm { opacity: 1; animation: none; }
@keyframes genRefFadeIn { from { opacity: 0; } to { opacity: 1; } }
.gen-ref-tile-label {
  font-size: var(--fs-10-5);
  color: var(--ink);
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* v833 — 📁 move-to-section on a This Shot tile. Hugo: "the Move button i wanted was on
   those images there" — this is where he spots a 3D render or depth pass sitting in the
   Hero row. Absolutely positioned and hover-revealed, never in flow: an in-flow button
   would change the tile's height and collapse the grid row (the v-recent-gen lesson).
   Sits TOP-LEFT so it can't fight the selected-✓ badge in the top-right. */
.gen-ref-move {
  position: absolute;
  top: 6px;
  left: 6px;
  width: 22px;
  height: 22px;
  border-radius: var(--r-xs);
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--shade-25) 72%, transparent);
  color: var(--ink-cream);
  opacity: 0;
  transition: opacity var(--dur-1) ease, background var(--dur-1) ease;
  cursor: pointer;
  z-index: 3;
}
.gen-ref-tile:hover .gen-ref-move,
.gen-ref-move:focus-visible { opacity: 1; }
.gen-ref-move:hover { background: color-mix(in srgb, var(--leaf) 92%, transparent); }
.gen-ref-tile-check {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--leaf) 85%, transparent);
  color: var(--ink-cream);
  display: grid;
  place-items: center;
  font-size: var(--fs-13);
  font-weight: var(--fw-bold);
  box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--olive-2) 85%, transparent), 0 1px 4px color-mix(in srgb, var(--surface-forest) 30%, transparent);
}

/* Selected-refs chips row */
.gen-refs-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px 0;
}
/* v07zz209 — locked reference chips + ready-to-generate confirm backdrop */
.gen-ref-chip--locked { background: linear-gradient(180deg, color-mix(in srgb, var(--purple-2) 30%, transparent), color-mix(in srgb, var(--purple-3) 22%, transparent)); border-color: color-mix(in srgb, var(--purple) 55%, transparent); }
.gen-ref-chip-lock { font-size: var(--fs-10); line-height: 1; flex: 0 0 auto; }
.gen-readygate-backdrop { position: fixed; inset: 0; z-index: var(--z-dialog); display: grid; place-items: center; background: color-mix(in srgb, var(--shade-26) 55%, transparent); padding: 20px; }
.gen-ref-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 4px 4px 6px;
  border-radius: var(--r-round);
  background: linear-gradient(180deg, color-mix(in srgb, var(--nav-active) 45%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold) 75%, var(--mix-light)) 35%, transparent));
  border: 1px solid color-mix(in srgb, var(--gold-9) 55%, transparent);
  font-size: var(--fs-11);
  color: var(--ink);
  max-width: 280px;
}
.gen-ref-chip-thumb {
  display: inline-block;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background-size: cover;
  background-position: center;
  flex-shrink: 0;
}
/* v07zz588 — chip thumb is now a real full-res <img> (draggable into other sites). */
img.gen-ref-chip-thumb { object-fit: cover; cursor: grab; -webkit-user-drag: element; }
img.gen-ref-chip-thumb:active { cursor: grabbing; }
.gen-ref-chip-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* v07zz5 — Allow the label to shrink inside the flex chip so it
     ellipsises instead of overflowing into the × button when the
     ref name is long (e.g. "Brazil EP4 · T0010_Brazil_A Natural
     History_EP4_Par"). max-width caps the chip itself so it never
     pushes the chip row off-screen on narrow viewports. */
  min-width: 0;
  flex: 1 1 auto;
  max-width: 200px;
}
.gen-ref-chip {
  max-width: 240px;
  min-width: 0;
}
/* v07zz294 — Swap Character / Swap Face: click a chip to mark it the SOURCE. */
.gen-ref-chip--pick { cursor: pointer; }
.gen-ref-chip--pick:hover { box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 60%, transparent); }
.gen-ref-chip--pick.is-source { box-shadow: 0 0 0 var(--ring-w) var(--leaf); background: color-mix(in srgb, var(--leaf) 12%, transparent); }
.gen-ref-chip-src { display: inline-block; padding: 0 4px; height: 14px; line-height: 14px; border-radius: 3px; background: var(--leaf); color: var(--white); font-size: 8px; font-weight: var(--fw-heavy); letter-spacing: var(--track-04); margin-right: 2px; }
.gen-ref-chip-x {
  font: inherit;
  font-size: var(--fs-14);
  line-height: 1;
  border: none;
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  padding: 0 2px 0 4px;
  flex: 0 0 auto;   /* v07zz397 — never shrink/spill the × */
}
.gen-ref-chip-x:hover { color: var(--ink); }
/* v07zz545 — "@N" badge on each selected-ref chip: click to drop "@imageN" into the prompt. */
.gen-ref-chip-num {
  flex: 0 0 auto; font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-heavy); line-height: 1;
  padding: 2px 6px; border-radius: var(--r-xs); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--leaf) 55%, transparent); background: color-mix(in srgb, var(--leaf) 18%, transparent); color: color-mix(in srgb, var(--olive-9) 78%, var(--mix-dark));
  letter-spacing: var(--track-01);
}
.gen-ref-chip-num:hover { background: color-mix(in srgb, var(--leaf) 34%, transparent); border-color: color-mix(in srgb, var(--leaf) 80%, transparent); }
/* v735 — video reference modes on the @ badge. Excluded from the Omni call-out:
   struck + dimmed but still clickable (click re-includes). First/Last: inert —
   the prompt never tags images there, so the badge is informational only. */
.gen-ref-chip-num.is-omnioff { opacity: 0.4; text-decoration: line-through; }
.gen-ref-chip-num.is-inert { opacity: 0.35; cursor: default; }
.gen-ref-chip-num.is-inert:hover { background: color-mix(in srgb, var(--leaf) 16%, transparent); border-color: color-mix(in srgb, var(--leaf) 45%, transparent); }
/* v736 — First/Last | Omni on their own row under the video head (the head row was
   already full — wedging them in there wrapped the pills and clipped Omni off).
   Head-row pills also get nowrap so "Motion transfer" can never fold to two lines. */
.gen-videohead-row .gen-swap-seg { white-space: nowrap; }
/* v769 — tidy the Video-inputs head row. It holds five things (label, Standard/Motion
   toggle, ◼ stop, Adjust, Craft) and had no shrink order, so flex squeezed whatever it
   liked: "Motion transfer" was clipping mid-word, and the always-disabled ◼ read as a
   stray square wedged between the toggle and Adjust. v765 made it worse by widening the
   craft label from a fixed "Craft with Kimi" to the real provider ("Craft with ChatGPT").
   Now the shrink order is explicit — label, toggle, stop and Adjust hold their size, and
   ONLY the craft button gives way, ellipsing rather than clipping a neighbour. Everything
   stays on one line and in flow, so the row height is unchanged: the panel below is a hard
   380px and a wrapped row would eat into it (see the v07zz652 note further down). */
/* v770 — head row rebuilt to Hugo's brief: captions gone, actions are small square icon
   buttons with tooltips, and the row now genuinely FITS instead of ellipsing Craft off the
   edge (v769 truncated it, which is not the same as fixing it). Left: the template toggle.
   Right: ◼ stop, ✎ adjust, and Craft as the one labelled action. */
/* v917 — Hugo: "these buttons are getting cropped when I resize the browser window."
   nowrap + no-shrink children meant a narrow window could only CLIP the row. Wrap is
   allowed now: at full width nothing changes (one line, same height); when the panel
   narrows, the controls flow onto a second line instead of vanishing off the edge. */
/* v937 — the head rebuilt as a GRID with two deliberate rows (Hugo: "this layout of
   buttons is atrocious"). DOM order untouched — every control is PLACED by aria-label
   or class into a fixed cell, so the layout is identical at every width and never
   reflows (the v917 wrap produced a different scatter at each window size):
     row 1:  Standard|Motion ……………………………… First/Last|Omni
     row 2:  Kimi|GPT|Gem  ⏱ ………………………………… ◼  ✎  ✨ Craft
   Column 3 is the 1fr spacer between the left and right groups of both rows. */
/* v955 -- the v937 grid placements are gone: toggles now sit inside labeled
   .gen-ph-group wrappers arranged by flex order. */
.gen-videohead-row .gen-craft-btn--inline:not(.gen-craft-btn--adjust) { min-width: 78px; }
.gen-videohead-row .gen-craft-stop--inline,
.gen-videohead-row .gen-craft-btn--adjust {
  flex: 0 0 auto; width: 26px; min-width: 26px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-13); line-height: 1;
}
/* Stop keeps its footprint (never reflow the row) but recedes until a craft is running. */
.gen-videohead-row .gen-craft-stop--inline { opacity: 0.3; transition: opacity var(--dur-1) ease; }
.gen-videohead-row .gen-craft-stop--inline:not(:disabled) { opacity: 1; }
.gen-videohead-row .gen-craft-btn--inline:not(.gen-craft-btn--adjust) {
  flex: 0 0 auto; white-space: nowrap; padding: 5px 11px;
}
.gen-videohead-subrow {
  display: flex; align-items: center; gap: 10px;
  margin: 2px 0 6px; flex-shrink: 0;
}
.gen-refmode-label { margin: 0; white-space: nowrap; }
.gen-videohead-subrow .gen-swap-seg { white-space: nowrap; }
.gen-videohead-subrow .gen-swap-seg:disabled { opacity: 0.4; cursor: default; }
.gen-refs-selected-hint { width: 100%; font-size: var(--fs-11); color: var(--ink-muted); margin: 0 0 6px; line-height: 1.4; }
.gen-refs-selected-hint b { color: var(--ink); font-weight: var(--fw-bold); }
/* v07zz420 — per-ref ROLE tag. When a chip carries a role <select> it stacks into a
   column (label row on top, role picker below) so the tag is always visible. Uniform
   across every chip, so the strip height doesn't jump as roles are picked. */
/* v07zz450 — the role tag is now a compact icon button that sits INLINE in the chip,
   so a normal chip stays a short pill. Only multigrid chips (which carry a row of G1/G2
   grid pills below) still stack into a column. */
.gen-ref-chip--multigrid {
  flex-direction: column;
  align-items: stretch;
  gap: 5px;
  padding: 6px 8px 7px 8px;
  border-radius: var(--r-md);
  max-width: 240px;
}
.gen-ref-chip--multigrid .gen-ref-chip-row { justify-content: flex-start; }
/* v07zz450 — compact icon role picker. Small button shows the current role's icon;
   the portalled popover (.gen-roleicon-menu, appended to #modal-root) lists every role
   with its icon + name so it's never clipped by the scrolling refs strip. */
.gen-roleicon-btn {
  flex: 0 0 auto; width: 24px; height: 22px; padding: 0; border-radius: var(--r-7);
  display: grid; place-items: center; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--gold-9) 50%, transparent); background: color-mix(in srgb, var(--mix-light) 50%, transparent);
  color: color-mix(in srgb, color-mix(in srgb, var(--ink-tan-deep) 66%, var(--mix-dark)) 85%, transparent);
}
.gen-roleicon-btn:hover, .gen-roleicon-btn.is-open {
  color: var(--ink); border-color: color-mix(in srgb, var(--gold-deep) 75%, transparent); background: color-mix(in srgb, var(--leaf) 18%, transparent);
}
.gen-roleicon-menu {
  z-index: var(--z-overlay); min-width: 150px; padding: 4px;
  background: var(--paper, var(--cream-20)); border: 1px solid color-mix(in srgb, var(--card-border) 75%, transparent); border-radius: var(--r-panel);
  box-shadow: 0 12px 34px color-mix(in srgb, var(--shadow-ink) 30%, transparent);
  display: flex; flex-direction: column; gap: 1px;
}
.gen-roleicon-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  font: inherit; font-size: var(--fs-11-5); color: var(--ink, var(--ink-3));
  padding: 6px 9px; border: none; border-radius: var(--r-7); background: none; cursor: pointer;
}
.gen-roleicon-item:hover { background: color-mix(in srgb, var(--leaf) 14%, transparent); }
.gen-roleicon-item.is-on { background: color-mix(in srgb, var(--leaf) 22%, transparent); font-weight: var(--fw-bold); }
.gen-roleicon-item svg { flex: 0 0 auto; color: color-mix(in srgb, var(--ink-umber-4) 85%, transparent); }
/* v07zz452 — auto-restored saved-set toast: fixed, bottom-centre, non-intrusive so it
   never shifts the Generate layout. */
.gen-set-restored-toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  z-index: var(--z-popover); pointer-events: none;
  padding: 9px 16px; border-radius: var(--r-round);
  background: color-mix(in srgb, color-mix(in srgb, var(--umber-2) 51%, var(--mix-dark)) 92%, transparent); color: color-mix(in srgb, var(--ink-cream-9) 71%, var(--mix-light));
  font-size: var(--fs-12); font-weight: var(--fw-semi); letter-spacing: var(--track-02);
  box-shadow: 0 8px 26px color-mix(in srgb, var(--shade-63) 35%, transparent);
  border: 1px solid color-mix(in srgb, var(--card-border) 40%, transparent);
  animation: gen-set-toast-in 200ms ease;
}
@keyframes gen-set-toast-in { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
/* v07zz4 — Combined-Grid per-ref grid filter. When >1 grid is in
   flight, each ref chip wraps to two rows: label + a row of pills
   one per grid. is-on = ref applies to that grid. Click to toggle. */
.gen-refs-selected-bar--multigrid {
  align-items: stretch;
  padding-bottom: 4px;
}
.gen-ref-chip--multigrid {
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 6px 8px 6px 6px;
  border-radius: var(--r-md);
}
/* v07zz397 — flex (not inline-flex) + min-width:0/max-width:100% so the row stays
   inside the chip's rounded bounds: the label ellipsises and the × never spills out. */
.gen-ref-chip-row { display: flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; }
.gen-ref-chip-grids { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.gen-ref-chip-gridpill {
  font: inherit;
  font-size: var(--fs-9-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-06);
  padding: 2px 6px;
  border-radius: var(--r-round);
  border: 1px solid color-mix(in srgb, var(--gold-9) 45%, transparent);
  background: color-mix(in srgb, var(--cream) 55%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  line-height: 1;
}
.gen-ref-chip-gridpill:hover { background: color-mix(in srgb, var(--cream) 85%, transparent); }
.gen-ref-chip-gridpill.is-on {
  background: color-mix(in srgb, var(--leaf) 85%, transparent);
  border-color: color-mix(in srgb, var(--olive-2) 85%, transparent);
  color: var(--ink-hi);
}

/* Direction textarea */
.gen-direction {
  width: 100%;
  font: inherit;
  font-size: var(--fs-13-5);
  line-height: 1.5;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent);
  color: var(--ink);
  resize: vertical;
  min-height: 120px;
}
.gen-direction:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }

/* Settings — model + resolution.
   v06o — Image settings now has THREE columns: Mode (Grid/Single/
   Upscale) | Model (Banana/GPT) | Resolution. Mode takes the most
   space (3 pills), Model also wide (3 pills), Resolution narrow. */
.gen-settings {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 200px;
  gap: 14px;
}
.gen-settings.gen-settings--image {
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1.6fr) minmax(0, 0.9fr);
}
/* v07zz146 — Stacked asset-gen controls (Mode / Model / Aspect / Resolution
   each on its own row) so the middle column stays slim and the preview can
   be wider. The 6 aspect-ratio options grid 6-up, wrapping on narrow widths. */
.gen-settings.ga-settings-stacked {
  grid-template-columns: 1fr;
  gap: 10px;
}
.gen-aspect-row {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 6px;
}
@media (max-width: 1500px) {
  .gen-aspect-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* v07zz149 — Asset-gen settings as a single 4-column row:
   Mode | Model | Aspect ratio | Resolution. Each panel stacks its options as
   rows (Aspect ratio uses 2 cols × 3 rows so all four panels are the same
   height). align-items: stretch keeps the four cells level so toggling a
   button NEVER changes the panel height. */
.gen-settings.ga-settings-row4 {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  align-items: stretch;
}
.ga-quad-col { display: flex; flex-direction: column; gap: 6px; }
.ga-quad-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
/* Buttons fill their cell (override the 160px min-width that overflowed a
   quarter-width panel) and share one height so rows line up cleanly. */
.ga-settings-row4 .gen-model-btn { min-width: 0; width: 100%; flex: 0 0 auto; padding-left: 6px; padding-right: 6px; }
.ga-settings-row4 .gen-res-btn { width: 100%; flex: 0 0 auto; }
@media (max-width: 1100px) {
  .gen-settings.ga-settings-row4 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 620px) {
  .gen-settings.ga-settings-row4 { grid-template-columns: 1fr; }
}
/* v07zz213 — asset gen 3-column row (Mode column removed): Model | Aspect | Resolution. */
.gen-settings.ga-settings-row3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; align-items: stretch; }
.ga-settings-row3 .gen-model-btn { min-width: 0; width: 100%; flex: 0 0 auto; padding-left: 6px; padding-right: 6px; }
.ga-settings-row3 .gen-res-btn { width: 100%; flex: 0 0 auto; }
@media (max-width: 900px) { .gen-settings.ga-settings-row3 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .gen-settings.ga-settings-row3 { grid-template-columns: 1fr; } }
/* v06d/v06k/v06l/v06n — Video settings: Model (matches Image's Model
   column position+width) | Resolution | Duration (slider needs more
   room) | Variant. All cards align to the same height regardless of
   inner content so the row matches the Image settings row height —
   no shift when toggling between Image and Video. */
.gen-settings.gen-settings--video {
  /* v765 — Model widened 2fr → 3fr. It holds THREE buttons since MiniMax (v762); at 2fr
     the cell was 204px, so each button got 51px and "Seedance 2.0" was clipped and wrapped
     to three lines (61px tall buttons). Variant/Resolution give up a little to pay for it. */
  /* v770 — v765's 3fr overcorrected: Model sprawled while Seedance Mode, Duration and
     Resolution were squeezed. Hugo: "make the model section not as wide, there is enough
     space to have everything be comfortable in their pills." Model keeps enough for three
     pills at 11.5px; the width it gives back goes to the three that were tight. */
  /* v802 — a FOURTH pill (Seedance 2.5) joins the Model row on the SAME line: Model
     takes back some width (2.2fr → 2.9fr) and the row's gap/padding tighten below —
     the row itself never wraps and the other cells stay comfortable. */
  grid-template-columns: minmax(0, 2.9fr) minmax(0, 0.95fr) minmax(0, 1.35fr) minmax(0, 1fr);
}
.gen-settings.gen-settings--video .gen-setting {
  /* Match image-row card height — Duration's slider was making the
     video row taller. Force cards to a consistent target height by
     centering content within a fixed min-height. */
  display: flex;
  flex-direction: column;
  justify-content: center;
}
@media (max-width: 1100px) {
  .gen-settings { grid-template-columns: 1fr; }
  .gen-settings.gen-settings--video { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 720px) {
  .gen-settings.gen-settings--video { grid-template-columns: 1fr; }
}
.gen-setting {
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-md);
  padding: 12px 14px;
}
.gen-setting-label {
  display: block;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-16);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 8px;
}
.gen-model-row { display: flex; gap: 8px; flex-wrap: wrap; }
/* v765 — VIDEO model row: keep Kling / Seedance / MiniMax on ONE line. .gen-model-btn
   carries min-width:160px, so a third button (v762's MiniMax) blew past the Model cell
   and wrapped to its own row. Scoped to the video settings so the image-mode row, which
   has more width to play with, is untouched. */
.gen-settings--video .gen-model-row { flex-wrap: nowrap; gap: 5px; }   /* v802 — 4 pills */
.gen-settings--video .gen-model-row .gen-model-btn {
  min-width: 0; flex: 1 1 0;                /* equal shares, allowed to shrink */
  padding-left: 5px; padding-right: 5px;     /* v802 — was 6px; pays for the 4th pill */
  white-space: nowrap;                       /* never stack a label over 3 lines */
  font-size: var(--fs-11-5); letter-spacing: 0;
}
/* v767 — …and match the REST of the video row to it. Shrinking the model pills to fit
   three across left them visibly smaller than Seedance Mode / Duration / Resolution,
   which were still 13px. Hugo: "match the font of the model pills to the rest, so put
   the smaller font everywhere." One size across the whole row. */
.gen-settings--video .gen-res-btn { font-size: var(--fs-11-5); letter-spacing: var(--track-02); }
/* v07zz239 — Character Swap mode hint */
.gen-swap-hint { margin-top: 8px; font-size: var(--fs-11-5); line-height: 1.45; color: var(--ink-muted); background: color-mix(in srgb, var(--gold-5) 10%, transparent); border: 1px solid color-mix(in srgb, var(--gold-5) 32%, transparent); border-radius: var(--r-sm); padding: 7px 10px; }
.gen-swap-hint strong { color: var(--ink); }
/* v07zz508 — Swap settings PANEL (right column, matches the Direction / Upscale panels). */
.gen-swap-panel { display: flex; flex-direction: column; gap: 9px; }
.gen-swap-toggle { display: inline-flex; align-self: flex-start; border-radius: var(--r-round); overflow: hidden; border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); }
.gen-swap-seg {
  font: inherit; font-size: var(--fs-11); font-weight: var(--fw-bold); letter-spacing: var(--track-02); padding: 6px 14px;
  cursor: pointer; border: none; border-left: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: transparent; color: var(--ink);
}
.gen-swap-seg:first-child { border-left: none; }
.gen-swap-seg:hover { background: color-mix(in srgb, var(--leaf) 14%, transparent); }
.gen-swap-seg.is-active { background: color-mix(in srgb, var(--leaf) 32%, transparent); }
/* v841 — the VIDEO craft row now carries a third control (the Kimi/GPT/Gem picker) next
   to Adjust, Craft and the reference-mode pills. Tighter horizontal padding on that one
   only, so the row still fits on one line — it must not wrap (invariant #20). */
.gen-swap-toggle--compact .gen-swap-seg { padding: 6px 9px; letter-spacing: var(--track-01); }
.gen-swap-objinput {
  width: 100%; font: inherit; font-size: var(--fs-12-5); padding: 8px 11px; border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink);
}
.gen-swap-help { font-size: var(--fs-11-5); line-height: 1.5; color: var(--ink-muted); background: color-mix(in srgb, var(--gold-5) 10%, transparent); border: 1px solid color-mix(in srgb, var(--gold-5) 30%, transparent); border-radius: var(--r-sm); padding: 8px 11px; }
.gen-swap-help strong { color: var(--ink); }
/* v07zz510 — Blank-mode prompt panel (right column). Textarea fills the panel height. */
.gen-blank-panel { display: flex; flex-direction: column; gap: 8px; }
.gen-blank-prompt { flex: 1 1 auto; min-height: 200px; resize: vertical; width: 100%; }
.gen-blank-hint { font-size: var(--fs-11); line-height: 1.45; color: var(--ink-muted); }
/* v07zz592 — Motion Transfer video template. Head row hosts the Standard|Motion
   toggle (reuses .gen-swap-toggle pills); the motion panel reserves the SAME
   height as the standard 4-field grid so toggling never shifts what's below. */
/* v955 — the band is a FLEX row of LABELED GROUPS (Hugo's chosen mockup):
   TEMPLATE · REF MODE · CRAFTER · TIMESTAMPS · [■ ✎ CRAFT], with the live
   status line as a full-width second row. DOM order is untouched (v938's) —
   inline `order` styles arrange the groups. The v937/v938 6-col grid is gone. */
/* v959 — MOCKUP-EXACT band: all four labeled groups AND the action cluster on ONE
   row (v955 let TIMESTAMPS wrap to a second line). Segments are compact enough to
   fit the ~540px panel; the status line is the only thing that wraps below. */
.gen-section-head.gen-videohead-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  /* v961 — one tidy row: the four toggles sit left-to-right, the Stop / Adjust /
     CRAFT cluster pins to the right edge. */
  justify-content: flex-start;
  background: linear-gradient(180deg, color-mix(in srgb, var(--cream-22) 85%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-8) 18%, var(--mix-light)) 50%, transparent));
  border: 1px solid color-mix(in srgb, var(--card-border) 42%, transparent);
  border-radius: var(--r-panel);
  padding: 7px 8px;
  margin-bottom: 8px;
  box-shadow: 0 1px 2px color-mix(in srgb, var(--umber-2) 6%, transparent);
}
/* v961 — the group LABELS are gone (Hugo: "Remove the titles on top"), which is
   what buys the single row: each control is just its pill-in-pill toggle. */
.gen-ph-group { display: flex; align-items: center; min-width: 0; flex: 0 0 auto; }
.gen-ph-label { display: none; }
/* compact, uppercase segments — the mockup's language */
.gen-videohead-row .gen-swap-toggle { flex: 0 0 auto; }
/* v960 — the panel is back to a sane width, so the segments get READABLE again
   (v959's 8.5px/4px was emergency compression to win a pixel fight). */
/* padding tuned so the whole band measures ~532px + 32px of gaps — it must clear
   the ~579px of inner track Hugo's panel gives at his window width, with margin. */
.gen-videohead-row .gen-swap-seg {
  font-size: var(--fs-9-5); font-weight: var(--fw-bold); letter-spacing: var(--track-02);
  text-transform: uppercase; padding: 5px 5px; white-space: nowrap;
}
.gen-videohead-row .gen-ph-actions { gap: 5px; margin-left: auto; }
/* v961 — TIMESTAMPS is a bare on/off switch: clock glyph only, no ON/OFF text. */
.gen-videohead-row .gen-ts-switch {
  width: 30px; padding: 5px 0; text-align: center; font-size: var(--fs-12); letter-spacing: 0;
}
.gen-videohead-row .gen-craft-stop--inline,
.gen-videohead-row .gen-craft-btn--adjust {
  width: 24px; height: 24px; min-width: 0; padding: 0; flex: 0 0 auto;
}
.gen-videohead-row .gen-craft-btn--inline:not(.gen-craft-btn--adjust) {
  min-width: 56px; padding: 6px 8px; font-size: var(--fs-10);
}
.gen-ph-actions {
  display: flex; align-items: center; gap: 5px;
  margin-left: auto; align-self: flex-end; flex: 0 0 auto;
}
.gen-videohead-row .gen-craft-btn--inline:not(.gen-craft-btn--adjust) {
  text-transform: uppercase; letter-spacing: var(--track-06); font-weight: var(--fw-heavy);
}
.gen-videohead-row > .gen-craft-status--inband {
  order: 6; flex: 1 1 100%;
  min-height: 15px; min-width: 0; margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  display: block; text-align: left;
  font-size: var(--fs-11); color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-2) 81%, var(--mix-light)));
}
/* v955 — panel identity above the band. */
.gen-ph-title { display: flex; flex-direction: column; gap: 1px; margin: 2px 2px 8px; }
.gen-ph-eyebrow {
  font-size: var(--fs-9); font-weight: var(--fw-heavy); letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--ink-muted);
}
.gen-ph-name {
  font-family: var(--font-display, "Bebas Neue"), sans-serif;
  font-size: var(--fs-26); line-height: 1; letter-spacing: var(--track-02); color: var(--ink);
}
/* v07zz652 — was `min-height: 316px`, a hard floor. Once the Craft-with-Kimi row was
   added above it, the Motion Transfer branch measured 453px inside a panel that is a hard
   380px, so 73px was clipped. The parent is already a flex column, so let this FILL the
   remaining height instead of demanding a fixed one — then no row added above can ever
   overflow it again. min-height:0 is required or a flex child refuses to shrink below its
   content, which is how the clipping comes back. */
.gen-video-inputs--motion { display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0; }
/* v938 — the EXTRA DETAILS field is the panel's flexible middle: the reserved height
   (matched to the standard 4-box grid, invariant #20) becomes usable typing room
   instead of a hole between the box and the attachment pills. */
.gen-video-inputs--motion .gen-video-field--wide {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
}
.gen-video-inputs--motion .gen-motion-extra { flex: 1 1 auto; min-height: 90px; resize: none; }
/* v938 — attachment pills in an ordered two-column grid, pinned to the panel foot. */
.gen-video-inputs--motion .gen-motion-opts {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
}
.gen-video-inputs--motion .gen-motion-opt { justify-content: flex-start; }
.gen-video-field--wide { width: 100%; display: flex; flex-direction: column; gap: 4px; flex: 1 1 auto; min-height: 0; }
.gen-motion-extra { width: 100%; resize: vertical; flex: 1 1 auto; min-height: 0; }
/* v07zz683 — Motion Transfer attachment toggles (start frame locked on, end frame,
   subject reference). Borrows the .gen-vo-group-row look — same cream fill, same green
   checked state, same accent-color — so it reads as an existing control rather than a new
   one. flex: 0 0 auto keeps the row a fixed height inside the flex column, so the extra
   textarea absorbs the space and nothing below the panel moves (invariant #20). */
/* v696 — Craft-prompt presets: saved queries as click-to-load chips under the brief
   box, plus the Save button. Chips wrap and the row scrolls rather than growing, so a
   long preset list can't push the Craft panel taller (invariant #20). */
.gen-craft-presets {
  display: flex; flex-wrap: wrap; gap: 5px; align-items: center;
  margin-top: 6px; max-height: 58px; overflow-y: auto; flex: 0 0 auto;
}
.gen-craft-preset {
  display: inline-flex; align-items: stretch;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); border-radius: var(--r-round);
  background: color-mix(in srgb, var(--cream) 72%, transparent); overflow: hidden;
}
.gen-craft-preset-load {
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-semi); letter-spacing: var(--track-01);
  max-width: 190px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  padding: 3px 8px; border: none; background: none; color: var(--ink); cursor: pointer;
}
.gen-craft-preset:hover { border-color: color-mix(in srgb, var(--leaf) 70%, transparent); background: color-mix(in srgb, var(--leaf) 14%, transparent); }
.gen-craft-preset-x {
  font: inherit; font-size: var(--fs-12); line-height: 1; padding: 0 6px;
  border: none; border-left: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent);
  background: none; color: var(--ink-muted); cursor: pointer;
}
.gen-craft-preset-x:hover { background: color-mix(in srgb, var(--danger-soft) 18%, transparent); color: var(--danger); }
.gen-craft-preset-save {
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-bold); letter-spacing: var(--track-03);
  padding: 3px 9px; border-radius: var(--r-round); cursor: pointer;
  border: 1px dashed color-mix(in srgb, var(--card-border) 80%, transparent); background: none; color: var(--ink-muted);
}
.gen-craft-preset-save:hover:not(:disabled) { border-style: solid; color: var(--ink); background: color-mix(in srgb, var(--leaf) 14%, transparent); }
.gen-craft-preset-save:disabled { opacity: 0.45; cursor: default; }

/* v706 — saved presets as cells in the TEMPLATE grid at the top, alongside New frame /
   Swap subject / Look-realism / Add detail (Hugo: "make the 3d preset part of the craft
   prompt template at the top"). They inherit .gen-model-btn wholesale so they are
   INDISTINGUISHABLE from the four built-ins — v707 removed a green tint I'd added to
   mark them as "your own"; Hugo wants one row of identical pills, and the hover ✕ is
   already the only distinction needed. The ✕ is ABSOLUTE and hover-only — an in-flow ✕
   is what made these unusable inside the grid in v700 (it ate the cell width and
   stranded itself at the far end). */
.gen-craft-presetcell { position: relative; }
/* v707 — NO min-height. The two-line reserve was added when a preset sat on its own
   grid row and rendered shorter than the four built-ins; now that every pill shares one
   row, grid's default align-items:stretch equalises the heights for free — and the
   reserve was actively wrong, pushing a one-line label to the TOP of a two-line box
   while its neighbours sat centred. .gen-model-btn is already a centred flex box, so
   with the reserve gone the label centres like every other pill. The clamp stays, to
   truncate a long preset name instead of blowing the row height out. */
.gen-craft-presetcell-label {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  min-width: 0; overflow: hidden; text-align: center;
}
.gen-craft-presetcell-x {
  position: absolute; top: 1px; right: 2px;
  width: 14px; height: 14px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: var(--fs-12); line-height: 1; cursor: pointer;
  color: var(--ink-muted); background: color-mix(in srgb, var(--cream) 90%, transparent);
  opacity: 0; transition: opacity 110ms ease, background 110ms ease, color 110ms ease;
}
.gen-craft-presetcell:hover .gen-craft-presetcell-x { opacity: 1; }
.gen-craft-presetcell-x:hover { background: color-mix(in srgb, var(--danger-soft) 90%, transparent); color: var(--ink-on-danger); }

/* v706 — Undo for the brief box. Sits in the "What do you need?" label row, right-
   aligned. ALWAYS rendered, only disabled, so the row height never moves (#20). */
.gen-craft-undo {
  float: right;
  font: inherit; font-size: var(--fs-9-5); font-weight: var(--fw-bold); letter-spacing: var(--track-05);
  text-transform: uppercase;
  padding: 1px 7px; border-radius: var(--r-round); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--card-border) 75%, transparent); background: color-mix(in srgb, var(--cream) 60%, transparent);
  color: var(--ink-muted);
}
.gen-craft-undo:hover:not(:disabled) { color: var(--ink); border-color: color-mix(in srgb, var(--gold) 90%, transparent); background: color-mix(in srgb, var(--gold) 16%, transparent); }
.gen-craft-undo:disabled { opacity: 0.32; cursor: default; }

/* v789 — Re-shoot frame | Swap character variant pills at the top of the motion panel. */
.gen-motion-variant { align-self: flex-start; margin-bottom: 2px; flex: 0 0 auto; }
.gen-motion-opts { display: flex; flex-wrap: wrap; gap: 6px; flex: 0 0 auto; }
.gen-motion-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px; border-radius: var(--r-7);
  border: 1px solid color-mix(in srgb, var(--card-border) 55%, transparent);
  background: color-mix(in srgb, var(--cream-2) 45%, transparent);
  font-size: var(--fs-11-5); color: var(--ink); cursor: pointer;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-motion-opt:hover { background: color-mix(in srgb, var(--cream-2) 85%, transparent); }
.gen-motion-opt.is-checked { background: color-mix(in srgb, var(--mint) 55%, transparent); border-color: color-mix(in srgb, var(--olive-5) 45%, transparent); }
.gen-motion-opt.is-locked { background: color-mix(in srgb, color-mix(in srgb, var(--pale-green) 60%, var(--mix-light)) 60%, transparent); border-color: color-mix(in srgb, var(--olive-5) 70%, transparent); cursor: default; }
.gen-motion-opt input[type="checkbox"] { cursor: inherit; accent-color: var(--olive-7); margin: 0; }
.gen-motion-tag {
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-9-5); letter-spacing: var(--track-04); color: var(--ink-muted);
}
/* 24 Sep 2026 — Motion > Re-shoot frame: up to 8 shots, each with its own pictures.
   Hugo: "fit 8 shots in there but keep it on one line" + "i dont get specific options for
   choosing first frame/last frame or just reference frame for each shot".
   - .gen-mshot-countrow: "Shots" + the 1..8 pills, ONE line at every count (nowrap, equal pills).
   - .gen-mshot-cards: one card per shot, all on ONE line; the cards share the width equally
     (a quarter each up to 4 shots, then they shrink together) and the row has ONE fixed height,
     so neither the count nor a mode moves anything (invariant #20).
   - Inside a card the long labels ("First + Last", <<<Image3>>>) give way to short ones
     ("F+L", @3) when the card or the picture is narrow (container queries), never cropped.
   Colours are the panel's own tokens (the .gen-motion-opt / .gen-swap-seg look). */
.gen-mshot-countrow { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; min-width: 0; white-space: nowrap; }
.gen-mshot-countlabel {
  flex: 0 0 auto; font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: var(--track-06);
  text-transform: uppercase; color: var(--ink-muted);
}
.gen-mshot-count { flex: 1 1 auto; min-width: 0; display: flex; }
.gen-mshot-count .gen-swap-seg { flex: 1 1 0; min-width: 0; padding: 6px 0; text-align: center; }
.gen-mshot-cards { display: flex; gap: 4px; flex: 0 0 auto; height: 132px; min-width: 0; overflow: hidden; }
.gen-mshot-card {
  flex: 0 1 calc((100% - 12px) / 4); min-width: 0; container-type: inline-size;
  display: flex; flex-direction: column; gap: 3px; padding: 3px;
  border-radius: var(--r-7); border: 1px solid color-mix(in srgb, var(--card-border) 55%, transparent);
  background: color-mix(in srgb, var(--cream-2) 45%, transparent); color: var(--ink);
}
.gen-mshot-label { font-size: var(--fs-10); font-weight: var(--fw-bold); line-height: 13px; height: 13px; padding-left: 2px; flex: 0 0 auto; }
.gen-mshot-thumbs { flex: 1 1 auto; min-height: 0; display: flex; gap: 2px; }
.gen-mshot-slot { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 1px; container-type: inline-size; }
.gen-mshot-pic {
  flex: 1 1 auto; min-height: 0; border-radius: var(--r-xs); overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  background: color-mix(in srgb, var(--cream) 40%, transparent);
}
.gen-mshot-slot.is-empty .gen-mshot-pic { border-style: dashed; background: transparent; }
.gen-mshot-slot.is-drop .gen-mshot-pic { border-color: var(--leaf); box-shadow: inset 0 0 0 1px var(--leaf); }
.gen-mshot-slot.is-over .gen-mshot-pic { border-color: var(--danger-2); }
.gen-mshot-pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.gen-mshot-tag {
  flex: 0 0 auto; height: 11px; line-height: 11px; text-align: center; white-space: nowrap; overflow: hidden;
  font-family: var(--font-mono, "JetBrains Mono"), monospace; font-size: var(--fs-8-5); color: var(--ink-muted);
}
.gen-mshot-slot.is-over .gen-mshot-tag { color: var(--danger-2); }
.gen-mshot-modes { flex: 0 0 auto; display: flex; flex-direction: column; align-self: stretch; border-radius: var(--r-xs); }
.gen-mshot-modes .gen-mshot-mode {
  border-left: none; border-top: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  padding: 0 2px; height: 14px; line-height: 14px; font-size: var(--fs-9); letter-spacing: 0;
  text-align: center; white-space: nowrap; overflow: hidden;
}
.gen-mshot-modes .gen-mshot-mode:first-child { border-top: none; }
.gen-mshot-full { display: none; }
.gen-mshot-short { display: inline; }
@container (min-width: 80px) {
  .gen-mshot-mode .gen-mshot-full { display: inline; }
  .gen-mshot-mode .gen-mshot-short { display: none; }
}
@container (min-width: 70px) {
  .gen-mshot-tag .gen-mshot-full { display: inline; }
  .gen-mshot-tag .gen-mshot-short { display: none; }
}
.gen-mshot-status {
  flex: 0 0 auto; height: 15px; line-height: 15px; white-space: nowrap; overflow: hidden;
  font-size: var(--fs-10-5); color: var(--ink-muted);
}
.gen-mshot-status.is-over { color: var(--danger-2); font-weight: var(--fw-bold); }
/* Subject / Character: one pill per line, never wrapping, so the row keeps one height at every
   shot count (their <<<ImageN>>> tags grow to two digits with more shots). */
.gen-video-inputs--motion .gen-motion-opts.gen-mshot-opts { grid-template-columns: 1fr; }
.gen-mshot-opts .gen-motion-opt { white-space: nowrap; min-width: 0; }

/* v07zz587 — New Angle mode panel (matches the Swap/Blank right-column panels).
   v07zz596 — the mode grid is now a clean 5×2 (10 modes); --span2 kept for reuse. */
.gen-model-btn--span2 { grid-column: 1 / -1; }
/* v07zz596 — Depth Map mode: source picker (this shot's frames + videos). */
.gen-depth-panel { display: flex; flex-direction: column; gap: 9px; }
.gen-depth-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 8px; overflow-y: auto; max-height: 250px; padding: 2px;
}
.gen-depth-tile {
  position: relative; border: 2px solid color-mix(in srgb, var(--card-border) 45%, transparent); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--cream) 60%, transparent); padding: 0; cursor: pointer; overflow: hidden;
  aspect-ratio: 21 / 11; display: block;
}
.gen-depth-tile:hover { border-color: color-mix(in srgb, var(--gold-4) 75%, transparent); }
.gen-depth-tile.is-picked { border-color: var(--gold-5); box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--gold-5) 35%, transparent); }
.gen-depth-thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.gen-depth-play {
  position: absolute; top: 4px; right: 5px; font-size: var(--fs-10); color: var(--white);
  text-shadow: 0 1px 3px rgba(0,0,0,0.7); pointer-events: none;
}
.gen-depth-label {
  position: absolute; left: 0; right: 0; bottom: 0; font-size: var(--fs-9-5); font-weight: var(--fw-semi);
  letter-spacing: var(--track-04); color: var(--white); background: linear-gradient(transparent, rgba(0,0,0,0.62));
  padding: 8px 5px 3px; text-align: left; pointer-events: none;
}
.gen-depth-msg { color: var(--ink); background: color-mix(in srgb, var(--gold-5) 12%, transparent); border: 1px solid color-mix(in srgb, var(--gold-5) 35%, transparent); border-radius: var(--r-sm); padding: 7px 10px; }
.gen-newangle-panel { display: flex; flex-direction: column; gap: 9px; }
.gen-newangle-field { display: flex; flex-direction: column; gap: 4px; }
.gen-newangle-input { width: 100%; min-height: 58px; resize: vertical; }

/* v07zz643 — Craft Prompt panel. Every row that changes with state (status line,
   tail preview) has a RESERVED fixed height, so switching model, crafting, erroring
   or tagging a reference never moves anything below it (invariant #20). */
/* v07zz651 — the four jobs in ONE row. The panel is ~640px wide so all four fit; a 2×2
   grid cost 34px of height and squeezed the tail preview down to 22px. Fixed columns means
   the panel height is constant whichever is picked (invariant #20). */
/* v707 — ONE ROW, however many presets there are. This was repeat(4, 1fr), so the
   moment a saved preset joined the four built-ins it wrapped onto a second row on its
   own — Hugo: "i need the 5 pills to be on one row". auto-flow:column + equal
   auto-columns means the row grows to fit N cells instead of wrapping. */
/* v1052 — TWO ROWS. grid-auto-flow:column is gone: it is what forced the single
   row, and it silently overrides the inline grid-template-columns that
   craftGridCols() sets. The column count comes from the component (half the cell
   count, rounded up) so the two rows stay balanced as presets are added.
   grid-auto-rows:1fr keeps both rows the same height even when one row's labels
   wrap to two lines and the other's don't. */
.gen-craft-intents {
  display: grid;
  grid-auto-rows: 1fr;
  gap: 6px; flex: 0 0 auto;
}
/* min-height reserves the two-line case so a one-word label and a wrapped label
   are the same cell — and so switching job never changes the block's height
   (invariant #20). */
.gen-craft-intents .gen-model-btn {
  width: 100%; min-width: 0; flex: unset; font-size: var(--fs-11-5); padding: 6px 8px;
  white-space: normal; line-height: 1.2; min-height: 34px;
}
/* v07zz654 — Craft with Kimi sits in the video head row, in line with the
   Standard / Motion transfer pills. The separate .gen-craft-videorow (with its Animate /
   Camera move / Action chips) is gone — those chips fought the input boxes. */
/* v955 -- gap owned by the labeled flex band above. */
/* v699 — was `justify-content: space-between`, which spread ALL FOUR children (model
   pills, Stop, Adjust, Craft) evenly across the row, so Stop and Adjust floated away
   from the Craft button they belong to. Push only the model pills left; the three
   action buttons then cluster together on the right at the normal 8px gap. */
.gen-craft-row { display: flex; align-items: center; justify-content: flex-start; gap: 8px; flex-wrap: wrap; }
/* The four children need ~387px and the panel is ~380px, so something always wraps.
   `space-between` scattered Stop/Adjust away from Craft; `margin-right:auto` on the
   pills pushed Craft onto its own line instead. Give the model pills a full row of
   their own — then Stop · Adjust · Craft prompt always land together on the next
   line, at the normal 8px gap, which is what Hugo asked for. */
.gen-craft-row > .gen-swap-toggle { flex: 1 1 100%; }
.gen-craft-row > .gen-craft-stop { margin-left: auto; }
.gen-craft-btn {
  flex: 0 0 auto; font: inherit; font-size: var(--fs-12); font-weight: var(--fw-bold); letter-spacing: var(--track-02);
  padding: 7px 14px; border-radius: var(--r-sm); cursor: pointer; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--gold-5) 55%, transparent);
  background: linear-gradient(150deg, color-mix(in srgb, var(--gold-10) 75%, var(--mix-light)), var(--gold) 70%); color: color-mix(in srgb, var(--ink-umber-2) 47%, var(--mix-dark));
  transition: filter var(--dur-1) ease, opacity var(--dur-1) ease, transform 60ms ease, box-shadow var(--dur-1) ease;
}
.gen-craft-btn:hover:not(:disabled) { filter: brightness(1.07); }
/* v07zz661 — Hugo: "it looks like clicking it worked but the button didnt actually
   clicked animation." It had no :active state at all, so a click that DID fire read as a
   dead button — and a craft takes 1-2 minutes before anything else happens. Press it in. */
.gen-craft-btn:active:not(:disabled) { transform: translateY(1px) scale(0.985); filter: brightness(0.92); }
.gen-craft-btn:focus-visible { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 75%, transparent); outline-offset: var(--ring-offset); }
.gen-craft-btn:disabled { opacity: 0.45; cursor: default; }
/* Working ≠ dead. While it thinks it stays gold and keeps its ticking label — dimming it
   to the 0.45 disabled state for 90 seconds is what made it look broken. */
.gen-craft-btn.is-busy:disabled {
  opacity: 1; cursor: progress;
  animation: gen-craft-pulse 1.5s ease-in-out infinite;
}
@keyframes gen-craft-pulse {
  0%, 100% { filter: brightness(1); box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold-5) 0%, transparent); }
  50%      { filter: brightness(1.1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold-5) 28%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .gen-craft-btn.is-busy:disabled { animation: none; }
  .gen-craft-btn:active:not(:disabled) { transform: none; }
}
/* v07zz661 — Hugo: "fix that gold pill so it's the same shape and size as the
   Standard/Motion transfer style pills." It was an 8px-radius rectangle sitting next to
   999px pills. Matches .gen-swap-seg — same radius, font, tracking and padding — and since
   both carry a 1px border they come out the same height.
   MUST stay BELOW .gen-craft-btn: same specificity, so the base class wins on ties. It was
   originally written ABOVE it and every property here was silently overridden. */
.gen-craft-btn--inline {
  margin-left: auto;
  border-radius: var(--r-round);
  font-size: var(--fs-11); font-weight: var(--fw-bold); letter-spacing: var(--track-02);
  padding: 6px 14px;
}
/* Two lines reserved: the busy line is the longest state and must not reflow the panel. */
.gen-craft-status {
  min-height: 30px; font-size: var(--fs-11-5); line-height: 1.32; color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-2) 81%, var(--mix-light)));
  display: flex; align-items: center;
}
.gen-craft-err { color: var(--danger-2); }
/* v07zz644 — the tail block FILLS the leftover height instead of claiming a fixed
   104px. The panel is a hard 380px with overflow hidden (.gen-section--match-refs), so
   a fixed height here made the content 464px and silently cropped 84px — Hugo could
   only see one line of the block. min-height:0 is required or a flex child refuses to
   shrink below its content and the clipping comes straight back. */
/* v726 — craft mode outgrew the hard 380px (5-cell job grid + presets + brief + provider
   row + this tail), so the tail flexed down to a one-line sliver — Hugo: "the
   cinematography block is cropped." Same fix as VO (v07zz552): both cards keep 380 as the
   FLOOR and grow with content; the tail gets a floor of its own so it is always readable.
   Heights only ever change when the MODE changes, never from a toggle inside the panel. */
/* v730 — grow-with-content (v726) was the wrong shape once the tail got long: the whole
   ROW ballooned (measured 951px) and shoved MODE/MODEL down the page — Hugo: "it's
   pushing everything down." Craft mode now has a FIXED taller row (same precedent as VO's
   460): both cards 620px, scrolling INSIDE if content ever exceeds it. Deterministic
   height, nothing below ever moves. */
.gen-row-2col--craft .gen-section--match-refs { height: 620px; overflow-y: auto; }
/* v732 — VIDEO gets the same treatment. v724's Cinematography fields pushed the video
   card's content past its fixed 380px, and a fixed FLEX COLUMN with overflow:hidden does
   not crop overflow — it SHRINKS every child until they fit, which squashed every
   textarea to a one-line sliver (Hugo: "why did this panel completely collapse??").
   Two halves, both required:
   1. the taller fixed card (620px, scrolling inside if content ever exceeds it);
   2. flex-shrink:0 on the card's children — WITHOUT this the column still crushes
      children before it ever scrolls, and the bug comes straight back. */
/* v853 — 620px → 520px. Hugo: "the button is too low at the page and we have a scroll.
   reduce the height of the middle block with the prompt boxes slightly so everything fits."
   v852 added Location / Light / Subject / Behaviour to the FROM THE SHOTLIST card above,
   which grew it from ~170px to 270px and pushed COPY PROMPT & MARK SENT off the fold. This
   hands back exactly that 100px. Measured at 520: the four boxes are still 114/161/161/161
   tall — the same size he was already typing into — and both columns of the row shrink
   together, so refs and prompt boxes stay aligned. */
/* v950 — 520 → 560: rails slimmed, 96px floors per box, card +40px.
   v955 — Hugo's chosen full-height layout: the shotlist card now stacks INSIDE the
   left column (above the refs), and this panel takes the whole right side. The
   fixed height goes — the panel stretches to the left column's height (row is
   align-items: stretch) and the flexible middle hands ALL of it to the typing
   boxes. min-height keeps the old floor; overflow still scrolls inside; children
   stay flex-shrink:0 so nothing can ever be crushed. */
.gen-row-2col--video .gen-section--match-refs { height: 100%; min-height: 0; overflow-y: auto; flex: 1 1 auto; }
.gen-row-2col--video .gen-section--match-refs > *,
.gen-row-2col--craft .gen-section--match-refs > * { flex-shrink: 0; }
.gen-craft-tailwrap { display: flex; flex-direction: column; gap: 4px; flex: 1 1 auto; min-height: 0; }
/* v730 — Hugo: "collapsable and scrollable with a specific height. At the moment it's
   pushing everything down." The v726 min-height floor let the box GROW past it with the
   long v729 role expansions, and the grow-with-content card grew along. FIXED height now:
   the box scrolls inside itself and the panel height is deterministic. The header is a
   collapse toggle (chevron rotates; state persists via filmtracker.craftTailOpen). */
.gen-row-2col--craft .gen-craft-tail { height: 170px; flex: 0 0 auto; }
.gen-craft-tailtoggle {
  display: flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; text-align: left; width: 100%;
}
.gen-craft-tailtoggle:hover { color: var(--ink, var(--ink-umber)); }
.gen-craft-tailchev { display: inline-block; font-size: var(--fs-10); transition: transform var(--dur-1) ease; }
.gen-craft-tailchev.is-open { transform: rotate(90deg); }
.gen-craft-tailwrap.is-collapsed { flex: 0 0 auto; }
.gen-craft-tail {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; white-space: pre-wrap; word-break: break-word;
  font-family: var(--font-mono, "JetBrains Mono", monospace); font-size: var(--fs-10-5); line-height: 1.45;
  padding: 7px 9px; border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--black) 5%, transparent); color: var(--ink, var(--ink-umber));
}
.gen-craft-tail-empty { font-family: var(--font-ui, "Inter", sans-serif); font-style: italic; opacity: 0.7; }
/* v07zy — Hugo: Mode column has 4 buttons. The default flex-wrap
   layout produced a 3+1 orphan ("Batch" on its own row) at narrower
   viewports. Force a 2×2 grid so the four buttons are always equal-
   sized and aligned regardless of column width. */
.gen-model-row--mode {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
/* v713 — Hugo: "why the hell are the pills all tall now in single image mode???
   Compared to Craft Mode."
   Because the settings row is flexible and Single/Grid mode shows an extra ASPECT RATIO
   column that Craft mode doesn't. That extra column stole width from MODE, the labels
   ran out of room, "Change Light" / "Modify Image" / "Craft Prompt" wrapped to two
   lines, and every pill in the grid grew to match. So the pills changed height purely
   because of which OTHER panel happened to be on screen — invariant #20, the thing that
   must never happen.
   Fixed both ends: the MODE column is now a FIXED width so no other panel can squeeze
   it, and the pills have a fixed height so a wrapped label can't change the row. */
.gen-setting:has(.gen-model-row--mode) {
  min-width: 244px;
  max-width: 244px;
  flex: 0 0 244px;
}
.gen-model-row--mode .gen-model-btn {
  min-width: 0;
  flex: unset;
  width: 100%;
  /* reserve the two-line case for everything, so 1-line and 2-line pills match */
  height: 42px;
  padding: 4px 8px;
  font-size: var(--fs-12);
  line-height: 1.18;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
}
/* v07zz643 — NOTE: Craft Prompt is the 12th mode, so the 2-column grid lands on a clean
   6×2 with no orphan. An earlier attempt spanned it full-width, which pushed Replace
   Assets into a half-empty row and made the column 7 rows tall. Don't re-add the span
   unless the mode count goes ODD again. */
/* v07zz400 — Mode | Model | Resolution as three equal-height columns.
   Mode keeps its 3×2 grid (6 buttons, 3 rows tall); Model + Resolution stack
   their options in ONE vertical column so the three cards match in height and
   nothing below shifts when you toggle anything (invariant #20). */
/* v726 — Hugo: "why is there a gap here next to mode in Craft Prompt mode?"
   Because v713 pinned the Mode CARD at 244px but this row is a GRID: max-width on a
   child does not narrow its TRACK. Track 1 stayed fr-sized, the 244px card sat at its
   left edge, and the rest of the track rendered as dead space — widest in craft's
   5-column template, which is where he saw it. The fix is to pin the TRACK: every
   template's first column is now the same 244px the card is. */
.gen-settings.gen-settings--stacked3 {
  grid-template-columns: 244px minmax(0, 1fr) minmax(0, 0.8fr);
  align-items: stretch;
}
.gen-settings--stacked3 .gen-setting {
  display: flex;
  flex-direction: column;
}
/* The button group fills the card below the label so the three columns line up. */
.gen-settings--stacked3 .gen-model-row,
.gen-settings--stacked3 .gen-res-row { flex: 1; }
/* v07zz414/439 — single/grid/batch add TWO extra columns between Model + Resolution:
   "Visual style" (6 buttons) and "Time of day" (12 buttons, v906) → FIVE columns total
   (Mode | Model | Visual style | Time of day | Resolution). Both button grids fill 3
   rows then wrap into more sub-columns, so their height matches Mode (3×2) / Model /
   Resolution — nothing below shifts (invariant #20). Time of day gets the widest track
   (12 presets → 4 sub-columns; the count must stay divisible by 3 or the last column
   rags). Keeping Resolution on this same row was the fix for it
   wrapping to a second line after the Time-of-day column was added. */
.gen-settings--stacked3.gen-settings--withstyle {
  grid-template-columns: 244px minmax(0, 0.98fr) minmax(0, 0.90fr) minmax(0, 1.40fr) minmax(0, 0.50fr);   /* v1058 — model track widened for its 2nd sub-column */
}
/* v07zz544 — single/grid/batch add a 6th "Aspect ratio" column (before Resolution) so the
   Resolution card stays ON this row instead of wrapping to a second line. */
.gen-settings--stacked3.gen-settings--withstyle.gen-settings--withaspect {
  grid-template-columns: 244px minmax(0, 0.95fr) minmax(0, 0.88fr) minmax(0, 1.25fr) minmax(0, 0.55fr) minmax(0, 0.45fr);   /* v1058 — model track widened for its 2nd sub-column */
}
/* v07zz461 — Upscale row: Mode | Model | Visual style | Target resolution (FOUR columns —
   no Time-of-day column, so it can't reuse the 5-col withstyle template). Style gets the
   wide track since it's the only preset column here. */
.gen-settings--stacked3.gen-settings--withstyle-us {
  grid-template-columns: 244px minmax(0, 1.0fr) minmax(0, 1.35fr) minmax(0, 0.5fr);   /* v1058 — model track widened for its 2nd sub-column */
}
/* 23 Sep 2026 — Change light gains the Aspect ratio column: Mode | Model | Visual style | Aspect | Resolution. */
.gen-settings--stacked3.gen-settings--withstyle-us.gen-settings--withaspect {
  grid-template-columns: 244px minmax(0, 1.0fr) minmax(0, 1.2fr) minmax(0, 0.55fr) minmax(0, 0.5fr);
}
.gen-style-grid {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 8px;
}
.gen-style-grid .gen-model-btn { min-width: 0; width: 100%; white-space: normal; line-height: 1.15; }
/* v1058 — THREE rows, wrapping into sub-columns, exactly like .gen-style-grid and
   the time-of-day grid beside it. Was a 5-tall flex stack, which only looked right
   while there were three models. Keep this in step with the model COUNT: at 3 rows
   a 6th model would still fit (3+3); a 7th starts a third sub-column and the track
   below needs widening again. */
/* v1064 — SIX models (three GPT API models + the subscription one): back to the v1058
   THREE rows, filling two sub-columns. The rows stretch to the card's full height
   (.gen-setting--models), so the pills line up with the 3-row neighbours top and bottom. */
.gen-setting--models { display: flex; flex-direction: column; }
.gen-model-row--stack {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 8px;
  flex: 1 1 auto;
}
.gen-model-row--stack .gen-model-btn {
  min-width: 0;
  width: 100%;
  white-space: normal;
  line-height: 1.15;
}
.gen-res-row--stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.gen-res-row--stack .gen-res-btn {
  flex: 1 1 0;
}
@media (max-width: 1100px) {
  /* Reuse the shared collapse — stacked3 folds to one column like the rest. */
  .gen-settings.gen-settings--stacked3 { grid-template-columns: 1fr; }
}
/* v07zz — Batch panel × buttons. Match the visual language of the
   modal close button (display: grid; place-items: center for true
   centering of the SVG glyph). No more drifty unicode "×". */
.gen-batch-x-btn {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--mix-light) 60%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  padding: 0;
  transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-batch-x-btn:hover {
  background: color-mix(in srgb, var(--danger-soft) 12%, transparent);
  color: var(--danger);
  border-color: var(--danger-border);
}
.gen-batch-x-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.gen-model-btn {
  flex: 1 1 auto;
  min-width: 160px;
  /* v06b — Single-line layout so the row sits level with the
     Resolution buttons (which are single-line). The API-model
     subtitle was dropped per Hugo: he doesn't need to see
     'gemini-3-pro-image-preview · default' under the friendly name. */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 14px;
  font: inherit;
  font-size: var(--fs-13);
  font-weight: var(--fw-semi);
  border-radius: var(--r-panel);
  border: 1.5px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 65%, transparent);
  color: var(--ink);
  cursor: pointer;
  text-align: center;
  transition: border-color var(--dur-1) ease, background var(--dur-1) ease;
}
.gen-model-btn:hover { background: color-mix(in srgb, var(--cream) 95%, transparent); }
.gen-model-btn.is-active {
  border-color: color-mix(in srgb, var(--leaf) 75%, transparent);
  background: color-mix(in srgb, var(--leaf) 12%, transparent);
  box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 30%, transparent);
}
.gen-res-row { display: flex; gap: 8px; }
.gen-res-btn {
  flex: 1;
  font: inherit;
  font-size: var(--fs-13);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-04);
  /* v06c — Match .gen-model-btn's vertical padding (10px) so the
     Resolution buttons render at the same height as the Model row
     and visually sit on the same baseline. */
  padding: 10px 0;
  border-radius: var(--r-panel);
  border: 1.5px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 65%, transparent);
  color: var(--ink);
  cursor: pointer;
}
.gen-res-btn:hover { background: color-mix(in srgb, var(--cream) 95%, transparent); }
.gen-res-btn.is-active {
  border-color: color-mix(in srgb, var(--leaf) 75%, transparent);
  background: color-mix(in srgb, var(--leaf) 18%, transparent);
}
/* v832 — the pixel sub-line under each tier name is GONE (Hugo: "get rid of those
   shitty little numbers. i diodnt ask for that"). The labels carry the meaning on
   their own now, so .gen-res-btn--px / .gen-res-px went with it. */

/* Prompt preview.
   v06e — Now split into two clearly-labeled sub-blocks: a muted
   "Reference" block for the header (saved to the log, NOT sent to
   the model) + an accent "Prompt sent to model" block for the body.
   The visual distinction answers the "does the header get sent?"
   question without needing a paragraph of copy. */
.gen-preview-section .gen-section-head { margin-bottom: 0; }
.gen-preview-split {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
}
.gen-preview-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.gen-preview-block-label {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.gen-preview-block-tag {
  display: inline-block;
  align-self: flex-start;
  font-size: var(--fs-9-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-12);
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--r-round);
  background: color-mix(in srgb, var(--ink-muted) 18%, transparent);
  color: var(--ink-muted);
}
.gen-preview-block-tag--accent {
  background: color-mix(in srgb, var(--leaf) 22%, transparent);
  border: 1px solid color-mix(in srgb, var(--leaf) 45%, transparent);
  color: var(--olive-3);
}
.gen-preview-block-sub {
  font-size: var(--fs-10);
  color: var(--ink-muted);
  font-style: italic;
  letter-spacing: var(--track-02);
}
.gen-preview-text {
  margin: 0;
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-11-5);
  line-height: 1.45;
  color: var(--ink);
  background: color-mix(in srgb, var(--shadow-ink) 6%, transparent);
  padding: 12px;
  border-radius: var(--r-sm);
  white-space: pre-wrap;
  max-height: 320px;
  overflow-y: auto;
  scrollbar-width: thin;
  /* v06o — Labels above this block left-align with this 12px padding. */
}
.gen-preview-text--muted {
  background: color-mix(in srgb, var(--ink-muted) 10%, transparent);
  color: var(--ink-muted);
  font-size: var(--fs-11);
  max-height: 160px;
}
/* v06o — Editable preview body: looks identical to the read-only
   <pre> but is now a <textarea> so the user can hand-tune the prompt
   before clicking Generate. */
.gen-preview-text--editable {
  width: 100%;
  border: 1px solid color-mix(in srgb, var(--leaf) 30%, transparent);
  resize: vertical;
  min-height: 160px;
  display: block;
  box-sizing: border-box;
}
.gen-preview-text--editable:focus {
  outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent);
  outline-offset: 0;
  border-color: transparent;
}
/* v06o — Block label tag + sub-line align with the textarea's
   internal padding (12px) so they sit flush with the content. */
.gen-preview-block-label {
  padding-left: 12px;
}
/* v07zz424 — Reference block collapses on its own; its label is a clickable row. */
.gen-preview-block-label--toggle {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
}
.gen-preview-block-label--toggle .gen-preview-block-chev,
.gen-preview-block-label--toggle .gen-section-head-chev {
  margin-left: auto;
  opacity: 0.6;
}
.gen-preview-block-label--toggle:hover .gen-section-head-chev { opacity: 1; }

/* Footer — generate button + job status.
   v06l — Removed the gradient background entirely. The button now
   sits directly on the page background with its own drop shadow —
   no more "beige rectangle" visible around it. The footer is just
   a positioning shell with padding to keep the button off the
   column edges. */
.gen-footer {
  /* v07zw — Hugo: drop the sticky footer entirely. The earlier fix
     added a cream gradient behind the button which read as a visible
     rectangle and looked wrong. Now the button just flows with the
     page — the assembled prompt preview area sits above it and grows
     naturally. */
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px 12px;
  background: transparent;
  pointer-events: none;
}
.gen-footer > * { pointer-events: auto; }
/* v07zz572 — "Open source frame on copy" is now an ELEGANT right-cap toggle integrated
   INTO the copy button (was a standalone checkbox above it — Hugo). The wrap is relative
   so the cap overlays the button's right end; the button reserves right padding so its
   centred label never slides under the cap. */
.gen-copy-wrap { position: relative; display: flex; width: 100%; }
.gen-copy-wrap > .gen-go-btn { flex: 1 1 auto; width: 100%; }
.gen-go-btn--frametoggle { padding-right: 150px; }
.gen-copy-frametoggle {
  position: absolute;
  top: 6px; bottom: 6px; right: 7px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 15px 0 16px;
  border: none;
  border-radius: var(--r-round);
  background: transparent;
  color: color-mix(in srgb, var(--ink-cream) 60%, transparent);
  font: inherit;
  font-size: var(--fs-11);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-06);
  text-transform: uppercase;
  cursor: pointer;
  user-select: none;
  text-shadow: 0 1px 1px color-mix(in srgb, var(--forest) 35%, transparent);
  transition: color var(--dur-2) ease, background var(--dur-2) ease, box-shadow var(--dur-2) ease;
}
/* hairline that separates the cap from the main copy action */
.gen-copy-frametoggle::before {
  content: "";
  position: absolute;
  left: 0; top: 5px; bottom: 5px;
  width: 1px;
  background: color-mix(in srgb, var(--ivory-2) 32%, transparent);
  transition: background var(--dur-2) ease;
}
.gen-copy-frametoggle svg { flex: 0 0 auto; opacity: 0.68; transition: opacity var(--dur-2) ease; }
.gen-copy-frametoggle:hover { color: color-mix(in srgb, var(--ink-cream) 92%, transparent); }
.gen-copy-frametoggle:hover svg { opacity: 0.95; }
.gen-copy-frametoggle.is-on {
  color: var(--ink-cream);
  background: color-mix(in srgb, var(--ivory-2) 20%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ivory-2) 45%, transparent), 0 1px 4px color-mix(in srgb, var(--surface-forest) 28%, transparent);
}
.gen-copy-frametoggle.is-on svg { opacity: 1; }
.gen-copy-frametoggle.is-on::before { background: color-mix(in srgb, var(--ivory-2) 14%, transparent); }
.gen-copy-frametoggle-label { white-space: nowrap; }
/* v06k — Liquid-glass Generate button. Semi-transparent fill, soft
   inner highlight, backdrop blur on the surface so background scroll
   content reads through subtly. Stays comfortably inside the footer
   padding so the edges never look cut. */
.gen-go-btn {
  font: inherit;
  font-size: var(--fs-14);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-08);
  text-transform: uppercase;
  padding: 14px 24px;
  border-radius: var(--r-round);
  border: 1px solid color-mix(in srgb, var(--leaf) 65%, transparent);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--ivory) 35%, transparent) 0%,
      color-mix(in srgb, var(--ivory) 8%, transparent) 50%,
      color-mix(in srgb, var(--black) 5%, transparent) 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--leaf) 75%, transparent) 0%, color-mix(in srgb, var(--olive-2) 82%, transparent) 100%);
  color: var(--ink-cream);
  cursor: pointer;
  backdrop-filter: blur(8px) saturate(1.1);
  -webkit-backdrop-filter: blur(8px) saturate(1.1);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ivory-2) 55%, transparent),
    inset 0 -1px 0 color-mix(in srgb, var(--surface-forest) 30%, transparent),
    0 6px 18px color-mix(in srgb, var(--surface-forest) 28%, transparent),
    0 1px 3px color-mix(in srgb, var(--surface-forest) 15%, transparent);
  transition: filter var(--dur-1) ease, transform 90ms ease, box-shadow var(--dur-1) ease;
  text-shadow: 0 1px 1px color-mix(in srgb, var(--forest) 35%, transparent);
}
.gen-go-btn:hover:not(:disabled) {
  filter: brightness(1.06);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ivory-2) 65%, transparent),
    inset 0 -1px 0 color-mix(in srgb, var(--surface-forest) 30%, transparent),
    0 8px 22px color-mix(in srgb, var(--surface-forest) 36%, transparent),
    0 1px 3px color-mix(in srgb, var(--surface-forest) 20%, transparent);
}
.gen-go-btn:active:not(:disabled) { transform: translateY(1px); }
.gen-go-btn:disabled {
  /* 24 Sep 2026 - readable when disabled (tokens.css): a quiet neutral fill and the full ink, never a 55% fade */
  cursor: not-allowed;
  background: var(--disabled-fill);
  border-color: var(--disabled-line);
  color: var(--disabled-ink);
}

/* v06k — Refine button row sits inside the prompt preview body block.
   Reset button is a subtle text-link. */
.gen-preview-refine-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.gen-refine-reset {
  font: inherit;
  font-size: var(--fs-11);
  font-weight: var(--fw-semi);
  color: var(--ink-muted);
  background: transparent;
  border: none;
  cursor: pointer;
  text-decoration: underline;
  padding: 4px 6px;
}
.gen-refine-reset:hover { color: var(--ink); }
.gen-refine-reset:disabled { opacity: 0.45; cursor: default; }   /* 23 Sep 2026 — drawn greyed while Refine is hidden */
.gen-refine-reset:disabled:hover { color: inherit; }

/* v06o — Voice Over panel layout. Voice + settings on the left,
   text + enhance on the right. Settings card holds 3 sliders +
   2 dropdowns; right card holds 2 textareas + enhance button. */
.gen-vo-settings {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1 1 0;
  min-height: 0;
}
/* v06p — Standalone styling. Earlier we layered `.gen-direction` on
   top of `.gen-vo-select`, which dragged in `min-height: 120px`
   from the textarea base and stretched every dropdown to 120px.
   The select now carries its own border / padding / font so it
   renders as a normal-height dropdown (~34px). */
.gen-vo-select {
  width: 100%;
  font: inherit;
  font-size: var(--fs-13-5);
  line-height: 1.4;
  height: 34px;
  min-height: 0;
  /* v06p — Explicit box-sizing so this matches `.gen-vo-locked-chip`
     pixel-for-pixel. Swapping between the two states (free-form
     vs locked voice) must NOT shift rows below. */
  box-sizing: border-box;
  padding: 0 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent);
  color: var(--ink);
  cursor: pointer;
}
.gen-vo-select:focus {
  outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent);
  outline-offset: 1px;
}
.gen-vo-slider-row {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.gen-vo-slider-row .gen-duration-slider {
  margin: 0;
}
.gen-vo-slider-row .gen-video-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
/* v06p — Hint next to the Voice label when an auto-pick happened. */
.gen-vo-locked-hint {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-10-5);
  color: var(--accent, var(--olive-5));
  margin-left: 6px;
}

/* v06p — Character picker as a horizontal row of round avatars.
   Replaces the old <select> dropdown so Hugo can pick by face.
   Wraps to multiple lines if the cast is large. */
.gen-vo-char-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 4px;
}
.gen-vo-char-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  background: transparent;
  border: none;
  padding: 4px 2px;
  cursor: pointer;
  width: 70px;
  flex: 0 0 auto;
  transition: transform var(--dur-1) ease;
}
.gen-vo-char-cell:hover { transform: translateY(-1px); }
.gen-vo-char-avatar {
  position: relative;
  width: 56px;
  height: 56px;
  /* v06p — Square with rounded corners (matches the rest of the
     UI's card radii). The previous round shape clashed visually
     with the panel cards. */
  border-radius: var(--r-panel);
  background-color: color-mix(in srgb, var(--tan-deep) 10%, transparent);
  background-size: cover;
  background-position: center top;
  border: 2px solid transparent;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--shadow-ink) 18%, transparent);
  transition: border-color var(--dur-2) ease, box-shadow var(--dur-2) ease, transform var(--dur-2) ease;
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* v06p — Proper metallic gold-foil active state. Stacked
   box-shadows create a multi-band ring: bright yellow-gold
   inside, deeper antique gold outside, with a warm glow and a
   subtle drop. Reads as actual foil rather than a brown
   accent. */
.gen-vo-char-cell.is-active .gen-vo-char-avatar {
  border-color: color-mix(in srgb, var(--gold-13) 77%, var(--mix-light));
  box-shadow:
    /* thin cream halo so the gold doesn't bleed into the bg */
    0 0 0 2px color-mix(in srgb, var(--cream) 95%, transparent),
    /* bright outer gold band */
    0 0 0 3px color-mix(in srgb, var(--gold-13) 76%, var(--mix-light)),
    /* deeper antique-gold band beneath that — produces the foil sheen */
    0 0 0 5px color-mix(in srgb, var(--gold) 94%, var(--mix-dark)),
    /* warm yellow glow */
    0 0 14px 2px color-mix(in srgb, color-mix(in srgb, var(--gold-13) 84%, var(--mix-light)) 55%, transparent),
    /* drop shadow */
    0 3px 8px color-mix(in srgb, color-mix(in srgb, var(--shadow-ink-2) 90%, var(--mix-dark)) 25%, transparent);
  transform: scale(1.04);
}
.gen-vo-char-cell:hover .gen-vo-char-avatar {
  border-color: color-mix(in srgb, var(--tan-deep) 45%, transparent);
}
.gen-vo-char-avatar--none {
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 2px dashed color-mix(in srgb, var(--tan-deep) 45%, transparent);
  color: var(--ink-muted);
  font-size: var(--fs-22);
  font-weight: 300;
  border-radius: var(--r-panel);
}
.gen-vo-char-cell.is-active .gen-vo-char-avatar--none {
  border-style: solid;
  border-color: color-mix(in srgb, var(--gold-13) 77%, var(--mix-light));
  background: color-mix(in srgb, var(--cream) 95%, transparent);
  color: var(--ink);
}
.gen-vo-char-initials {
  font-family: var(--font-display, "Bebas Neue"), sans-serif;
  font-size: var(--fs-18);
  color: var(--ink);
  letter-spacing: var(--track-04);
}
/* v06p — Characters without an assigned voice render slightly
   dimmed so Hugo can tell at a glance which ones are wired up
   without needing a label or pip. Active state still wins (full
   opacity + gold foil). Hover lifts opacity too. */
.gen-vo-char-cell.no-voice .gen-vo-char-avatar { opacity: 0.55; }
.gen-vo-char-cell.no-voice:hover .gen-vo-char-avatar,
.gen-vo-char-cell.no-voice.is-active .gen-vo-char-avatar { opacity: 1; }
.gen-vo-char-cell.no-voice .gen-vo-char-name { color: var(--ink-muted); }
.gen-vo-char-name {
  font-size: var(--fs-10-5);
  font-weight: var(--fw-med);
  letter-spacing: var(--track-02);
  color: var(--ink);
  max-width: 70px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gen-vo-char-cell.is-active .gen-vo-char-name {
  color: color-mix(in srgb, var(--gold) 94%, var(--mix-dark));
  font-weight: var(--fw-bold);
}

/* v06p — Locked-voice chip: replaces the Voice dropdown when the
   selected character has an assigned voice. Shows mic icon + voice
   name + "from <character>" + an Override button to release the
   lock for this one generation. Height MUST match the .gen-vo-select
   dropdown exactly so swapping between the two states (free-form
   vs character with voice) doesn't shift the rows below. */
.gen-vo-locked-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  height: 34px;
  box-sizing: border-box;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--olive-5) 45%, transparent);
  background: color-mix(in srgb, var(--mint) 55%, transparent);
  font-size: var(--fs-13);
  color: var(--ink);
}
.gen-vo-locked-mic { font-size: var(--fs-14); }
.gen-vo-locked-name {
  font-weight: var(--fw-semi);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gen-vo-locked-from {
  font-size: var(--fs-11);
  color: var(--ink-muted);
  white-space: nowrap;
  margin-left: -2px;
}
.gen-vo-locked-override {
  margin-left: auto;
  font: inherit;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-med);
  letter-spacing: var(--track-04);
  text-transform: uppercase;
  padding: 2px 9px;
  height: 22px;
  line-height: 1;
  border-radius: 5px;
  border: 1px solid color-mix(in srgb, var(--olive-5) 55%, transparent);
  background: transparent;
  color: var(--accent, var(--olive-5));
  cursor: pointer;
  transition: background var(--dur-1) ease;
}
.gen-vo-locked-override:hover { background: color-mix(in srgb, var(--mix-light) 50%, transparent); }
.gen-vo-relock-btn {
  font: inherit;
  font-size: var(--fs-10);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-04);
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 5px;
  border: 1px solid color-mix(in srgb, var(--olive-5) 45%, transparent);
  background: transparent;
  color: var(--accent, var(--olive-5));
  cursor: pointer;
  margin-left: 8px;
}

/* v06p — Eleven v3 stability preset buttons. Three pills laid out
   side-by-side; the active one gets the same green treatment as
   the Mode / Model / Resolution buttons elsewhere on the page. */
.gen-vo-preset-row {
  display: flex;
  gap: 6px;
  margin-top: 4px;
}
.gen-vo-preset-btn {
  flex: 1 1 0;
  font: inherit;
  font-size: var(--fs-12);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-04);
  text-transform: uppercase;
  padding: 7px 8px;
  border-radius: var(--r-7);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream-2) 55%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-vo-preset-btn:hover {
  background: color-mix(in srgb, var(--cream-2) 85%, transparent);
  color: var(--ink);
}
.gen-vo-preset-btn.is-active {
  background: color-mix(in srgb, var(--olive-10) 85%, transparent);
  color: var(--white);
  border-color: color-mix(in srgb, var(--olive-10) 95%, transparent);
}
.gen-vo-preset-hint {
  margin-top: 4px;
  font-size: var(--fs-11);
  color: var(--ink-muted);
  font-style: italic;
}

/* v06p — Per-character direction preset chips. Sit above the
   Direction textarea in VO mode whenever the picked character has
   saved presets. Click one to drop its body into the textarea. */
.gen-vo-direction-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 4px 0 6px;
}
.gen-vo-direction-preset {
  font: inherit;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-med);
  padding: 4px 10px;
  border-radius: var(--r-card);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  color: var(--ink);
  cursor: pointer;
  transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-vo-direction-preset:hover {
  background: color-mix(in srgb, var(--mint) 65%, transparent);
  border-color: color-mix(in srgb, var(--olive-5) 55%, transparent);
}
.gen-vo-direction-preset.is-active {
  background: color-mix(in srgb, var(--olive-10) 85%, transparent);
  color: var(--white);
  border-color: color-mix(in srgb, var(--olive-10) 95%, transparent);
}
.gen-vo-direction-presets-hint {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-10-5);
  color: var(--accent, var(--olive-5));
  margin-left: 6px;
}

/* v06p — Generated VO history. Sits below the Generate button.
   Each row is one completed take: status pill, version label,
   shot scope, reveal-in-folder button, inline audio scrubber.
   Stacked newest-first so the user can compare takes without
   losing earlier ones. */
.gen-vo-results {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}
.gen-vo-result {
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 1px solid var(--card-border);
}
.gen-vo-result .gen-job-line {
  align-items: center;
  gap: 10px;
}
.gen-vo-result-scope {
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-10-5);
  color: var(--ink-muted);
  margin-left: 4px;
}
.gen-vo-result-actions {
  margin-left: auto;
  display: inline-flex;
  gap: 6px;
}
.gen-vo-result-reveal {
  position: static !important;
  width: 26px;
  height: 26px;
}

/* v06p — Multi-shot grouping section. Sits above the 2-col row in
   VO mode; lets Hugo include adjacent narration shots in one
   continuous take so ElevenLabs has 3+ sentences of context. */
.gen-vo-group-section .gen-section-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.gen-vo-group-hint {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-11);
  color: var(--ink-muted);
  font-style: italic;
}
.gen-vo-group-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 8px;
  max-height: 220px;
  overflow-y: auto;
  scrollbar-gutter: stable;
}
.gen-vo-group-row {
  display: grid;
  grid-template-columns: 18px 60px 120px 1fr;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  border-radius: var(--r-7);
  border: 1px solid transparent;
  background: color-mix(in srgb, var(--cream-2) 45%, transparent);
  font-size: var(--fs-12-5);
  color: var(--ink);
  cursor: pointer;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-vo-group-row:hover { background: color-mix(in srgb, var(--cream-2) 85%, transparent); }
.gen-vo-group-row.is-checked {
  background: color-mix(in srgb, var(--mint) 55%, transparent);
  border-color: color-mix(in srgb, var(--olive-5) 45%, transparent);
}
.gen-vo-group-row.is-anchor {
  background: color-mix(in srgb, color-mix(in srgb, var(--pale-green) 60%, var(--mix-light)) 60%, transparent);
  border-color: color-mix(in srgb, var(--olive-5) 70%, transparent);
  cursor: default;
}
.gen-vo-group-row input[type="checkbox"] {
  cursor: inherit;
  accent-color: var(--olive-7);
}
.gen-vo-group-id {
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-11);
  font-weight: var(--fw-semi);
  color: var(--ink);
}
.gen-vo-group-speaker {
  font-size: var(--fs-10);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-08);
  text-transform: uppercase;
  color: var(--accent, var(--olive-5));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gen-vo-group-snippet {
  font-size: var(--fs-12);
  color: var(--ink-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* v06p — Voice picker dropdown inside CharacterDetailModal. Mirrors
   the .gen-vo-select look for consistency. */
.char-voice-select {
  flex: 1 1 0;
  min-width: 0;
  height: 36px;
  padding: 4px 10px;
  font: inherit;
  font-size: var(--fs-13);
  cursor: pointer;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--card-border) 55%, transparent);
  background: color-mix(in srgb, var(--cream-2) 75%, transparent);
  color: var(--ink);
}
.char-voice-select:focus {
  outline: var(--ring-w) solid color-mix(in srgb, var(--olive-5) 45%, transparent);
  outline-offset: 1px;
}
.gen-upscale-inputs--single {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1 1 0;
  min-height: 0;
}
.gen-upscale-inputs--single .gen-video-field {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.gen-upscale-inputs--single .gen-direction {
  flex: 1 1 0;
  min-height: 0;
  resize: none;
}

/* v06l — Upscale inputs (Override + Customized) inside the match-refs
   container — both textareas flex-fill so the panel never has dead
   space below. */
.gen-section--upscale .gen-upscale-inputs {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1 1 0;
  min-height: 0;
}
.gen-section--upscale .gen-upscale-inputs .gen-video-field {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.gen-section--upscale .gen-upscale-inputs .gen-direction {
  flex: 1 1 0;
  min-height: 0;
  resize: none;
}
.gen-upscale-base-btn {
  font: inherit;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-03);
  padding: 8px 14px;
  border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 55%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
}
.gen-upscale-base-btn:hover {
  background: color-mix(in srgb, var(--cream) 95%, transparent);
  color: var(--ink);
}

/* v06l — Base template editor modal. Reuses .modal-backdrop from
   modal.css so the dim + viewport coverage matches every other
   modal in the app. */
.gen-base-modal {
  position: relative;
  width: min(720px, 92vw);
  max-height: 80vh;
  background: linear-gradient(180deg, color-mix(in srgb, var(--cream-2) 98%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-5) 20%, var(--mix-light)) 96%, transparent));
  border: 1px solid color-mix(in srgb, var(--card-border) 55%, transparent);
  border-radius: var(--r-card);
  padding: 18px 20px 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow: 0 20px 60px color-mix(in srgb, var(--shade-15) 45%, transparent);
  color: var(--ink);
}
.gen-base-modal-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.gen-base-modal-x {
  border: none;
  background: color-mix(in srgb, var(--tan-deep) 10%, transparent);
  color: var(--ink);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: var(--fs-18);
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}
.gen-base-modal-x:hover { background: color-mix(in srgb, var(--tan-deep) 20%, transparent); }
.gen-base-modal-textarea {
  flex: 1;
  min-height: 280px;
  resize: vertical;
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-11-5);
  line-height: 1.45;
}
.gen-base-modal-foot {
  display: flex;
  align-items: center;
  gap: 8px;
}
.gen-base-modal-reset {
  font: inherit;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-semi);
  padding: 7px 12px;
  border-radius: var(--r-round);
  border: 1px solid color-mix(in srgb, var(--amber-5) 45%, transparent);
  background: color-mix(in srgb, var(--hi-3) 45%, transparent);
  color: color-mix(in srgb, var(--ink-tan-deep) 92%, var(--mix-dark));
  cursor: pointer;
}
.gen-base-modal-reset:hover { background: color-mix(in srgb, var(--hi-3) 85%, transparent); }
.gen-base-modal-cancel,
.gen-base-modal-save {
  font: inherit;
  font-size: var(--fs-12);
  font-weight: var(--fw-bold);
  padding: 8px 16px;
  border-radius: var(--r-round);
  cursor: pointer;
  letter-spacing: var(--track-04);
}
.gen-base-modal-cancel {
  background: transparent;
  border: 1px solid var(--card-border);
  color: var(--ink);
}
.gen-base-modal-cancel:hover { background: color-mix(in srgb, var(--cream) 55%, transparent); }
.gen-base-modal-save {
  background: linear-gradient(180deg, color-mix(in srgb, var(--leaf) 85%, transparent), color-mix(in srgb, var(--olive-2) 92%, transparent));
  border: 1px solid color-mix(in srgb, var(--olive-2) 85%, transparent);
  color: var(--ink-cream);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--surface-forest) 25%, transparent);
}
.gen-base-modal-save:hover { filter: brightness(1.06); }

/* Job status panel */
.gen-job {
  padding: 12px 14px;
  border-radius: var(--r-panel);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
}
.gen-job--started   { border-color: color-mix(in srgb, var(--warn) 65%, transparent); background: color-mix(in srgb, var(--hi-2) 85%, transparent); }
.gen-job--completed { border-color: color-mix(in srgb, var(--ok) 65%, transparent);  background: color-mix(in srgb, color-mix(in srgb, var(--mint) 91%, var(--mix-light)) 65%, transparent); }
.gen-job--failed    { border-color: color-mix(in srgb, var(--danger-soft-2) 65%, transparent);   background: color-mix(in srgb, color-mix(in srgb, var(--amber) 31%, var(--mix-light)) 65%, transparent); }
/* v06d — Video manual job: prompt copied + queue row inserted, now
   waiting for the user to run the generation externally and drop the
   resulting MP4 into the watched folder. */
.gen-job--manual    { border-color: color-mix(in srgb, var(--blue-10) 65%, transparent); background: color-mix(in srgb, var(--blue-11) 65%, transparent); }
.gen-job--manual .gen-job-dot { background: var(--blue-9); animation: gen-pulse var(--dur-pulse) ease-in-out infinite; }

/* v06g/v06n — Upscale actions row. The buttons used to touch the
   Customized prompt textarea above — added margin-top + a soft
   divider to space it out. */
.gen-upscale-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed color-mix(in srgb, var(--card-border) 30%, transparent);
  flex-shrink: 0;
}
/* v06m — Customize button shrunk to match the Edit Base Template
   button size. They sit side-by-side in the actions row so they
   should read as a matched pair. */
.gen-upscale-customize-btn {
  font: inherit;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-03);
  padding: 8px 14px;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--gold-9) 55%, transparent);
  background: color-mix(in srgb, color-mix(in srgb, var(--gold-3) 56%, var(--mix-light)) 55%, transparent);
  color: color-mix(in srgb, var(--ink-tan-deep) 58%, var(--mix-dark));
  cursor: pointer;
  transition: transform 90ms ease, filter var(--dur-1) ease, background var(--dur-1) ease;
}
.gen-upscale-customize-btn:hover:not(:disabled) {
  filter: brightness(1.04);
  background: color-mix(in srgb, color-mix(in srgb, var(--gold-3) 56%, var(--mix-light)) 85%, transparent);
}
.gen-upscale-customize-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.gen-upscale-hint {
  font-size: var(--fs-11-5);
  color: var(--ink-muted);
  font-style: italic;
}
.gen-upscale-error {
  font-size: var(--fs-11-5);
  color: var(--danger-ink);
  background: color-mix(in srgb, var(--danger-soft-2) 10%, transparent);
  padding: 4px 10px;
  border-radius: var(--r-xs);
}
.gen-upscale-badge {
  display: inline-block;
  margin-left: 8px;
  font-size: var(--fs-9-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-08);
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: var(--r-round);
  background: color-mix(in srgb, var(--leaf) 22%, transparent);
  color: var(--olive-3);
  border: 1px solid color-mix(in srgb, var(--leaf) 40%, transparent);
}
.gen-upscale-badge--empty {
  background: color-mix(in srgb, var(--ink-muted) 12%, transparent);
  color: var(--ink-muted);
  border-color: color-mix(in srgb, var(--ink-muted) 25%, transparent);
}
.gen-job-line {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-12);
}
.gen-job-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--leaf);
}
.gen-job--started .gen-job-dot   { background: var(--warn); animation: gen-pulse 1.2s ease-in-out infinite; }
.gen-job--completed .gen-job-dot { background: var(--ok); }
.gen-job--failed .gen-job-dot    { background: var(--danger-soft-2); }
@keyframes gen-pulse {
  0%, 100% { opacity: 0.6; transform: scale(0.85); }
  50%      { opacity: 1;   transform: scale(1.1); }
}
.gen-job-status {
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-10);
  color: var(--ink);
}
.gen-job-id {
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-10-5);
  color: var(--ink-muted);
  margin-left: auto;
}
/* v06i — Elapsed-time chip — sits between the status text and the
   job id. Updates every 500ms while a job is in flight. */
.gen-job-elapsed {
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-semi);
  color: var(--ink);
  background: color-mix(in srgb, var(--shadow-ink) 8%, transparent);
  padding: 1px 8px;
  border-radius: var(--r-round);
}
/* v06i — Live subprocess log. Scrollable terminal-style output of
   every line streamed from the Python subprocess via SSE. */
.gen-job-log {
  margin-top: 10px;
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-11);
  line-height: 1.4;
  background: color-mix(in srgb, var(--shade-10) 85%, transparent);
  color: color-mix(in srgb, var(--ink-paper-2) 90%, var(--mix-dark));
  padding: 10px 12px;
  border-radius: var(--r-xs);
  max-height: 180px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--gold-9) 45%, transparent) transparent;
}
.gen-job-log-line {
  white-space: pre-wrap;
  word-break: break-word;
}
.gen-job-log-line--stderr {
  color: color-mix(in srgb, var(--gold-16) 60%, var(--mix-light));
}
.gen-job-detail {
  margin-top: 8px;
  font-size: var(--fs-12-5);
  color: var(--ink);
}
.gen-job-detail code {
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-11);
  background: color-mix(in srgb, var(--shadow-ink) 8%, transparent);
  padding: 1px 5px;
  border-radius: 4px;
}
.gen-job-error {
  margin-top: 8px;
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-11);
  color: var(--danger-ink);
  background: color-mix(in srgb, var(--danger-soft-2) 10%, transparent);
  padding: 8px 10px;
  border-radius: var(--r-xs);
  white-space: pre-wrap;
}
.gen-error {
  padding: 10px 12px;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--danger-soft-2) 65%, transparent);
  background: color-mix(in srgb, color-mix(in srgb, var(--amber) 31%, var(--mix-light)) 65%, transparent);
  color: var(--danger-ink);
  font-size: var(--fs-12-5);
}

/* v07zz50 — Asset-mode generation panel. Mirrors the .gen-shell two-
   column layout (picker | builder) but with an asset list on the left
   instead of a shot list. WIP grid sits beneath the form. */
.gen-shell--asset {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}
.gen-asset-picker {
  background: color-mix(in srgb, var(--shade-21) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--cream-3) 8%, transparent);
  border-radius: var(--r-panel);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: calc(100vh - 200px);
}
.gen-asset-cattabs {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  border-bottom: 1px solid color-mix(in srgb, var(--cream-3) 8%, transparent);
  padding-bottom: 8px;
}
.gen-asset-cattab {
  font: inherit;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-semi);
  letter-spacing: var(--track-08);
  text-transform: uppercase;
  padding: 5px 9px;
  border-radius: var(--r-xs);
  border: 1px solid color-mix(in srgb, var(--amber) 32%, transparent);
  background: transparent;
  color: var(--ink-cream-8);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-asset-cattab:hover { background: color-mix(in srgb, color-mix(in srgb, var(--surface-forest) 84%, var(--mix-light)) 45%, transparent); border-color: color-mix(in srgb, var(--gold-3) 55%, transparent); }
.gen-asset-cattab.is-active {
  background: color-mix(in srgb, var(--gold-3) 18%, transparent);
  border-color: color-mix(in srgb, var(--gold-3) 85%, transparent);
  color: var(--ink-hi-3);
}
.gen-asset-cattab-count {
  font-size: var(--fs-9);
  padding: 1px 5px;
  background: color-mix(in srgb, var(--black) 30%, transparent);
  border-radius: var(--r-sm);
  opacity: 0.85;
}
.gen-asset-list {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.gen-asset-empty {
  padding: 24px 12px;
  text-align: center;
  font-size: var(--fs-12);
  color: var(--ink-muted, var(--ink-grey-7));
  font-style: italic;
}
.gen-asset-row {
  display: flex;
  gap: 10px;
  padding: 8px;
  border-radius: var(--r-7);
  border: 1px solid transparent;
  background: transparent;
  cursor: pointer;
  align-items: center;
  font: inherit;
  text-align: left;
  color: inherit;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-asset-row:hover {
  background: color-mix(in srgb, color-mix(in srgb, var(--surface-forest) 84%, var(--mix-light)) 35%, transparent);
  border-color: color-mix(in srgb, var(--gold-3) 30%, transparent);
}
.gen-asset-row.is-active {
  background: color-mix(in srgb, var(--gold-3) 14%, transparent);
  border-color: color-mix(in srgb, var(--gold-3) 85%, transparent);
  box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--gold-3) 35%, transparent), 0 0 10px color-mix(in srgb, var(--gold-3) 25%, transparent);
}
.gen-asset-row-thumb {
  width: 42px; height: 42px;
  border-radius: var(--r-xs);
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--surface-forest) 89%, var(--mix-light)) 60%, transparent), color-mix(in srgb, color-mix(in srgb, var(--surface-forest) 67%, var(--mix-light)) 45%, transparent));
  background-size: cover;
  background-position: center;
  display: grid; place-items: center;
  font-size: var(--fs-16); font-weight: var(--fw-bold);
  color: color-mix(in srgb, var(--ink-cream-9) 84%, var(--mix-dark));
  flex-shrink: 0;
}
.gen-asset-row-body { min-width: 0; flex: 1; }
.gen-asset-row-name { font-size: var(--fs-13); font-weight: var(--fw-semi); color: var(--ink-cream-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gen-asset-row-sub  { font-size: var(--fs-11); color: color-mix(in srgb, var(--ink-cream-3) 55%, transparent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.gen-prompt-input {
  width: 100%;
  font: inherit;
  font-family: var(--font-mono, "JetBrains Mono", monospace);
  font-size: var(--fs-12-5);
  line-height: 1.55;
  padding: 12px;
  background: color-mix(in srgb, var(--black) 25%, transparent);
  border: 1px solid color-mix(in srgb, var(--cream-3) 12%, transparent);
  border-radius: var(--r-sm);
  color: var(--ink-cream-3);
  resize: vertical;
  min-height: 140px;
}
.gen-prompt-input:focus { outline: none; border-color: color-mix(in srgb, var(--gold-3) 65%, transparent); box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--gold-3) 25%, transparent); }

.gen-section-head {
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-14);
  text-transform: uppercase;
  color: var(--ink-muted, color-mix(in srgb, var(--ink-cream-3) 62%, transparent));
  margin: 14px 0 8px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.gen-asset-attach-btn,
.gen-asset-refresh {
  margin-left: auto;
  font: inherit;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-semi);
  padding: 4px 11px;
  border-radius: var(--r-xs);
  border: 1px solid color-mix(in srgb, var(--leaf) 45%, transparent);
  background: color-mix(in srgb, var(--leaf) 18%, transparent);
  color: color-mix(in srgb, var(--pale-green) 36%, var(--mix-light));
  cursor: pointer;
}
.gen-asset-attach-btn:hover, .gen-asset-refresh:hover { background: color-mix(in srgb, var(--leaf) 32%, transparent); }

.gen-asset-refs-empty,
.gen-asset-wip-empty {
  padding: 20px;
  text-align: center;
  font-size: var(--fs-12);
  color: var(--ink-muted, color-mix(in srgb, var(--ink-cream-3) 55%, transparent));
  font-style: italic;
  background: color-mix(in srgb, var(--black) 12%, transparent);
  border-radius: var(--r-sm);
  border: 1px dashed color-mix(in srgb, var(--cream-3) 10%, transparent);
}
.gen-asset-refs-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.gen-asset-ref-tile {
  position: relative;
  width: 90px; height: 60px;
  border-radius: var(--r-xs);
  overflow: hidden;
  background: var(--ied-bg-8);
  border: 1px solid color-mix(in srgb, var(--cream-3) 10%, transparent);
}
.gen-asset-ref-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gen-asset-ref-x {
  position: absolute; top: 3px; right: 3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--danger-soft) 85%, transparent);
  border: none; color: var(--white);
  cursor: pointer;
  font-size: var(--fs-13); line-height: 16px;
  font-weight: var(--fw-bold);
}
.gen-asset-ref-name {
  position: absolute; left: 4px; right: 4px; bottom: 3px;
  font-size: var(--fs-9);
  color: var(--white);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gen-asset-models { display: flex; gap: 6px; flex-wrap: wrap; }
.gen-asset-model-pill {
  font: inherit;
  font-size: var(--fs-11);
  font-weight: var(--fw-semi);
  padding: 6px 12px;
  border-radius: var(--r-round);
  border: 1px solid color-mix(in srgb, var(--amber) 32%, transparent);
  background: color-mix(in srgb, var(--shade-22) 55%, transparent);
  color: var(--ink-cream-8);
  cursor: pointer;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}
.gen-asset-model-pill:hover { background: color-mix(in srgb, color-mix(in srgb, var(--surface-forest) 84%, var(--mix-light)) 55%, transparent); border-color: color-mix(in srgb, var(--gold-3) 55%, transparent); }
.gen-asset-model-pill.is-active {
  background: linear-gradient(135deg, color-mix(in srgb, var(--hi-2) 92%, transparent) 0%, color-mix(in srgb, var(--nav-active) 82%, transparent) 50%, color-mix(in srgb, var(--gold-deep) 55%, transparent) 100%);
  border-color: color-mix(in srgb, var(--gold-deep) 92%, transparent);
  color: var(--ink-2);
}

.gen-asset-wip-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
}
.gen-asset-wip-tile {
  position: relative;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--ied-bg-7);
  border: 1px solid color-mix(in srgb, var(--cream-3) 10%, transparent);
  aspect-ratio: var(--project-aspect, 21 / 9);
}
.gen-asset-wip-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gen-asset-wip-actions {
  position: absolute;
  top: 6px; left: 6px; right: 6px;
  display: flex;
  justify-content: space-between;
  gap: 6px;
}
.gen-asset-wip-promote {
  font: inherit;
  font-size: var(--fs-10-5);
  font-weight: var(--fw-bold);
  padding: 5px 10px;
  border-radius: var(--r-xs);
  border: 1px solid color-mix(in srgb, var(--gold-deep) 85%, transparent);
  background: linear-gradient(135deg, color-mix(in srgb, var(--hi-2) 92%, transparent) 0%, color-mix(in srgb, var(--nav-active) 82%, transparent) 50%, color-mix(in srgb, var(--gold-deep) 55%, transparent) 100%);
  color: var(--ink-2);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  text-shadow: 0 1px 0 color-mix(in srgb, var(--hi) 45%, transparent);
}
.gen-asset-wip-promote:hover { filter: brightness(1.08); }
.gen-asset-wip-discard {
  font: inherit;
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--danger-soft) 65%, transparent);
  background: color-mix(in srgb, var(--danger-soft) 18%, transparent);
  color: color-mix(in srgb, var(--gold-16) 51%, var(--mix-light));
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  font-size: var(--fs-14);
  line-height: 1;
}
.gen-asset-wip-discard:hover { background: color-mix(in srgb, var(--danger-soft) 35%, transparent); }
.gen-asset-wip-meta {
  position: absolute;
  left: 6px; right: 6px; bottom: 6px;
  font-size: var(--fs-9-5);
  color: var(--white);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85);
  font-family: var(--font-mono, monospace);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gen-empty-state {
  padding: 50px 30px;
  text-align: center;
  font-size: var(--fs-14);
  color: color-mix(in srgb, var(--ink-cream-3) 55%, transparent);
  font-style: italic;
}

/* ═══ v07zz84 — Asset Generation page (3-column, built to Hugo's UI
   reference). picker | builder | preview. Cream/forest language to
   match the rest of the app. ═════════════════════════════════════════ */
.ga-shell {
  display: grid;
  /* v07zz87 — first column 320px = EXACT shots-picker width so the
     left panel reads as the same panel as Shots (Hugo: "stay in the
     same panel as the shots but switch to assets"). */
  /* v07zz146 — Wider preview (was 300px) + slimmer middle: Hugo wanted
     more room for the generated image. The stacked Mode/Model/Aspect/Res
     controls free the horizontal space the middle column no longer needs. */
  grid-template-columns: 300px minmax(0, 1fr) 420px;
  gap: 16px;
  flex: 1;
  min-height: 0;
  align-items: stretch;
  /* v07zz102 — Hugo: the Assets picker must read as the SAME integrated
     panel as the Shots picker — its right edge running all the way to
     the top. The old `padding: 16px 4px` inset the whole grid (picker
     included) down from the top, so the cream picker floated with a
     strip of page background above it instead of butting against the
     top like .gen-shotpicker. Mirror .gen-shell exactly: zero padding,
     so the picker reaches the top; the builder/preview .ga-drawer panels
     carry their own internal padding for breathing room. */
  padding: 0;
}
.ga-eyebrow {
  font-size: var(--fs-10);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-16);
  text-transform: uppercase;
  color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-4) 70%, transparent));
  margin-bottom: 10px;
}
.ga-block-head {
  font-size: var(--fs-10);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-14);
  text-transform: uppercase;
  color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-4) 70%, transparent));
  margin-bottom: 8px;
}

/* v07zz457 — Additive Visual-style picker (props / animals asset gen). Chips reuse
   the shot-gen .gen-camstyle-chip pill family. The head carries a plain-English hint
   that the pick is added ON TOP of the prompt, never replacing it. */
.ga-style-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.ga-style-hint {
  font-size: var(--fs-9-5); font-weight: var(--fw-semi); letter-spacing: var(--track-02); text-transform: none;
  color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-4) 60%, transparent)); font-style: italic;
}
.ga-style-chips { display: flex; flex-wrap: wrap; gap: 7px; }
/* The "+ STYLE …" indicator under the prompt box — a read-only badge showing the
   line that will be appended on Generate (it is NOT part of the editable prompt). */
.ga-style-append {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 8px;
  padding: 4px 9px; border-radius: var(--r-round);
  background: linear-gradient(180deg, color-mix(in srgb, var(--nav-active) 35%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold) 75%, var(--mix-light)) 28%, transparent));
  border: 1px solid color-mix(in srgb, var(--gold-9) 50%, transparent);
  font-size: var(--fs-10-5); line-height: 1.1; color: var(--ink);
}
.ga-style-append-tag { font-weight: var(--fw-heavy); letter-spacing: var(--track-06); text-transform: uppercase; font-size: var(--fs-9-5); }
.ga-style-append-txt { font-weight: var(--fw-semi); }
.ga-style-append-note { color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-4) 65%, transparent)); font-style: italic; }

/* ─── LEFT: picker ─────────────────────────────────────────────────── */
.ga-picker {
  display: flex;
  flex-direction: column;
  /* v07zz104 — Outer shell is flush (no padding); the .ga-picker-head
     band below carries the padding + the SAME golden gradient as
     .gen-shotpicker-head, and the grid/foot supply their own padding, so
     the Assets picker reads as the exact same drawer as Shots. */
  gap: 0;
  background: color-mix(in srgb, var(--cream-2) 65%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-card);
  padding: 0;
  min-height: 0;
  overflow: hidden;
}
.ga-picker-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 14px 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, color-mix(in srgb, var(--gold-2) 26%, var(--mix-light)) 85%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-8) 31%, var(--mix-light)) 65%, transparent));
}
.ga-search-row { display: flex; gap: 6px; }
.ga-search {
  flex: 1; font: inherit; font-size: var(--fs-12-5);
  padding: 7px 11px; border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent); color: var(--ink, var(--ink-umber));
}
.ga-search:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }
.ga-search::placeholder { color: color-mix(in srgb, var(--ink-deep) 42%, transparent); }
.ga-search-clear {
  width: 34px; border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--leaf) 55%, transparent);
  background: color-mix(in srgb, var(--leaf) 85%, transparent);
  color: var(--white); cursor: pointer;
  display: grid; place-items: center;
}
.ga-search-clear:hover { background: var(--leaf); }
/* 23 Sep 2026 - Hugo: "make pills go on a second line and never crop on the side". A music project has
   six or more categories (Instruments, Wardrobe, Design...), so the row WRAPS instead of running off the
   panel's edge. The row's height is fixed by the project's category list, never by a click, so nothing
   moves when you pick a pill. */
.ga-kindpills { display: flex; gap: 6px; flex-wrap: wrap; }
/* v07zz151/154 — Hugo: pills size to their word (never crop "Characters"). min-width: max-content
   guarantees the full label fits. 23 Sep 2026 - Hugo: "i dont like that empty space at the right. make
   all the pills fit": flex-grow 1, so the pills on each line share the spare width and every line ends
   flush with the search row above. */
.ga-kindpills .ga-kindpill { flex: 1 1 auto; min-width: max-content; padding: 5px 9px; text-align: center; font-size: var(--fs-10-5); white-space: nowrap; }
.ga-kindpill {
  font: inherit; font-size: var(--fs-11); font-weight: var(--fw-semi);
  padding: 5px 11px; border-radius: var(--r-7);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 55%, transparent); color: var(--ink, var(--ink-umber));
  cursor: pointer; transition: background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}
.ga-kindpill:hover { background: color-mix(in srgb, var(--cream) 95%, transparent); border-color: color-mix(in srgb, var(--gold-deep) 65%, transparent); }
.ga-kindpill.is-active {
  background: linear-gradient(135deg, color-mix(in srgb, var(--hi-2) 95%, transparent) 0%, color-mix(in srgb, var(--nav-active) 85%, transparent) 60%, color-mix(in srgb, var(--gold-4) 65%, transparent) 100%);
  border-color: color-mix(in srgb, var(--gold-deep) 92%, transparent); color: var(--ink-2);
}
.ga-grid {
  flex: 1 1 0; min-height: 0; overflow-y: auto; overflow-x: hidden;
  /* v07zz87 — minmax(0,1fr) lets the tracks shrink BELOW the cards'
     min-content width (long asset names like "Hernando de Escalante
     Fontaneda" were forcing the tracks wide → the grid overflowed the
     picker and the 2nd column got clipped, which looked like a second
     panel). With minmax(0,1fr) the cards fit and the names ellipsize. */
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
  align-content: start; padding: 10px 12px 0;
}
.ga-grid-empty { grid-column: 1 / -1; padding: 24px 8px; text-align: center; font-size: var(--fs-12); font-style: italic; color: var(--ink-muted); }
.ga-card {
  display: flex; flex-direction: column; gap: 4px; padding: 6px;
  min-width: 0;
  border-radius: var(--r-9); border: 1px solid color-mix(in srgb, var(--card-border) 40%, transparent);
  background: color-mix(in srgb, var(--cream) 55%, transparent); cursor: pointer;
  font: inherit; text-align: left; color: inherit;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.ga-card:hover { background: color-mix(in srgb, var(--cream) 95%, transparent); border-color: color-mix(in srgb, var(--gold-deep) 50%, transparent); }
/* Hugo: selected card is GOLD. */
.ga-card.is-active {
  border-color: color-mix(in srgb, var(--gold-4) 95%, transparent);
  box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--gold-4) 55%, transparent), 0 0 12px color-mix(in srgb, var(--gold-3) 30%, transparent);
  background: color-mix(in srgb, var(--hi-2) 90%, transparent);
}
.ga-card-thumb {
  width: 100%; aspect-ratio: 1; border-radius: var(--r-xs);
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 80%, var(--mix-light)) 40%, transparent), color-mix(in srgb, var(--taupe) 30%, transparent));
  background-size: cover; background-position: center top;
  display: grid; place-items: center; position: relative; overflow: hidden;
  font-size: var(--fs-22); font-weight: var(--fw-bold); color: color-mix(in srgb, var(--ink-deep) 50%, transparent);
}
/* v07zz212 — solid cream placeholder + super-fast 90ms fade. Warm images skip it. */
.ga-card-thumb--img { background: color-mix(in srgb, var(--paper) 97%, var(--mix-dark)); }
.ga-card-thumb-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center top; border-radius: inherit;
  display: block; opacity: 0; transition: opacity 90ms linear;
}
.ga-card-thumb-img.is-loaded { opacity: 1; }
.ga-card-thumb-img.is-warm { opacity: 1; transition: none; }
.ga-card-name {
  font-size: var(--fs-12); font-weight: var(--fw-semi); color: var(--ink, var(--ink-umber));
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ga-card--add { align-items: center; justify-content: center; border-style: dashed; background: transparent; }
.ga-card--add .ga-card-add-plus { font-size: var(--fs-26); color: var(--ink-muted); line-height: 1; margin-bottom: 4px; }
.ga-card--add .ga-card-name { color: var(--ink-muted); }
.ga-picker-foot {
  display: flex; align-items: center; justify-content: space-between;
  font-size: var(--fs-11); color: var(--ink-muted); padding-top: 6px;
  border-top: 1px solid color-mix(in srgb, var(--card-border) 40%, transparent);
}
.ga-page-nav { display: flex; gap: 4px; }
.ga-page-nav button {
  width: 26px; height: 26px; border-radius: var(--r-xs);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink);
  cursor: pointer; font-size: var(--fs-14); line-height: 1;
}
.ga-page-nav button:disabled { opacity: 0.35; cursor: default; }
.ga-page-nav button:not(:disabled):hover { background: color-mix(in srgb, var(--hi-2) 95%, transparent); }

/* ─── Shared drawer shell (builder + preview) ──────────────────────── */
/* v07zz89 — Hugo: the builder + preview should read as cohesive cream
   drawers (same family as the Shots picker), "not some floaty ones".
   Each is one panel; the inner .ga-block sections are borderless and
   separated by dashed dividers instead of being little floating cards. */
.ga-drawer {
  background: color-mix(in srgb, var(--cream-2) 70%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-card);
  min-height: 0;
  overflow-y: auto;
  padding: 16px 18px;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.ga-drawer .ga-block {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 16px 0 0;
  margin-top: 16px;
  border-top: 1px dashed color-mix(in srgb, var(--card-border) 50%, transparent);
}
.ga-drawer .gen-settings { margin-top: 16px; }
.ga-drawer .gen-footer { padding: 16px 0 0; }

/* ─── MIDDLE: builder ──────────────────────────────────────────────── */
/* v07zz103 — Builder is NO LONGER a single .ga-drawer panel. It mirrors
   the Shots builder (.gen-builder): a transparent, scrollable column where
   the SELECTED ASSET header sits straight on the page background and each
   .ga-block below is its own bordered cream panel. */
.ga-builder {
  display: flex; flex-direction: column; gap: 12px;
  min-width: 0; min-height: 0; overflow-y: auto;
  /* v07zz104 — padding-top 18 = .gen-builder's 14 + .gen-header's 4, so
     the SELECTED ASSET eyebrow sits at the SAME Y as Shots' CREATE A
     PROMPT eyebrow (no header shift when toggling tabs). */
  padding: 18px 8px 24px 2px;
  scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
/* Header unit (eyebrow + title) matched to .gen-header / .gen-eyebrow /
   .gen-title so it reads identically to the Shots header. */
.ga-head-wrap { display: flex; flex-direction: column; }
.ga-head-wrap > .ga-eyebrow { margin-bottom: 4px; font-size: var(--fs-10-5); letter-spacing: var(--track-18); }

/* v07zz89 — Cleaner selected-asset header. */
.ga-asset-head { display: flex; flex-direction: column; gap: 8px; }
.ga-asset-head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.ga-title-line { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.ga-title {
  font-family: var(--font-display, "Bebas Neue", sans-serif);
  /* v07zz104 — match .gen-title (32px / 1.05) so the Assets title is the
     same size + baseline as the Shots title. */
  font-size: var(--fs-32); letter-spacing: var(--track-005); line-height: 1.05; color: var(--ink, var(--ink-2)); margin: 0;
}
.ga-kind-pill {
  font-size: var(--fs-9-5); font-weight: var(--fw-bold); letter-spacing: var(--track-10);
  padding: 3px 8px; border-radius: 5px;
  background: color-mix(in srgb, var(--leaf) 18%, transparent); color: color-mix(in srgb, var(--olive-2) 77%, var(--mix-dark));
}
/* v07zz104 — Match the green "Open shot ↗" pill in the Shots builder
   (ShotContextCard) exactly. */
.ga-open-btn {
  margin-left: auto; font: inherit; font-size: var(--fs-11); font-weight: var(--fw-semi);
  padding: 4px 10px; border-radius: var(--r-xs);
  border: 1px solid color-mix(in srgb, var(--olive-2) 55%, transparent);
  background: color-mix(in srgb, var(--leaf) 20%, transparent); color: var(--ink-forest-2); cursor: pointer;
}
.ga-open-btn:hover { background: color-mix(in srgb, var(--leaf) 32%, transparent); border-color: color-mix(in srgb, var(--olive-2) 80%, transparent); }
/* v07zz282 — Notes button next to "Open asset" + the notes panel it opens. */
.ga-head-actions { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; }
.ga-head-actions .ga-open-btn { margin-left: 0; }
.ga-notes-btn { background: color-mix(in srgb, var(--gold) 16%, transparent); border-color: color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 92%, var(--mix-light)) 50%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); }
.ga-notes-btn:hover { background: color-mix(in srgb, var(--gold) 28%, transparent); border-color: color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 92%, var(--mix-light)) 80%, transparent); }
.ga-notes-overlay {
  position: fixed; inset: 0; z-index: var(--z-crop);
  background: color-mix(in srgb, var(--shade-6) 55%, transparent); backdrop-filter: blur(var(--blur-scrim)); -webkit-backdrop-filter: blur(var(--blur-scrim));
  display: grid; place-items: center; padding: 32px;
  animation: ga-notes-fade var(--dur-2) ease-out;
}
@keyframes ga-notes-fade { from { opacity: 0; } to { opacity: 1; } }
.ga-notes-panel {
  width: min(560px, 92vw); max-height: 78vh; display: flex; flex-direction: column;
  background: var(--cream-15); border: 1px solid color-mix(in srgb, var(--taupe) 35%, transparent); border-radius: var(--r-card);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.42); overflow: hidden;
}
.ga-notes-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid color-mix(in srgb, var(--taupe) 18%, transparent);
  background: color-mix(in srgb, var(--gold) 7%, transparent);
}
.ga-notes-title { font-family: var(--font-display); font-size: var(--fs-16); letter-spacing: var(--track-02); color: var(--ink-bg); }
.ga-notes-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.ga-notes-copy {
  font: inherit; font-size: var(--fs-12); font-weight: var(--fw-semi); padding: 6px 12px; border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--taupe) 40%, transparent); background: color-mix(in srgb, var(--mix-light) 60%, transparent); color: color-mix(in srgb, var(--ink-umber-3) 90%, var(--mix-light)); cursor: pointer;
}
.ga-notes-copy:hover:not(:disabled) { border-color: color-mix(in srgb, var(--gold) 75%, transparent); }
.ga-notes-copy:disabled { opacity: 0.45; cursor: default; }
.ga-notes-close {
  font: inherit; font-size: var(--fs-15); width: 30px; height: 30px; border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--taupe) 30%, transparent); background: color-mix(in srgb, var(--mix-light) 50%, transparent); color: color-mix(in srgb, var(--archive) 67%, var(--mix-dark)); cursor: pointer;
}
.ga-notes-close:hover { background: color-mix(in srgb, var(--mix-light) 85%, transparent); }
.ga-notes-body { overflow-y: auto; padding: 10px 16px 16px; display: flex; flex-direction: column; gap: 10px; }
.ga-notes-empty { font-size: var(--fs-13); color: color-mix(in srgb, var(--ink-taupe-5) 86%, var(--mix-light)); font-style: italic; padding: 22px 4px; text-align: center; }
.ga-note { padding: 10px 12px; border-radius: var(--r-panel); background: color-mix(in srgb, var(--taupe) 6%, transparent); border: 1px solid color-mix(in srgb, var(--taupe) 14%, transparent); }
.ga-note-meta { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; font-size: var(--fs-11); }
.ga-note-author { font-weight: var(--fw-bold); color: color-mix(in srgb, var(--ink-umber-3) 90%, var(--mix-light)); }
.ga-note-resolved { color: var(--ink-forest-5); font-weight: var(--fw-semi); }
.ga-note-date { color: color-mix(in srgb, var(--ink-cream-6) 66%, var(--mix-dark)); margin-left: auto; }
.ga-note-text { font-size: var(--fs-13-5); line-height: 1.45; color: var(--ink-bg); white-space: pre-wrap; word-break: break-word; }
.ga-desc { font-size: var(--fs-13-5); line-height: 1.5; color: var(--ink, color-mix(in srgb, var(--ink-taupe) 58%, var(--mix-dark))); margin: 0; }
.ga-meta { display: flex; gap: 18px; flex-wrap: wrap; font-size: var(--fs-12); color: var(--ink, color-mix(in srgb, var(--ink-taupe) 58%, var(--mix-dark))); }
.ga-meta-k { font-size: var(--fs-9-5); font-weight: var(--fw-bold); letter-spacing: var(--track-10); color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-4) 65%, transparent)); margin-right: 4px; }

.ga-block {
  background: color-mix(in srgb, var(--cream-2) 55%, transparent);
  border: 1px solid var(--card-border);
  border-radius: var(--r-md); padding: 14px 16px;
}
.ga-block-sub { font-size: var(--fs-11-5); color: var(--ink-muted); margin: -4px 0 10px; }

/* ─── Camera Scout framings picker (v07zz405) ─────────────────────────── */
/* Only renders for a camera_scout template on a location, so it never shifts
   any other panel's height. Reads as one contained, scrollable checklist
   inside the cream ga-block, with shot-id chips + ellipsised framing text. */
.ga-scout-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.ga-scout-head .ga-block-head { margin-bottom: 0; }
.ga-scout-allbtn {
  font: inherit;
  font-size: var(--fs-10);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-06);
  text-transform: uppercase;
  padding: 5px 11px;
  border-radius: var(--r-7);
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  background: color-mix(in srgb, var(--cream) 70%, transparent);
  color: var(--ink-muted);
  cursor: pointer;
  flex-shrink: 0;
  transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.ga-scout-allbtn:hover { background: color-mix(in srgb, var(--hi-2) 95%, transparent); color: var(--ink); border-color: color-mix(in srgb, var(--card-border) 95%, transparent); }
.ga-scout-hint {
  font-size: var(--fs-10);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-05);
  text-transform: uppercase;
  color: var(--ink-muted);
  opacity: 0.8;
  margin-bottom: 8px;
}
.ga-scout-empty {
  font-size: var(--fs-11-5);
  font-style: italic;
  line-height: 1.5;
  color: var(--ink-muted);
  padding: 11px 13px;
  border: 1px dashed color-mix(in srgb, var(--card-border) 55%, transparent);
  border-radius: var(--r-panel);
  background: color-mix(in srgb, var(--cream-2) 45%, transparent);
}
/* Contained scroll panel — rows are clean dividers inside it, not dozens of
   floating bordered boxes. */
.ga-scout-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 280px;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent);
  border-radius: var(--r-panel);
  background: color-mix(in srgb, var(--cream-2) 50%, transparent);
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.ga-scout-list::-webkit-scrollbar { width: 8px; }
.ga-scout-list::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--card-border) 45%, transparent); border-radius: var(--r-sm); }
.ga-scout-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  box-sizing: border-box;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 110ms ease, border-color 110ms ease;
}
.ga-scout-row:hover { background: color-mix(in srgb, var(--hi-2) 70%, transparent); }
.ga-scout-row.is-checked {
  background: color-mix(in srgb, var(--leaf) 12%, transparent);
  border-color: color-mix(in srgb, var(--leaf) 45%, transparent);
}
.ga-scout-check {
  flex-shrink: 0;
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--leaf);
  cursor: pointer;
}
.ga-scout-id {
  flex-shrink: 0;
  font-size: var(--fs-11);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-04);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  background: color-mix(in srgb, var(--card-border) 28%, transparent);
  padding: 2px 7px;
  border-radius: 5px;
}
.ga-scout-row.is-checked .ga-scout-id { background: color-mix(in srgb, var(--leaf) 25%, transparent); }
.ga-scout-framing {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-11-5);
  color: var(--ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ga-scout-title { color: color-mix(in srgb, color-mix(in srgb, var(--ink-taupe) 97%, var(--mix-dark)) 70%, transparent); }

/* References */
.ga-ref-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.ga-ref-tab {
  font: inherit; font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: var(--track-06);
  padding: 6px 12px; border-radius: var(--r-7);
  border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent);
  background: color-mix(in srgb, var(--cream) 50%, transparent); color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-4) 75%, transparent));
  cursor: pointer;
}
.ga-ref-tab:hover { color: var(--ink); border-color: color-mix(in srgb, var(--gold-deep) 55%, transparent); }
.ga-ref-tab.is-active { background: color-mix(in srgb, var(--leaf) 85%, transparent); border-color: color-mix(in srgb, var(--leaf) 90%, transparent); color: var(--white); }
/* v07zz448 — the ASSETS tab's category sub-selector: a lighter/smaller pill row
   nested under the main tab strip so props / characters / other locations can be
   browsed as references. */
.ga-ref-subcats { display: flex; gap: 6px; flex-wrap: wrap; margin: -4px 0 12px; }
.ga-ref-subcat {
  font: inherit; font-size: var(--fs-9); font-weight: var(--fw-bold); letter-spacing: var(--track-05);
  padding: 4px 10px; border-radius: var(--r-round);
  border: 1px solid color-mix(in srgb, var(--card-border) 40%, transparent);
  background: color-mix(in srgb, var(--cream) 35%, transparent); color: var(--ink-muted, color-mix(in srgb, var(--ink-umber-4) 70%, transparent));
  cursor: pointer;
}
.ga-ref-subcat:hover { color: var(--ink); border-color: color-mix(in srgb, var(--gold-deep) 50%, transparent); }
.ga-ref-subcat.is-active { background: color-mix(in srgb, var(--gold-deep) 85%, transparent); border-color: color-mix(in srgb, var(--gold-deep) 90%, transparent); color: var(--white); }
/* v07zz89 — Hugo: "2 max [rows] and needs to be scrollable… why dont
   the card just span the whole width of the panel?" The flex/flex-wrap
   layout left dead space on the right (fixed 110px cards never filled
   the row) and grew unbounded. Now a grid of 1fr columns stretches the
   cards edge-to-edge, caps at ~2 rows, and scrolls. */
.ga-ref-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 8px;
  /* v07zz104 — Fixed 3-row height. grid-auto-rows pins every row to 104px,
     so exactly 3 rows (3*104 + 2*8 gap = 328px) always render: more cards
     scroll, fewer leave empty space. Kills the height jitter Hugo flagged. */
  grid-auto-rows: 104px;
  height: 328px;
  overflow-y: auto;
  align-content: start;
  padding-right: 2px;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.ga-ref-check {
  position: absolute; top: 5px; right: 5px; width: 20px; height: 20px; border-radius: 50%;
  background: color-mix(in srgb, var(--gold-4) 95%, transparent); color: var(--ink-2); font-size: var(--fs-12); font-weight: var(--fw-bold);
  display: grid; place-items: center;
}
.ga-ref-add {
  width: auto; height: 100%; border-radius: var(--r-9);
  border: 1.5px dashed color-mix(in srgb, var(--gold-deep) 55%, transparent); background: color-mix(in srgb, var(--cream) 35%, transparent);
  color: var(--ink-muted); cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  font-size: var(--fs-10-5); font-weight: var(--fw-semi);
}
.ga-ref-add:hover { background: color-mix(in srgb, var(--hi-2) 60%, transparent); border-color: color-mix(in srgb, var(--gold-deep) 80%, transparent); }
.ga-ref-add-plus { font-size: var(--fs-24); line-height: 1; }

/* v07zz86 — Reference CARDS (one per batch / image). Batch cards show a
   count badge + a selected-count; clicking opens the picker modal. */
.ga-ref-empty { width: 100%; padding: 18px; text-align: center; font-size: var(--fs-12); font-style: italic; color: var(--ink-muted); }
.ga-ref-card {
  position: relative; width: auto; border-radius: var(--r-9);
  border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent); background: transparent;
  cursor: pointer; padding: 0; overflow: hidden; text-align: left;
  display: flex; flex-direction: column;
  transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.ga-ref-card:hover { border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
.ga-ref-card.is-attached { border-color: color-mix(in srgb, var(--gold-4) 95%, transparent); box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--gold-4) 40%, transparent); }
.ga-ref-card-thumb {
  /* v07zz104 — fill the fixed grid cell (minus the name strip) instead of
     a 4/3 ratio, so all cards are the same height for the 3-row grid. */
  position: relative; width: 100%; flex: 1 1 auto; min-height: 0;
  background: var(--parchment); background-size: cover; background-position: center top; background-repeat: no-repeat;
}
.ga-ref-card-count {
  position: absolute; bottom: 5px; left: 5px;
  font-size: var(--fs-10); font-weight: var(--fw-bold); padding: 2px 7px; border-radius: var(--r-round);
  background: color-mix(in srgb, var(--shade-27) 78%, transparent); color: var(--ink-paper);
}
.ga-ref-card-name {
  font-size: var(--fs-10-5); font-weight: var(--fw-semi); color: var(--ink); padding: 5px 7px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  background: color-mix(in srgb, var(--cream) 70%, transparent);
}

/* Reference batch picker modal. */
.ga-refmodal-backdrop {
  position: fixed; inset: 0; z-index: var(--z-dialog);
  background: color-mix(in srgb, var(--shade) 55%, transparent); backdrop-filter: blur(var(--blur-scrim-3));
  display: grid; place-items: center; padding: 40px;
}
.ga-refmodal {
  width: min(900px, 92vw); max-height: 86vh; display: flex; flex-direction: column;
  background: color-mix(in srgb, var(--cream-2) 98%, transparent); border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent);
  border-radius: 16px; overflow: hidden;
  box-shadow: 0 24px 60px color-mix(in srgb, var(--shade) 40%, transparent);
}
.ga-refmodal-head { display: flex; align-items: flex-start; justify-content: space-between; padding: 18px 22px; border-bottom: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent); }
.ga-refmodal-eyebrow { font-size: var(--fs-9-5); font-weight: var(--fw-bold); letter-spacing: var(--track-14); color: var(--ink-muted); }
.ga-refmodal-title { font-family: var(--font-display, "Bebas Neue", sans-serif); font-size: var(--fs-22); color: var(--ink); margin-top: 2px; }
.ga-refmodal-sub { font-size: var(--fs-11-5); color: var(--ink-muted); margin-top: 3px; }
.ga-refmodal-close { width: 32px; height: 32px; border-radius: 50%; border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent); background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink); cursor: pointer; font-size: var(--fs-18); line-height: 1; }
.ga-refmodal-close:hover { background: color-mix(in srgb, var(--hi-2) 95%, transparent); }
/* v07zz409 — header actions group + WIP reveal toggle (WIP refs hidden until clicked). */
.ga-refmodal-head-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.ga-refmodal-wiptoggle {
  font: inherit; font-size: var(--fs-10); font-weight: var(--fw-heavy); letter-spacing: var(--track-06); text-transform: uppercase;
  padding: 6px 12px; border-radius: var(--r-round); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--gold-14) 60%, transparent); background: color-mix(in srgb, var(--gold-14) 14%, transparent); color: var(--ink-tan-deep);
  transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.ga-refmodal-wiptoggle:hover { background: color-mix(in srgb, var(--gold-14) 26%, transparent); }
.ga-refmodal-wiptoggle.is-on { background: color-mix(in srgb, var(--gold-14) 92%, transparent); color: color-mix(in srgb, var(--ink-deep-2) 61%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-14) 95%, transparent); }
/* v07zz89 — Modal was "completely broken": the grid had `flex: 1 1 0`
   inside a content-sized modal (max-height only, no fixed height), so
   flex-grow had no free space to hand out and the grid collapsed to 0
   height — tiles squished into a sliver. Removing the flex lets the
   grid take its content height; `min-height:0` + overflow still lets it
   scroll once the modal hits its 86vh cap. */
/* v07zz104 — Masonry: each reference keeps its TRUE aspect ratio and the
   tiles pack into balanced columns (Pinterest-style), instead of forcing
   every image into the same 3/4 box. CSS multi-column + break-inside. */
.ga-refmodal-grid {
  min-height: 0; overflow-y: auto; padding: 18px 22px;
  columns: 168px; column-gap: 10px;
}
.ga-refmodal-tile {
  position: relative; display: block; width: 100%;
  margin: 0 0 10px; break-inside: avoid;
  border-radius: var(--r-9); overflow: hidden;
  border: 2px solid transparent; background: var(--parchment); cursor: pointer; padding: 0;
}
.ga-refmodal-tile img { width: 100%; height: auto; object-fit: contain; display: block; }
.ga-refmodal-tile:hover { border-color: color-mix(in srgb, var(--gold-4) 55%, transparent); }
.ga-refmodal-tile.is-attached { border-color: color-mix(in srgb, var(--gold-4) 95%, transparent); box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--gold-4) 40%, transparent); }
/* v07zz246 — Per-tile caption (e.g. "SH0010 · v002_f3 (archived)") so the four
   near-identical candidate frames of a shot are individually identifiable in
   the chooser. Absolutely positioned over the image bottom — no layout impact
   on the masonry columns. */
.ga-refmodal-tile-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 8px 8px 5px; pointer-events: none;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--fs-10-5); font-weight: var(--fw-semi); letter-spacing: var(--track-01);
  color: var(--ink-on-accent); text-align: left; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: linear-gradient(to top, color-mix(in srgb, var(--shade-28) 82%, transparent), color-mix(in srgb, var(--shade-28) 0%, transparent));
}
/* v07zz408 — WIP badge on chooser tiles for not-yet-approved references. */
.ga-refmodal-tile-wip {
  position: absolute; top: 6px; left: 6px; z-index: 3; pointer-events: none;
  font-size: var(--fs-9); font-weight: var(--fw-heavy); letter-spacing: var(--track-06); text-transform: uppercase;
  padding: 2px 6px; border-radius: 5px;
  background: color-mix(in srgb, var(--gold-14) 94%, transparent); color: color-mix(in srgb, var(--ink-deep-2) 61%, var(--mix-dark));
}
.ga-refmodal-foot { padding: 14px 22px; border-top: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent); display: flex; justify-content: flex-end; }
/* ─── v891 — chooser force-refresh ──────────────────────────────────────────
   "⟳ Refresh" shares the WIP-toggle pill; fixed width so Reading… never nudges
   the pills beside it. NEW badge = the WIP badge's twin, right corner, green. */
.ga-refmodal-refresh { min-width: 92px; text-align: center; }
.ga-refmodal-refresh.is-busy { opacity: 0.6; cursor: progress; }
.ga-refmodal-newmsg { color: var(--ink-muted); }
.ga-refmodal-newmsg.is-new { color: color-mix(in srgb, var(--leaf-bright) 60%, var(--mix-dark)); font-weight: var(--fw-bold); }
.ga-refmodal-newmsg.is-err { color: var(--red-12); }
.ga-refmodal-tile-new {
  position: absolute; top: 6px; right: 6px; z-index: 3; pointer-events: none;
  font-size: var(--fs-9); font-weight: var(--fw-heavy); letter-spacing: var(--track-06); text-transform: uppercase;
  padding: 2px 6px; border-radius: 5px;
  background: color-mix(in srgb, color-mix(in srgb, var(--leaf-bright) 74%, var(--mix-dark)) 96%, transparent); color: var(--ink-mint-3);
}
.ga-refmodal-done { max-width: 180px; }
/* v07zz104 — Always-present row with a reserved min-height so attaching /
   removing a reference never changes the REFERENCES panel height. */
.ga-attached-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; padding-top: 12px; border-top: 1px dashed color-mix(in srgb, var(--card-border) 50%, transparent); min-height: 76px; }
.ga-attached-empty { font-size: var(--fs-11-5); font-style: italic; color: var(--ink-muted); }
.ga-attached-tile { position: relative; width: 64px; height: 64px; border-radius: var(--r-7); overflow: hidden; border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: var(--parchment); }
.ga-attached-tile.is-iteration { border-color: color-mix(in srgb, var(--blue-40) 85%, transparent); box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--blue-40) 50%, transparent); }
.ga-attached-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ga-attached-x { position: absolute; top: 2px; right: 2px; width: 17px; height: 17px; border-radius: 50%; border: none; background: color-mix(in srgb, var(--danger-soft) 90%, transparent); color: var(--white); cursor: pointer; font-size: var(--fs-12); line-height: 15px; font-weight: var(--fw-bold); }
/* v07zz291 — send-order number badge so templates can reference "image 1 / image 2". */
.ga-attached-num { position: absolute; bottom: 2px; left: 2px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 5px; background: color-mix(in srgb, var(--shade-9) 78%, transparent); color: var(--white); font-size: var(--fs-10); font-weight: var(--fw-heavy); line-height: 16px; text-align: center; pointer-events: none; }
/* v07zz294 — Face Swap: click an attached image to pick the face/character source. */
.ga-attached-tile.is-pickable { cursor: pointer; }
.ga-attached-tile.is-pickable:hover { border-color: color-mix(in srgb, var(--leaf) 75%, transparent); }
.ga-attached-tile.is-face { border-color: var(--leaf); box-shadow: 0 0 0 var(--ring-w) var(--leaf), 0 0 10px 1px color-mix(in srgb, var(--leaf) 50%, transparent); }
.ga-attached-face { position: absolute; top: 2px; left: 2px; padding: 0 5px; height: 15px; border-radius: 4px; background: var(--leaf); color: var(--white); font-size: var(--fs-8-5); font-weight: var(--fw-heavy); letter-spacing: var(--track-05); line-height: 15px; text-align: center; pointer-events: none; }

/* Template */
.ga-tmpl-summary { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; border-radius: var(--r-panel); border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent); background: color-mix(in srgb, var(--cream) 60%, transparent); margin-bottom: 12px; }
.ga-tmpl-summary-text { flex: 1; min-width: 0; }
.ga-tmpl-summary-name { font-size: var(--fs-14); font-weight: var(--fw-bold); color: var(--ink); }
.ga-tmpl-summary-desc {
  font-size: var(--fs-12); color: var(--ink-muted); margin-top: 2px; line-height: 1.45;
  /* v07zz147 — reserve exactly 2 lines so switching templates NEVER changes
     the panel height (Hugo: never shift panel height on a button click). 1-line
     descriptions occupy the same space; longer ones clamp (full text lives in
     "View details"). */
  min-height: 2.9em;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.ga-tmpl-details { font: inherit; font-size: var(--fs-12); font-weight: var(--fw-semi); color: var(--ink-muted); background: none; border: none; cursor: pointer; white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; }
.ga-tmpl-details:hover { color: var(--ink); }
.ga-chev { transition: transform var(--dur-2) ease; display: inline-block; }
.ga-chev.is-open { transform: rotate(180deg); }
.ga-tmpl-body { font-family: var(--font-mono, monospace); font-size: var(--fs-11-5); line-height: 1.6; color: var(--ink); background: color-mix(in srgb, var(--black) 5%, transparent); border-radius: var(--r-sm); padding: 10px 12px; margin-bottom: 12px; white-space: pre-wrap; }
/* v07zz160 — editable template body + save bar. */
.ga-tmpl-editwrap { margin-bottom: 12px; }
.ga-tmpl-body--edit {
  display: block; width: 100%; resize: vertical; min-height: 86px; margin-bottom: 8px;
  border: 1px solid var(--card-border);
}
.ga-tmpl-body--edit:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }
.ga-tmpl-editbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ga-tmpl-edithint { font-size: var(--fs-11); color: var(--ink-muted); }
.ga-tmpl-save {
  flex-shrink: 0; font: inherit; font-size: var(--fs-12); font-weight: var(--fw-semi); cursor: pointer;
  padding: 6px 14px; border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--leaf) 60%, transparent); background: color-mix(in srgb, var(--leaf) 16%, transparent); color: var(--ink);
  transition: background var(--dur-1) ease, opacity var(--dur-1) ease;
}
.ga-tmpl-save:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 28%, transparent); }
.ga-tmpl-save:disabled { opacity: 0.5; cursor: default; }
/* v1078 — Hugo: "make all these buttons smaller so they fit only on 2 rows". The
   column count comes from the template count (GeneratePage: two rows at most); the
   tile itself is compact: less padding, a 16px icon, a one-line label. A column too
   narrow for 7 tiles a row (under ~764px: 7 x 104px + gaps) falls back to the v1061
   count of about six a row, passed in as --tmpl-cols-narrow. */
.ga-tmpl-tiles-wrap { container-type: inline-size; }
.ga-tmpl-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 6px; }
@container (max-width: 763px) {
  .ga-tmpl-tiles { grid-template-columns: repeat(var(--tmpl-cols-narrow, 5), minmax(0, 1fr)) !important; }
}
.ga-tmpl-tile {
  display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 7px 4px; min-width: 0;
  border-radius: var(--r-panel); border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent);
  background: color-mix(in srgb, var(--cream) 50%, transparent); color: var(--ink); cursor: pointer;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.ga-tmpl-tile:hover { background: color-mix(in srgb, var(--hi-2) 80%, transparent); border-color: color-mix(in srgb, var(--gold-deep) 55%, transparent); }
.ga-tmpl-tile.is-active { border-color: color-mix(in srgb, var(--leaf) 90%, transparent); box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--leaf) 50%, transparent); background: color-mix(in srgb, var(--leaf) 12%, transparent); }
.ga-tmpl-tile-icon { color: var(--ink-muted); display: inline-flex; }
.ga-tmpl-tile-icon svg { width: 16px; height: 16px; }
.ga-tmpl-tile.is-active .ga-tmpl-tile-icon { color: color-mix(in srgb, var(--olive-2) 77%, var(--mix-dark)); }
.ga-tmpl-tile-label { font-size: var(--fs-11); font-weight: var(--fw-semi); text-align: center; line-height: 1.2; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ga-extrafield { width: 100%; margin-top: 12px; font: inherit; font-size: var(--fs-13); padding: 10px 12px; border-radius: var(--r-sm); border: 1px solid var(--card-border); background: color-mix(in srgb, var(--cream) 85%, transparent); color: var(--ink); }
.ga-extrafield:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }

/* v07zz292 — segmented toggle for a template "switch" field (e.g. Face Swap scope).
   Both options always render side by side (align-items:stretch keeps them equal height,
   even when one label wraps) so toggling never shifts the panel. */
.ga-fieldswitch { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.ga-fieldswitch-label { font-size: var(--fs-11); font-weight: var(--fw-bold); letter-spacing: var(--track-04); text-transform: uppercase; color: var(--ink-muted, color-mix(in srgb, var(--ink-taupe) 89%, var(--mix-light))); }
.ga-fieldswitch-opts { display: flex; gap: 6px; align-items: stretch; }
.ga-fieldswitch-opt { flex: 1 1 0; min-width: 0; font: inherit; font-size: var(--fs-12-5); font-weight: var(--fw-semi); line-height: 1.25; text-align: center; padding: 8px 10px; border-radius: var(--r-sm); border: 1px solid var(--card-border); background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink); cursor: pointer; transition: background var(--dur-1) ease, border-color var(--dur-1) ease, box-shadow var(--dur-1) ease; }
.ga-fieldswitch-opt:hover { border-color: color-mix(in srgb, var(--leaf) 50%, transparent); }
.ga-fieldswitch-opt.is-on { background: color-mix(in srgb, var(--leaf) 16%, transparent); border-color: color-mix(in srgb, var(--leaf) 75%, transparent); box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 50%, transparent) inset; }

/* v07zz660 — Craft Prompt panel (asset gen). Only rendered for the craft-prompt
   template, so it can't shift any other template's layout. Intent chips reuse the
   .ga-fieldswitch-opt look so the page keeps one button vocabulary. */
.ga-craft { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
/* v707 — ONE ROW here, however many presets there are (was 1fr 1fr).
   v1053 — and it STAYS one row. v1052 gave the SHOT panel two rows because Hugo
   asked for two rows there; this panel was not part of that request and is back
   to how it was. The two panels no longer match, and that is deliberate — do not
   "restore consistency" by changing this one without asking. */
.ga-craft-intents {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  grid-template-columns: none;
  gap: 6px;
}
.ga-craft-intent {
  font: inherit; font-size: var(--fs-12-5); font-weight: var(--fw-semi); line-height: 1.25; text-align: center;
  padding: 8px 10px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink);
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.ga-craft-intent:hover { border-color: color-mix(in srgb, var(--leaf) 50%, transparent); }
.ga-craft-intent.is-on { background: color-mix(in srgb, var(--leaf) 16%, transparent); border-color: color-mix(in srgb, var(--leaf) 75%, transparent); box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 50%, transparent) inset; }
/* v706/v707 — saved presets back in this grid (see the shot panel's
   .gen-craft-presetcell). No colour of their own: they must be indistinguishable from
   the four built-ins. The ✕ is absolute + hover-only, which is what makes them fit.
   .ga-craft-intent already centres via text-align, and the label is a plain inline-ish
   block so it sits on the same baseline as its neighbours. */
.ga-craft-intent--preset { position: relative; }
.ga-craft-presetcell-label { display: block; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; }
.ga-craft-presetcell-x {
  position: absolute; top: 2px; right: 3px;
  width: 15px; height: 15px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: var(--fs-12); line-height: 1; cursor: pointer;
  color: var(--ink-muted); background: color-mix(in srgb, var(--cream) 92%, transparent);
  opacity: 0; transition: opacity 110ms ease, background 110ms ease, color 110ms ease;
}
.ga-craft-intent--preset:hover .ga-craft-presetcell-x { opacity: 1; }
.ga-craft-presetcell-x:hover { background: color-mix(in srgb, var(--danger-soft) 90%, transparent); color: var(--ink-on-danger); }
/* Undo for the asset brief box — sits in the model/actions row, always rendered. */
.ga-craft-undo {
  font: inherit; font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: var(--track-04); text-transform: uppercase;
  padding: 4px 10px; border-radius: var(--r-round); cursor: pointer; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--card-border) 75%, transparent); background: color-mix(in srgb, var(--cream) 60%, transparent); color: var(--ink-muted);
}
.ga-craft-undo:hover:not(:disabled) { color: var(--ink); border-color: color-mix(in srgb, var(--gold) 90%, transparent); background: color-mix(in srgb, var(--gold) 16%, transparent); }
.ga-craft-undo:disabled { opacity: 0.32; cursor: default; }
.ga-craft-brief {
  width: 100%; font: inherit; font-size: var(--fs-13); line-height: 1.5;
  padding: 10px 12px; border-radius: var(--r-sm); resize: vertical;
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent); color: var(--ink);
}
.ga-craft-brief:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }
.ga-craft-row { display: flex; align-items: stretch; gap: 8px; }
.ga-craft-providers { display: flex; border-radius: var(--r-sm); overflow: hidden; border: 1px solid var(--card-border); }
.ga-craft-provider {
  font: inherit; font-size: var(--fs-11-5); font-weight: var(--fw-semi); padding: 0 10px; cursor: pointer;
  border: none; border-right: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink-muted, color-mix(in srgb, var(--ink-taupe) 89%, var(--mix-light)));
}
.ga-craft-provider:last-child { border-right: none; }
.ga-craft-provider.is-on { background: color-mix(in srgb, var(--leaf) 18%, transparent); color: var(--ink); }
.ga-craft-btn {
  flex: 1 1 auto; font: inherit; font-size: var(--fs-12-5); font-weight: var(--fw-bold); padding: 9px 14px;
  border-radius: var(--r-sm); cursor: pointer; border: 1px solid color-mix(in srgb, var(--leaf) 75%, transparent);
  background: color-mix(in srgb, var(--leaf) 18%, transparent); color: var(--ink);
  transition: background var(--dur-1) ease;
}
.ga-craft-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 30%, transparent); }
.ga-craft-btn:active:not(:disabled) { transform: translateY(1px) scale(0.99); background: color-mix(in srgb, var(--leaf) 40%, transparent); }
.ga-craft-btn:focus-visible { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 75%, transparent); outline-offset: var(--ring-offset); }
.ga-craft-btn:disabled { opacity: 0.5; cursor: default; }
.ga-craft-btn.is-busy:disabled { opacity: 1; cursor: progress; animation: gen-craft-pulse 1.5s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .ga-craft-btn.is-busy:disabled { animation: none; } }
/* Fixed two-line slot — the status text changes constantly (idle → counting →
   result → error) and must never move the prompt box below it (invariant #20). */
.ga-craft-status {
  min-height: 32px; font-size: var(--fs-11-5); line-height: 1.4;
  color: var(--ink-muted, color-mix(in srgb, var(--ink-taupe) 89%, var(--mix-light)));
}
.ga-craft-err { color: var(--red-3); }

/* Prompt */
.ga-prompt {
  width: 100%; font: inherit; font-size: var(--fs-13); line-height: 1.55;
  padding: 11px 13px; border-radius: var(--r-9);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent); color: var(--ink); resize: vertical; min-height: 70px;
}
.ga-prompt:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }

/* Settings + Generate button styles live in the shared .gen-settings /
   .gen-model-btn / .gen-res-btn / .gen-go-btn rules (reused so the asset
   builder matches the shot builder). The old bespoke .ga-setting-opt /
   .ga-generate variants were removed as dead code (v07zz92 audit). */

/* Assembled prompt preview */
.ga-assembled-wrap { position: relative; }
.ga-assembled {
  font-family: var(--font-mono, "JetBrains Mono", monospace); font-size: var(--fs-12); line-height: 1.6;
  padding: 12px 14px 24px; border-radius: var(--r-9); background: color-mix(in srgb, var(--cream) 70%, transparent);
  border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent); color: var(--ink); white-space: pre-wrap;
}
.ga-assembled-count {
  position: absolute; bottom: 7px; right: 12px;
  font-size: var(--fs-10-5); font-family: var(--font-mono, monospace); color: var(--ink-muted);
}
/* v07zz147 — Assembled prompt is editable on the fly (textarea variant of
   .ga-assembled). Same look; resizable; reserves room for the char count. */
.ga-assembled-edit {
  width: 100%;
  display: block;
  resize: vertical;
  min-height: 84px;
  white-space: pre-wrap;
}
.ga-assembled-edit:focus { outline: var(--ring-w) solid color-mix(in srgb, var(--leaf) 55%, transparent); outline-offset: 1px; }

/* v07zz427 — Auto-prompt toggle in the prompt block header. */
.ga-assembled-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ga-assembled-tools { display: flex; align-items: center; gap: 10px; }
.ga-autoprompt-insert { border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 60%, transparent); color: var(--ink-muted); font: inherit; font-size: var(--fs-11); font-weight: var(--fw-semi); letter-spacing: 0; text-transform: none; padding: 3px 10px; border-radius: var(--r-round); cursor: pointer; }
.ga-autoprompt-insert:hover { background: color-mix(in srgb, var(--leaf) 16%, transparent); color: var(--ink-forest-4); border-color: color-mix(in srgb, var(--leaf) 60%, transparent); }
/* v07zz442 — Save-auto-prompt is now an icon-only button (was a "💾 Save auto-prompt"
   text pill). Same cream/border palette + green hover as the Reset pill; height matches
   the pill so the header row never shifts. is-saved = solid green with a check glyph. */
.ga-saveprompt-icon { display: grid; place-items: center; width: 26px; height: 22px; padding: 0; border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 60%, transparent); color: var(--ink-muted); border-radius: var(--r-7); cursor: pointer; transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease; }
.ga-saveprompt-icon:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 16%, transparent); color: var(--ink-forest-4); border-color: color-mix(in srgb, var(--leaf) 60%, transparent); }
.ga-saveprompt-icon:disabled { opacity: 0.5; cursor: default; }
.ga-saveprompt-icon.is-saved { background: color-mix(in srgb, var(--ok) 92%, transparent); color: var(--white); border-color: color-mix(in srgb, var(--ok) 92%, transparent); }
.ga-autoprompt-switch { display: inline-flex; align-items: center; gap: 7px; border: none; background: transparent; cursor: pointer; padding: 0; }
.ga-autoprompt-txt { font-size: var(--fs-11); font-weight: var(--fw-bold); letter-spacing: var(--track-06); text-transform: uppercase; color: var(--ink-muted); }
.ga-autoprompt-switch.is-on .ga-autoprompt-txt { color: var(--ink-forest-4); }
.ga-autoprompt-track { position: relative; width: 34px; height: 18px; border-radius: var(--r-round); background: color-mix(in srgb, var(--tan-deep) 28%, transparent); transition: background var(--dur-2) ease; }
.ga-autoprompt-switch.is-on .ga-autoprompt-track { background: color-mix(in srgb, var(--leaf) 90%, transparent); }
.ga-autoprompt-knob { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: var(--mix-light); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35); transition: transform var(--dur-2) ease; }
.ga-autoprompt-switch.is-on .ga-autoprompt-knob { transform: translateX(16px); }

/* v07zz147 — Per-model generation bars (always present; fill while running). */
.ga-genbars .ga-genbar-row { margin-bottom: 10px; }
.ga-genbars .ga-genbar-row:last-child { margin-bottom: 0; }
.ga-genbar-top { display: flex; justify-content: space-between; align-items: baseline; font-size: var(--fs-11-5); color: var(--ink-muted); margin-bottom: 4px; }
.ga-genbar-label { font-weight: var(--fw-semi); color: var(--ink); }
.ga-genbar-status { font-variant-numeric: tabular-nums; }
/* v07zz238 — cancel/clear a running or stuck generation */
.ga-genbar-right { display: inline-flex; align-items: center; gap: 7px; }
.ga-genbar-cancel { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; padding: 0; border: none; border-radius: 50%; background: color-mix(in srgb, var(--red-19) 14%, transparent); color: var(--red-11); font-size: var(--fs-10); line-height: 1; cursor: pointer; transition: background var(--dur-1) ease; }
.ga-genbar-cancel:hover { background: color-mix(in srgb, var(--red-19) 28%, transparent); }
.ga-genbar-track { height: 7px; border-radius: 99px; background: color-mix(in srgb, var(--leaf) 14%, transparent); overflow: hidden; border: 1px solid color-mix(in srgb, var(--card-border) 40%, transparent); }
.ga-genbar-fill { height: 100%; border-radius: 99px; width: 0; transition: width 1s linear; background: linear-gradient(90deg, var(--leaf), var(--olive-2)); }
.ga-genbar-fill[data-state="idle"] { background: transparent; }
.ga-genbar-fill[data-state="error"] { background: linear-gradient(90deg, color-mix(in srgb, var(--amber) 89%, var(--mix-dark)), var(--amber-4)); }

/* v07zz148 — Full-size in-app lightbox for generated previews (stays in the
   tab; replaces the old new-browser-tab "open full size"). */
/* ── Crop tool (Generate preview → save a section as a new WIP image) ──── */
.ga-crop-backdrop { position: fixed; inset: 0; z-index: var(--z-toast); display: flex; flex-direction: column; background: color-mix(in srgb, var(--shade-30) 90%, transparent); padding: 22px 22px 14px; animation: ga-lightbox-in var(--dur-2) ease; }
.ga-crop-stage { flex: 1 1 0; min-height: 0; display: flex; align-items: center; justify-content: center; }
.ga-crop-imgwrap { position: relative; display: inline-block; line-height: 0; }
.ga-crop-img { display: block; max-width: calc(100vw - 48px); max-height: calc(100vh - 120px); -webkit-user-select: none; user-select: none; -webkit-user-drag: none; }
.ga-crop-surface { position: absolute; inset: 0; cursor: crosshair; }
.ga-crop-rect { position: absolute; border: 1.5px solid var(--gold-13); box-shadow: 0 0 0 9999px rgba(0,0,0,0.55); cursor: move; box-sizing: border-box; }
.ga-crop-rect.is-tiny { border-style: dashed; }
.ga-crop-h { position: absolute; width: 14px; height: 14px; background: var(--gold-13); border: 2px solid var(--ink-on-gold-3); border-radius: 50%; box-shadow: 0 1px 3px rgba(0,0,0,0.5); }
.ga-crop-h.nw { top: -7px; left: -7px; cursor: nwse-resize; }
.ga-crop-h.ne { top: -7px; right: -7px; cursor: nesw-resize; }
.ga-crop-h.sw { bottom: -7px; left: -7px; cursor: nesw-resize; }
.ga-crop-h.se { bottom: -7px; right: -7px; cursor: nwse-resize; }
.ga-crop-bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 14px 16px; padding: 12px 4px 2px; flex-wrap: wrap; }
.ga-crop-hint { font-size: var(--fs-12-5); color: color-mix(in srgb, var(--ink-cream-4) 82%, transparent); flex: 1 1 auto; text-align: center; min-width: 140px; }
/* v07zz540 — locked-aspect ratio pills in the crop bar (Free / Project / 1:1 / 16:9 / 4:3 / 9:16). */
.ga-crop-aspects { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.ga-crop-aspects-label { font-size: var(--fs-11); font-weight: var(--fw-bold); letter-spacing: var(--track-06); text-transform: uppercase; color: color-mix(in srgb, var(--ink-cream-4) 55%, transparent); margin-right: 3px; }
.ga-crop-aspect { font: inherit; font-size: var(--fs-11-5); font-weight: var(--fw-semi); padding: 4px 10px; border-radius: var(--r-7); cursor: pointer; border: 1px solid color-mix(in srgb, var(--white) 20%, transparent); background: color-mix(in srgb, var(--mix-light) 6%, transparent); color: color-mix(in srgb, var(--ink-cream-7) 90%, transparent); transition: background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease; }
.ga-crop-aspect:hover:not(:disabled) { background: color-mix(in srgb, var(--mix-light) 14%, transparent); }
.ga-crop-aspect.is-active { border-color: var(--gold); background: color-mix(in srgb, var(--gold) 92%, transparent); color: var(--ink-on-gold-3); font-weight: var(--fw-bold); }
.ga-crop-aspect:disabled { opacity: 0.45; cursor: default; }
.ga-crop-bar-btns { display: flex; gap: 10px; }
.ga-crop-btn { font: inherit; font-size: var(--fs-13); font-weight: var(--fw-semi); padding: 9px 18px; border-radius: var(--r-9); cursor: pointer; border: 1px solid color-mix(in srgb, var(--white) 25%, transparent); background: color-mix(in srgb, var(--mix-light) 8%, transparent); color: var(--ink-cream-7); transition: background var(--dur-1) ease, filter var(--dur-1) ease; }
.ga-crop-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--mix-light) 16%, transparent); }
.ga-crop-btn--save { border-color: var(--gold); background: var(--gold); color: var(--ink-on-gold-3); font-weight: var(--fw-bold); }
.ga-crop-btn--save:hover:not(:disabled) { filter: brightness(1.08); }
.ga-crop-btn:disabled { opacity: 0.45; cursor: default; }

.ga-lightbox-backdrop {
  position: fixed; inset: 0; z-index: var(--z-dropdown);
  background: color-mix(in srgb, var(--shade-29) 82%, transparent);
  -webkit-backdrop-filter: blur(var(--blur-scrim-3)); backdrop-filter: blur(var(--blur-scrim-3));
  display: grid; place-items: center; padding: 3vh 3vw;
  animation: ga-lightbox-in var(--dur-2) ease;
}
@keyframes ga-lightbox-in { from { opacity: 0; } to { opacity: 1; } }
/* v07zz231 — 1:1 actual-resolution zoom. Backdrop scrolls so an oversized image
   can be panned; the image renders at native pixel size.
   v07zz246 — grab-drag to inspect: the whole zoomed surface is a pan handle. */
.ga-lightbox-backdrop.is-zoomed { place-items: start; overflow: auto; cursor: grab; }
.ga-lightbox-backdrop.is-zoomed.is-panning { cursor: grabbing; -webkit-user-select: none; user-select: none; }
/* v07zz263 — when NOT zoomed, stack the image above an info panel (model + prompt). */
.ga-lightbox-backdrop.has-info { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; }
.ga-lb-info {
  width: min(720px, 92vw); max-height: 24vh; overflow-y: auto;
  background: color-mix(in srgb, var(--shade-8) 82%, transparent); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border: 1px solid color-mix(in srgb, var(--white) 12%, transparent); border-radius: var(--r-md); padding: 12px 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45); color: var(--ink-cream-7);
  scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--white) 30%, transparent) transparent;
}
.ga-lb-info-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 9px; }
.ga-lb-info-model {
  font-size: var(--fs-12); font-weight: var(--fw-bold); letter-spacing: var(--track-03); padding: 4px 11px; border-radius: var(--r-sm);
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--gold-13) 46%, var(--mix-light)) 95%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-17) 75%, var(--mix-light)) 92%, transparent)); color: var(--ink-deep);
}
.ga-lb-info-chip {
  font-size: var(--fs-11); font-weight: var(--fw-semi); padding: 3px 9px; border-radius: var(--r-7);
  background: color-mix(in srgb, var(--mix-light) 8%, transparent); border: 1px solid color-mix(in srgb, var(--white) 15%, transparent); color: color-mix(in srgb, var(--ink-cream-8) 93%, var(--mix-dark));
}
.ga-lb-info-chip.is-promoted { background: color-mix(in srgb, var(--ok) 25%, transparent); border-color: color-mix(in srgb, var(--ok) 50%, transparent); color: color-mix(in srgb, var(--leaf-bright) 40%, var(--mix-light)); }
.ga-lb-info-chip.is-wip { background: color-mix(in srgb, var(--gold-4) 22%, transparent); border-color: color-mix(in srgb, var(--gold-4) 50%, transparent); color: color-mix(in srgb, var(--nav-active) 70%, var(--mix-light)); }
.ga-lb-info-prompt {
  font-family: var(--font-mono, monospace); font-size: var(--fs-12); line-height: 1.55;
  color: color-mix(in srgb, var(--ink-cream-7) 97%, var(--mix-dark)); white-space: pre-wrap; word-break: break-word; margin: 0;
}
.ga-lb-info-noprompt { font-size: var(--fs-12); font-style: italic; color: color-mix(in srgb, var(--ink-cream-7) 55%, transparent); }
.ga-lightbox-close {
  position: fixed; top: 18px; right: 24px; z-index: var(--z-dropdown-close);
  width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--white) 35%, transparent); background: color-mix(in srgb, var(--shade-8) 60%, transparent);
  color: var(--white); font-size: var(--fs-22); line-height: 1; cursor: pointer;
  display: grid; place-items: center;
}
.ga-lightbox-close:hover { background: color-mix(in srgb, var(--shade-8) 85%, transparent); }

/* ─── RIGHT: preview + actions ─────────────────────────────────────── */
.ga-preview { display: flex; flex-direction: column; gap: 0; min-width: 0; }
/* v07zz156 — Generated Preview slides in from the right when the Assets
   generator mounts (i.e. on switch from Shots). Toggle in Settings. */
@keyframes ga-drawer-slidein {
  from { opacity: 0; transform: translateX(46px); }
  to   { opacity: 1; transform: translateX(0); }
}
.ga-preview.ga-drawer--slidein { animation: ga-drawer-slidein 380ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
.ga-preview .ga-preview-img { margin-bottom: 12px; }
.ga-preview .ga-preview-tools { margin-bottom: 4px; }
.ga-preview-img {
  position: relative;   /* v07zz570 — anchor the grid-icon overlay badge */
  border-radius: var(--r-md); overflow: hidden; background: color-mix(in srgb, color-mix(in srgb, var(--umber-4) 67%, var(--mix-dark)) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent); display: grid; place-items: center;
}
/* v07zz152 — When an image is loaded the box wraps the image's OWN aspect
   ratio (height:auto). Empty state keeps a placeholder shape (set inline to
   the chosen aspect ratio, falling back to 1:1). */
.ga-preview-img:not(.has-img) { aspect-ratio: 1; }
/* v07zz231 — width:auto (not 100%) so the box shrink-wraps the image's OWN
   aspect ratio. The parent is display:grid; place-items:center, so a portrait
   renders at its natural width (never wider than the column) and the box
   collapses to the real height — true portrait box for portrait, landscape for
   landscape, no upscaling, no letterbox. */
.ga-preview-img img { max-width: 100%; width: auto; height: auto; max-height: 72vh; object-fit: contain; display: block; }
.ga-preview-empty { text-align: center; font-size: var(--fs-12); color: var(--ink-muted); font-style: italic; line-height: 1.6; padding: 20px; }
.ga-preview-tools { display: flex; gap: 8px; justify-content: center; }
.ga-preview-tools button {
  width: 38px; height: 34px; border-radius: var(--r-sm);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink); cursor: pointer;
  display: grid; place-items: center;
}
.ga-preview-tools button:hover:not(:disabled) { background: color-mix(in srgb, var(--hi-2) 95%, transparent); }
.ga-preview-tools button:disabled { opacity: 0.4; cursor: default; }
.ga-info-row { display: flex; justify-content: space-between; gap: 10px; font-size: var(--fs-12); padding: 5px 0; }
.ga-info-row span:first-child { color: var(--ink-muted); }
.ga-info-row span:last-child { color: var(--ink); font-weight: var(--fw-med); text-align: right; }
.ga-actions { display: flex; flex-direction: column; gap: 8px; }
.ga-action {
  font: inherit; font-size: var(--fs-13); font-weight: var(--fw-semi); padding: 11px 14px; border-radius: var(--r-9);
  cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid transparent; transition: filter var(--dur-1) ease, background var(--dur-1) ease;
}
.ga-action:disabled {   /* 24 Sep 2026 - readable when disabled (tokens.css): no 45% fade; "Approved ✓" and an
                           unavailable action read clearly, on the quiet disabled fill */
  cursor: default;
  background: var(--disabled-fill);
  border-color: var(--disabled-line);
  color: var(--disabled-ink);
}
.ga-action--promote { background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--leaf-bright) 54%, var(--mix-light)) 95%, transparent), color-mix(in srgb, var(--pale-green) 90%, transparent)); color: color-mix(in srgb, var(--leaf-bright) 32%, var(--mix-dark)); border-color: color-mix(in srgb, var(--ok) 60%, transparent); }
.ga-action--promote:hover:not(:disabled) { filter: brightness(1.05); }
.ga-action--wip { background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--gold-13) 46%, var(--mix-light)) 90%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-17) 75%, var(--mix-light)) 85%, transparent)); color: color-mix(in srgb, var(--ink-tan-deep) 67%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
.ga-action--wip:hover:not(:disabled) { filter: brightness(1.04); }
/* v1037 — "Mask head". Deliberately the quietest of the three: it is a utility,
   not an approval, and must not compete with the green Promote above it. */
.ga-action--mask { background: color-mix(in srgb, var(--grey-8) 85%, transparent); color: var(--grey-8-ink); border-color: color-mix(in srgb, var(--grey-9) 55%, transparent); }
.ga-action--mask:hover:not(:disabled) { background: color-mix(in srgb, var(--grey-10) 95%, transparent); }
/* v836 — "→ Storyboard" / "→ 3D" sit UNDER the big Set-as-shot-frame button, as a pair.
   Smaller and quieter on purpose: the primary action keeps its size and its green, and
   these read as the secondary "this gen isn't a frame" route. Equal columns so the pair
   is symmetrical, and the row only renders for a non-grid preview — it is never an empty
   reserved strip. */
.ga-sendrow { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 6px; }
.ga-action--send {
  font-size: var(--fs-11-5); font-weight: var(--fw-semi); padding: 7px 8px; border-radius: var(--r-7);
  background: color-mix(in srgb, var(--cream) 72%, transparent);
  color: var(--ink);
  border-color: color-mix(in srgb, var(--card-border) 60%, transparent);
  letter-spacing: var(--track-01);
}
.ga-action--send:hover:not(:disabled) { background: color-mix(in srgb, var(--gold-2) 26%, transparent); border-color: color-mix(in srgb, color-mix(in srgb, var(--gold) 92%, var(--mix-dark)) 70%, transparent); }
/* Gallery-mode twin — inherits .gen-gens-act's sizing, just the quieter fill. */
.gen-gens-act--send { background: color-mix(in srgb, var(--cream) 72%, transparent); color: var(--ink); border-color: color-mix(in srgb, var(--card-border) 60%, transparent); }
.gen-gens-act--send:hover:not(:disabled) { background: color-mix(in srgb, var(--gold-2) 26%, transparent); border-color: color-mix(in srgb, color-mix(in srgb, var(--gold) 92%, var(--mix-dark)) 70%, transparent); }
/* v714 — drop / paste an image onto the asset page's REFERENCES panel. The whole
   panel is the target (a small pill is a needle to thread), and the hint says where
   the image will land, because that follows the active tab. */
.ga-refblock { position: relative; }
.ga-refblock.is-dropover { outline: var(--ring-w) dashed color-mix(in srgb, var(--leaf) 95%, transparent); outline-offset: -4px; }
.ga-ref-drophint {
  float: right; font-size: var(--fs-9-5); font-weight: var(--fw-bold); letter-spacing: var(--track-06);
  text-transform: uppercase; color: var(--ink-muted); opacity: 0.75;
}
.ga-refblock.is-dropover .ga-ref-drophint,
.ga-refblock.is-dropbusy .ga-ref-drophint { color: var(--olive-3); opacity: 1; }
.ga-ref-dropveil {
  position: absolute; inset: 0; z-index: 4; pointer-events: none; border-radius: var(--r-md);
  background: color-mix(in srgb, var(--leaf) 10%, transparent);
}
.ga-recent-empty { font-size: var(--fs-12); color: var(--ink-muted); font-style: italic; padding: 8px 0; }
/* v713 — a FAILED list fetch, which used to be silently indistinguishable from
   "this shot has no generations". Loud on purpose, and it reassures about the files. */
.ga-recent-err {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  font-size: var(--fs-12); padding: 9px 10px; border-radius: var(--r-9);
  background: color-mix(in srgb, var(--danger-soft) 10%, transparent); border: 1px solid color-mix(in srgb, var(--danger-soft) 42%, transparent);
  color: var(--ink, var(--ink-4));
}
.ga-recent-err-msg { font-family: ui-monospace, monospace; font-size: var(--fs-10-5); opacity: 0.85; word-break: break-word; }
.ga-recent-err-hint { font-size: var(--fs-11); opacity: 0.75; }
.ga-recent-retry {
  margin-top: 3px; padding: 3px 12px; border-radius: var(--r-round); cursor: pointer;
  font-size: var(--fs-11); font-weight: var(--fw-bold);
  border: 1px solid color-mix(in srgb, var(--danger-soft) 55%, transparent); background: color-mix(in srgb, var(--cream) 90%, transparent);
  color: var(--ink, var(--ink-4));
}
.ga-recent-retry:hover { background: var(--mix-light); border-color: color-mix(in srgb, var(--danger-soft) 85%, transparent); }
.ga-recent-list { display: flex; flex-direction: column; gap: 8px; }
/* v07zz251 — Hugo: "the more I add to View All Generations, the more it
   shrinks the viewer up top. shouldn't happen." The preview column
   (.ga-preview.ga-drawer) is a fixed-height flex column (its parent
   .ga-shell is align-items:stretch), so a growing RECENT GENERATIONS
   list used to steal height from the preview image — squishing it to a
   sliver. Fix: pin every block at its natural size (flex-shrink:0) and
   let ONLY the recent list absorb the slack + scroll internally. The
   preview viewer now never resizes; the recent list scrolls in place.
   (Scoped to the wide desktop layout; the narrow @media rule below
   re-flows .ga-preview into a wrap row and overrides these.) */
.ga-preview > * { flex-shrink: 0; }
.ga-preview > .ga-recent { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ga-preview > .ga-recent > .ga-block-head { flex: 0 0 auto; }
.ga-preview > .ga-recent > .ga-recent-list { flex: 0 1 auto; min-height: 60px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent; }
.ga-preview > .ga-recent > .ga-recent-viewall { flex: 0 0 auto; }
.ga-recent-item {
  position: relative;
  display: flex; gap: 10px; align-items: center; padding: 6px; border-radius: var(--r-9);
  border: 1px solid transparent; background: color-mix(in srgb, var(--cream) 45%, transparent); cursor: pointer;
  font: inherit; text-align: left; color: inherit;
}
/* v07zz513 — action buttons live in an absolute overlay pinned to the row's right edge,
   revealed on hover. This keeps them OUT of flow so the meta column never collapses in
   the narrow (~290px) shot drawer (the in-flow buttons squeezed meta to min-content and
   wrapped every word vertically). Gap handles spacing; inner button margins are reset. */
.ga-recent-actions {
  position: absolute; top: 0; right: 0; bottom: 0; z-index: 3;
  display: flex; align-items: center; gap: 6px;
  padding: 0 7px 0 24px;
  border-top-right-radius: var(--r-9); border-bottom-right-radius: var(--r-9);
  background: linear-gradient(90deg, color-mix(in srgb, color-mix(in srgb, var(--hi-2) 68%, var(--mix-light)) 0%, transparent) 0%, color-mix(in srgb, color-mix(in srgb, var(--hi-3) 60%, var(--mix-light)) 96%, transparent) 42%);
  opacity: 0; pointer-events: none; transition: opacity var(--dur-1) ease;
}
.ga-recent-item:hover .ga-recent-actions,
.ga-recent-item:focus-within .ga-recent-actions { opacity: 1; pointer-events: auto; }
.ga-recent-actions > button { margin: 0 !important; }
.ga-recent-item:hover { background: color-mix(in srgb, var(--hi-2) 80%, transparent); }
.ga-recent-item.is-active { border-color: color-mix(in srgb, var(--gold-4) 80%, transparent); background: color-mix(in srgb, var(--hi-2) 90%, transparent); }
.ga-recent-thumb { position: relative; width: 52px; height: 52px; border-radius: var(--r-7); overflow: hidden; flex-shrink: 0; background: var(--parchment); }
.ga-recent-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* v07zz458 — visual-style pill overlaid on a Recent Generations thumbnail. Bottom-full
   width strip on the tiny 52px workbench thumb; a rounded corner pill on the larger v2
   history thumb (see .ga2-history-thumb .ga-style-pill below). Dark scrim so it reads
   over any image; the full preset name is on the element's title tooltip. */
.ga-style-pill {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 2px 4px;
  font-size: 8px; font-weight: var(--fw-heavy); letter-spacing: var(--track-02); text-transform: uppercase;
  line-height: 1.25; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: color-mix(in srgb, var(--ink-paper) 96%, var(--mix-light));
  background: linear-gradient(180deg, color-mix(in srgb, color-mix(in srgb, var(--shadow-ink) 77%, var(--mix-dark)) 0%, transparent) 0%, color-mix(in srgb, color-mix(in srgb, var(--shadow-ink) 77%, var(--mix-dark)) 82%, transparent) 55%);
  pointer-events: none;
}
.ga-recent-meta { min-width: 0; }
.ga-recent-date { font-size: var(--fs-11-5); font-weight: var(--fw-semi); color: var(--ink); }
.ga-recent-model { font-size: var(--fs-10-5); color: var(--ink-muted); margin-top: 2px; }
/* v07zz152 — discard ✕ on each recent-generation row. Matches the tracker's
   standard circular close-button language (SVG glyph, subtle border, neutral
   default → red on hover). Far right of the row; visible only on row hover. */
.ga-recent-discard {
  margin-left: auto; flex-shrink: 0;
  width: 26px; height: 26px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 70%, transparent);
  color: var(--ink-muted); cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.ga-recent-item:hover .ga-recent-discard,
.ga-recent-item:focus-within .ga-recent-discard { opacity: 1; }
.ga-recent-discard:hover { background: color-mix(in srgb, var(--danger-soft) 12%, transparent); color: var(--danger); border-color: color-mix(in srgb, var(--danger-soft) 50%, transparent); }
/* reuse-prompt button — same affordance as discard, green (positive) hover */
.ga-recent-reuse {
  margin-left: auto; flex-shrink: 0;
  width: 26px; height: 26px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 70%, transparent);
  color: var(--ink-muted); cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.ga-recent-item:hover .ga-recent-reuse,
.ga-recent-item:focus-within .ga-recent-reuse { opacity: 1; }
.ga-recent-reuse:hover { background: color-mix(in srgb, var(--leaf) 16%, transparent); color: var(--ink-forest-4); border-color: color-mix(in srgb, var(--leaf) 60%, transparent); }
.ga-recent-reuse + .ga-recent-discard { margin-left: 6px; }
/* v07zz425 — A/B compare button on a recent-gen row. Same affordance as reuse/discard;
   gold (compare) hover. Reveals on row hover; first right-aligned button. */
.ga-recent-cmp {
  margin-left: auto; flex-shrink: 0;
  width: 26px; height: 26px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 70%, transparent);
  color: var(--ink-muted); cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.ga-recent-item:hover .ga-recent-cmp,
.ga-recent-item:focus-within .ga-recent-cmp { opacity: 1; }
.ga-recent-cmp:hover { background: color-mix(in srgb, var(--gold-4) 16%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
.ga-recent-cmp + .ga-recent-reuse,
.ga-recent-cmp + .ga-recent-discard { margin-left: 6px; }
/* v07zz595 — Depth-map button on a recent-gen row (Panel drawer). Same circle as reuse/cmp. */
.ga-recent-depth {
  flex-shrink: 0;
  width: 26px; height: 26px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 70%, transparent);
  color: var(--ink-muted); cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.ga-recent-item:hover .ga-recent-depth,
.ga-recent-item:focus-within .ga-recent-depth { opacity: 1; }
.ga-recent-depth:hover { background: color-mix(in srgb, var(--gold-4) 16%, transparent); color: color-mix(in srgb, var(--ink-tan-deep) 84%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent); }
.ga-recent-viewall {
  margin-top: 10px; width: 100%; font: inherit; font-size: var(--fs-12); font-weight: var(--fw-semi);
  padding: 9px; border-radius: var(--r-sm); border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink); cursor: pointer;
}
.ga-recent-viewall:hover { background: color-mix(in srgb, var(--hi-2) 95%, transparent); }
/* v07zz261 — Recent Generations header row with a WIP/promoted filter toggle. */
.ga-recent-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ga-recent-filter {
  display: inline-flex; align-items: center; gap: 5px; font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-semi);
  letter-spacing: var(--track-04); text-transform: uppercase; padding: 4px 8px; border-radius: var(--r-7); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--ink-muted);
}
.ga-recent-filter:hover { background: color-mix(in srgb, var(--hi-2) 95%, transparent); color: var(--ink); }
.ga-recent-filter.is-on {
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--gold-13) 46%, var(--mix-light)) 95%, transparent), color-mix(in srgb, color-mix(in srgb, var(--gold-17) 75%, var(--mix-light)) 90%, transparent));
  color: color-mix(in srgb, var(--ink-tan-deep) 67%, var(--mix-dark)); border-color: color-mix(in srgb, var(--gold-4) 60%, transparent);
}
/* v07zz262 — header actions group + "Discard rest" (soft bulk discard). */
.ga-recent-head-actions { display: flex; align-items: center; gap: 6px; }
.ga-recent-clear {
  display: inline-flex; align-items: center; gap: 5px; font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-semi);
  letter-spacing: var(--track-04); text-transform: uppercase; padding: 4px 8px; border-radius: var(--r-7); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--danger-soft-2) 45%, transparent); background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--danger);
}
.ga-recent-clear:hover:not(:disabled) { background: color-mix(in srgb, var(--danger-soft) 12%, transparent); border-color: color-mix(in srgb, var(--danger-soft) 50%, transparent); }
.ga-recent-clear:disabled { opacity: 0.4; cursor: default; }

/* Responsive: stack the 3 columns on narrow viewports. */
@media (max-width: 1200px) {
  .ga-shell { grid-template-columns: 280px minmax(0, 1fr); }
  .ga-preview { grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; position: static; }
  .ga-preview > * { flex: 1 1 220px; }
}

/* ═══ v07zz87 — v1/v2 layout switch + V2 (Studio) layout ════════════ */

.ga-shell { position: relative; }

/* ═══ v07zz91 — V2 Studio layout, rebuilt to match concept image 1 ═══
   Two stacked cream panels: a top panel (title + controls + asset
   strip) and a body panel (SELECTED ASSET OVERVIEW | LATEST GENERATION).
   The page scrolls as a whole; the strip scrolls horizontally. */
.ga2-shell {
  position: relative;
  display: flex; flex-direction: column; gap: 16px;
  /* v07zz102 — top inset removed so the top panel reaches the top edge
     like the Shots picker (see .ga-shell). */
  flex: 1; min-height: 0; overflow-y: auto; padding: 0 4px 16px;
  scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.ga2-panel {
  background: color-mix(in srgb, var(--cream-2) 70%, transparent);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  padding: 18px 20px;
  flex: 0 0 auto;
}
.ga2-topbar {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 14px;
}
.ga2-topbar-left { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.ga2-kindpills { display: flex; gap: 6px; flex-wrap: wrap; }
.ga2-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; position: relative; padding-right: 78px; }
.ga2-searchwrap {
  display: flex; align-items: center; gap: 7px;
  padding: 0 11px; height: 34px; border-radius: var(--r-9);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent); color: var(--ink-muted);
}
.ga2-searchwrap input {
  border: none; background: transparent; font: inherit; font-size: var(--fs-12-5);
  color: var(--ink); width: 180px; outline: none;
}
.ga2-ctl-btn {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 13px;
  font: inherit; font-size: var(--fs-12-5); font-weight: var(--fw-semi); border-radius: var(--r-9);
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 85%, transparent); color: var(--ink); cursor: pointer;
}
.ga2-ctl-btn:hover { background: color-mix(in srgb, var(--hi-2) 95%, transparent); }
/* Horizontal asset strip — taller portrait cards with name + sub-line. */
.ga2-strip {
  display: flex; gap: 12px; overflow-x: auto; overflow-y: hidden;
  align-items: flex-start;
  padding: 2px 2px 8px; scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--card-border) 45%, transparent) transparent;
}
.ga2-strip-card {
  position: relative;
  flex: 0 0 150px; display: flex; flex-direction: column; gap: 7px;
  padding: 8px; border-radius: var(--r-md); border: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  background: color-mix(in srgb, var(--cream) 60%, transparent); cursor: pointer; text-align: left;
  font: inherit; color: inherit;
  transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease, background var(--dur-1) ease;
}
.ga2-strip-card:hover { border-color: color-mix(in srgb, var(--leaf) 55%, transparent); background: color-mix(in srgb, var(--cream) 95%, transparent); }
.ga2-strip-card.is-active {
  border-color: color-mix(in srgb, var(--leaf) 95%, transparent);
  box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--leaf) 50%, transparent), 0 6px 16px color-mix(in srgb, color-mix(in srgb, var(--surface-forest-2) 88%, var(--mix-light)) 18%, transparent);
  background: color-mix(in srgb, var(--mint-2) 95%, transparent);
}
.ga2-strip-thumb {
  position: relative; width: 100%; height: 150px; border-radius: var(--r-9);
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 80%, var(--mix-light)) 40%, transparent), color-mix(in srgb, var(--taupe) 30%, transparent));
  background-size: cover; background-position: center top; background-repeat: no-repeat;
  display: grid; place-items: center; font-size: var(--fs-30); font-weight: var(--fw-bold); color: color-mix(in srgb, var(--ink-deep) 50%, transparent);
}
.ga2-strip-check {
  position: absolute; top: 7px; left: 7px; width: 22px; height: 22px; border-radius: 50%;
  background: color-mix(in srgb, var(--leaf) 95%, transparent); color: var(--white); display: grid; place-items: center;
  font-size: var(--fs-13); font-weight: var(--fw-bold); box-shadow: 0 1px 4px color-mix(in srgb, var(--surface-forest) 35%, transparent);
}
.ga2-strip-name { font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ga2-strip-sub { font-size: var(--fs-11); color: var(--ink-muted); margin-top: -3px; }
.ga2-strip-selected {
  align-self: flex-start; font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: var(--track-04);
  padding: 3px 9px; border-radius: var(--r-round);
  background: color-mix(in srgb, var(--leaf) 85%, transparent); color: var(--white);
}

/* ─── Body: 2-col — SELECTED ASSET OVERVIEW | LATEST GENERATION ─────── */
.ga2-bodypanel { flex: 1 1 auto; }
.ga2-body { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 26px; align-items: start; }
.ga2-left, .ga2-right { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
/* Sections inside the studio body are borderless — the panel is the card. */
.ga2-left .ga-block, .ga2-right .ga-block {
  background: transparent; border: none; border-radius: 0; padding: 0;
}
.ga2-left .gen-settings { margin: 2px 0; }
.ga2-left .gen-footer { padding: 4px 0 0; }

/* Compact overview header card. */
.ga2-head { display: flex; flex-direction: column; gap: 10px; }
.ga2-head-card {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border-radius: var(--r-md);
  border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent); background: color-mix(in srgb, var(--cream) 60%, transparent);
}
.ga2-head-thumb {
  width: 48px; height: 48px; border-radius: var(--r-panel); flex-shrink: 0;
  background: linear-gradient(135deg, color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 80%, var(--mix-light)) 40%, transparent), color-mix(in srgb, var(--taupe) 30%, transparent));
  background-size: cover; background-position: center top;
  display: grid; place-items: center; font-size: var(--fs-18); font-weight: var(--fw-bold); color: color-mix(in srgb, var(--ink-deep) 55%, transparent);
}
.ga2-head-titles { flex: 1; min-width: 0; }
.ga2-head-name { font-size: var(--fs-16); font-weight: var(--fw-bold); color: var(--ink); }
.ga2-head-sub { font-size: var(--fs-12); color: var(--ink-muted); margin-top: 1px; }
.ga2-desc { font-size: var(--fs-13); line-height: 1.5; color: var(--ink); margin: 0; }

/* REFERENCE SOURCES — 3 summary cards. */
.ga2-refsources { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.ga2-refsource {
  display: flex; flex-direction: column; gap: 7px; padding: 8px;
  border-radius: 11px; border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent);
  background: color-mix(in srgb, var(--cream) 60%, transparent); cursor: pointer; text-align: left;
  font: inherit; color: inherit; transition: border-color var(--dur-1) ease, background var(--dur-1) ease;
}
.ga2-refsource:hover { border-color: color-mix(in srgb, var(--gold-deep) 60%, transparent); background: color-mix(in srgb, var(--hi-2) 85%, transparent); }
.ga2-refsource-thumb {
  position: relative; width: 100%; aspect-ratio: 16 / 10; border-radius: var(--r-sm);
  background: var(--parchment) center/cover no-repeat;
}
.ga2-refsource-count {
  position: absolute; bottom: 6px; right: 6px;
  font-size: var(--fs-11); font-weight: var(--fw-bold); padding: 2px 8px; border-radius: var(--r-round);
  background: color-mix(in srgb, var(--shade-27) 78%, transparent); color: var(--ink-paper);
}
.ga2-refsource-label { font-size: var(--fs-9-5); font-weight: var(--fw-bold); letter-spacing: var(--track-08); color: var(--ink-muted); }
.ga2-refsource-viewall { font-size: var(--fs-11); font-weight: var(--fw-semi); color: color-mix(in srgb, var(--olive-2) 77%, var(--mix-dark)); }

/* PROMPT TEMPLATES — 3 descriptive cards. */
.ga2-tmpl-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.ga2-tmpl-card {
  position: relative; display: flex; flex-direction: column; gap: 6px; padding: 13px;
  border-radius: 11px; border: 1px solid color-mix(in srgb, var(--card-border) 50%, transparent);
  background: color-mix(in srgb, var(--cream) 60%, transparent); cursor: pointer; text-align: left;
  font: inherit; color: var(--ink); transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease, background var(--dur-1) ease;
}
.ga2-tmpl-card:hover { border-color: color-mix(in srgb, var(--leaf) 60%, transparent); background: color-mix(in srgb, var(--mint-2) 80%, transparent); }
.ga2-tmpl-card.is-active {
  border-color: color-mix(in srgb, var(--leaf) 95%, transparent);
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--leaf) 50%, transparent);
  background: color-mix(in srgb, color-mix(in srgb, var(--leaf-bright) 18%, var(--mix-light)) 90%, transparent);
}
.ga2-tmpl-card-icon { color: var(--ink-muted); }
.ga2-tmpl-card.is-active .ga2-tmpl-card-icon { color: color-mix(in srgb, var(--olive-2) 77%, var(--mix-dark)); }
.ga2-tmpl-card-check {
  position: absolute; top: 9px; right: 9px; width: 18px; height: 18px; border-radius: 50%;
  background: color-mix(in srgb, var(--leaf) 95%, transparent); color: var(--white); display: grid; place-items: center; font-size: var(--fs-11); font-weight: var(--fw-bold);
}
.ga2-tmpl-card-name { font-size: var(--fs-13); font-weight: var(--fw-bold); }
.ga2-tmpl-card-desc { font-size: var(--fs-11); color: var(--ink-muted); line-height: 1.4; }

/* LATEST GENERATION column. */
.ga2-latest-head { display: flex; flex-direction: column; gap: 6px; }
.ga2-latest-status { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ga2-badge-completed {
  font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: var(--track-06); padding: 3px 10px; border-radius: var(--r-round);
  background: color-mix(in srgb, var(--ok) 85%, transparent); color: var(--white);
}
.ga2-latest-meta { font-size: var(--fs-11-5); color: var(--ink-muted); }
/* v07zz231 — reserve the 380px band only on the LOADED state and centre the
   intrinsic-sized image inside it, so flipping between portrait/landscape
   history thumbs re-centres the image instead of jumping the panel (inv #20).
   Empty state keeps its placeholder shape via :not(.has-img){aspect-ratio:1}. */
.ga2-preview-img { aspect-ratio: auto; margin: 4px 0; }
.ga2-preview-img.has-img { min-height: 380px; align-content: center; }
.ga2-actions { display: flex; gap: 8px; }
.ga2-actions .ga-action { flex: 1; }
.ga2-history .ga-block-head { margin-bottom: 8px; }
.ga2-history-strip { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 6px; scrollbar-width: thin; }
.ga2-history-thumb {
  position: relative;
  flex: 0 0 84px; height: 84px; border-radius: var(--r-9); overflow: hidden; padding: 0;
  border: 2px solid transparent; background: var(--parchment); cursor: pointer;
}
.ga2-history-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* v07zz458 — on the larger v2 history thumb the pill reads as a proper corner chip. */
.ga2-history-thumb .ga-style-pill { font-size: var(--fs-8-5); padding: 3px 5px; }
.ga2-history-thumb.is-active { border-color: color-mix(in srgb, var(--leaf) 90%, transparent); box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 50%, transparent); }
@media (max-width: 1100px) {
  .ga2-body { grid-template-columns: 1fr; }
}

/* v07zz266 — instant big hover preview for REFERENCE thumbnails (same system as the
   Presentations picker). Height set inline per-hover → same height for every aspect. */
.ga-hoverprev {
  /* z-index history: 4000 → 6000 (v07zz376, clear the ref picker .ga-refmodal-backdrop
     z4000) → 6900 (v07zz577). The shot-modal Add-from-library picker (.addlib-overlay
     z6200) and inline edit (.shotedit-overlay z6250) portal to #modal-root AFTER this
     layer, so at z6000 they COVERED the hover preview — hovering a Locations-tab tile
     showed the big preview stuck BEHIND the modal. 6900 floats above every modal that
     hosts the hover, yet stays safely BELOW the crop (7000) / Lightbox (8000) / notes
     overlay (9000). pointer-events:none keeps it click-through. Any NEW modal that hosts
     a useHoverPreview picker must sit below 6900 (or this needs another bump). */
  position: fixed; z-index: var(--z-hover-preview); transform: translateY(-50%);
  width: max-content; pointer-events: none;
  border-radius: var(--r-md); overflow: hidden; background: var(--ied-bg);
  border: 2px solid color-mix(in srgb, var(--white) 90%, transparent);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.55);
}
.ga-hoverprev img { display: block; height: 100%; width: auto; max-width: 100%; object-fit: contain; }
/* v07zz426 — GEN/REF badge shown while flicking a recent-gen hover preview with C. */
.ga-hoverprev-tag { position: absolute; top: 8px; left: 8px; z-index: 2; background: rgba(0, 0, 0, 0.66); color: var(--white); font-size: var(--fs-11); font-weight: var(--fw-bold); letter-spacing: var(--track-06); padding: 3px 9px; border-radius: var(--r-xs); pointer-events: none; }
.ga-hoverprev-tag:empty { display: none; }

/* ─── v07zz425 — A/B image compare modal (asset Generate page) ──────────────
   Flick mode (press C / click) snaps between a REFERENCE (A) and a GENERATION
   (B) instantly; swipe mode drags a divider. Portals to #modal-root. */
.abcmp-backdrop {
  position: fixed; inset: 0; z-index: var(--z-scrim);
  background: rgba(0, 0, 0, 0.62); backdrop-filter: blur(var(--blur-scrim-3));
  display: grid; place-items: center; padding: 24px;
}
.abcmp-card {
  width: 97vw; max-width: 2200px; height: 95vh;   /* v07zz428 — take most of the frame */
  background: var(--ied-bg); color: var(--ink-grey-11);
  border: 1px solid color-mix(in srgb, var(--white) 14%, transparent); border-radius: 16px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.6);
  display: flex; flex-direction: column; overflow: hidden;
}
.abcmp-head {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 16px; border-bottom: 1px solid color-mix(in srgb, var(--white) 10%, transparent); flex: 0 0 auto;
}
.abcmp-title { font-weight: var(--fw-bold); font-size: var(--fs-15); letter-spacing: var(--track-02); }
.abcmp-title-sub { opacity: 0.6; font-weight: var(--fw-med); }
.abcmp-modes { display: inline-flex; gap: 2px; background: color-mix(in srgb, var(--mix-light) 7%, transparent); border-radius: var(--r-sm); padding: 2px; }
.abcmp-mode { border: none; background: transparent; color: color-mix(in srgb, var(--white) 65%, transparent); font: inherit; font-size: var(--fs-12); font-weight: var(--fw-semi); padding: 5px 12px; border-radius: var(--r-xs); cursor: pointer; }
.abcmp-mode.is-on { background: color-mix(in srgb, var(--mix-light) 16%, transparent); color: var(--white); }
.abcmp-hint { font-size: var(--fs-12); opacity: 0.55; }
.abcmp-close { margin-left: auto; width: 30px; height: 30px; border-radius: 50%; border: 1px solid color-mix(in srgb, var(--white) 18%, transparent); background: color-mix(in srgb, var(--mix-light) 6%, transparent); color: var(--white); cursor: pointer; font-size: var(--fs-15); line-height: 1; display: grid; place-items: center; }
.abcmp-close:hover { background: color-mix(in srgb, var(--mix-light) 16%, transparent); }
/* v07zz426 — A on top, B on the bottom, image in the middle. Strips are short,
   scroll sideways (no visible scrollbar), and their tiles keep true aspect. */
.abcmp-body { flex: 1 1 auto; display: flex; flex-direction: column; gap: 10px; padding: 10px 14px 12px; min-height: 0; }
.abcmp-strip { flex: 0 0 auto; height: 96px; display: flex; flex-direction: column; min-width: 0; }
.abcmp-strip-head { font-size: var(--fs-11); text-transform: uppercase; letter-spacing: var(--track-08); opacity: 0.62; margin-bottom: 5px; display: flex; align-items: center; gap: 7px; }
.abcmp-strip-tag { display: inline-grid; place-items: center; width: 17px; height: 17px; border-radius: 4px; background: color-mix(in srgb, var(--gold-17) 90%, transparent); color: var(--ink-on-gold-4); font-size: var(--fs-10); font-weight: var(--fw-heavy); }
.abcmp-wiptoggle { margin-left: 8px; border: 1px solid color-mix(in srgb, var(--white) 18%, transparent); background: color-mix(in srgb, var(--mix-light) 6%, transparent); color: color-mix(in srgb, var(--white) 80%, transparent); font: inherit; font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: var(--track-04); text-transform: uppercase; padding: 2px 9px; border-radius: var(--r-round); cursor: pointer; }
.abcmp-wiptoggle:hover { background: color-mix(in srgb, var(--mix-light) 14%, transparent); }
.abcmp-wiptoggle.is-on { background: color-mix(in srgb, var(--gold-17) 85%, transparent); color: var(--ink-on-gold-4); border-color: transparent; }
.abcmp-strip-list { flex: 1 1 auto; display: flex; align-items: stretch; gap: 8px; overflow-x: auto; overflow-y: hidden; min-height: 0; scrollbar-width: none; -ms-overflow-style: none; scroll-behavior: smooth; }
.abcmp-strip-list::-webkit-scrollbar { display: none; }
.abcmp-strip-empty { font-size: var(--fs-12); opacity: 0.45; align-self: center; padding: 0 4px; }
.abcmp-tile { position: relative; flex: 0 0 auto; height: 100%; border: 2px solid transparent; border-radius: var(--r-sm); overflow: hidden; background: var(--black); cursor: pointer; padding: 0; }
.abcmp-tile img { height: 100%; width: auto; display: block; }
.abcmp-tile.is-sel { border-color: var(--gold-17); box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--gold-17) 35%, transparent); }
.abcmp-tile-badge { position: absolute; top: 3px; left: 3px; min-width: 15px; height: 15px; padding: 0 3px; border-radius: 4px; background: rgba(0, 0, 0, 0.6); color: var(--white); font-size: var(--fs-9); font-weight: var(--fw-bold); display: grid; place-items: center; }
.abcmp-tile.is-sel .abcmp-tile-badge { background: var(--gold-17); color: var(--ink-on-gold-4); }
.abcmp-center { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; min-width: 0; min-height: 0; }
.abcmp-stage { position: relative; width: 100%; height: 100%; background: var(--ied-bg-2); border-radius: var(--r-md); overflow: hidden; display: grid; place-items: center; user-select: none; }
/* v07zz464 — HUG mode (shot compare only; the card gets .abcmp-card--hug when the caller
   passes a fixed stageAspect). The center shrinks to the stage and the body floats the
   [strip · image · strip] group so the strips hug the frame — no vertical letterbox. The
   stage's own size comes from the inline style (aspect-ratio + width + maxWidth/maxHeight
   caps). --abcmp-vcap reserves room for the header + both strips + gaps so it never clips;
   the ≤960px tier shrinks the reserve to match the shorter 78px strips. The asset generator
   passes no stageAspect → none of this applies and the original fill layout is used. */
.abcmp-card--hug { --abcmp-vcap: calc(95vh - 290px); }
.abcmp-card--hug .abcmp-body { justify-content: center; }
.abcmp-card--hug .abcmp-center { flex: 0 1 auto; }
.abcmp-card--hug .abcmp-stage { width: auto; height: auto; }
.abcmp-stage.is-swipe { cursor: ew-resize; }
.abcmp-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; opacity: 0; }
.abcmp-img.is-on { opacity: 1; }   /* NO transition — flick is instant so differences pop */
.abcmp-img--top { z-index: 2; }
.abcmp-badge { position: absolute; left: 12px; bottom: 12px; z-index: 5; background: rgba(0, 0, 0, 0.62); color: var(--white); font-size: var(--fs-12); font-weight: var(--fw-semi); padding: 5px 10px; border-radius: var(--r-7); pointer-events: none; }
.abcmp-empty { position: absolute; z-index: 6; font-size: var(--fs-13); opacity: 0.5; text-align: center; padding: 0 20px; pointer-events: none; }
.abcmp-divider { position: absolute; top: 0; bottom: 0; width: 2px; background: color-mix(in srgb, var(--mix-light) 92%, transparent); z-index: 3; transform: translateX(-1px); pointer-events: none; }
.abcmp-divider-grip { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 30px; height: 30px; border-radius: 50%; background: color-mix(in srgb, var(--mix-light) 96%, transparent); color: var(--ink-on-gold-4); display: grid; place-items: center; font-size: var(--fs-14); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5); }
.abcmp-swipe-label { position: absolute; top: 10px; z-index: 4; background: rgba(0, 0, 0, 0.55); color: var(--white); font-size: var(--fs-11); font-weight: var(--fw-bold); padding: 3px 8px; border-radius: var(--r-xs); pointer-events: none; }
.abcmp-swipe-label--l { left: 10px; }
.abcmp-swipe-label--r { right: 10px; }
@media (max-width: 960px) { .abcmp-strip { height: 78px; } .abcmp-card--hug { --abcmp-vcap: calc(95vh - 254px); } }

/* ── v07zz485 — VO Tag Studio (standalone freeform emotion-tag mode) ───────── */
.vo-submode-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 4px 0 14px; }
.vo-submode-label { font: 700 12px/1 "Inter", system-ui, sans-serif; letter-spacing: var(--track-08); text-transform: uppercase; opacity: .7; }
.vo-submode-btns { display: inline-flex; background: color-mix(in srgb, var(--black) 5%, transparent); border: 1px solid color-mix(in srgb, var(--tan-deep) 28%, transparent); border-radius: var(--r-round); padding: 3px; gap: 2px; }
.vo-submode-btn { border: 0; background: transparent; font: 600 12.5px/1 "Inter", system-ui, sans-serif; padding: 7px 15px; border-radius: var(--r-round); cursor: pointer; color: var(--ink, var(--ink-umber)); opacity: .72; transition: background var(--dur-1), opacity var(--dur-1); }
.vo-submode-btn:hover { opacity: 1; }
.vo-submode-btn.is-active { background: var(--gold-17); color: color-mix(in srgb, var(--ink-deep-2) 92%, var(--mix-dark)); opacity: 1; box-shadow: 0 1px 3px rgba(0,0,0,.18); }
.vo-submode-hint { font-size: var(--fs-12); opacity: .6; flex: 1 1 260px; min-width: 200px; }

.vo-tagstudio { display: flex; flex-direction: column; gap: 14px; }
.vo-ts-grid { display: grid; grid-template-columns: minmax(240px, 320px) 1fr; gap: 14px; align-items: start; }
.vo-ts-opt { font-weight: 400; opacity: .55; letter-spacing: var(--track-02); text-transform: none; }
.vo-ts-h2 { margin-top: 14px; }
.vo-ts-select { width: 100%; padding: 9px 11px; border-radius: var(--r-9); border: 1px solid color-mix(in srgb, var(--black) 16%, transparent); background: color-mix(in srgb, var(--mix-light) 80%, transparent); font: inherit; font-size: var(--fs-13-5); }
.vo-ts-presets { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 6px; }
.vo-ts-preset { border: 1px solid color-mix(in srgb, var(--tan-deep) 35%, transparent); background: color-mix(in srgb, var(--mix-light) 60%, transparent); border-radius: var(--r-round); padding: 5px 11px; font: 500 12px/1 "Inter", system-ui, sans-serif; cursor: pointer; color: inherit; }
.vo-ts-preset.is-active { background: var(--gold-17); color: color-mix(in srgb, var(--ink-deep-2) 92%, var(--mix-dark)); border-color: var(--gold-17); }
.vo-ts-emotion, .vo-ts-text, .vo-ts-out { width: 100%; padding: 11px 13px; border-radius: var(--r-panel); border: 1px solid color-mix(in srgb, var(--black) 16%, transparent); background: color-mix(in srgb, var(--mix-light) 82%, transparent); font: inherit; font-size: var(--fs-14); line-height: 1.55; resize: vertical; }
.vo-ts-out { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: var(--fs-13); background: var(--cream-19); }
.vo-ts-go { margin-top: 12px; width: 100%; }
.vo-ts-err { margin-top: 8px; }
.vo-ts-result-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.vo-ts-copy { border: 1px solid color-mix(in srgb, var(--tan-deep) 40%, transparent); background: var(--gold-17); color: color-mix(in srgb, var(--ink-deep-2) 92%, var(--mix-dark)); border-radius: var(--r-sm); padding: 7px 16px; font: 600 12.5px/1 "Inter", system-ui, sans-serif; cursor: pointer; }
.vo-ts-copy.is-copied { background: var(--ok); color: var(--white); border-color: var(--ok); }
@media (max-width: 820px) { .vo-ts-grid { grid-template-columns: 1fr; } }

/* ═══ v07zz508 — Lightbox IMAGE EDITOR — DARK mode, BIG image, FLOATING side panels ═══
   The paint bar + camera-raw panel float over the image edges (position:absolute) so
   the image keeps its full size — the panels no longer squeeze it into a flex row. */
/* v07zz543 — column so an optional "MATCH TO" strip can sit above the editor row. With no
   strip (asset gen) the single row child still fills the viewport exactly as before. */
.gen-ied-backdrop { display: flex; flex-direction: column; align-items: stretch; justify-content: flex-start; background: color-mix(in srgb, var(--ied-bg-13) 94%, transparent); }
/* v07zz512 — centred [tools · image · adjust] row: panels sit right beside the image. */
/* v07zz631 — THE ROW WAS WIDER THAN THE SCREEN. Fixed chrome is tools(76) +
   adjust(330) + 2 gaps(28) = 434px, but the canvas only reserved 360px, so the row
   overflowed by ~74px and `justify-content:center` split that between the two edges:
   the paint rail was clipped off the left, the adjust panel off the right, and the
   MATCH TO strip ran underneath the panel. (Hugo: "It's even cropping the sides of
   the panels unless I enlarge the image for it to fit.")
   The right panel is now PINNED to the right edge for its full height, and everything
   else reserves exactly that much room — the three regions in Hugo's annotation. */
.gen-ied-row {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  width: 100%; flex: 1 1 auto; min-height: 0;
  padding: 0 var(--ied-right-w, 346px) 0 12px;   /* keep clear of the pinned panel */
  box-sizing: border-box;
}
.gen-ied-backdrop { --ied-right-w: 346px; --ied-tools-w: 76px; }
/* the adjust column spans the full height at the right edge, above everything.
   Scoped to .gen-ied-backdrop so it beats the plain `.gen-ied-adjust` rule further
   down the file (same specificity would lose to it on source order). */
.gen-ied-backdrop .gen-ied-adjust {
  position: fixed; top: 8px; right: 8px; bottom: 8px; z-index: 9;
  width: 330px; height: auto; max-height: none;
}
/* the top bands stop before it instead of running under it */
.gen-ied-matchrow, .gen-ied-layerpick { padding-right: var(--ied-right-w, 346px); }
/* v07zz543 — when the match strip is present, cap the image shorter so the strip + editor fit. */
.gen-ied-backdrop:has(.gen-ied-matchrow) .gen-ied-canvas { max-height: 80vh; }
/* v07zz513 — Stage sizes to the image; image is capped by VIEWPORT (not by the flex parent,
   which collapsed it). max-width reserves ~360px for the two side panels + gaps so the image
   is as BIG as possible while the panels still sit beside it. */
.gen-ied-stage {
  position: relative; flex: 0 0 auto; line-height: 0; border-radius: var(--r-panel); overflow: hidden;
  box-shadow: 0 14px 60px rgba(0,0,0,0.6); background: var(--ied-bg-6);
}
/* v07zz512 — zoom wrapper transforms both canvases together (transform-origin center). */
.gen-ied-zoomwrap { position: relative; line-height: 0; transform-origin: center center; will-change: transform; }
.gen-ied-canvas { max-width: calc(100vw - 360px); max-height: 94vh; width: auto; height: auto; display: block; }
.gen-ied-canvas--paint { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; }
.gen-ied-stage.is-painting .gen-ied-canvas--paint { cursor: crosshair; }
.gen-ied-stage.is-view .gen-ied-canvas--paint { cursor: zoom-in; }
.gen-ied-stage.is-view.is-zoomed .gen-ied-canvas--paint { cursor: grab; }
.gen-ied-stage.is-view.is-zoomed:active .gen-ied-canvas--paint { cursor: grabbing; }
/* v07zz512 — zoom % + reset chip, bottom-right of the stage. */
.gen-ied-zoomreset {
  position: absolute; bottom: 12px; right: 12px; z-index: 3;
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-bold); letter-spacing: var(--track-03);
  padding: 4px 11px; border-radius: var(--r-round); cursor: pointer;
  background: color-mix(in srgb, var(--ied-bg-10) 90%, transparent); color: var(--ied-ink); border: 1px solid color-mix(in srgb, var(--white) 18%, transparent);
}
.gen-ied-zoomreset:hover { background: color-mix(in srgb, var(--leaf) 40%, transparent); }
.gen-ied-loading { position: absolute; inset: 0; display: grid; place-items: center; color: color-mix(in srgb, var(--white) 85%, transparent); font-size: var(--fs-13); background: color-mix(in srgb, var(--ied-bg-6) 60%, transparent); min-width: 340px; min-height: 200px; }
/* v07zz508 — BEFORE/AFTER badge (A/B flick). */
.gen-ied-abbadge {
  position: absolute; top: 12px; left: 12px; z-index: 2;
  font-size: var(--fs-11); font-weight: var(--fw-heavy); letter-spacing: var(--track-10); padding: 4px 11px; border-radius: var(--r-round);
  background: color-mix(in srgb, var(--leaf) 92%, transparent); color: var(--ink-ied-bg-6); box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.gen-ied-abbadge.is-before { background: color-mix(in srgb, var(--mix-light) 90%, transparent); color: var(--ink-ied-bg-6); }

/* v07zz543 — "Match to another shot" strip (top) + A/B overlay + flick badge. */
/* v07zz649 — Hugo: "in camera raw mode, the top panel is completely busted, going
   behind the right panel." The reserve-space rule further UP the file
   (.gen-ied-matchrow, .gen-ied-layerpick { padding-right: var(--ied-right-w) }) was
   being silently undone here: this `padding` SHORTHAND is later in the same file at the
   same specificity, so it reset padding-right to 58px and the strip ran under the ADJUST
   panel. The layer picker was unaffected only because its padding lives on the inner
   .gen-section--layerpick, which is why LAYERS looked right and ADJUST didn't.
   Re-assert padding-right AFTER the shorthand so it can't be clobbered again. */
.gen-ied-matchrow {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px;
  padding: 10px 58px 8px 16px;
  padding-right: var(--ied-right-w, 346px);
  background: color-mix(in srgb, var(--shade-28) 60%, transparent); border-bottom: 1px solid color-mix(in srgb, var(--white) 6%, transparent);
}
.gen-ied-matchrow-head { display: flex; align-items: center; gap: 12px; }
.gen-ied-matchrow-label { font-size: var(--fs-11); font-weight: var(--fw-heavy); letter-spacing: var(--track-10); color: color-mix(in srgb, var(--ink-cream-4) 60%, transparent); }
.gen-ied-matchsearch { font: inherit; font-size: var(--fs-12-5); padding: 5px 10px; border-radius: var(--r-7); border: 1px solid color-mix(in srgb, var(--white) 18%, transparent); background: color-mix(in srgb, var(--mix-light) 7%, transparent); color: var(--ink-cream-7); width: 190px; }
.gen-ied-matchclear { font: inherit; font-size: var(--fs-11-5); font-weight: var(--fw-semi); padding: 4px 11px; border-radius: var(--r-7); border: 1px solid color-mix(in srgb, var(--gold-13) 50%, transparent); background: color-mix(in srgb, var(--gold-13) 16%, transparent); color: var(--ink-cream-7); cursor: pointer; }
.gen-ied-matchclear:hover { background: color-mix(in srgb, var(--gold-13) 28%, transparent); }
.gen-ied-matchhint { font-size: var(--fs-11-5); color: color-mix(in srgb, var(--ink-cream-4) 50%, transparent); }
.gen-ied-matchstrip { display: flex; gap: 7px; overflow-x: auto; overflow-y: hidden; padding-bottom: 4px; }
.gen-ied-matchthumb { position: relative; flex: 0 0 auto; width: 122px; aspect-ratio: var(--project-aspect, 21 / 9); border-radius: var(--r-xs); overflow: hidden; border: 2px solid transparent; background: var(--ied-bg-3); cursor: pointer; padding: 0; }
.gen-ied-matchthumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gen-ied-matchthumb:hover { border-color: color-mix(in srgb, var(--gold-13) 50%, transparent); }
.gen-ied-matchthumb.is-active { border-color: var(--gold-13); box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--gold-13) 35%, transparent); }
.gen-ied-matchthumb-id { position: absolute; left: 4px; bottom: 3px; font-size: var(--fs-9-5); font-weight: var(--fw-bold); color: var(--white); background: rgba(0,0,0,0.62); padding: 1px 5px; border-radius: 4px; pointer-events: none; }
.gen-ied-matchempty { color: color-mix(in srgb, var(--ink-cream-4) 50%, transparent); font-size: var(--fs-12); font-style: italic; padding: 8px 4px; }
/* The B image drawn over the whole stage (object-fit contain, ignores zoom — it's a reference). */
.gen-ied-matchimg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; z-index: 5; cursor: pointer; background: var(--black); }
/* A/B flick badge, top-right of the stage. */
.gen-ied-matchbadge {
  position: absolute; top: 12px; right: 12px; z-index: 6;
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: var(--fs-11-5); font-weight: var(--fw-bold); letter-spacing: var(--track-02);
  padding: 5px 8px 5px 12px; border-radius: var(--r-round); cursor: pointer;
  background: color-mix(in srgb, color-mix(in srgb, var(--shadow-ink) 79%, var(--mix-dark)) 85%, transparent); color: var(--ink-cream-7); border: 1px solid color-mix(in srgb, var(--gold-13) 50%, transparent);
}
.gen-ied-matchbadge.is-b { background: color-mix(in srgb, var(--gold-13) 92%, transparent); color: var(--ink-on-gold-3); border-color: var(--gold-13); }
.gen-ied-matchbadge-key { display: inline-grid; place-items: center; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 5px; font-size: var(--fs-10); font-weight: var(--fw-heavy); background: color-mix(in srgb, var(--mix-light) 14%, transparent); }
.gen-ied-matchbadge.is-b .gen-ied-matchbadge-key { background: color-mix(in srgb, var(--black) 18%, transparent); }

/* v07zz512 — shared dark panel chrome; in-flow flex items beside the image (no longer absolute). */
.gen-ied-tools, .gen-ied-adjust {
  flex: 0 0 auto; z-index: 5;
  background: color-mix(in srgb, var(--ied-bg-10) 95%, transparent); border: 1px solid color-mix(in srgb, var(--white) 13%, transparent); border-radius: 13px;
  box-shadow: 0 8px 30px rgba(0,0,0,0.5); backdrop-filter: blur(var(--blur-scrim-6));
}
.gen-ied-tools { width: 76px; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 11px 7px; max-height: 96vh; overflow-y: auto; }
/* v07zz624 — Hugo: full height, wider, no scroll bar. */
.gen-ied-adjust { width: 330px; height: 96vh; overflow: hidden; padding: 13px; display: flex; flex-direction: column; gap: 8px; }
.gen-ied-tools-head { font-size: var(--fs-9); font-weight: var(--fw-heavy); letter-spacing: 0.11em; color: color-mix(in srgb, var(--ied-ink-2) 55%, transparent); }
.gen-ied-toolbtn {
  width: 40px; height: 32px; border-radius: var(--r-sm); border: 1px solid color-mix(in srgb, var(--white) 16%, transparent);
  background: color-mix(in srgb, var(--mix-light) 7%, transparent); color: var(--ied-ink); cursor: pointer; display: grid; place-items: center; padding: 0;
}
.gen-ied-toolbtn:hover { background: color-mix(in srgb, var(--leaf) 28%, transparent); }
.gen-ied-toolbtn.is-active { background: color-mix(in srgb, var(--leaf) 45%, transparent); border-color: color-mix(in srgb, var(--pale-green) 90%, transparent); color: var(--white); }
.gen-ied-toolbtn:disabled { opacity: 0.32; cursor: default; }
.gen-ied-colors { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-top: 2px; }
.gen-ied-color { width: 17px; height: 17px; border-radius: 50%; border: 1px solid color-mix(in srgb, var(--white) 35%, transparent); cursor: pointer; padding: 0; }
.gen-ied-color.is-active { outline: var(--ring-w) solid color-mix(in srgb, var(--pale-green) 95%, transparent); outline-offset: 1px; }
.gen-ied-colorpick { width: 40px; height: 22px; padding: 0 1px; border: 1px solid color-mix(in srgb, var(--white) 18%, transparent); border-radius: var(--r-xs); background: color-mix(in srgb, var(--mix-light) 8%, transparent); cursor: pointer; }
.gen-ied-sizerange { width: 46px; accent-color: color-mix(in srgb, var(--leaf) 83%, var(--mix-light)); }
.gen-ied-slider { display: flex; flex-direction: column; gap: 1px; }
.gen-ied-slider-top { display: flex; justify-content: space-between; align-items: baseline; }
.gen-ied-slider-label { font-size: var(--fs-10); font-weight: var(--fw-bold); letter-spacing: var(--track-06); color: color-mix(in srgb, var(--ied-ink-2) 60%, transparent); text-transform: uppercase; }
.gen-ied-slider-val { font-family: var(--font-mono, monospace); font-size: var(--fs-10); color: var(--ied-ink); font-variant-numeric: tabular-nums; }
.gen-ied-slider input[type=range] { width: 100%; accent-color: color-mix(in srgb, var(--leaf) 83%, var(--mix-light)); }
.gen-ied-curve { width: 100%; border: 1px solid color-mix(in srgb, var(--white) 14%, transparent); border-radius: var(--r-sm); background: color-mix(in srgb, var(--mix-light) 5%, transparent); cursor: ns-resize; }
.gen-ied-reset {
  font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-bold); padding: 6px 10px; border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--white) 16%, transparent); background: color-mix(in srgb, var(--mix-light) 7%, transparent); cursor: pointer; color: var(--ied-ink);
}
.gen-ied-reset:hover { background: color-mix(in srgb, var(--leaf) 28%, transparent); }
.gen-ied-reset:disabled { opacity: 0.38; cursor: default; }
.gen-ied-save {
  margin-top: 2px; font: inherit; font-size: var(--fs-12); font-weight: var(--fw-heavy); letter-spacing: var(--track-03);
  padding: 10px 12px; border-radius: var(--r-panel); border: 1px solid color-mix(in srgb, color-mix(in srgb, var(--leaf) 84%, var(--mix-dark)) 90%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--leaf) 83%, var(--mix-light)), var(--leaf)); color: var(--white); cursor: pointer;
}
.gen-ied-save:hover { filter: brightness(1.08); }
.gen-ied-save:disabled { opacity: 0.42; cursor: default; filter: none; }
/* v07zz512 — secondary "Use as reference" button (outline on dark). */
.gen-ied-useref {
  font: inherit; font-size: var(--fs-11-5); font-weight: var(--fw-bold); letter-spacing: var(--track-02);
  padding: 9px 12px; border-radius: var(--r-panel); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--white) 22%, transparent); background: color-mix(in srgb, var(--mix-light) 8%, transparent); color: var(--ied-ink);
}
.gen-ied-useref:hover { background: color-mix(in srgb, var(--leaf) 28%, transparent); border-color: color-mix(in srgb, var(--pale-green) 70%, transparent); }
.gen-ied-useref:disabled { opacity: 0.42; cursor: default; }
.gen-ied-copyimg.is-copied { background: color-mix(in srgb, var(--ok) 90%, transparent); color: var(--white); border-color: color-mix(in srgb, color-mix(in srgb, var(--leaf) 84%, var(--mix-dark)) 90%, transparent); }
.gen-ied-savehint { font-size: var(--fs-10); color: color-mix(in srgb, var(--ied-ink-2) 50%, transparent); line-height: 1.35; }
/* Meta pills float at the bottom, dark. */
.gen-ied-meta {
  position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 5;
  max-width: min(70vw, 900px); background: color-mix(in srgb, var(--ied-bg-10) 92%, transparent); border: 1px solid color-mix(in srgb, var(--white) 12%, transparent);
  border-radius: var(--r-md); padding: 8px 12px; box-shadow: 0 6px 24px rgba(0,0,0,0.5); backdrop-filter: blur(var(--blur-scrim-6));
}
.gen-ied-meta .ga-lb-info-model { color: var(--ied-ink-3); }
.gen-ied-meta .ga-lb-info-chip { background: color-mix(in srgb, var(--mix-light) 12%, transparent); color: var(--ied-ink-4); }
.gen-ied-meta .ga-lb-info-prompt, .gen-ied-meta .ga-lb-info-noprompt { color: color-mix(in srgb, var(--ied-ink-5) 82%, transparent); }
.gen-ied-meta-row { cursor: pointer; user-select: none; }
/* 23 Sep 2026 — the plain full-size VIEWER that replaced the removed image editor
   (ImageEditLightbox in GeneratePage.jsx). Image on top, one bar below: details + Use as reference.
   The image box is capped so opening the prompt (inside the scrolling .ga-lb-info) never moves it. */
.ga-lightbox-backdrop.gen-iv-backdrop { justify-content: flex-start; padding-top: 4vh; }   /* pinned to the top: the details grow DOWN */
.gen-iv-img {
  max-width: 94vw; max-height: 74vh; object-fit: contain; display: block;
  border-radius: var(--r-md); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
  -webkit-user-select: none; user-select: none;
}
.gen-iv-bar { display: flex; align-items: flex-start; gap: 10px; width: min(860px, 94vw); }
.gen-iv-bar .gen-iv-meta { flex: 1 1 auto; width: auto; margin: 0; }
.gen-iv-useref { flex: 0 0 auto; }
.gen-ied-meta-caret { margin-left: auto; color: color-mix(in srgb, var(--white) 60%, transparent); font-size: var(--fs-12); }
@media (max-width: 1100px) {
  .gen-ied-row { gap: 6px; }
  .gen-ied-adjust { width: 200px; }
}

/* v07zz536 — Censored-word pre-flight scan panel under the video Copy button. */
.gen-censor-scan { margin-top: 10px; padding: 10px 12px; border-radius: var(--r-panel); background: color-mix(in srgb, var(--gold-2) 12%, transparent); border: 1px solid color-mix(in srgb, color-mix(in srgb, var(--gold) 96%, var(--mix-light)) 40%, transparent); font-size: var(--fs-12-5); }
.gen-censor-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.gen-censor-warn { font-weight: var(--fw-bold); color: var(--ink-tan-deep); letter-spacing: var(--track-01); }
.gen-censor-copy { margin-left: auto; padding: 6px 13px; border: 1px solid color-mix(in srgb, var(--blue-5) 50%, transparent); border-radius: var(--r-7); background: color-mix(in srgb, var(--blue-5) 15%, transparent); color: var(--blue-5-ink); font-size: var(--fs-12); font-weight: var(--fw-semi); cursor: pointer; }
.gen-censor-copy:hover { background: color-mix(in srgb, var(--blue-5) 28%, transparent); }
.gen-censor-swaps { margin-top: 6px; color: var(--olive-9); font-weight: var(--fw-semi); }
.gen-censor-flag { margin-top: 5px; color: var(--ink-tan-deep); font-style: italic; }

/* v772 — per-shot AUDIO chips (video mode). One row above the Model settings; chips echo
   the reference-chip look at pill scale. Absent entirely when the shot has no audio. */
.gen-audio-strip {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 0 10px; padding: 8px 12px;
  background: var(--card-bg, color-mix(in srgb, var(--mix-light) 45%, transparent));
  border: 1px solid var(--card-border, color-mix(in srgb, var(--umber-2) 14%, transparent)); border-radius: var(--r-panel);
}
.gen-audio-label {
  font-size: var(--fs-10-5); font-weight: var(--fw-bold); letter-spacing: var(--track-08); text-transform: uppercase;
  color: var(--ink-muted); flex: 0 0 auto;
}
.gen-audio-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 260px;
  padding: 5px 11px; border-radius: var(--r-round); cursor: grab; user-select: none; -webkit-user-select: none;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 70%, transparent);
  font-size: var(--fs-11-5); color: var(--ink);
}
.gen-audio-chip:active { cursor: grabbing; }
.gen-audio-chip:hover { background: color-mix(in srgb, var(--leaf) 14%, transparent); }
.gen-audio-chip.is-playing { background: color-mix(in srgb, var(--leaf) 28%, transparent); border-color: color-mix(in srgb, var(--leaf) 70%, transparent); }
.gen-audio-ic { flex: 0 0 auto; font-size: var(--fs-12); line-height: 1; }
.gen-audio-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* v894 — clip length on the pill. Tabular digits + a fixed minimum width so "–:––" and
   "1:07" occupy the same space; the pill never shifts when the duration lands. */
.gen-audio-dur {
  flex: 0 0 auto; min-width: 2.9em; text-align: right;
  font-family: "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace; font-size: var(--fs-10-5);
  font-variant-numeric: tabular-nums; color: var(--ink-muted); letter-spacing: var(--track-02);
}
.gen-audio-dur.is-pending { opacity: 0.45; }
.gen-audio-chip.is-playing .gen-audio-dur { color: var(--ink); }
/* v797 — per-chip "open in Explorer" (audio drag rejected by some platform dropzones —
   Hugo: open the file in Explorer and drag from there). The base .reveal-folder-btn is a
   26px shadowed circle for image corners; inside the slim pill it must sit UNDER the text
   line height so the chip never grows (invariant #20). */
.gen-audio-chip .reveal-folder-btn {
  width: 16px; height: 16px; flex: 0 0 auto;
  background: none; border: none; box-shadow: none;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-radius: 4px; color: var(--ink-muted); opacity: 0.75;
}
.gen-audio-chip .reveal-folder-btn:hover { opacity: 1; color: var(--ink); background: color-mix(in srgb, var(--umber-2) 10%, transparent); }

/* v775 — the funnel pills live on their OWN row under the tab bar now (the Videos pill
   made the single row overcrowd + wrap). */
.gen-refs-shotfilter-row { display: flex; align-items: center; margin: 2px 0 8px; }
.gen-refs-shotfilter-row .gen-refs-shotfilter { margin: 0; }

/* v779 — AUDIO chips: their OWN full-width line at the BOTTOM of the References card,
   below the selected-refs row (v775 rendered beside the chips on one line — Hugo).
   Block-level + stretch so the dashed rule spans the card. */
.gen-audio-strip--inline {
  display: flex; align-self: stretch; width: 100%;
  margin: 6px 0 0; padding: 8px 2px 0;
  background: none; border: none; border-radius: 0;
  border-top: 1px dashed color-mix(in srgb, var(--umber-2) 22%, transparent);
}

/* v788 — 👤 Twain SUBJECT pill: per-shot toggle in the video panel's Cinematography
   strip (v787's insert-at-caret refs-bar chip is gone — Hugo never saw it). Pinned to
   the strip's right edge; is-on = the SUBJECT block rides this shot's prompt. */
.gen-twain-chip {
  display: inline-flex; align-items: center; flex: 0 0 auto;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 70%, transparent);
  border-radius: var(--r-round); overflow: hidden;
}
/* v794 — Other-Notes template pills sit LEFT of the Twain pill; the presets row now
   owns the auto-margin (Twain keeps the strip's right edge via order). Scrolls
   horizontally when there are many pills so the strip never wraps (invariant #20). */
.gen-notes-presets {
  margin-left: auto; display: flex; align-items: center; gap: 4px;
  overflow-x: auto; max-width: 52%; flex: 0 1 auto; scrollbar-width: none;
}
.gen-notes-presets::-webkit-scrollbar { display: none; }
.gen-notes-preset .gen-twain-btn { padding: 5px 6px 5px 10px; max-width: 130px; overflow: hidden; text-overflow: ellipsis; }
.gen-notes-preset .gen-twain-edit { padding: 5px 8px 5px 2px; }
.gen-notes-preset-add {
  flex: 0 0 auto; border: 1px dashed color-mix(in srgb, var(--card-border) 70%, transparent); background: color-mix(in srgb, var(--mix-light) 50%, transparent);
  border-radius: var(--r-round); width: 24px; height: 24px; padding: 0; line-height: 1;
  font-size: var(--fs-13); color: var(--ink-muted); cursor: pointer;
}
.gen-notes-preset-add:hover:not(:disabled) { color: color-mix(in srgb, var(--olive-2) 65%, var(--mix-dark)); border-color: color-mix(in srgb, var(--leaf) 80%, transparent); background: color-mix(in srgb, var(--leaf) 12%, transparent); }
.gen-notes-preset-add:disabled { opacity: 0.4; cursor: default; }
/* v941 — labelled save buttons: the bare 24px ＋ circles were unfindable once the
   v940 rails regrouped them. Same dashed-pill family, stretched to carry words. */
.gen-notes-preset-add--labelled {
  width: auto; height: 24px; padding: 0 10px;
  font-size: var(--fs-11); font-weight: var(--fw-bold); letter-spacing: var(--track-01); white-space: nowrap;
}
.gen-twain-chip--cine { margin-left: 8px; flex: 0 0 auto; }
.gen-twain-chip.is-on {
  background: color-mix(in srgb, var(--leaf) 16%, transparent);
  border-color: color-mix(in srgb, var(--leaf) 75%, transparent);
}
.gen-twain-chip.is-on .gen-twain-btn { color: color-mix(in srgb, var(--olive-2) 65%, var(--mix-dark)); font-weight: var(--fw-semi); }
.gen-twain-btn {
  border: 0; background: none; padding: 5px 4px 5px 11px;
  font-size: var(--fs-11-5); color: var(--ink); cursor: pointer; white-space: nowrap;
}
.gen-twain-btn:hover { background: color-mix(in srgb, var(--leaf) 14%, transparent); }
.gen-twain-edit {
  border: 0; background: none; padding: 5px 9px 5px 4px;
  font-size: var(--fs-11); color: var(--ink-muted); cursor: pointer;
}
.gen-twain-edit:hover { color: var(--ink); }

/* v775 — video tiles in the This Shot ▸ Videos pill: never text-select mid-drag. */
.gen-ref-tile--video { user-select: none; -webkit-user-select: none; position: relative; }
/* v780 — ↗ open-the-file button on video tiles (drag-to-Topview fallback). */
.gen-ref-vid-open {
  position: absolute; top: 6px; left: 6px; z-index: 3;
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border-radius: var(--r-xs); cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--card-border) 65%, transparent); background: color-mix(in srgb, var(--mix-light) 85%, transparent); color: var(--ink-umber-2);
}
.gen-ref-vid-open:hover { background: var(--mix-light); border-color: color-mix(in srgb, var(--leaf) 80%, transparent); color: color-mix(in srgb, var(--olive-2) 65%, var(--mix-dark)); }

/* v07zz537 — THIS SHOT reference funnel (Hero | WIP | Archived) — small pill row. */
.gen-refs-shotfilter { display: inline-flex; gap: 4px; margin: 2px 0 10px; padding: 3px; background: color-mix(in srgb, var(--taupe) 10%, transparent); border-radius: var(--r-round); }
.gen-refs-sf-btn { padding: 5px 14px; border: 0; border-radius: var(--r-round); background: transparent; color: var(--ink-muted); font-size: var(--fs-12); font-weight: var(--fw-semi); letter-spacing: var(--track-02); cursor: pointer; transition: background var(--dur-1) ease, color var(--dur-1) ease; }
.gen-refs-sf-btn:hover { color: var(--ink); }
.gen-refs-sf-btn.is-on { background: var(--card-bg, var(--mix-light)); color: var(--ink); box-shadow: 0 1px 3px color-mix(in srgb, var(--shadow-ink) 14%, transparent); }
/* v07zz563 — the funnel sits INLINE in the tab row now (no dedicated row): tighter pills,
   pushed to the right edge next to the Filter box. */
.gen-refs-shotfilter--inline { margin: 0 6px 0 auto; padding: 2px; align-self: center; flex: 0 0 auto; }
.gen-refs-shotfilter--inline .gen-refs-sf-btn { padding: 3px 9px; font-size: var(--fs-10-5); }

/* v07zz539 — Slice button on asset-gen tiles (same affordance as reuse/discard, blue hover). */
.ga-recent-slice {
  flex-shrink: 0; margin-left: 6px;
  width: 26px; height: 26px; border-radius: 50%; padding: 0;
  border: 1px solid color-mix(in srgb, var(--card-border) 60%, transparent); background: color-mix(in srgb, var(--mix-light) 70%, transparent);
  color: var(--ink-muted); cursor: pointer; display: grid; place-items: center;
  opacity: 0; transition: opacity var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}
.ga-recent-item:hover .ga-recent-slice,
.ga-recent-item:focus-within .ga-recent-slice { opacity: 1; }
.ga-recent-slice:hover { background: color-mix(in srgb, var(--blue-5) 16%, transparent); color: var(--blue-5-ink); border-color: color-mix(in srgb, var(--blue-5) 60%, transparent); }
.ga-recent-slice:disabled { opacity: 0.5; cursor: default; }
.ga-recent-slice + .ga-recent-discard { margin-left: 6px; }

/* ─── v07zz620 — "Drag all refs" chips (shot-gen chips row + asset-gen attached row).
   One draggable element that carries EVERY selected reference as a File. ─── */
.gen-ref-chip--dragall { cursor: grab; border-style: dashed; user-select: none; -webkit-user-select: none; }
.gen-ref-chip--dragall:active { cursor: grabbing; }
.ga-attached-dragall {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  cursor: grab; border: 1.5px dashed color-mix(in srgb, color-mix(in srgb, var(--tan-deep) 89%, var(--mix-dark)) 55%, transparent);
  background: color-mix(in srgb, var(--mix-light) 35%, transparent); user-select: none; -webkit-user-select: none;
}
.ga-attached-dragall:active { cursor: grabbing; }
.ga-attached-dragall-glyph { font-size: var(--fs-15); line-height: 1; opacity: 0.85; }
.ga-attached-dragall-label { font-size: var(--fs-9); font-weight: var(--fw-heavy); letter-spacing: var(--track-06); opacity: 0.85; }

/* ─── v07zz623 — image editor LAYERS (tabs + stack panel + mask tools) ─────────
   The right panel is now ADJUST | LAYERS. The tab body is a fixed-height scroller
   so switching tabs never resizes the panel (invariant: no layout shift). */
.gen-ied-tools-head--sub { margin-top: 4px; }
.gen-ied-tabs { display: flex; gap: 5px; }
.gen-ied-tab {
  flex: 1; border: 1px solid color-mix(in srgb, var(--white) 16%, transparent); background: color-mix(in srgb, var(--mix-light) 6%, transparent);
  color: color-mix(in srgb, var(--ied-ink-2) 72%, transparent); border-radius: var(--r-sm); padding: 5px 6px; cursor: pointer;
  font-size: var(--fs-9-5); font-weight: var(--fw-heavy); letter-spacing: 0.09em;
}
.gen-ied-tab:hover { background: color-mix(in srgb, var(--leaf) 22%, transparent); }
.gen-ied-tab.is-on { background: color-mix(in srgb, var(--leaf) 42%, transparent); border-color: color-mix(in srgb, var(--pale-green) 85%, transparent); color: var(--white); }
.gen-ied-tabbody {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column; gap: 8px; padding-right: 2px;
}
.gen-ied-tabnote { font-size: var(--fs-10); line-height: 1.45; color: color-mix(in srgb, var(--ied-ink-2) 50%, transparent); }

/* add-layer buttons + the shot picker */
.gen-ied-layeradd { display: flex; gap: 5px; }
.gen-ied-addbtn {
  flex: 1; border: 1px dashed color-mix(in srgb, var(--pale-green) 55%, transparent); background: color-mix(in srgb, var(--leaf) 14%, transparent);
  color: color-mix(in srgb, var(--pale-green) 32%, var(--mix-light)); border-radius: var(--r-sm); padding: 7px 4px; cursor: pointer; font-size: var(--fs-10-5); font-weight: var(--fw-bold);
}
.gen-ied-addbtn:hover { background: color-mix(in srgb, var(--leaf) 30%, transparent); }
.gen-ied-addbtn:disabled { opacity: 0.45; cursor: default; }
.gen-ied-shotpick {
  border: 1px solid color-mix(in srgb, var(--white) 14%, transparent); border-radius: var(--r-9); padding: 7px;
  background: color-mix(in srgb, var(--black) 28%, transparent); display: flex; flex-direction: column; gap: 6px;
}
.gen-ied-shotpick-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 5px; max-height: 190px; overflow-y: auto; }
.gen-ied-shotpick-item {
  border: 1px solid color-mix(in srgb, var(--white) 14%, transparent); background: color-mix(in srgb, var(--mix-light) 5%, transparent); border-radius: var(--r-7);
  padding: 0; cursor: pointer; overflow: hidden; display: flex; flex-direction: column;
}
.gen-ied-shotpick-item:hover { border-color: color-mix(in srgb, var(--pale-green) 90%, transparent); }
.gen-ied-shotpick-item img { width: 100%; aspect-ratio: 16/9; object-fit: cover; display: block; }
.gen-ied-shotpick-item span { font-size: var(--fs-8-5); font-weight: var(--fw-bold); color: color-mix(in srgb, var(--ied-ink-2) 75%, transparent); padding: 2px 0 3px; }

/* the stack */
.gen-ied-layerlist { display: flex; flex-direction: column; gap: 5px; }
.gen-ied-layer {
  border: 1px solid color-mix(in srgb, var(--white) 13%, transparent); border-radius: var(--r-9); background: color-mix(in srgb, var(--mix-light) 4.5%, transparent);
  padding: 6px; cursor: pointer;
}
.gen-ied-layer.is-sel { border-color: color-mix(in srgb, var(--pale-green) 85%, transparent); background: color-mix(in srgb, var(--leaf) 16%, transparent); }
.gen-ied-layer-row { display: flex; align-items: center; gap: 6px; }
.gen-ied-layer-eye {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: var(--r-xs); border: 1px solid color-mix(in srgb, var(--white) 16%, transparent);
  background: color-mix(in srgb, var(--mix-light) 7%, transparent); color: var(--ied-ink); cursor: pointer; display: grid; place-items: center; padding: 0;
}
.gen-ied-layer-eye.is-off { opacity: 0.45; }
/* v07zz658 — Photoshop-size layer thumbnail. Hugo sent the PS layers panel as the
   reference: "tiny thumbnails". PS uses a ~36px square-ish chip with a hard 1px frame,
   not a 34x24 sliver. */
.gen-ied-layer-thumb {
  flex: 0 0 auto; width: 40px; height: 34px; border-radius: 2px; overflow: hidden;
  background: color-mix(in srgb, var(--black) 50%, transparent); border: 1px solid color-mix(in srgb, var(--white) 35%, transparent);
}
.gen-ied-layer-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The chain between layer and mask, exactly as PS draws it. */
.gen-ied-layer-link {
  flex: 0 0 auto; display: grid; place-items: center; width: 12px;
  color: color-mix(in srgb, var(--ied-ink-2) 55%, transparent);
}
/* THE MASK SWATCH — the element Hugo kept telling me was missing. White = the layer is
   revealed; black = it starts hidden and gets painted back with Reveal. Same read as
   Photoshop's mask thumbnail. */
.gen-ied-layer-mask {
  flex: 0 0 auto; width: 40px; height: 34px; border-radius: 2px; padding: 0; cursor: pointer;
  background: var(--mix-light); border: 1px solid color-mix(in srgb, var(--white) 35%, transparent);
  position: relative; display: grid; place-items: center;
}
.gen-ied-layer-mask.is-hidden { background: var(--ied-bg-5); }
.gen-ied-layer-mask:hover { border-color: color-mix(in srgb, var(--pale-green) 90%, transparent); }
.gen-ied-layer-mask.has-strokes { box-shadow: inset 0 0 0 var(--ring-w) color-mix(in srgb, var(--leaf) 85%, transparent); }
.gen-ied-layer-mask-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--leaf); }
.gen-ied-layer-name {
  flex: 1; min-width: 0; font-size: var(--fs-11); font-weight: var(--fw-bold); color: var(--ied-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gen-ied-layer-lock { font-size: var(--fs-8-5); font-weight: var(--fw-heavy); letter-spacing: var(--track-08); color: color-mix(in srgb, var(--ied-ink-2) 42%, transparent); }
.gen-ied-layer-acts { display: flex; gap: 2px; }
.gen-ied-layer-acts button {
  width: 19px; height: 19px; border-radius: 5px; border: 1px solid color-mix(in srgb, var(--white) 14%, transparent);
  background: color-mix(in srgb, var(--mix-light) 6%, transparent); color: color-mix(in srgb, var(--ied-ink-2) 80%, transparent); cursor: pointer;
  font-size: 8px; line-height: 1; padding: 0;
}
.gen-ied-layer-acts button:hover { background: color-mix(in srgb, var(--leaf) 30%, transparent); }
.gen-ied-layer-del:hover { background: var(--danger-border) !important; color: var(--white); }
/* v07zz658 — Photoshop's two compact header rows ("Normal ▾  Opacity: 100%" /
   "Lock: …  Fill: 100%"). Numeric fields, NOT the full-width stacked sliders Hugo
   called garbage — those ate the panel and looked nothing like PS. */
.gen-ied-ps-row {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: var(--fs-10-5); color: color-mix(in srgb, var(--ied-ink-2) 80%, transparent);
}
.gen-ied-ps-blend {
  flex: 1 1 auto; min-width: 0; background: color-mix(in srgb, var(--black) 45%, transparent); color: var(--ied-ink);
  border: 1px solid color-mix(in srgb, var(--white) 22%, transparent); border-radius: 3px; padding: 2px 4px; font-size: var(--fs-10-5);
}
.gen-ied-ps-num { flex: 0 0 auto; display: flex; align-items: center; gap: 4px; white-space: nowrap; }
.gen-ied-ps-num input {
  width: 44px; background: color-mix(in srgb, var(--black) 45%, transparent); color: var(--ied-ink); text-align: right;
  border: 1px solid color-mix(in srgb, var(--white) 22%, transparent); border-radius: 3px; padding: 2px 4px; font: inherit; font-size: var(--fs-10-5);
}
.gen-ied-ps-lock { flex: 1 1 auto; display: flex; align-items: center; gap: 5px; min-width: 0; }
.gen-ied-ps-mini {
  border: 1px solid color-mix(in srgb, var(--white) 20%, transparent); background: color-mix(in srgb, var(--mix-light) 7%, transparent);
  color: color-mix(in srgb, var(--ied-ink-2) 85%, transparent); border-radius: 3px; padding: 2px 7px; font: inherit; font-size: var(--fs-10); cursor: pointer;
}
.gen-ied-ps-mini:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 30%, transparent); }
.gen-ied-ps-mini:disabled { opacity: 0.38; cursor: default; }
.gen-ied-layer-ctl { margin-top: 7px; display: flex; flex-direction: column; gap: 6px; cursor: default; }
.gen-ied-layer-lab { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-size: var(--fs-10); font-weight: var(--fw-bold); color: color-mix(in srgb, var(--ied-ink-2) 70%, transparent); }
.gen-ied-layer-lab select {
  flex: 1; max-width: 120px; background: color-mix(in srgb, var(--black) 40%, transparent); color: var(--ied-ink);
  border: 1px solid color-mix(in srgb, var(--white) 18%, transparent); border-radius: var(--r-xs); padding: 3px 5px; font-size: var(--fs-10-5);
}
.gen-ied-layer-btns { display: flex; flex-wrap: wrap; gap: 4px; }
.gen-ied-layer-chip {
  border: 1px solid color-mix(in srgb, var(--white) 18%, transparent); background: color-mix(in srgb, var(--mix-light) 6%, transparent); color: color-mix(in srgb, var(--ied-ink-2) 85%, transparent);
  border-radius: var(--r-round); padding: 3px 8px; font-size: var(--fs-9-5); font-weight: var(--fw-bold); cursor: pointer;
}
.gen-ied-layer-chip:hover { background: color-mix(in srgb, var(--leaf) 30%, transparent); }
.gen-ied-layer-chip.is-on { background: color-mix(in srgb, var(--leaf) 45%, transparent); border-color: color-mix(in srgb, var(--pale-green) 90%, transparent); color: var(--white); }
.gen-ied-layer-chip:disabled { opacity: 0.4; cursor: default; }

/* drop-an-image-on-the-stage affordance */
.gen-ied-stage.is-drophot { outline: var(--ring-w) dashed color-mix(in srgb, var(--pale-green) 95%, transparent); outline-offset: -6px; }
.gen-ied-drophint {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  background: color-mix(in srgb, var(--ied-bg-10) 92%, transparent); color: color-mix(in srgb, var(--pale-green) 32%, var(--mix-light)); border: 1px solid color-mix(in srgb, var(--pale-green) 70%, transparent);
  border-radius: var(--r-panel); padding: 10px 16px; font-size: var(--fs-12); font-weight: var(--fw-bold); pointer-events: none;
}

/* ─── v07zz624 — editor: top "ADD A LAYER" browser + labelled mask tools ───────
   v07zz630 — Hugo: "This is what I want the reference panel to look like, the same
   (in dark mode) as the one in the asset gen. And it needs to take the whole empty
   space at the top. The right panel should not go over it obviously."
   So: full-bleed band across the TOP of the backdrop, the Generate REFERENCES panel
   exactly as-is (category pills + labelled tile grid) but re-skinned dark, and the
   floating side panels shortened + pushed down so they clear it. */
.gen-ied-layerpick {
  position: relative; z-index: 8;
  flex: 0 0 auto; width: 100%; margin: 0;
  max-height: 46vh; overflow: hidden;
  background: color-mix(in srgb, var(--ied-bg-11) 97%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--white) 9%, transparent);
  box-shadow: 0 10px 34px rgba(0,0,0,0.5);
}
/* ── re-skin the shared references panel for the editor's dark mode ── */
.gen-ied-layerpick .gen-section--layerpick {
  margin: 0; height: auto; max-height: 46vh;
  background: transparent; border: none; box-shadow: none;
  border-radius: 0; padding: 12px 54px 12px 18px;
}
.gen-ied-layerpick .gen-section-head,
.gen-ied-layerpick .gen-section-title { color: color-mix(in srgb, var(--ink-cream-7) 92%, transparent); }
.gen-ied-layerpick .gen-section-sub,
.gen-ied-layerpick .gen-refs-overflow,
.gen-ied-layerpick .gen-refs-empty { color: color-mix(in srgb, var(--ink-cream-4) 50%, transparent); }
.gen-ied-layerpick .gen-refs-tabs { border-bottom-color: color-mix(in srgb, var(--white) 10%, transparent); }

/* ─── v887 — refs SEARCH lives in the section header ─────────────────────────
   Moved out of the drag-scrolling tab row, where it sat off-screen past DROP /
   PASTE. Same 22px height as the job-slot pills so the header never grows
   (invariant #20); resets the header's uppercase / tracking so typed text
   reads normally. */
.gen-section--refs .gen-section-head .gen-refs-search {
  margin-left: auto;
  flex: 0 1 220px;
  width: 220px;
  max-width: 45%;
  height: 22px;
  padding: 0 8px;
  box-sizing: border-box;
  font-size: var(--fs-11-5);
  font-weight: var(--fw-med);
  letter-spacing: normal;
  text-transform: none;
  line-height: 20px;
}
/* ─── v905 — whole-set preset pills above the video direction boxes ──────────
   Fixed min-height so gaining/losing pills never shifts the boxes below (#20).
   Pills reuse the Twain/notes-preset chip family. */
.gen-vset-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  min-height: 26px; margin: 0 0 6px; padding: 0 2px;
}
.gen-vset-label {
  font-size: var(--fs-8-5); font-weight: var(--fw-heavy); letter-spacing: var(--track-14); color: var(--ink-muted);
  flex: 0 0 auto; margin-right: 2px;
}
/* v977 — how many reference images a set carries. Sits between the name button and
   the ×, OUTSIDE the width-capped name so it never truncates the name. line-height 1
   and a font-size below the chip's own keep the pill's height untouched (#20). */
.gen-vset-refcount {
  flex: 0 0 auto; font-size: var(--fs-8-5); line-height: 1; font-weight: var(--fw-bold);
  letter-spacing: var(--track-02); color: var(--ink-muted); opacity: 0.85;
  padding: 0 1px 0 2px; white-space: nowrap;
}

/* ─── v940 — the DIRECTION SHEET (video panel): SETS header rail + the four boxes +
   the cinematography footer rail read as ONE bounded card, in the same console
   language as the v938 head band. Fixes the orphan "SETS ⊕" strip and the clipping,
   unwrappable bottom tags Hugo called garbage. Scoped to the video section only. */
/* v956 — Hugo's mockup: SETS is a PLAIN labeled row (the v940 card-header rail is
   gone), and the box grid is a borderless container whose FIELDS are the cards. */
.gen-section--match-refs .gen-vset-row {
  margin: 0 0 2px; padding: 2px 2px; min-height: 24px;
}
.gen-section--match-refs .gen-vset-label { font-size: var(--fs-9); letter-spacing: var(--track-16); }
.gen-section--match-refs .gen-vset-row .gen-notes-preset-add { margin-left: auto; }
/* v959 — explicit row sizing so the four boxes stay MOCKUP-SIZED and the panel can
   never stretch them into the absurd (Hugo: "WAY too tall, absolute garbage").
   Rows: two box rows that share the flexible height, then the cinematography block
   and the character row at their natural size. */
.gen-section--match-refs .gen-video-inputs--compact {
  border: none;
  padding: 0;
  background: transparent;
  gap: 9px;
  grid-template-rows: minmax(140px, 1fr) minmax(140px, 1fr) auto auto;
}
/* every direction box is its own paper card, label inside (the mockup) */
.gen-section--match-refs .gen-video-inputs--compact .gen-video-field {
  border: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  border-radius: var(--r-panel);
  background: color-mix(in srgb, var(--cream-15) 55%, transparent);
  padding: 8px 10px 9px;
  gap: 5px;
}
.gen-section--match-refs .gen-video-inputs--compact .gen-video-field .gen-direction {
  border: none; background: transparent; box-shadow: none; padding: 2px 0 0;
}
.gen-section--match-refs .gen-video-inputs--compact .gen-video-field .gen-direction:focus {
  outline: none;
}
.gen-section--match-refs .gen-video-inputs--compact .gen-video-field:focus-within {
  border-color: color-mix(in srgb, var(--leaf) 65%, transparent);
  box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--leaf) 20%, transparent);
}
/* camera card header: label left, compact Add-move select right */
.gen-vf-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.gen-vf-head .gen-cammove-select {
  flex: 0 1 auto; min-width: 0; max-width: 128px;
  font-size: var(--fs-10-5); padding: 2px 4px; height: 22px;
}
/* notes pills pinned at the card foot */
.gen-notes-presets--incard {
  display: flex; flex-wrap: wrap; gap: 4px; align-items: center;
  margin-top: auto; padding-top: 6px;
  border-top: 1px dashed color-mix(in srgb, var(--card-border) 35%, transparent);
}
/* v950 — the four direction boxes get a HARD floor (~5 visible lines). The card's
   height:auto grows to fit, so the rails can never squeeze typing room again. */
.gen-section--match-refs .gen-video-inputs--compact .gen-direction {
  min-height: 96px;
}
/* v956 — CINEMATOGRAPHY: a plain full-width row (label + hint + Save) with the
   standing block VISIBLE in a bordered preview box below (Hugo's mockup). The
   v940 gradient rail + bleed margins are gone. */
.gen-section--match-refs .gen-video-inputs--compact .gen-cine-field {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  border: none; background: transparent; padding: 0;
}
.gen-section--match-refs .gen-cine-head {
  display: flex; align-items: center; gap: 6px;
  flex-wrap: wrap; row-gap: 4px;
  background: transparent; border: none; padding: 0 2px; margin: 0;
}
/* v959 — preset pills sit ON the cinematography label's row (mockup), not wrapped
   underneath: the long "always appended…" hint is what pushed them down, so it is
   hidden here and survives as the toggle's tooltip. */
/* v961 — one bottom row: ▸ Cinematography · preset pills · 👤 Twain. */
.gen-section--match-refs .gen-cine-head .gen-notes-presets {
  display: inline-flex; flex-wrap: nowrap; gap: 4px; align-items: center;
  margin-left: 2px; flex: 0 1 auto; min-width: 0; overflow: hidden;
}
.gen-section--match-refs .gen-cine-head .gen-twain-chip--cine { flex: 0 0 auto; }
.gen-section--match-refs .gen-cine-head .gen-dir-ovr { display: none; }
.gen-section--match-refs .gen-cine-head .gen-craft-tailtoggle { flex: 0 0 auto; width: auto; }
.gen-cine-preview {
  border: 1px solid color-mix(in srgb, var(--card-border) 45%, transparent);
  border-radius: var(--r-panel);
  background: color-mix(in srgb, var(--cream-15) 55%, transparent);
  padding: 8px 10px;
  margin-top: 5px;
  font-family: var(--font-mono, "JetBrains Mono"), monospace;
  font-size: var(--fs-10-5); line-height: 1.5; color: var(--ink-muted);
  white-space: pre-wrap;
  max-height: 64px; overflow: hidden;
  cursor: pointer;
}
.gen-cine-preview:hover { border-color: color-mix(in srgb, var(--leaf) 55%, transparent); color: var(--ink); }
.gen-section--match-refs .gen-cine-field .gen-cine-cols { margin: 6px 0 4px; }
/* v956 — CHARACTER row at the panel foot */
.gen-char-row {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 10px;
  padding: 2px 2px 0;
}
/* v959 — the v956 "fill the page" min-height (100vh - 560px) blew the panel out to
   ~1300px on Hugo's tall monitor and stretched the four boxes into a wall of empty
   space. The row is a DETERMINISTIC height instead: both columns fill it, the
   REFS panel absorbs any slack on the left, and the boxes keep mockup proportions. */
/* flex:0 0 auto is REQUIRED — the row is an item in a column flex parent, so a bare
   height gets shrunk (measured 640 → 524). */
/* v960 — taller (Hugo: "we can go taller than that, look at all the dead space at
   the bottom"): the extra height goes to the REFERENCES panel on the left and the
   typing boxes on the right. */
.gen-row-2col--video { height: 730px; flex: 0 0 auto; }
/* v959 — video mode gives the builder more width so the whole control band fits on
   ONE row like the mockup (the 1.2/0.8 split left it ~90px short). */
/* v960 — REFERENCES get the wider column back (v959's 1/1.25 made the builder far
   too wide and squeezed the refs to a single thumb row — Hugo: "the panel is now
   wayy too wide … i need more space for the references"). */
.gen-row-2col--video { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
.gen-videohead-row .gen-ph-label { font-size: 8px; letter-spacing: 0.13em; }
.gen-videohead-row .gen-swap-toggle { gap: 0; }
.gen-row-2col--video > .gen-col { height: 100%; min-height: 0; }
.gen-row-2col--video .gen-col--refs > .gen-section:last-child { flex: 1 1 auto; min-height: 0; }

/* ─── v900 — GOOD TAKE buttons (both drawer components) ──────────────────────
   Green check family — the video funnel's Good, now on frames. */
.ga-action--good { color: var(--ink-forest-4); border-color: color-mix(in srgb, var(--olive-11) 55%, transparent); background: color-mix(in srgb, var(--ok) 10%, transparent); }
.ga-action--good:hover { background: color-mix(in srgb, var(--ok) 20%, transparent); }
.ga-action--good.is-good { background: color-mix(in srgb, var(--ok) 30%, transparent); border-color: color-mix(in srgb, var(--olive-11) 85%, transparent); color: color-mix(in srgb, var(--ink-forest-6) 74%, var(--mix-dark)); }
.gen-gens-act--good { color: var(--ink-forest-4); }
.gen-gens-act--good.is-good { background: color-mix(in srgb, var(--ok) 30%, transparent); color: color-mix(in srgb, var(--ink-forest-6) 74%, var(--mix-dark)); }

/* ─── v889 — drag-to-reorder the selected-ref chips ──────────────────────────
   Grab a chip, drop it on another: the gold bar shows which side it lands on
   and the dragged chip dims. Box-shadow only — nothing moves until the drop
   (invariant #20). Off during a Swap pick (chips have the pointer cursor there). */
.gen-ref-chip--sortable { cursor: grab; }
.gen-ref-chip--sortable:active { cursor: grabbing; }
.gen-ref-chip.is-dragging { opacity: 0.35; }
.gen-ref-chip.is-drop-before { box-shadow: -4px 0 0 0 color-mix(in srgb, var(--gold-16) 76%, var(--mix-dark)); }
.gen-ref-chip.is-drop-after  { box-shadow:  4px 0 0 0 color-mix(in srgb, var(--gold-16) 76%, var(--mix-dark)); }

.gen-section--refs .gen-section-head .gen-refs-search::placeholder {
  letter-spacing: normal;
  text-transform: none;
  color: color-mix(in srgb, var(--ink-umber) 45%, transparent);
}
.gen-ied-layerpick .gen-refs-tab {
  color: color-mix(in srgb, var(--ink-cream-4) 62%, transparent);
  background: color-mix(in srgb, var(--mix-light) 5%, transparent);
  border-color: color-mix(in srgb, var(--white) 14%, transparent);
}
.gen-ied-layerpick .gen-refs-tab:hover { color: color-mix(in srgb, var(--ink-cream-6) 56%, var(--mix-light)); background: color-mix(in srgb, var(--mix-light) 11%, transparent); }
.gen-ied-layerpick .gen-refs-tab.is-active {
  color: var(--ink-on-leaf-3); background: var(--leaf); border-color: var(--pale-green);
}
.gen-ied-layerpick .gen-refs-filter,
.gen-ied-layerpick input[type="search"], .gen-ied-layerpick input[type="text"] {
  background: color-mix(in srgb, var(--mix-light) 7%, transparent); color: var(--ink-cream-7); border-color: color-mix(in srgb, var(--white) 18%, transparent);
}
.gen-ied-layerpick .gen-refs-grid {
  max-height: 30vh;
  scrollbar-color: color-mix(in srgb, var(--white) 30%, transparent) transparent;
}
.gen-ied-layerpick .gen-ref-tile { background: var(--ied-bg-9); border-color: color-mix(in srgb, var(--white) 14%, transparent); }
.gen-ied-layerpick .gen-ref-tile:hover { border-color: color-mix(in srgb, var(--pale-green) 80%, transparent); }
.gen-ied-layerpick .gen-ref-tile-label,
.gen-ied-layerpick .gen-ref-tile-cap { color: color-mix(in srgb, var(--ink-cream-4) 75%, transparent); }
.gen-ied-layerpick .gen-refs-loadmore,
.gen-ied-layerpick .gen-src-morepill {
  color: color-mix(in srgb, var(--ink-cream-4) 80%, transparent); background: color-mix(in srgb, var(--mix-light) 7%, transparent); border-color: color-mix(in srgb, var(--white) 18%, transparent);
}
.gen-ied-layerpick-close {
  position: absolute; top: 10px; right: 14px; z-index: 3;
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid color-mix(in srgb, var(--white) 22%, transparent);
  background: color-mix(in srgb, var(--mix-light) 10%, transparent); color: var(--ink-cream-7); cursor: pointer; font-size: var(--fs-16); line-height: 1; padding: 0;
}
.gen-ied-layerpick-close:hover { background: color-mix(in srgb, var(--danger-4) 90%, transparent); color: var(--white); border-color: color-mix(in srgb, var(--danger-4) 90%, transparent); }
/* v07zz650 — Hugo: "not sure what the hell is happening with that Layers panel. it's
   not docked to the right neither spanning the whole browser's height."
   That was THIS rule (mine, from v630). It shrank the right panel to ~54vh and set
   height:auto whenever the image browser was open, which also out-specified the
   `top:8 / bottom:8` docking rule — so the panel floated mid-screen.
   It was never needed: the browser band already reserves the panel's width via
   `padding-right: var(--ied-right-w)`, so the panel sits in that gutter and the band's
   content never runs under it. The panel now stays docked full-height in BOTH modes.
   Only the canvas still gets capped (below) so the image clears the band. */
.gen-ied-backdrop:has(.gen-ied-layerpick) .gen-ied-canvas { max-height: calc(100vh - 46vh - 32px); }
.gen-ied-addbtn--wide { flex: 1 1 100%; }
.gen-ied-layeradd { flex-wrap: wrap; }
/* labelled tool buttons (Move / Hide / Reveal) */
.gen-ied-toolbtn--lab {
  width: 100%; height: auto; padding: 6px 4px; gap: 2px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.gen-ied-toolbtn--lab span { font-size: var(--fs-8-5); font-weight: var(--fw-heavy); letter-spacing: var(--track-04); }
.gen-ied-toolhint {
  font-size: var(--fs-8-5); line-height: 1.3; text-align: center;
  color: color-mix(in srgb, var(--ied-ink-2) 42%, transparent); padding: 0 2px;
}

/* v07zz662 — Drag-all readiness. The chip used to look identical whether or not its
   payload existed, so a drag that carried nothing was indistinguishable from one that
   worked ("looks like it's dragging but drags nothing"). Now it says so. */
.gen-ref-chip--dragall.is-notready,
.ga-attached-dragall.is-notready {
  opacity: 0.55; cursor: progress;
}
.gen-ref-chip--dragall.is-failed,
.ga-attached-dragall.is-failed {
  opacity: 1; cursor: pointer;
  border-color: color-mix(in srgb, var(--red-3) 70%, transparent) !important;
  color: var(--red-3);
}

/* v07zz666 — Stop + Adjust on the craft controls. Both are always in the DOM and merely
   disabled when they don't apply, so the row's width and wrap never change with state
   (invariant #20). */
.gen-craft-stop {
  flex: 0 0 auto; font: inherit; font-size: var(--fs-10); line-height: 1;
  padding: 0 9px; align-self: stretch; min-height: 26px;
  border-radius: var(--r-round); cursor: pointer;
  border: 1px solid var(--card-border);
  background: color-mix(in srgb, var(--cream) 70%, transparent); color: var(--danger-2);
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, opacity var(--dur-1) ease;
}
.gen-craft-stop:hover:not(:disabled) { background: color-mix(in srgb, var(--danger-2) 14%, transparent); border-color: color-mix(in srgb, var(--danger-2) 60%, transparent); }
.gen-craft-stop:active:not(:disabled) { transform: translateY(1px); }
.gen-craft-stop:disabled { opacity: 0.3; cursor: default; color: var(--ink-muted, color-mix(in srgb, var(--ink-taupe) 89%, var(--mix-light))); }
.gen-craft-stop--inline { min-height: 30.5px; }
/* Adjust is the quieter sibling of Craft — same pill, no gold fill, so the primary
   action still reads as primary. */
.gen-craft-btn--adjust {
  background: color-mix(in srgb, var(--cream) 75%, transparent);
  border-color: var(--card-border);
  color: var(--ink);
}
.gen-craft-btn--adjust:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 16%, transparent); border-color: color-mix(in srgb, var(--leaf) 60%, transparent); filter: none; }

/* v700 — Craft presets: compact auto-width pills on their OWN wrapped row (v698 put
   them inside the 2-col .ga-craft-intents GRID, so each stretched to half the panel with
   the ✕ marooned). Save preset is its own small pill, NOT a segment of the model toggle —
   v698 gave it .ga-craft-provider + a dashed border and it read as a broken 4th model. */
.ga-savepreset-pill {
  flex: 0 0 auto; font: inherit; font-size: var(--fs-10-5); font-weight: var(--fw-bold); letter-spacing: var(--track-03);
  padding: 5px 11px; border-radius: var(--r-round); cursor: pointer; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--card-border) 70%, transparent); background: color-mix(in srgb, var(--cream) 72%, transparent); color: var(--ink);
}
.ga-savepreset-pill:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 18%, transparent); border-color: color-mix(in srgb, var(--leaf) 75%, transparent); }
.ga-savepreset-pill:disabled { opacity: 0.4; cursor: default; }
.ga-preset-nameinput {
  width: 100%; font: inherit; font-size: var(--fs-13); padding: 8px 10px; margin-bottom: 8px;
  border: 1px solid color-mix(in srgb, var(--card-border) 80%, transparent); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--cream) 90%, transparent); color: var(--ink);
}
.confirm-delete-btn--go { background: var(--accent-strong, var(--leaf)); }

/* v703 — Adjust on the asset craft row: same size as Craft, visually secondary so the
   primary action stays obvious. Stop reuses .gen-craft-stop from the shot row. */
.ga-craft-btn--adjust { background: color-mix(in srgb, var(--cream) 80%, transparent); color: var(--ink); border: 1px solid color-mix(in srgb, var(--card-border) 70%, transparent); }
.ga-craft-btn--adjust:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 18%, transparent); border-color: color-mix(in srgb, var(--leaf) 75%, transparent); }

/* v709 — DROP / PASTE pill. Sits last in the References tab row, same pill geometry as
   the category tabs so the row reads as one strip (Hugo: "as a pill next to External
   References, like Upload"). Dashed until you drag over it, then it fills — the only
   affordance that says "this one is a target, not a filter". */
.gen-refs-droppill {
  border-style: dashed !important;
  white-space: nowrap;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease, color var(--dur-1) ease;
}
.gen-refs-droppill:not(:disabled):hover { border-style: solid !important; }
.gen-refs-droppill.is-over {
  border-style: solid !important;
  background: color-mix(in srgb, var(--leaf) 28%, transparent) !important;
  border-color: color-mix(in srgb, var(--leaf) 95%, transparent) !important;
  color: color-mix(in srgb, var(--olive-7) 45%, var(--mix-dark)) !important;
}
.gen-refs-droppill.is-busy { opacity: 0.7; cursor: progress; }
.gen-refs-droppill:disabled { opacity: 0.4; cursor: not-allowed; }
.gen-refs-droperr {
  align-self: center; margin-left: 8px;
  font-size: var(--fs-11); color: var(--danger, var(--red-13));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px;
}

/* v710 — Photoshop parity in the layer editor.
   1. The mask swatch is a PAINT TARGET, not an invert button. When it's the active
      target it gets Photoshop's white targeting ring, so you can always see whether
      your brush is going to hit the mask.
   2. Scrubby sliders: the WORDS "Opacity" and "Size" are draggable, so the number can
      be scrubbed without aiming at a tiny field. */
.gen-ied-layer-mask.is-target {
  box-shadow: 0 0 0 var(--ring-w) var(--white), 0 0 0 3.5px color-mix(in srgb, var(--shade) 90%, transparent);
}
.gen-ied-scrub {
  cursor: ew-resize;
  user-select: none; -webkit-user-select: none;
  touch-action: none;
  padding-right: 2px;
  border-bottom: 1px dotted currentColor;   /* the affordance: this word is draggable */
}
.gen-ied-scrub:hover { color: var(--accent, color-mix(in srgb, var(--gold-8) 92%, var(--mix-light))); }

/* ═══ v711 — PHOTOSHOP PARITY PASS ════════════════════════════════════════════
   Hugo: "can you do a pass on this whole photoshop clone thing so it LOOKS and
   ACTUALLY behaves just like photoshop??" Four pieces of real PS chrome that
   were missing: the options bar, the canvas checkerboard, the status bar, and
   the layers-panel footer icon strip. */

/* ── 1. OPTIONS BAR — the strip across the top, above everything ───────────── */
/* FIXED height (invariant #20): the contents change with the tool, the bar does
   not, so the image never shifts when you pick a different tool. */
.gen-ied-optbar {
  flex: 0 0 auto; height: 38px; box-sizing: border-box;
  display: flex; align-items: center; gap: 10px;
  padding: 0 calc(var(--ied-right-w, 346px) + 40px) 0 12px;   /* clear the pinned panel + the × */
  background: color-mix(in srgb, var(--mix-light) 5%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--white) 10%, transparent);
}
.gen-ied-opt-tool {
  flex: 0 0 auto; font-size: var(--fs-10); font-weight: var(--fw-heavy); letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ied-ink); min-width: 88px;
}
.gen-ied-opt-sep { flex: 0 0 auto; width: 1px; height: 18px; background: color-mix(in srgb, var(--mix-light) 14%, transparent); }
.gen-ied-opt-ctl {
  flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-11); color: color-mix(in srgb, var(--ied-ink-2) 72%, transparent);
  overflow: hidden; white-space: nowrap;
}
.gen-ied-opt-lab { font-size: var(--fs-11); font-weight: var(--fw-bold); color: color-mix(in srgb, var(--ied-ink-2) 85%, transparent); }
.gen-ied-opt-range { width: 132px; accent-color: var(--leaf); }
.gen-ied-opt-val {
  font-size: var(--fs-10-5); font-weight: var(--fw-bold); color: var(--ied-ink);
  min-width: 34px;                       /* reserved — "0.5%" and "12%" don't jiggle the row */
  font-variant-numeric: tabular-nums;
}
.gen-ied-opt-swatch {
  width: 18px; height: 18px; border-radius: 4px;
  border: 1px solid color-mix(in srgb, var(--white) 40%, transparent); flex: 0 0 auto;
}
.gen-ied-opt-target { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.gen-ied-opt-target b { color: var(--ied-ink); font-weight: var(--fw-bold); }
.gen-ied-opt-hist { flex: 0 0 auto; display: flex; align-items: center; gap: 4px; }
.gen-ied-opt-histbtn {
  width: 26px; height: 24px; border-radius: var(--r-xs); padding: 0; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--white) 16%, transparent); background: color-mix(in srgb, var(--mix-light) 7%, transparent);
  color: var(--ied-ink); display: grid; place-items: center;
}
.gen-ied-opt-histbtn:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 32%, transparent); border-color: color-mix(in srgb, var(--pale-green) 80%, transparent); }
.gen-ied-opt-histbtn:disabled { opacity: 0.32; cursor: default; }
.gen-ied-opt-histcount {
  font-size: var(--fs-9-5); font-weight: var(--fw-heavy); color: color-mix(in srgb, var(--ied-ink-2) 50%, transparent);
  min-width: 16px; text-align: right; font-variant-numeric: tabular-nums;
}

/* ── 2. CHECKERBOARD behind the canvas ─────────────────────────────────────── */
/* PS shows transparency as a grey chequer. Ours also makes it obvious where the
   image ends when a layer is dragged past the frame edge. */
.gen-ied-stage {
  background-color: var(--ied-bg-4);
  background-image:
    linear-gradient(45deg, rgba(255,255,255,0.045) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.045) 75%),
    linear-gradient(45deg, rgba(255,255,255,0.045) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.045) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
}
/* the hand tool, held with Space — grabbing beats every other cursor */
.gen-ied-stage.is-handpan .gen-ied-canvas--paint,
.gen-ied-stage.is-handpan { cursor: grab; }
.gen-ied-stage.is-handpan:active .gen-ied-canvas--paint,
.gen-ied-stage.is-handpan:active { cursor: grabbing; }

/* ── 3. STATUS BAR — bottom-left of the canvas, always on ──────────────────── */
.gen-ied-statusbar {
  position: absolute; left: 8px; bottom: 8px; z-index: 4;
  display: flex; align-items: center; gap: 7px; height: 24px; padding: 0 9px;
  border-radius: var(--r-7); background: color-mix(in srgb, var(--ied-bg-12) 82%, transparent);
  border: 1px solid color-mix(in srgb, var(--white) 12%, transparent); backdrop-filter: blur(var(--blur-scrim-6));
  font-size: var(--fs-10-5); color: color-mix(in srgb, var(--ied-ink-2) 78%, transparent); line-height: 1;
}
.gen-ied-status-zoom {
  font-weight: var(--fw-heavy); color: var(--ied-ink);
  min-width: 44px;                       /* "5%" … "1600%" — reserved so nothing shuffles */
  font-variant-numeric: tabular-nums;
}
.gen-ied-status-btn {
  border: 1px solid color-mix(in srgb, var(--white) 15%, transparent); background: color-mix(in srgb, var(--mix-light) 7%, transparent);
  color: var(--ied-ink); border-radius: 5px; padding: 2px 6px; font-size: var(--fs-9-5);
  font-weight: var(--fw-bold); cursor: pointer; line-height: 1.2;
}
.gen-ied-status-btn:hover { background: color-mix(in srgb, var(--leaf) 32%, transparent); border-color: color-mix(in srgb, var(--pale-green) 80%, transparent); }
.gen-ied-status-doc { color: color-mix(in srgb, var(--ied-ink-2) 55%, transparent); font-variant-numeric: tabular-nums; }
.gen-ied-status-hint { color: color-mix(in srgb, var(--ied-ink-2) 42%, transparent); }

/* ── 4. LAYERS PANEL FOOTER — Photoshop's icon strip under the stack ───────── */
.gen-ied-layerfoot {
  display: flex; align-items: center; gap: 4px; margin-top: 7px; padding-top: 7px;
  border-top: 1px solid color-mix(in srgb, var(--white) 10%, transparent);
}
.gen-ied-footbtn {
  width: 26px; height: 24px; border-radius: var(--r-xs); padding: 0; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--white) 14%, transparent); background: color-mix(in srgb, var(--mix-light) 6%, transparent);
  color: color-mix(in srgb, var(--ied-ink-2) 85%, transparent); display: grid; place-items: center;
}
.gen-ied-footbtn:hover:not(:disabled) { background: color-mix(in srgb, var(--leaf) 30%, transparent); border-color: color-mix(in srgb, var(--pale-green) 80%, transparent); color: var(--white); }
.gen-ied-footbtn:disabled { opacity: 0.34; cursor: default; }
.gen-ied-footbtn--del { margin-left: auto; }
.gen-ied-footbtn--del:hover:not(:disabled) { background: var(--danger-border); border-color: color-mix(in srgb, color-mix(in srgb, var(--amber) 92%, var(--mix-dark)) 85%, transparent); }

/* ═══ v718/v719 — SWAP A REFERENCE IN PLACE ═══════════════════════════════════
   Click a pill to arm it, then pick a replacement from the tabs — it lands in
   THAT slot and keeps its @N, so a prompt saying "@image2" keeps pointing at the
   same slot. v719: the WHOLE pill is the target (Hugo: "not that little tiny
   square"), and the armed state is shown ON the pill instead of in a banner
   above the row — a banner would have pushed every row below it down. */
.gen-ref-chip-thumbwrap { position: relative; display: inline-flex; line-height: 0; }
.gen-ref-chip-swap {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: color-mix(in srgb, var(--shade) 55%, transparent); color: var(--white); border-radius: inherit;
  opacity: 0; transition: opacity 110ms ease; pointer-events: none;
}
/* the badge answers "what does clicking this pill do?", so it follows PILL hover */
.gen-ref-chip--swappable:hover .gen-ref-chip-swap { opacity: 1; }
.gen-ref-chip-thumbwrap.is-armed .gen-ref-chip-swap { opacity: 1; background: color-mix(in srgb, var(--leaf) 78%, transparent); }
/* Same selected language as .gen-ref-chip--pick.is-source above — this row already
   says "chosen" that way, and box-shadow/background can't shift layout. */
.gen-ref-chip--swappable { cursor: pointer; }
.gen-ref-chip--swappable:hover { box-shadow: 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 60%, transparent); }
.gen-ref-chip--swaparmed,
.gen-ref-chip--swaparmed:hover { box-shadow: 0 0 0 var(--ring-w) var(--leaf); background: color-mix(in srgb, var(--leaf) 16%, transparent); }

/* ── 5. LAYER RESTACK BY DRAG ──────────────────────────────────────────────── */
.gen-ied-layer[draggable="true"] { cursor: grab; }
.gen-ied-layer.is-dragging { opacity: 0.45; cursor: grabbing; }
.gen-ied-layer.is-dropinto { box-shadow: 0 -2px 0 0 var(--leaf) inset, 0 0 0 var(--hairline-w) color-mix(in srgb, var(--leaf) 60%, transparent); }

/* ═══ v712 — TOOL ≠ TARGET, AND A BRUSH THAT HAS A SOFT EDGE ═════════════════
   Hugo: "I dont have softness control for the brush, i dont have shortcuts to
   change brush size and softness. When I click on mask, i dont get the brush,
   then if i click on brush, i get kicked out of the mask." */

/* ── Foreground / background swatches, Photoshop's corner of the toolbar ───── */
.gen-ied-fgbg { position: relative; width: 46px; height: 42px; margin: 2px auto 4px; flex: 0 0 auto; }
.gen-ied-sw {
  position: absolute; width: 26px; height: 26px; border-radius: 3px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--white) 55%, transparent); box-shadow: 0 1px 4px rgba(0,0,0,0.5);
  display: block; overflow: hidden;
}
.gen-ied-sw input { opacity: 0; width: 100%; height: 100%; cursor: pointer; border: 0; padding: 0; }
.gen-ied-sw--fg { left: 0; top: 0; z-index: 2; }
.gen-ied-sw--bg { right: 0; bottom: 0; z-index: 1; }
.gen-ied-swswap {
  position: absolute; right: -2px; top: -3px; z-index: 3;
  width: 14px; height: 14px; padding: 0; border: 0; background: none; cursor: pointer;
  color: color-mix(in srgb, var(--ied-ink-2) 75%, transparent); display: grid; place-items: center;
}
.gen-ied-swswap:hover { color: var(--white); }
.gen-ied-swreset {
  position: absolute; left: -3px; bottom: -1px; z-index: 3;
  width: 11px; height: 11px; padding: 0; cursor: pointer; border-radius: 2px;
  border: 1px solid color-mix(in srgb, var(--white) 50%, transparent);
  background: linear-gradient(135deg, var(--mix-light) 0 50%, var(--black) 50% 100%);
}

/* ── The brush cursor: the real footprint, plus the hard core when soft ────── */
.gen-ied-stage.is-brushing .gen-ied-canvas--paint { cursor: none; }
.gen-ied-brushcur {
  position: absolute; z-index: 5; pointer-events: none;
  transform: translate(-50%, -50%); border-radius: 50%;
  /* two rings, light over dark, so the outline reads on ANY image underneath */
  border: 1px solid color-mix(in srgb, var(--white) 95%, transparent);
  box-shadow: 0 0 0 var(--hairline-w) rgba(0,0,0,0.55), inset 0 0 0 var(--hairline-w) rgba(0,0,0,0.55);
  display: grid; place-items: center;
}
.gen-ied-brushcur-core {
  border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--white) 55%, transparent);
  box-shadow: 0 0 0 var(--hairline-w) rgba(0,0,0,0.35);
}

/* ── Options bar: room for Size + Hardness + Opacity on one fixed-height row ── */
.gen-ied-opt-range--sm { width: 84px; }
.gen-ied-optbar .gen-ied-opt-range { width: 96px; }
/* The permanent "what am I painting on" readout — a button, not just a label. */
.gen-ied-opt-on {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-start;
  gap: 1px; padding: 2px 8px; cursor: pointer; max-width: 230px;
  border-radius: var(--r-xs); border: 1px solid color-mix(in srgb, var(--white) 16%, transparent);
  background: color-mix(in srgb, var(--mix-light) 6%, transparent); color: var(--ied-ink); line-height: 1.15;
}
.gen-ied-opt-on:hover { background: color-mix(in srgb, var(--leaf) 26%, transparent); border-color: color-mix(in srgb, var(--pale-green) 80%, transparent); }
.gen-ied-opt-on.is-mask { background: color-mix(in srgb, color-mix(in srgb, var(--gold-5) 75%, var(--mix-light)) 20%, transparent); border-color: color-mix(in srgb, color-mix(in srgb, var(--gold-5) 71%, var(--mix-light)) 75%, transparent); }
.gen-ied-opt-on-k { font-size: var(--fs-7-5); font-weight: var(--fw-heavy); letter-spacing: var(--track-10); color: color-mix(in srgb, var(--ied-ink-2) 55%, transparent); }
.gen-ied-opt-on-v {
  font-size: var(--fs-10-5); font-weight: var(--fw-bold); max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Targeting brackets: Photoshop marks the ACTIVE target, and now so do we ── */
.gen-ied-layer-thumb {
  padding: 0; cursor: pointer; display: block;
  /* was a <span>; as a button it needs the frame back explicitly */
  background: color-mix(in srgb, var(--black) 50%, transparent); border: 1px solid color-mix(in srgb, var(--white) 35%, transparent);
}
.gen-ied-layer-thumb.is-target,
.gen-ied-layer-mask.is-target {
  box-shadow: 0 0 0 var(--ring-w) var(--white), 0 0 0 3.5px color-mix(in srgb, var(--shade) 90%, transparent);
}
.gen-ied-layer-thumb:hover, .gen-ied-layer-mask:hover { border-color: color-mix(in srgb, var(--pale-green) 90%, transparent); }
.gen-ied-footbtn.is-on { background: color-mix(in srgb, color-mix(in srgb, var(--gold-5) 75%, var(--mix-light)) 28%, transparent); border-color: color-mix(in srgb, color-mix(in srgb, var(--gold-5) 71%, var(--mix-light)) 80%, transparent); color: var(--white); }

/* ═══ v724/v733 — CINEMATOGRAPHY block (video prompts only) ═══════════════════
   Editable + saved server-side. v733: spans BOTH columns of the video-fields
   grid, collapsed by default behind a chevron header; expanded, the two boxes
   sit side by side (Camera physics | Beat structure). */
.gen-cine-field {
  grid-column: 1 / -1;
  border-top: 1px dashed color-mix(in srgb, var(--taupe-2) 45%, transparent);
  padding-top: 8px; margin-top: 4px;
}
/* The card's spare height goes to the FIELD rows, never the cine row — auto rows
   all stretch by default, so the collapsed header row was swallowing ~140px of
   dead space. Fields grow to fill instead. */
/* v959 — FOUR rows now (two box rows + cinematography + character) with a 140px
   floor per box row. This is the rule that actually wins the cascade — the
   .gen-section--match-refs one above is less specific. */
/* v961 — THREE rows again: the character row is gone (Twain moved onto the
   cinematography pill row), so the two box rows take everything else. */
.gen-row-2col--video .gen-section--match-refs .gen-video-inputs--compact {
  grid-template-rows: minmax(140px, 1fr) minmax(140px, 1fr) auto;
}
.gen-cine-head { display: flex; align-items: center; gap: 8px; }
.gen-cine-save {
  /* v788 — was margin-left:auto (right edge). The 👤 Twain pill owns the right edge of
     this strip now (always visible); Save appears next to the label it saves. */
  margin-left: 4px;
  min-width: 62px; text-align: center;   /* Saving… / Saved ✓ / Save all fit one box */
}
.gen-cine-cols {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  margin-top: 6px;
}
.gen-cine-col { display: flex; flex-direction: column; min-width: 0; }
/* The compact card flex-fills .gen-direction (flex:1 1 0) — inside the accordion's
   auto-height columns that would crush the boxes to slivers. rows= governs here. */
.gen-section--match-refs .gen-video-inputs--compact .gen-cine-cols .gen-direction {
  flex: 0 0 auto; resize: vertical;
}
.gen-cine-beatlabel { display: block; }
.gen-cine-beatlabel input { vertical-align: -1px; margin-right: 2px; }

/* ─── v814 — JOB SLOTS (shot-gen References header) ──────────────────────────
   Four independent jobs on one shot. Sits inline in the section head, right of
   the "References" label. Fixed size per pill and a reserved dot row, so the
   header never changes height as slots gain/lose work (invariant #20). */
.gen-section-head .gen-jobslots {
  display: inline-flex; gap: 4px; margin-left: 10px; vertical-align: middle;
}
.gen-jobslot {
  position: relative;
  width: 22px; height: 22px; padding: 0; border-radius: var(--r-xs); cursor: pointer;
  font: inherit; font-size: var(--fs-11); font-weight: var(--fw-bold); line-height: 1;
  display: inline-grid; place-items: center;
  background: color-mix(in srgb, var(--cream) 35%, transparent);
  border: 1px solid color-mix(in srgb, var(--taupe) 28%, transparent);
  color: color-mix(in srgb, var(--ink-umber) 62%, transparent);
  transition: background 110ms ease, border-color 110ms ease, color 110ms ease;
}
.gen-jobslot:hover { background: color-mix(in srgb, var(--cream) 80%, transparent); color: color-mix(in srgb, color-mix(in srgb, var(--ink-umber) 86%, var(--mix-dark)) 90%, transparent); }
.gen-jobslot.is-on {
  background: color-mix(in srgb, color-mix(in srgb, var(--leaf) 84%, var(--mix-light)) 50%, transparent);
  border-color: color-mix(in srgb, var(--olive-11) 85%, transparent);
  color: color-mix(in srgb, var(--leaf) 28%, var(--mix-dark));
}
/* A slot that holds refs or a prompt but isn't the one you're looking at. */
.gen-jobslot.has-work::after {
  content: ""; position: absolute; top: 2px; right: 2px;
  width: 4px; height: 4px; border-radius: 50%;
  background: color-mix(in srgb, color-mix(in srgb, var(--gold-16) 76%, var(--mix-dark)) 95%, transparent);
}

/* ─── v854 — Generate page: fit the button on screen in IMAGE mode ─────────────
   Hugo: "in many modes, the button goes under the scroll which i dont want to at
   all. so find ways to shrink some sections so i can see everything."

   Measured the whole centre stack in image mode: 1586px against a 1080 viewport.
   The waste was NOT padding — it was the MODE column. Twelve mode buttons in a
   2-column grid is SIX rows, and because the settings columns all stretch to the
   tallest one, that forced Resolution's two buttons to 143px EACH and Model's to
   93px. Nobody needs a 143px-tall "2K" button.

   Three columns makes it four rows: the settings row drops 344px -> 238px and the
   stretched neighbours shrink with it. The buttons go to 11px with tighter side
   padding so the longest label ("Swap Character") still fits the narrower box —
   verified live that NO mode button overflows horizontally or vertically. */
.gen-settings--image .gen-model-row--mode {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.gen-settings--image .gen-model-row--mode .gen-model-btn {
  padding: 4px 5px;
  font-size: var(--fs-11);
  line-height: 1.15;
}
/* 23 Sep 2026 — Hugo's image-mode decisions: FIVE mode buttons (Single image, Grid, Upscale,
   Edit an image, Craft prompt) + a fixed-height options band under them. A 6-track grid puts
   three buttons on row 1 (span 2) and two on row 2 (span 3): no orphan cell. The column keeps
   the old four-row height (26 + 2x42+6 + 6 + 2x42+6 = 212px), so the settings row and
   everything below sit exactly where they did, and switching mode/flavour/task moves nothing
   (invariant #20). */
.gen-settings--image .gen-model-row--mode.gen-model-row--mode5 {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  grid-template-rows: repeat(2, 42px);
  flex: 0 0 auto;
}
/* Measured on Hugo's 2268px page: the settings row was 245.5px in the six-column modes
   (single / grid / several shots / no shot context / swap / craft) and 238px in the
   four-column ones (upscale / change light / match vibe / new angle / modify / replace), a
   7.5px jump that came from the neighbouring columns, not from Mode. With the six edit tasks
   now one picker, that jump would happen on every task click, so the row reserves the taller
   state for every image mode. */
.gen-settings--image.gen-settings--stacked3 { min-height: 246px; }
/* The Grid size switch in the Mode header is 27.75px tall against the header's 22px floor,
   so the five buttons dropped 5.75px whenever Grid was picked. Reserve the switch's height. */
.gen-setting:has(.gen-model-row--mode5) .gen-setting-labelrow { min-height: 28px; }
.gen-model-row--mode5 .gen-model-btn { grid-column: span 2; }
.gen-model-row--mode5 .gen-model-btn:nth-child(n+4) { grid-column: span 3; }
.gen-modeopts {
  flex: 0 0 90px;
  height: 90px;
  margin-top: 6px;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-width: 0;
}
.gen-modeopts-switch {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}
.gen-modeopts-switch .gen-slicemode-btns { display: flex; }
.gen-modeopts-switch .gen-slicemode-btn { flex: 1 1 0; min-width: 0; padding: 3px 6px; white-space: nowrap; }
.gen-settings--stacked3 .gen-model-row.gen-model-row--task {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: repeat(2, 42px);
  gap: 6px;
  flex: 0 0 auto;
}
.gen-model-row--task .gen-model-btn {
  min-width: 0;
  width: 100%;
  height: 42px;
  padding: 4px 5px;
  font-size: var(--fs-11);
  line-height: 1.15;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
}
/* 24 Sep 2026 — Hugo: "why is model with 2 colums and three rows when there are 4 pills?? what is
   this empty column on the right of resolution??" The shot settings row was a hand-tuned GRID of
   tracks per mode class, and every pill panel was a fixed 3-row grid. Both broke silently when a
   count changed: 4 models in a 3-row grid (2 empty cells), 5 aspects in 2x3 (1 empty), and Swap
   character's six-track template holding five cards (an empty track right of Resolution).
   Now the row is a FLEX row that lays out only the cards it actually renders, and each card is
   as wide as its pill columns need: --pg-cols (set in GeneratePage.jsx by _pillGridVars from the
   real item count) x the card's pill unit. The spare width is shared in proportion, so every card
   scales together and no card or cell is ever empty. The row keeps its 246px floor, so switching
   mode, task or model moves nothing below (invariant #20). */
.gen-settings.gen-settings--image.gen-settings--stacked3 {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 14px;
  /* the builder is a scrolling flex column: without this the row shrank to its 246px floor on
     a short screen and its cards spilled over the panel below */
  flex-shrink: 0;
}
.gen-settings--image.gen-settings--stacked3 > .gen-setting {
  --pg-unit: 64;
  flex-grow: calc(var(--pg-cols, 1) * var(--pg-unit));
  flex-shrink: 1;
  flex-basis: 0px;
  min-width: calc(var(--pg-cols, 1) * var(--pg-unit) * 1px);
}
.gen-settings--image.gen-settings--stacked3 > .gen-setting:has(.gen-model-row--mode5) { flex: 0 0 244px; min-width: 244px; }
.gen-settings--image.gen-settings--stacked3 > .gen-setting--models { --pg-unit: 96; }
.gen-settings--image.gen-settings--stacked3 > .gen-setting--style  { --pg-unit: 80; }
.gen-settings--image.gen-settings--stacked3 > .gen-setting--tod    { --pg-unit: 58; }
.gen-settings--image.gen-settings--stacked3 > .gen-setting--aspect { --pg-unit: 52; }
.gen-settings--image.gen-settings--stacked3 > .gen-setting--res    { --pg-unit: 64; }
/* The pill grid: exactly --pg-cols x --pg-rows, filled column by column (the order Hugo knows:
   Time of day reads Dawn, Morning, Late morning down the first column). Rows share the card's
   height, so the pills fill it top to bottom. */
.gen-settings--image.gen-settings--stacked3 .gen-model-row.gen-pillgrid {
  display: grid;
  grid-template-columns: repeat(var(--pg-cols, 1), minmax(0, 1fr));
  grid-template-rows: repeat(var(--pg-rows, 1), minmax(0, 1fr));
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 8px;
  flex: 1 1 auto;
}
.gen-settings--image.gen-settings--stacked3 .gen-pillgrid .gen-model-btn {
  min-width: 0;
  width: 100%;
  white-space: normal;
  line-height: 1.15;
  padding-left: 6px;
  padding-right: 6px;
}
/* A narrow builder (1280-wide screens): Mode takes its own line and the other cards share the
   second one, so there are always exactly two lines and a mode switch never adds or removes one.
   The second line keeps one height for every mode. */
@container genbuilder (max-width: 1090px) {
  .gen-settings--image.gen-settings--stacked3 > .gen-setting:has(.gen-model-row--mode5) { flex: 1 1 100%; max-width: none; }
  .gen-settings--image.gen-settings--stacked3 > .gen-setting:not(:has(.gen-model-row--mode5)) { height: 216px; }
  .gen-settings--image.gen-settings--stacked3 > .gen-setting--models { --pg-unit: 80; }
  .gen-settings--image.gen-settings--stacked3 > .gen-setting--style  { --pg-unit: 82; }
  .gen-settings--image.gen-settings--stacked3 > .gen-setting--tod    { --pg-unit: 58; }
  .gen-settings--image.gen-settings--stacked3 > .gen-setting--aspect { --pg-unit: 46; }
  .gen-settings--image.gen-settings--stacked3 > .gen-setting--res    { --pg-unit: 56; }
  /* VIDEO row on a narrow builder: "1080p" ran 6px past its card (the Model track took 2.9fr).
     Model gives a little width to Resolution; its four pills still fit on one line. */
  .gen-settings.gen-settings--video { grid-template-columns: minmax(0, 2.4fr) minmax(0, 0.95fr) minmax(0, 1.15fr) minmax(0, 1.3fr); }
}
.gen-builder { container: genbuilder / inline-size; }
/* v852 gave the FROM THE SHOTLIST card seven rows (Location / Light / Subject /
   Behaviour joined Action / Narration / Shot type). A tighter row rhythm keeps every
   one of them visible without the card charging 270px for it. */
.gen-context-grid { gap: 2px; }
.gen-context-row { padding-top: 2px; padding-bottom: 2px; }

/* v859 — LIVE CRAFT OUTPUT. Hugo: "can we have the AI assistants stream the generations?
   It takes too long to wait for the whole thing to finish before I can see anything."
   The model's raw text as it arrives. Capped height with its own scroll so a 2,000-character
   answer can never push the Craft button off screen mid-run — the whole point of v853/v854
   was getting that button back on the page. Mono + small, because this is a working view of
   text being written, not the finished prompt (that lands in the box below when it's done). */
.gen-craft-live {
  margin-top: 6px;
  max-height: 132px;
  overflow-y: auto;
  padding: 8px 10px;
  border: 1px dashed color-mix(in srgb, var(--taupe-2) 55%, transparent);
  border-radius: var(--r-xs);
  background: color-mix(in srgb, var(--cream-14) 55%, transparent);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: var(--fs-11);
  line-height: 1.5;
  color: var(--ink-muted, color-mix(in srgb, var(--ink-taupe-3) 84%, var(--mix-dark)));
  white-space: pre-wrap;
  word-break: break-word;
}

/* v860 — ASSISTANT CHAT streaming. Hugo: "i was talking about the chat assistants in the
   pop up bubble". The reply types out instead of landing in one lump after 30-180s. */
.aichat-bub--live { white-space: pre-wrap; }
.aichat-caret {
  display: inline-block; width: 2px; height: 1em; margin-left: 2px;
  vertical-align: -0.15em; background: currentColor; opacity: 0.7;
  animation: aichat-blink 1s step-end infinite;
}
@keyframes aichat-blink { 0%, 100% { opacity: 0.7; } 50% { opacity: 0; } }
/* The reasoning phase. Same bubble box as a reply so the thread never jumps when it
   switches from thinking to writing. */
.aichat-thinking { font-style: italic; opacity: 0.75; }

/* v1003 — asset REFERENCES strip: drag a tile onto another to re-order (the @N badges
   follow). Mirrors the shot-gen chip styling in .gen-ref-chip so both surfaces read the
   same. The tile is not `draggable` itself — the <img> inside is natively draggable and
   still carries the full-res file out to Kling / Seedance / Explorer; its dragstart just
   bubbles up to arm the reorder. */
.ga-attached-tile--sortable { cursor: grab; }
.ga-attached-tile--sortable:active { cursor: grabbing; }
.ga-attached-tile.is-dragging { opacity: 0.35; }
.ga-attached-tile.is-drop-before { box-shadow: -4px 0 0 0 color-mix(in srgb, var(--gold-16) 76%, var(--mix-dark)); }
.ga-attached-tile.is-drop-after  { box-shadow:  4px 0 0 0 color-mix(in srgb, var(--gold-16) 76%, var(--mix-dark)); }

/* v1059 — Hugo: "all the text in the buttons got bigger somehow, match the text
   size of the Mode ones."

   Nothing grew: Mode has been 11px since v07zz561 (its 3-column grid needed the
   smaller type so "Swap Character" fits), while every other column in the row
   sat at the base 13px. The gap only became obvious once Model went from a
   narrow 5-tall stack to full-width pills at v1058 — bigger boxes, so the bigger
   type finally read as wrong.

   One size for the whole settings row: Model, Visual style, Time of day, Aspect
   ratio and Resolution all drop to Mode's 11px / 1.15. Scoped to
   .gen-settings--image, so the VIDEO panel (.gen-settings--video, which sets its
   own 11.5px) and the asset panel are untouched. Mode's own rule already says
   11px and is more specific, so it is unaffected either way. */
.gen-settings--image .gen-model-btn,
.gen-settings--image .gen-res-btn {
  font-size: var(--fs-11);
  line-height: 1.15;
}

/* v1061 — asset settings row: compact. Hugo: "Make sure the models box is not
   this tall and theres so much empty space everywhere."
   Measured before: Model 284px, Aspect 250px, Resolution 186px — the Model card
   alone was taller than the picture beside it. The cause is 13px labels wrapping
   to three lines inside a half-width cell. Same 11px the shot settings row uses
   (v1059), plus tighter padding, and one minimum height so the three cards agree
   instead of raggedly disagreeing. */
.ga-settings-row3 .gen-model-btn,
.ga-settings-row3 .gen-res-btn {
  font-size: var(--fs-11);
  line-height: 1.15;
  padding: 7px 6px;
  white-space: normal;
  min-height: 30px;
}
/* The three button groups fill their card, so the cards end up the same height
   and nothing below shifts when the model list changes length (invariant #20). */
.ga-settings-row3 .gen-setting { display: flex; flex-direction: column; }
.ga-settings-row3 .ga-quad-col,
.ga-settings-row3 .ga-quad-2col { flex: 1 1 auto; align-content: start; }

/* v1078 — Hugo: "why is it a column? make inline buttons that fit in better shapes".
   The options are short buttons sized to their label, side by side, wrapping as needed.
   The Model card gets the most room (the longest names), Resolution the least. The cards
   still stretch to one height, and only Resolution changes length on a toggle (2 or 3
   buttons, one row either way), so nothing below moves (invariant #20). */
@media (min-width: 901px) {
  .gen-settings.ga-settings-row3 { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1.2fr) minmax(0, 0.75fr); }
}
.ga-opt-wrap { display: flex; flex-wrap: wrap; gap: 6px; align-content: flex-start; }
.ga-settings-row3 .ga-opt-wrap .gen-model-btn,
.ga-settings-row3 .ga-opt-wrap .gen-res-btn { width: auto; min-width: 0; flex: 0 0 auto; padding: 7px 11px; white-space: nowrap; }
.ga-settings-row3 .ga-opt-wrap .gen-res-btn { min-width: 44px; }
