/* ═══════════════════════════════════════════════════════════════
   Composer v2 — unified LumiYing-style generation composer
   slice-dashboard-composer-redesign (Phase 2A: shell + toolbar)

   Frontend reskin only. The legacy #panel-image / #panel-video stay
   in the DOM as the engine (DOM-ID contract); this surface is the new
   face. Everything binds to theme.css tokens so dark + light both work.
   Accent is --accent (= --violet, CG purple). NEVER --cyan.
   ═══════════════════════════════════════════════════════════════ */

/* ── Mode swap ───────────────────────────────────────────────────
   composer.js adds body.composer-v2 once it has initialised. Until
   then (and if the script ever throws) the legacy workbench renders,
   so this is a graceful fallback, not a hard cutover. */
#composer-v2 { display: none; }
body.composer-v2 #composer-v2 { display: block; }
body.composer-v2 #panel-image,
body.composer-v2 #panel-video { display: none !important; }

/* ── Hide legacy control surfaces redundant with the composer ─────
   ALL scoped to body.composer-v2 and display:none only — nothing
   leaves the DOM. Toggle the class off (devtools) and the full legacy
   UI returns intact, preserving the graceful fallback + DOM-ID
   contract (costFor / generate* / ref systems still read these). */

/* Legacy model rail (the two #sidebar model-list panels). The
   composer toolbar's model dropdown is now the sole model picker.
   Profile link + Brand Kit + Credits panels in the sidebar stay. */
body.composer-v2 #sidebar section.panel:has(.model-list) { display: none; }

/* Brand Kit + Credits sidebar panels — redundant in the composer
   (Credits stays reachable via the topbar credits pill). CSS-only,
   DOM intact; toggle composer-v2 off and both return. */
body.composer-v2 #brandKitPanel,
body.composer-v2 #sidebarCreditsPanel { display: none !important; }
/* With both its only children (Brand Kit + Credits) hidden and the
   Director reparented into .sidebar-scroll (not here), .sidebar-pinned is
   fully empty under v2 — hide the whole container so its border-top
   (var(--border2), theme-aware) doesn't draw an orphaned divider line. */
body.composer-v2 #sidebar .sidebar-pinned { display: none !important; }

/* Legacy Image / Video tab buttons — the composer's media switch owns
   that choice. Storyboard / Shot List share this .tabs bar and must
   stay reachable, so we hide ONLY the image/video buttons. */
body.composer-v2 .tabs .tab[data-tab="image"],
body.composer-v2 .tabs .tab[data-tab="video"] { display: none; }

/* When an admin opens Storyboard / Shot List the composer hides
   (body gets .cmp-aux from composer.js); re-expose the Image/Video
   tabs there so they have a way back to the composer. */
body.composer-v2.cmp-aux .tabs .tab[data-tab="image"],
body.composer-v2.cmp-aux .tabs .tab[data-tab="video"] { display: inline-flex; }

/* ── Card shell ──────────────────────────────────────────────── */
#composer-v2 {
  --cmp-radius: 18px;
  --cmp-pill-radius: 10px;
}
.cmp-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px;
  background: var(--surface, #0f1128);
  border: 1px solid var(--line-strong, rgba(255,255,255,0.14));
  border-radius: var(--cmp-radius);
  box-shadow: var(--shadow, 0 4px 20px rgba(0,0,0,0.5));
}
.cmp-card:focus-within {
  border-color: var(--accent, #7c6dfa);
  box-shadow: var(--shadow-violet, 0 8px 32px rgba(124,109,250,0.3));
}

/* ── Cascading reference slots ───────────────────────────────── */
.cmp-refs {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.cmp-ref-slot {
  position: relative;
  width: 72px;
  height: 72px;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: var(--field-bg, rgba(8,10,28,0.85));
  border: 1px dashed var(--line-strong, rgba(255,255,255,0.18));
  border-radius: 12px;
  color: var(--mute, rgba(240,242,255,0.62));
  cursor: pointer;
  font-family: inherit;
  transition: border-color .16s ease, color .16s ease, transform .16s ease;
}
.cmp-ref-slot:hover {
  border-color: var(--accent, #7c6dfa);
  color: var(--text, #f0f2ff);
  transform: translateY(-1px);
}
.cmp-ref-slot.is-primary { border-style: solid; }
/* Drag-and-drop affordance — highlight the tile a file is hovering over.
   Scoped to body.composer-v2 so the reskin stays isolated (no global leak). */
body.composer-v2 .cmp-ref-slot.is-drop-hover {
  border-style: solid;
  border-color: var(--accent, #7c6dfa);
  color: var(--text, #f0f2ff);
  box-shadow: 0 0 0 2px var(--accent, #7c6dfa) inset;
  transform: translateY(-1px);
}
/* Phase 2: drop affordance on the prompt textarea + the choice popover. */
body.composer-v2 .cmp-prompt.is-drop-hover,
body.composer-v2 .cmp-prompt-wrap:has(.cmp-prompt.is-drop-hover) {
  box-shadow: 0 0 0 2px var(--accent, #7c6dfa) inset;
  border-radius: 12px;
}
body.composer-v2 .cmp-prompt-drop-popover {
  display: flex;
  flex-direction: column;
  min-width: 180px;
  padding: 6px;
  gap: 4px;
  background: var(--panel, #14162e);
  border: 1px solid var(--line-strong, rgba(255,255,255,0.18));
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.5);
}
body.composer-v2 .cmp-prompt-drop-popover button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  border-radius: 7px;
  color: var(--text, #f0f2ff);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
body.composer-v2 .cmp-prompt-drop-popover button:hover {
  background: var(--accent, #7c6dfa);
  color: #fff;
}
.cmp-ref-plus { font-size: 22px; line-height: 1; font-weight: 300; }
.cmp-ref-hint { font-size: 10px; letter-spacing: .02em; }
.cmp-ref-slot[hidden] { display: none; }
/* a filled slot shows its thumb; wired in 2C */
.cmp-ref-slot .cmp-ref-thumb {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; border-radius: 11px;
  display: none;
}
.cmp-ref-slot.is-filled .cmp-ref-thumb { display: block; }
.cmp-ref-slot.is-filled .cmp-ref-plus,
.cmp-ref-slot.is-filled .cmp-ref-hint { display: none; }

/* Remove (×) affordance on a FILLED tile (slice-composer-polish UC1).
   A <span> inside the slot <button> — composer.js intercepts clicks on it
   before the open-picker path. Hidden until hover (always visible on
   touch / keyboard focus-within so it stays reachable without hover). */
.cmp-ref-x {
  position: absolute;
  top: 3px;
  right: 3px;
  z-index: 2;
  width: 18px;
  height: 18px;
  display: none;
  align-items: center;
  justify-content: center;
  line-height: 1;
  font-size: 13px;
  border-radius: 50%;
  background: rgba(8, 10, 28, 0.82);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.22);
  cursor: pointer;
}
.cmp-ref-slot.is-filled .cmp-ref-x { display: flex; }
.cmp-ref-x:hover { background: var(--red, #ef4444); border-color: var(--red, #ef4444); }
/* Only reveal on hover/focus on hover-capable pointers; coarse pointers
   (touch) keep it always-on (set above via is-filled). */
@media (hover: hover) {
  .cmp-ref-slot.is-filled .cmp-ref-x { display: none; }
  .cmp-ref-slot.is-filled:hover .cmp-ref-x,
  .cmp-ref-slot.is-filled:focus-within .cmp-ref-x { display: flex; }
}

/* ── Prompt ──────────────────────────────────────────────────────
   UC3 (slice-composer-polish): roomier default that fills the freed
   space + JS auto-grow (composer.js) up to a cap, so it's usable
   without a manual drag. The max-height cap keeps the toolbar +
   Generate row on-screen at 800/900px viewport heights. resize:vertical
   is retained as a manual override.
   UC2: the textarea is wrapped (.cmp-prompt-wrap) so the @image token
   chip mirror can sit behind it — the wrap owns the field background +
   border, and the textarea goes transparent so the chips show through. */
.cmp-prompt-wrap {
  position: relative;
  width: 100%;
  background: var(--field-bg, rgba(8,10,28,0.85));
  border: 1px solid var(--line, rgba(255,255,255,0.07));
  border-radius: 12px;
}
.cmp-prompt-wrap:focus-within { border-color: var(--accent, #7c6dfa); }
.cmp-prompt {
  display: block;
  width: 100%;
  min-height: 140px;
  max-height: min(46vh, 420px);
  resize: vertical;
  padding: 12px 14px;
  background: var(--field-bg, rgba(8,10,28,0.85));
  border: 1px solid var(--line, rgba(255,255,255,0.07));
  border-radius: 12px;
  color: var(--text, #f0f2ff);
  font-family: inherit;
  font-size: 14px;
  line-height: 1.5;
  overflow-y: auto;
}
/* When wrapped, the wrap draws the field chrome; the textarea is a
   transparent layer on top of the chip mirror. */
.cmp-prompt-wrap > .cmp-prompt {
  position: relative;
  z-index: 1;
  background: transparent;
  border-color: transparent;
}
.cmp-prompt::placeholder { color: var(--faint, rgba(240,242,255,0.42)); }
.cmp-prompt:focus { outline: none; border-color: var(--accent, #7c6dfa); }
.cmp-prompt-wrap > .cmp-prompt:focus { border-color: transparent; }
/* The token chip mirror over #cmpPrompt reuses the multichar chip
   classes (multichar-refs.css). Pin it under the textarea inside the wrap. */
.cmp-prompt-wrap .multichar-token-mirror { z-index: 0; }

/* ── Bottom toolbar ──────────────────────────────────────────── */
.cmp-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.cmp-tools-l,
.cmp-tools-r {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
/* Slice composer-sound-toggle: cost + Generate get their own full-width row
   below the pill toolbar, flush RIGHT (LumiYing bottom-right submit). The
   toolbar's justify-content:space-between would otherwise pin this single
   wrapped item to the LEFT of its line. flex-basis:100% forces the dedicated
   row (no cramming onto the 6-pill row); flex-end right-aligns within it.
   Order stays [cost] [Generate]. The ≤680px column layout overrides below. */
.cmp-tools-r {
  flex-basis: 100%;
  justify-content: flex-end;
}

/* Pills — base control used by every dropdown trigger + actions */
.cmp-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 12px;
  background: var(--glass, rgba(255,255,255,0.04));
  border: 1px solid var(--line-strong, rgba(255,255,255,0.14));
  border-radius: var(--cmp-pill-radius);
  color: var(--text, #f0f2ff);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .16s ease, background .16s ease, color .16s ease;
}
.cmp-pill:hover {
  border-color: var(--accent, #7c6dfa);
  background: var(--glass-strong, rgba(255,255,255,0.07));
}
.cmp-pill svg { width: 15px; height: 15px; flex: 0 0 auto; }
.cmp-pill .cmp-caret { width: 12px; height: 12px; opacity: .6; }
.cmp-pill[hidden] { display: none; }
.cmp-pill-label { font-weight: 700; }

/* Dropdown container + menu */
.cmp-dd { position: relative; }
.cmp-dd.is-open > .cmp-pill {
  border-color: var(--accent, #7c6dfa);
  background: var(--glass-strong, rgba(255,255,255,0.07));
}
.cmp-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  z-index: 60;
  min-width: 220px;
  max-height: 360px;
  overflow-y: auto;
  padding: 6px;
  background: var(--bg-elevated, #0a0c20);
  border: 1px solid var(--line-strong, rgba(255,255,255,0.14));
  border-radius: 14px;
  box-shadow: var(--shadow-lg, 0 8px 40px rgba(0,0,0,0.6));
  display: none;
}
.cmp-dd.is-open > .cmp-menu { display: block; }
.cmp-menu-models { min-width: 280px; }
.cmp-menu-settings { min-width: 300px; }

/* Menu options (model list + media switch) with checkmark */
.cmp-opt {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  background: transparent;
  border: 0;
  border-radius: 9px;
  color: var(--text, #f0f2ff);
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.cmp-opt:hover { background: var(--glass-strong, rgba(255,255,255,0.07)); }
.cmp-opt .cmp-check {
  width: 14px;
  flex: 0 0 auto;
  color: var(--accent, #7c6dfa);
  opacity: 0;
  font-size: 13px;
}
.cmp-opt.is-active .cmp-check { opacity: 1; }
.cmp-opt.is-active { color: var(--accent, #7c6dfa); }
.cmp-opt-main { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.cmp-opt-name { font-weight: 600; }
.cmp-opt-meta { font-size: 11px; color: var(--mute, rgba(240,242,255,0.62)); }
.cmp-opt-credit {
  margin-left: auto;
  font-size: 11px;
  font-weight: 700;
  color: var(--mute, rgba(240,242,255,0.62));
  white-space: nowrap;
}
.cmp-badge {
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .04em;
  padding: 1px 5px;
  border-radius: 5px;
  text-transform: uppercase;
}
.cmp-badge.is-new  { background: rgba(6,247,161,0.16);  color: var(--green, #06f7a1); }
.cmp-badge.is-beta { background: rgba(124,109,250,0.18); color: var(--accent, #7c6dfa); }

/* Combined settings panel (Ratio + Resolution + Duration) */
.cmp-set-group { padding: 6px 4px; }
.cmp-set-group + .cmp-set-group {
  border-top: 1px solid var(--line, rgba(255,255,255,0.07));
  margin-top: 4px;
}
.cmp-set-group[hidden] { display: none; }
.cmp-set-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--faint, rgba(240,242,255,0.42));
  margin: 2px 6px 8px;
}
.cmp-seg {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 4px;
}
.cmp-seg-opt {
  padding: 6px 12px;
  background: var(--glass, rgba(255,255,255,0.04));
  border: 1px solid var(--line-strong, rgba(255,255,255,0.14));
  border-radius: 8px;
  color: var(--text2, rgba(240,242,255,0.7));
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.cmp-seg-opt:hover { border-color: var(--accent, #7c6dfa); }
.cmp-seg-opt.is-active {
  background: var(--accent, #7c6dfa);
  border-color: var(--accent, #7c6dfa);
  color: var(--accent-text, #fff);
}

/* Cost readout + Generate */
.cmp-cost {
  font-size: 13px;
  font-weight: 700;
  color: var(--text2, rgba(240,242,255,0.7));
  white-space: nowrap;
}
.cmp-cost strong { color: var(--text, #f0f2ff); }
.cmp-generate {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 20px;
  background: var(--accent, #7c6dfa);
  border: 1px solid var(--accent, #7c6dfa);
  border-radius: 12px;
  color: var(--accent-text, #fff);
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: background .16s ease, transform .12s ease, box-shadow .16s ease;
}
.cmp-generate:hover {
  background: var(--accent-hover, #9b8fff);
  box-shadow: var(--shadow-violet, 0 8px 32px rgba(124,109,250,0.3));
}
.cmp-generate:active { transform: translateY(1px); }
.cmp-generate svg { width: 16px; height: 16px; }
.cmp-generate.is-busy { opacity: .7; pointer-events: none; }

/* ── Presets panel — anchored to the #cmpPresets button like the model /
   settings dropdowns (absolute within a positioned wrapper, opening
   upward), NOT pinned to the viewport. composer.js moves it into
   .cmp-presets-dd; togglePresets toggles its display. Right-aligned to
   the button (presets sits on the right of the toolbar) so it extends
   left and stays on-screen on narrow windows. ─────────────────────── */
.cmp-presets-dd { position: relative; display: inline-flex; }
body.composer-v2 #presets-panel {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;            /* extend rightward from the button, like the model/settings menus */
  right: auto;
  z-index: 90;
  width: min(420px, calc(100vw - 48px));
  /* The legacy rule sets max-width: calc(100% - 48px); now the panel's
     containing block is the small .cmp-presets-dd anchor, so that would
     clamp it to ~button width. Override it. */
  max-width: none;
  max-height: 70vh;
  overflow-y: auto;
}

/* ── Topaz upscale — collapsed section below the composer ──────── */
.cmp-upscale {
  margin-top: 14px;
  background: var(--surface, #0f1128);
  border: 1px solid var(--line-strong, rgba(255,255,255,0.14));
  border-radius: var(--cmp-radius, 18px);
  padding: 4px 18px;
}
.cmp-upscale-summary {
  cursor: pointer;
  padding: 12px 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--text, #f0f2ff);
  list-style: none;
  user-select: none;
}
.cmp-upscale-summary::-webkit-details-marker { display: none; }
.cmp-upscale-summary::after { content: '▾'; float: right; opacity: .6; transition: transform .2s; }
.cmp-upscale[open] .cmp-upscale-summary::after { transform: rotate(180deg); }
.cmp-upscale .upscale-section { margin-top: 0 !important; border-top: 0 !important; padding-top: 8px !important; padding-bottom: 16px; }

/* ── Responsive ──────────────────────────────────────────────── */
@media (max-width: 680px) {
  .cmp-toolbar { flex-direction: column; align-items: stretch; }
  .cmp-tools-r { justify-content: space-between; }
  .cmp-menu { min-width: min(280px, calc(100vw - 48px)); }
}
