/* public/stream/sec-obs-live.css — Live OBS Studio sub-tab (§09 Phase 1).
   Tokens + component classes only; see docs/design/DESIGN-GUIDELINES.md. */
.obslive { display: flex; flex-direction: column; gap: var(--space-3); }
.obslive__scene { font-weight: 700; color: var(--text); }

/* ── Multi-region workspace (OBS-like): a central PREVIEW with four EDGE regions
   (left / right / top / bottom) around it, ALL visible at once. Each dock (Scenes /
   Sources / Audio mixer) is assigned to an edge (a per-dock picker in its header); edges
   are drag-resizable and empty edges collapse to 0. The workspace height is fitted to the
   viewport in JS. Assignment + edge sizes persist (localStorage). ── */
.obslive__ws {
  display: grid;
  width: 100%;
  min-height: 440px;
  grid-template-columns: var(--ed-left, 0px) minmax(0, 1fr) var(--ed-right, 0px);
  grid-template-rows: var(--ed-top, 0px) minmax(0, 1fr) var(--ed-bottom, 0px);
  grid-template-areas: "top top top" "left center right" "bottom bottom bottom";
  gap: var(--space-2);
}

/* Layout controls bar (Reset). */
.obslive__ws-bar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.obslive__ws-bar .spacer { flex: 1 1 auto; }

/* Preview — the central, dominant region. A 16:9 box sized to the largest that FITS
   (letterbox bars in the region, never distortion; layout boxes stay aligned to 16:9). */
.obslive__ws-preview { grid-area: center; position: relative; min-width: 120px; min-height: 120px; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.obslive__ws-preview .obslive__preview { position: absolute; inset: 0; margin: auto; width: auto; height: auto; aspect-ratio: 16 / 9; max-width: 100%; max-height: 100%; }

/* Edge regions — hold the docks assigned to that side. Left/right stack vertically;
   top/bottom lay out in a row. position:relative anchors the resize handle. */
.obslive__edge { position: relative; display: flex; gap: var(--space-2); min-width: 0; min-height: 0; overflow: hidden; }
.obslive__edge--left { grid-area: left; flex-direction: column; }
.obslive__edge--right { grid-area: right; flex-direction: column; }
.obslive__edge--top { grid-area: top; flex-direction: row; }
.obslive__edge--bottom { grid-area: bottom; flex-direction: row; }
.obslive__edge > .obslive__dock { flex: 1 1 0; min-width: 0; min-height: 0; }

/* Edge resize handle — a thin bar on the INNER border of an edge region (toward center). */
.obslive__edgesplit { position: absolute; z-index: 2; touch-action: none; }
.obslive__edgesplit::before { content: ""; position: absolute; inset: 0; margin: auto; background: var(--border); transition: background var(--dur, 180ms) var(--ease); }
.obslive__edgesplit:hover::before, .obslive__edgesplit.is-dragging::before { background: var(--accent); }
.obslive__edgesplit--v { top: 0; bottom: 0; width: 9px; cursor: col-resize; }
.obslive__edgesplit--v::before { width: 2px; top: 6px; bottom: 6px; }
.obslive__edgesplit--h { left: 0; right: 0; height: 9px; cursor: row-resize; }
.obslive__edgesplit--h::before { height: 2px; left: 6px; right: 6px; }
.obslive__edge--left .obslive__edgesplit { right: -6px; }
.obslive__edge--right .obslive__edgesplit { left: -6px; }
.obslive__edge--top .obslive__edgesplit { bottom: -6px; }
.obslive__edge--bottom .obslive__edgesplit { top: -6px; }
/* GROW handle on the bottom of the bottom dock: drag DOWN to make the bottom dock taller AND
   grow the whole workspace (the page scrolls) — the preview/center keeps its size. Sits fully
   inside the edge's bottom (so overflow:hidden doesn't clip it). */
.obslive__edgegrow { position: absolute; left: 0; right: 0; bottom: 0; height: 11px; z-index: 3; cursor: ns-resize; touch-action: none; }
.obslive__edgegrow::before { content: ""; position: absolute; left: 16px; right: 16px; bottom: 3px; height: 3px; border-radius: 2px; background: var(--border); transition: background var(--dur, 180ms) var(--ease); }
.obslive__edgegrow:hover::before, .obslive__edgegrow.is-dragging::before { background: var(--accent); }
/* Per-dock edge picker in the header. */
.obslive__dock-pos { font-size: 10px; padding: 1px 4px; color: var(--text-dim); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); cursor: pointer; }

.obslive__dock { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); overflow: hidden; }
.obslive__dock-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); font-family: var(--font-display); font-weight: 700; font-size: var(--fs-small, 12px); text-transform: uppercase; letter-spacing: .04em; color: var(--text-dim); padding: var(--space-1) var(--space-2) var(--space-1) var(--space-3); border-bottom: 1px solid var(--border); background: var(--surface-inset); }
.obslive__dock-head .obslive__dock-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.obslive__dock-body { padding: var(--space-1); flex: 1 1 auto; min-height: 80px; overflow-y: auto; display: flex; flex-direction: column; }
.obslive__dock-toolbar { display: flex; align-items: center; gap: 2px; padding: var(--space-1) var(--space-2); border-top: 1px solid var(--border); background: var(--surface-inset); min-height: 38px; }
/* Collapse the toolbar when a dock doesn't use it (Audio never does; Scenes only when editing
   a non-program scene) — otherwise it renders as an awkward empty black strip at the dock's
   bottom. Sources always has its action buttons, so its toolbar stays. */
.obslive__dock-toolbar:empty { display: none; }
.obslive__dock-action { margin-left: auto; }
.obslive__toolbar-sep { width: 1px; align-self: stretch; background: var(--border); margin: var(--space-1) 4px; }
.obslive__toolbtn { padding: 4px; min-width: 30px; height: 28px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; font-size: 14px; }
.obslive__toolbtn:disabled { opacity: .3; cursor: not-allowed; }

/* Audio mixer dock — OBS-style: a row of vertical channel strips (name on top, a VERTICAL
   fader, mute at the bottom). Strips sit side by side and wrap. The mixer FILLS the dock body
   (flex:1 + min-height:0) so the strips/faders size to the dock's height instead of forcing a
   fixed tall height that overflows a short dock (esp. the bottom dock). */
.obslive__mixer { display: flex; flex-direction: row; flex-wrap: wrap; align-items: stretch; gap: var(--space-2); padding: var(--space-2); flex: 1 1 auto; min-height: 0; }
.obslive__mix { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-2); border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface-inset); min-width: 72px; min-height: 0; }
.obslive__mix.is-muted { opacity: .6; }
.obslive__mix-name { flex: 0 0 auto; font-size: 11px; font-weight: 600; max-width: 88px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; }
/* The fader sizes to the strip: flex-basis 0 (NOT auto/px) so its height is purely the
   grow-allocated share of the strip's free space. A vertical <input type=range> has an
   intrinsic ~120px length that Chromium REFUSES to flex-SHRINK below — so basis:auto/px
   overflowed the short bottom dock (the bug in the screenshot: mute scrolled off, scrollbar).
   With basis:0 there's nothing to "shrink": the height grows from 0 to fill the strip, so it
   fits any dock height (down to a usable 44px floor, capped at 300px). */
.obslive__mix-fader { writing-mode: vertical-lr; direction: rtl; width: 22px; flex: 1 1 0; min-height: 44px; max-height: 300px; accent-color: var(--accent); cursor: pointer; }
.obslive__mix-mute { flex: 0 0 auto; padding: 2px 7px; font-size: 13px; }
.obslive__mix-mute.is-muted { color: var(--danger); border-color: var(--danger); }

/* Generic selectable list row (used by both docks). */
.obslive__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }
.obslive__listitem { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2); border-radius: var(--r-sm); cursor: pointer; min-width: 0; }
.obslive__listitem:hover { background: var(--surface-inset); }
.obslive__listitem.is-sel { background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--border-accent); }
.obslive__listitem-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1 1 auto; min-width: 0; }
/* Inline rename (✎) — subtle, revealed on row hover; swaps the name span for an input. */
.obslive__rename { flex: 0 0 auto; margin-left: 4px; padding: 0 5px; font-size: 11px; line-height: 1.5; background: none; border: 1px solid transparent; border-radius: var(--r-sm); color: var(--text-dim); cursor: pointer; opacity: 0; transition: opacity var(--dur, 180ms) var(--ease), color var(--dur, 180ms) var(--ease); }
.obslive__listitem:hover .obslive__rename, .obslive__source:hover .obslive__rename { opacity: 1; }
.obslive__rename:hover, .obslive__rename:focus-visible { color: var(--accent); border-color: var(--border); }
.obslive__rename-input { font-size: 12px; padding: 1px 5px; max-width: 170px; flex: 1 1 auto; min-width: 0; }
.obslive__livetag { flex: 0 0 auto; margin-left: auto; font-family: var(--font-mono); font-size: 9px; font-weight: 700; letter-spacing: .06em; color: var(--danger); border: 1px solid var(--danger); border-radius: var(--r-pill); padding: 1px 6px; }

/* Source row = a list row with an eye toggle + name/badge (no per-row buttons; the
   dock toolbar acts on the selection). */
.obslive__source { /* extends .obslive__listitem */ }
.obslive__source-main { display: flex; align-items: center; gap: var(--space-2); min-width: 0; flex: 1 1 auto; }
.obslive__source-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.obslive__source-main .badge { flex: 0 0 auto; }
.obslive__source-eye { flex: 0 0 auto; }
/* Drag-to-reorder grip. */
.obslive__source-grip { flex: 0 0 auto; cursor: grab; color: var(--text-faint); user-select: none; line-height: 1; padding: 0 2px; }
.obslive__listitem:hover .obslive__source-grip { color: var(--text-dim); }
.obslive__source--dragging { opacity: .5; }
.obslive__source--dropbefore { box-shadow: inset 0 2px 0 var(--accent, #9147ff); }
.obslive__source--dropafter { box-shadow: inset 0 -2px 0 var(--accent, #9147ff); }
.obslive__addmenu, .obslive__props { margin-top: var(--space-2); padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--r-sm); display: flex; flex-direction: column; gap: var(--space-2); }
/* Optional custom-name field above the Add-source kind picker. */
.obslive__addname { display: flex; flex-direction: column; gap: var(--space-1); }
.obslive__addname > .lbl { margin: 0; color: var(--text-dim); font-size: 12px; }
.obslive__addname > .input { width: 100%; }
/* Name (display label) field at the top of the source Properties modal. */
.obslive__propname { padding-bottom: var(--space-2); border-bottom: 1px solid var(--border); }
.obslive__propname > .help { color: var(--text-dim); font-size: 11px; }
/* Deferred "Edit source settings" section (opening it reads the live source). */
.obslive__props-settings > summary { cursor: pointer; padding: var(--space-2) 0; font-weight: 600; }
.obslive__props-settings-body { display: flex; flex-direction: column; gap: var(--space-2); }
/* ── OBS-style properties modal (Add wizard + Edit pop-up) ──────────────────── */
.obslive__modal-overlay { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; padding: var(--space-3); background: color-mix(in srgb, #000 55%, transparent); }
.obslive__modal { display: flex; flex-direction: column; width: 100%; max-width: min(560px, 92vw); max-height: 85vh; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); }
.obslive__modal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-3); border-bottom: 1px solid var(--border); }
.obslive__modal-x { flex: 0 0 auto; }
.obslive__modal-body { overflow-y: auto; padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.obslive__modal-foot { display: flex; justify-content: flex-end; gap: var(--space-2); padding: var(--space-3); border-top: 1px solid var(--border); }
.obslive__group { font-size: 12px; color: var(--text-dim); margin-top: var(--space-2); }
/* Add-source picker buttons: a clear task label + a one-line description (stacked,
   left-aligned), so "ffmpeg" → "Media file / stream" and the webcam is obvious. */
.obslive__addkind { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left; width: 100%; height: auto; padding: var(--space-2); }
.obslive__addkind-label { font-weight: 600; }
.obslive__addkind-desc { font-size: 11px; color: var(--text-dim); }
/* Image add-step: file picker → cloud upload → /o/image browser source. */
.obslive__imgadd { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-1) 0; }
.obslive__imgadd .muted { font-size: 12px; color: var(--text-dim); margin: 0; }
.obslive__or { font-size: 11px; color: var(--text-dim); text-align: center; margin-top: var(--space-1); }
.obslive__imgadd-urlrow { display: flex; gap: var(--space-2); align-items: center; }
.obslive__imgadd-urlrow .input { flex: 1; }
.obslive__imgadd-status { font-size: 12px; color: var(--text-dim); }
.obslive__imgadd-status.danger { color: var(--danger, #e5484d); }
/* Cloud library picker (media + slideshow add steps): thumbnail grid. */
.obslive__lib { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: var(--space-2); max-height: 220px; overflow-y: auto; padding: var(--space-1); border: 1px solid var(--border); border-radius: var(--r-sm); }
.obslive__lib-item { padding: 0; border: 2px solid transparent; border-radius: var(--r-sm); overflow: hidden; cursor: pointer; background: var(--surface-2, #1a1a1a); aspect-ratio: 16 / 9; display: flex; align-items: center; justify-content: center; }
.obslive__lib-item.is-sel { border-color: var(--accent, #4f8cff); }
.obslive__lib-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.obslive__lib-chip { font-size: 11px; color: var(--text-dim); padding: var(--space-1); text-align: center; word-break: break-all; }
.obslive__lib-empty { padding: var(--space-2); font-size: 12px; }
.obslive__props-title { font-weight: 700; }
/* Property editor rows: clean two-column label | control grid (overrides the shared
   .field column layout that left checkboxes/inputs floating centered). Label sits
   left at a fixed width; the control fills the rest, left-aligned + consistent. */
.obslive__props .field {
  display: grid;
  grid-template-columns: minmax(7rem, 13rem) 1fr;
  align-items: center;
  gap: var(--space-3);
  margin: 0;
}
.obslive__props .field > .lbl { margin: 0; text-align: left; align-self: center; }
.obslive__props .field > .select,
.obslive__props .field > .input { width: 100%; max-width: none; }
.obslive__props .field > input[type="checkbox"] { width: 1.05rem; height: 1.05rem; justify-self: start; margin: 0; }
.obslive__props-json { width: 100%; min-height: 10rem; font-family: var(--font-mono); resize: vertical; }
/* Generic property editor: the raw-JSON escape hatch, collapsed by default. */
.obslive__props-advanced { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); }
.obslive__props-advanced > summary { cursor: pointer; font-size: 12px; color: var(--text-dim); }
/* §09 Phase 2 — filter/effect UI (scoped inside the props panel). */
.obslive__filters { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: var(--space-2); }
.obslive__filters-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.obslive__filter { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2); border: 1px solid var(--border); border-radius: var(--r-sm); }
.obslive__filter-name { font-weight: 600; flex: 1 1 auto; }
/* §09 Phase 3 — scene-item transform / lock form (scoped inside the props panel). */
.obslive__source-eye { flex: 0 0 auto; }
.obslive__transform { margin-top: var(--space-3); padding-top: var(--space-3); border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: var(--space-2); }
.obslive__tx-field { display: flex; align-items: center; gap: var(--space-2); }
.obslive__tx-field .input { max-width: 10rem; }
/* §09 Phase 4 — live frame preview (GetSourceScreenshot poll). 16:9 stage at the
   top of the panel; the placeholder shows until the first frame arrives. */
/* NO border-radius: this box clips the live <video>, and a ROUNDED clip forces the
   playing video to re-rasterize on the main thread every frame → app-wide input lag.
   A square overflow:hidden clip is free. (Same fix as .preview-stage in sections.css.) */
.obslive__preview { position: relative; width: 100%; aspect-ratio: 16 / 9; background: var(--surface-inset); border: 1px solid var(--border); overflow: hidden; display: flex; align-items: center; justify-content: center; }
.obslive__preview-img { width: 100%; height: 100%; object-fit: contain; display: block; }
.obslive__preview-video { width: 100%; height: 100%; object-fit: contain; display: block; background: #000; }
/* display:block above overrides the `hidden` attribute the JS toggles, so an
   un-fetched frame showed a broken-image glyph / black video box. Let [hidden] win
   → the placeholder shows until a real frame arrives. */
.obslive__preview-img[hidden], .obslive__preview-video[hidden] { display: none; }
.obslive__preview-placeholder { text-align: center; padding: var(--space-3); }
/* ── In-view layout editor — drag/resize sources on the preview ── */
.obslive__layoutbar { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-2); }
.obslive__layout-toggle.is-on { background: var(--accent, #9147ff); color: #fff; }
.obslive__layout-hint { font-size: 12px; }
/* The interactive overlay sits ON TOP of the preview image; only the boxes capture
   pointer events so the rest of the preview stays inert. */
.obslive__layout-layer { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
.obslive__layout-box {
  position: absolute;
  border: 1.5px solid var(--accent, #9147ff);
  background: color-mix(in srgb, var(--accent, #9147ff) 12%, transparent);
  box-sizing: border-box;
  cursor: move;
  pointer-events: auto;
  touch-action: none;
}
.obslive__layout-box.is-dragging { background: color-mix(in srgb, var(--accent, #9147ff) 22%, transparent); }
.obslive__layout-box-label {
  position: absolute; top: 0; left: 0; max-width: 100%;
  font-size: 10px; font-weight: 700; line-height: 1.3;
  padding: 0 4px; background: var(--accent, #9147ff); color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.obslive__layout-handle {
  position: absolute; right: -6px; bottom: -6px; width: 12px; height: 12px;
  background: var(--accent, #9147ff); border: 2px solid #fff; border-radius: 2px;
  cursor: nwse-resize; pointer-events: auto; touch-action: none;
}
