/* Studio — Scrape Builder.
   Nested-card scrape planner for #studio-root (subjects redesign).

   Design dictionary is dashboard/style-reference.html. This file ONLY adds
   sbx-* layout + the tree's st-check checkbox. The card atoms (.card /
   .card-filled), badges (.badge / .badge-accent), buttons (.btn / .btn-primary
   / .icon-btn) and the attribute modal (.ps-redesign .attr-modal*) all come
   from shared.css + product-settings.css and are reused as-is. Surface "shades
   of white" are the --page-bg / --surface-bg tokens, alternating per depth.
   Every gap / pad / margin is on the 8 / 16 / 24 / 32 / 40 / 48 scale. Nesting
   is shown by inset, not by a wire. */

/* ---------- page ---------- */
/* Fill the canvas like the Mentions / Insights content views: no centered cap,
   32px horizontal inset (their content-area padding). The .sbx-sub keeps its
   own 600px measure so the subtitle line stays readable. Full-height flex column
   so the launch bar can pin to the bottom even when the plan is near-empty. */
#studio-root { height: 100%; }
.sbx-main { max-width: none; margin: 0; padding: 24px 32px 32px; min-height: 100%; display: flex; flex-direction: column; position: relative; }
/* CSV drag-and-drop overlay: shown while a file is dragged over the builder. */
.sbx-main.sbx-dragging::after {
  content: 'Drop CSV to import products';
  position: absolute;
  inset: 12px;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px dashed var(--accent);
  border-radius: 12px;
  background: var(--accent-subtle);
  color: var(--accent);
  font-size: var(--text-base);
  font-weight: 600;
  pointer-events: none;
}
.sbx-header { margin-bottom: 32px; }
.sbx-title { font-family: 'Host Grotesk', sans-serif; font-size: var(--text-2xl); font-weight: 600; letter-spacing: -0.03em; color: var(--text-primary); }
.sbx-sub { margin: 8px 0 0; color: var(--text-secondary); font-size: var(--text-base); max-width: 600px; line-height: 1.6; }
.sbx-plan { display: flex; flex-direction: column; gap: 16px; }

/* Cards: reuse .card / .card-filled from shared.css, drop their padding so the
   header / body own the spacing. Even depth sits on --page-bg (.card), odd on
   --surface-bg (.card-filled) so each nested level steps one shade. */
.sbx-card, .sbx-leaf { padding: 0; border-radius: 0; }
.sbx-card { position: relative; }
.sbx-card.is-new::before,
.sbx-leaf.is-new::before {
  content: '';
  position: absolute;
  left: -1px;
  top: -1px;
  width: 8px;
  height: 8px;
  background: var(--accent);
  z-index: 2;
  pointer-events: none;
}
.sbx-card.k-keyword {
  background: var(--page-bg);
  border-style: solid;
}
/* Search-term leaf: no fill + a dashed border, so the scrapable unit reads as a
   light "draft" row distinct from the solid, filled container cards above it.
   (Overrides the .card / .card-filled background + solid border from shared.css —
   scrape-builder.css loads later at equal specificity.) */
.sbx-leaf { position: relative; background: transparent; border-style: dashed; }

/* ---------- shared header (containers + leaves) ----------
   Leaf: pad-left 16 + icon 20 + gap 8 puts the text column at 44px; every leaf
   sub-row (attributes, platform summary) starts at 44 too, so the text lines up.
   The slot is a fixed square so glyph and image/logo headers align — leaves at
   20px, container headers at 28px (below) to stand the same height as the header's
   Create-new buttons. */
.sbx-head { display: flex; align-items: center; gap: 8px; padding: 8px 16px; }
.sbx-ic { flex: 0 0 auto; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; color: var(--text-tertiary); }
.sbx-ic svg { width: 16px; height: 16px; stroke-width: 1.6; }
/* real product image / brand logo in the icon slot — mirrors the Library .st-row-thumb */
.sbx-ic--thumb { border-radius: var(--radius); overflow: hidden; background: var(--surface-bg); }
.sbx-ic--thumb img { width: 100%; height: 100%; object-fit: cover; }
/* Editable image/logo slot: a button that reveals a pencil overlay on hover so
   the user can swap, remove, or paste a URL for the image. Glyph-fallback rows
   are editable too (to add a missing image), so the overlay sits on the bare
   slot as well as on a thumb. */
.sbx-ic--editable { position: relative; padding: 0; border: none; background: transparent; cursor: pointer; border-radius: var(--radius); overflow: hidden; }
.sbx-ic-edit {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.55); color: #fff; opacity: 0;
  transition: opacity var(--transition-fast); border-radius: inherit;
}
.sbx-ic--editable:hover .sbx-ic-edit,
.sbx-ic--editable:focus-visible .sbx-ic-edit { opacity: 1; }
.sbx-ic-edit svg { width: 14px; height: 14px; stroke-width: 2; color: #fff; }
/* Container headers (topic / brand / product / keyword) grow the icon slot to the
   Create-new button height (28px) so the product image / brand logo balances the
   buttons; the glyph stays 16px centred. Leaves keep the compact 20px slot + 44px
   sub-row column, so nothing in the leaf shifts. */
.sbx-card > .sbx-head > .sbx-ic { width: 28px; height: 28px; }
.sbx-meta { display: flex; flex-direction: row; align-items: center; gap: 8px; min-width: 0; flex: 1; }
.sbx-kind { flex: 0 0 auto; font-size: 11px; font-weight: 600; color: var(--text-tertiary); }
.sbx-dot { flex: 0 0 auto; color: var(--text-tertiary); font-size: 11px; line-height: 1; }
.sbx-name-static { color: var(--text-tertiary); font-size: var(--text-base); }

/* editable name / term: reads as text until focused */
.sbx-name {
  flex: 1; min-width: 0; max-width: 440px;
  border: 1px solid transparent; background: transparent; font-family: inherit; color: var(--text-primary);
  border-radius: var(--radius); padding: 1px 8px; margin-left: -8px;
  transition: background var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.sbx-name::placeholder { color: var(--text-tertiary); }
.sbx-name:hover { background: var(--page-bg); }
.sbx-name:focus { outline: none; background: var(--page-bg); border-color: var(--accent-border); box-shadow: var(--shadow-focus); }
.sbx-name.n-topic { font-size: var(--text-md); font-weight: 600; letter-spacing: -0.01em; }
.sbx-name.n-brand { font-size: var(--text-md); font-weight: 600; }
.sbx-name.n-product { font-size: var(--text-base); font-weight: 600; }
.sbx-name.n-leaf { font-size: var(--text-base); font-weight: 600; }

.sbx-head-side { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
/* Ownership toggle (Yours / Watch) in the header. Reuses the shared .seg atom
   verbatim — sized to match the 28px .sbx-create-opt buttons beside it. */
.sbx-own { flex: 0 0 auto; }
.sbx-own.seg { padding: 3px; }
.sbx-own .seg__btn { height: 20px; padding: 0 10px; }
.sbx-own .seg__thumb { top: 3px; bottom: 3px; }
.sbx-remove { color: var(--text-tertiary); }
.sbx-remove:hover { color: var(--negative); background: rgba(255, 96, 92, 0.10); }

/* ---------- container body + add row ----------
   Inset children 16px on every side so the parent surface frames each nested
   card: that inset IS the nesting cue. It equals the header padding, so a
   child's left edge lines up under its parent's icon. */
.sbx-body { padding: 8px 16px 16px; display: flex; flex-direction: column; gap: 8px; }

/* New-child actions: distinct standalone bordered buttons matching the surface's
   .sbx-plat / .sbx-depth-opt control language. */
.sbx-create { display: inline-flex; align-items: center; gap: 8px; }
.sbx-create-opt {
  height: 28px; padding: 0 10px 0 8px; display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--border-default); border-radius: var(--radius); background: transparent;
  color: var(--text-secondary); font-family: inherit; font-size: var(--text-sm); font-weight: 500;
  cursor: pointer; white-space: nowrap;
  transition: color var(--transition-fast), background var(--transition-fast), border-color var(--transition-fast);
}
.sbx-create-opt svg { width: 13px; height: 13px; stroke-width: 1.9; }
.sbx-create-opt:hover { color: var(--accent); background: var(--accent-subtle); border-color: var(--accent-border); }

/* ---------- leaf (keyword / search term) ---------- */
.sbx-leaf .sbx-ic { color: var(--text-tertiary); }
.sbx-gear { color: var(--text-tertiary); }
.sbx-gear.is-open, .sbx-gear:hover { color: var(--accent); }
.sbx-settings-anchor { position: relative; display: inline-flex; align-items: center; }
.sbx-leaf.is-pending { opacity: 0.6; }
.sbx-leaf.is-failed { opacity: 1; }
.sbx-leaf.is-failed .sbx-ic { color: var(--negative); }
.sbx-leaf.is-failed .sbx-name-static { color: var(--negative); }

/* attributes row: flex wrap, left edge at the 40px text column. */
.sbx-attrs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 0 16px 8px 44px; }
/* Icon cluster (copy / paste / edit) sits as one unit left of the chips.
   Tighter gap between the three icons than between the cluster and chips. */
.sbx-attr-icons { display: flex; align-items: center; gap: 2px; }
.sbx-attr-clip { width: 24px; height: 24px; flex: 0 0 auto; }
.sbx-attr-clip svg { width: 14px; height: 14px; }
.sbx-attr-edit svg { stroke-width: 1.7; }

/* "Last scraped …" tag on an already-tracked leaf: the .badge atom, sitting
   right after the term name so the user reads the term's freshness inline.
   Launching the term still re-runs it (see the badge title). */
.sbx-rescrape { gap: 6px; flex: 0 0 auto; }
.sbx-rescrape svg { width: 12px; height: 12px; stroke-width: 1.7; }
/* Per-attribute "last scraped" freshness tag inside the Edit attributes modal. */
.sbx-attr-scraped { align-self: flex-start; margin-top: 2px; }
.sbx-attr-scraped svg { width: 12px; height: 12px; stroke-width: 1.7; }
/* The badge lives in .sbx-meta next to the name, so the name input must hug its
   text instead of growing to fill the row, otherwise the badge floats far right. */
.sbx-leaf.is-tracking .sbx-name { flex: 0 1 auto; width: auto; min-width: 80px; field-sizing: content; }

/* platform / depth collapsed summary, real platform icon PNGs */
.sbx-adv { padding: 0 16px 8px 44px; }
.sbx-adv-btn {
  display: inline-flex; align-items: center; gap: 8px; border: none; background: none; cursor: pointer;
  color: var(--text-tertiary); font-family: inherit; font-size: var(--text-xs); padding: 0;
  transition: color var(--transition-fast);
}
.sbx-adv-btn:hover { color: var(--accent); }
/* Platform icons overlap like an avatar stack: no gap, each circle pulled under
   the previous so it is ~40% covered by the NEXT one. The later DOM node paints
   on top, so they read in platform order (YouTube first … X last, rightmost fully
   visible). A 1.5px ring in the leaf surface colour carves each circle out from
   its neighbour; the search-term leaf alternates .card (--page-bg) / .card-filled
   (--surface-bg) by depth, so the ring follows the matching shade. */
.sbx-pics { display: inline-flex; align-items: center; gap: 0; }
.sbx-pico {
  width: 16px; height: 16px; object-fit: contain;
  display: inline-block; position: relative; margin-left: -6px;
  /* Round: these are external brand marks (round by design). object-fit:contain
     shows the whole logo, so the wide YouTube mark (100x70) fits instead of being
     cropped to a red square; the square 100x100 assets fill the circle identically. */
  border-radius: 50%;
}
.sbx-pico:first-child { margin-left: 0; }
/* Ring carves each circle out of the surface now BEHIND the transparent leaf — the
   parent container's fill, which is always the opposite depth-parity to the leaf
   (so the leaf's own .card-filled state maps to the opposite token here). */
.sbx-leaf.card-filled .sbx-pico { box-shadow: 0 0 0 1.5px var(--page-bg); }
.sbx-leaf:not(.card-filled) .sbx-pico { box-shadow: 0 0 0 1.5px var(--surface-bg); }
.sbx-depthtext { color: var(--text-tertiary); }

/* ---------- settings popover ---------- */
.sbx-pop {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60; width: 288px; padding: 16px;
  border-radius: var(--radius-md);
  --glass-bg: rgba(255, 255, 255, 0.72);
  --glass-border: rgba(255, 255, 255, 0.58);
  --glass-shadow: rgba(44, 48, 80, 0.16);
  --glass-highlight: rgba(255, 255, 255, 0.62);
  --glass-inset: rgba(255, 255, 255, 0.46);
}
html.dark .sbx-pop {
  --glass-bg: rgba(26, 29, 46, 0.76);
  --glass-border: rgba(255, 255, 255, 0.12);
  --glass-shadow: rgba(0, 0, 0, 0.42);
  --glass-highlight: rgba(255, 255, 255, 0.06);
  --glass-inset: rgba(255, 255, 255, 0.08);
}
.sbx-pop > * { position: relative; z-index: 1; }
.sbx-pop-title { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); margin-bottom: 16px; display: flex; align-items: center; justify-content: space-between; }
.sbx-pop-group { margin-bottom: 16px; }
.sbx-pop-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); margin-bottom: 8px; }
.sbx-plats { display: flex; flex-wrap: wrap; gap: 8px; }
.sbx-plat {
  height: 32px; padding: 0 8px; display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--border-default); border-radius: var(--radius); background: transparent;
  color: var(--text-secondary); font-family: inherit; font-size: 11.5px; font-weight: 500; cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.sbx-plat img { width: 14px; height: 14px; object-fit: contain; }
.sbx-plat.on { color: var(--accent); border-color: var(--accent-border); background: var(--accent-subtle); }
.sbx-plat:hover { border-color: var(--neutral-300); }
.sbx-depth { display: flex; flex-wrap: wrap; gap: 8px; }
.sbx-depth-opt {
  min-width: 40px; height: 32px; padding: 0 8px; border: 1px solid var(--border-default); border-radius: var(--radius);
  background: transparent; color: var(--text-secondary); font-family: inherit; font-size: 11.5px; font-weight: 500; cursor: pointer;
  transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.sbx-depth-opt.on { color: var(--accent); border-color: var(--accent-border); background: var(--accent-subtle); }
.sbx-pop-note { font-size: var(--text-xs); color: var(--text-tertiary); line-height: 1.5; }
.sbx-pop-input {
  width: 100%; box-sizing: border-box; height: 34px; padding: 0 10px; margin-bottom: 6px;
  border: 1px solid var(--border-default); border-radius: var(--radius); background: transparent;
  color: var(--text-primary); font-family: inherit; font-size: 12px;
  transition: border-color var(--transition-fast);
}
.sbx-pop-input:focus { outline: none; border-color: var(--accent-border); }
.sbx-pop-input::placeholder { color: var(--text-tertiary); }
.sbx-pop-done { width: 100%; justify-content: center; margin-top: 8px; }

/* ---------- Amazon listings (manual multi-URL) ----------
   A URL input + submit (▶) row above removable ASIN (.tld) badges. Reuses
   .sbx-pop-input + the style-reference .badge atom; only the row/submit/remove
   affordances are local. */
.sbx-amz-banner { font-size: var(--text-xs); color: var(--text-tertiary); line-height: 1.5; margin-bottom: 8px; }
.sbx-amz-row { display: flex; gap: 6px; align-items: center; }
.sbx-amz-row .sbx-pop-input { flex: 1 1 auto; margin-bottom: 0; }
.sbx-amz-add {
  flex: 0 0 auto; width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-default); border-radius: var(--radius); background: transparent; color: var(--text-secondary);
  cursor: pointer; transition: color var(--transition-fast), border-color var(--transition-fast), background var(--transition-fast);
}
.sbx-amz-add:hover { color: var(--accent); border-color: var(--accent-border); background: var(--accent-subtle); }
.sbx-amz-add i { width: 15px; height: 15px; }
.sbx-amz-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.sbx-amz-badge { font-variant-numeric: tabular-nums; }
.sbx-amz-x {
  display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; background: transparent;
  color: var(--text-tertiary); cursor: pointer; line-height: 0; transition: color var(--transition-fast);
}
.sbx-amz-x:hover { color: var(--negative); }
.sbx-amz-x i { width: 12px; height: 12px; }
.sbx-amz-err { font-size: var(--text-xs); color: var(--negative); margin-top: 6px; line-height: 1.4; }

/* ---------- attribute modal additions ----------
   Product-settings owns the base .ps-redesign .attr-modal styles. These rules
   only stack the Studio scrape-builder's per-term attribute rows so each name
   carries the LLM-facing description that the assignment prompt consumes. */
.ps-redesign .attr-edit-row.attr-edit-row--stack {
  align-items: stretch;
  flex-direction: column;
  gap: 8px;
  background: var(--surface-bg);
}
.ps-redesign .attr-edit-main {
  display: flex;
  align-items: center;
  gap: 8px;
}
.ps-redesign .attr-edit-row.attr-edit-row--stack .attr-edit-input {
  min-width: 0;
}
.ps-redesign .attr-edit-description {
  width: 100%;
  min-height: 52px;
  padding: 8px 0 0;
  border: none;
  border-top: 1px solid var(--border-subtle);
  background: transparent;
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--text-xs);
  line-height: 1.45;
  outline: none;
  resize: vertical;
}
.ps-redesign .attr-edit-description::placeholder {
  color: var(--text-tertiary);
}
.ps-redesign .attr-edit-description:focus {
  color: var(--text-primary);
}

/* ---------- attribute modal: reuse + generation (Studio) ----------
   Adds the set-level toolbar, the empty-state hero, the unified Add combobox +
   its dropdown, the Copy-from picker, and the per-row regenerate control. All
   scoped under the builder's #sbx-attr-modal-host so they never touch the legacy
   product-edit modal. Tokens + the .rw-combo dropdown pattern, reused. */

/* set-level toolbar (populated state) */
.ps-redesign .sbx-attr-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding-bottom: 12px; margin-bottom: 4px; border-bottom: 1px solid var(--border-subtle);
}
.ps-redesign .sbx-attr-toolbar-label { font-size: var(--text-xs); font-weight: 500; color: var(--text-tertiary); }
.ps-redesign .sbx-attr-toolbar-actions { display: flex; align-items: center; gap: 6px; }
/* compact real buttons for the toolbar */
.ps-redesign .sbx-attr-tbtn {
  height: 32px;
  padding: 0 12px;
  font-size: var(--text-sm);
  gap: 6px;
  background: var(--surface-bg);
}
.ps-redesign .sbx-attr-tbtn svg { width: 14px; height: 14px; stroke-width: 1.8; }

/* empty-state hero */
.ps-redesign .sbx-attr-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 12px 8px 4px; gap: 2px;
}
.ps-redesign .sbx-attr-empty-glyph { color: var(--accent); margin-bottom: 6px; }
.ps-redesign .sbx-attr-empty-glyph svg { width: 28px; height: 28px; stroke-width: 1.5; }
.ps-redesign .sbx-attr-empty h3 { font-size: var(--text-md); font-weight: 600; color: var(--text-primary); }
.ps-redesign .sbx-attr-empty p { font-size: 13px; color: var(--text-secondary); max-width: 320px; margin: 4px 0 14px; line-height: 1.5; }
.ps-redesign .sbx-attr-empty-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.ps-redesign .sbx-attr-or { font-size: var(--text-xs); color: var(--text-tertiary); margin: 14px 0 8px; }
/* the hero's add field is a full-width, left-aligned control */
.ps-redesign .sbx-attr-empty .sbx-attr-add { width: 100%; text-align: left; }

/* generating state (no rows yet) */
.ps-redesign .sbx-attr-generating {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; padding: 36px 16px; color: var(--text-secondary);
}
.ps-redesign .sbx-attr-generating p { font-size: 13px; color: var(--text-secondary); }

/* ungrounded-generation note */
.ps-redesign .sbx-attr-note {
  display: flex; align-items: center; gap: 6px; margin-bottom: 8px;
  padding: 8px 10px; border-radius: var(--radius);
  background: var(--accent-subtle); color: var(--text-secondary); font-size: var(--text-xs); line-height: 1.4;
}
.ps-redesign .sbx-attr-note svg { flex: 0 0 auto; width: 14px; height: 14px; color: var(--accent); }

/* rows list + per-row icon buttons (regenerate, remove) */
.ps-redesign .sbx-attr-rows { display: flex; flex-direction: column; gap: 8px; }
.ps-redesign .sbx-attr-iconbtn {
  flex: 0 0 auto; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--text-tertiary); border-radius: var(--radius); cursor: pointer;
  transition: color var(--transition-fast), background var(--transition-fast);
}
.ps-redesign .sbx-attr-iconbtn:hover { color: var(--accent); background: var(--accent-subtle); }
.ps-redesign .sbx-attr-iconbtn:disabled { cursor: default; }
.ps-redesign .sbx-attr-iconbtn svg { width: 13px; height: 13px; stroke-width: 1.8; }
.ps-redesign .attr-edit-row.is-busy .attr-edit-description { opacity: 0.6; }

/* unified Add combobox field shell */
.ps-redesign .sbx-attr-add { position: relative; margin: 0 0 12px; }
.ps-redesign .sbx-attr-add-field {
  display: flex; align-items: center; gap: 6px; height: 38px; padding: 0 4px 0 10px;
  border: 1px solid var(--border-default); border-radius: var(--radius); background: var(--page-bg);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
.ps-redesign .sbx-attr-add-field:focus-within { border-color: var(--accent-border); box-shadow: var(--shadow-focus); }
.ps-redesign .sbx-attr-add-ic {
  flex: 0 0 auto;
  display: inline-flex;
  width: 14px;
  height: 14px;
  color: var(--text-tertiary);
  stroke-width: 1.7;
}
.ps-redesign .sbx-attr-add-ic svg { width: 14px; height: 14px; }
.ps-redesign .sbx-attr-add-input {
  flex: 1; min-width: 0; border: none; background: transparent; font-family: inherit; font-size: 13px;
  color: var(--text-primary); outline: none;
}
.ps-redesign .sbx-attr-add-input::placeholder { color: var(--text-tertiary); }
.ps-redesign .sbx-attr-add-go {
  flex: 0 0 auto; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--text-tertiary); border-radius: var(--radius); cursor: pointer;
  transition: color var(--transition-fast), background var(--transition-fast);
}
.ps-redesign .sbx-attr-add-go:hover { color: var(--accent); background: var(--accent-subtle); }
.ps-redesign .sbx-attr-add-go svg { width: 16px; height: 16px; }

/* dropdown menu. The Add menu opens UPWARD (the field sits at the modal's
   bottom); the Copy menu is inline + downward (the field sits near the top). */
.ps-redesign .sbx-attr-menu {
  list-style: none; margin: 0; padding: 4px; z-index: 5;
  background: var(--page-bg); border: 1px solid var(--border-default); border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(44, 48, 80, 0.18);
  max-height: 240px; overflow-y: auto;
}
.ps-redesign .sbx-attr-add .sbx-attr-menu { position: absolute; left: 0; right: 0; top: calc(100% + 4px); }
.ps-redesign .sbx-attr-menu-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 7px 10px; border-radius: var(--radius); cursor: pointer; font-size: 13px; color: var(--text-primary);
}
.ps-redesign .sbx-attr-menu-opt:hover { background: var(--accent-subtle); }
.ps-redesign .sbx-attr-menu-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-redesign .sbx-attr-menu-hint { flex: 0 0 auto; font-size: var(--text-xs); color: var(--text-tertiary); }
.ps-redesign .sbx-attr-menu-sep {
  padding: 8px 10px 3px; font-size: 10px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-tertiary);
}
.ps-redesign .sbx-attr-menu-empty,
.ps-redesign .sbx-attr-menu-loading {
  display: flex; align-items: center; gap: 8px; padding: 10px; font-size: var(--text-xs); color: var(--text-tertiary);
}
.ps-redesign .sbx-attr-menu-novel { color: var(--accent); gap: 8px; justify-content: flex-start; }
.ps-redesign .sbx-attr-menu-novel svg { flex: 0 0 auto; width: 13px; height: 13px; }

/* ---------- empty + root add ---------- */
.sbx-empty {
  position: relative;
  border: 1px dashed var(--border-default); border-radius: 0; padding: 48px 32px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.sbx-library-cue {
  position: absolute; left: 16px; top: 42px; width: 204px; margin: 0;
  display: flex; align-items: flex-start; gap: 12px;
  color: var(--text-secondary); font-size: 12px; line-height: 1.45; text-align: left;
}
.sbx-library-cue svg {
  flex: 0 0 auto; width: 40px; height: 16px; margin-top: 2px;
  color: var(--accent); stroke-width: 1.5;
}
.sbx-empty-glyph { color: var(--accent); margin-bottom: 8px; }
.sbx-empty-glyph svg { width: 32px; height: 32px; stroke-width: 1.5; }
.sbx-empty h3 { font-size: var(--text-lg); font-weight: 600; color: var(--text-primary); }
.sbx-empty p { color: var(--text-secondary); font-size: 13px; max-width: 380px; margin: 0 0 16px; line-height: 1.6; }
.sbx-empty .sbx-library-cue { font-size: 12px; max-width: 204px; margin: 0; line-height: 1.45; }
.sbx-empty-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.sbx-rootadd { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- launch bar (persistent Studio footer) ---------- */
.sbx-launchbar {
  width: 100%;
  background: #141725; border: none; border-top: 1px solid var(--border-default);
  border-radius: 0; box-shadow: none;
  padding: 10px 32px; display: flex; align-items: center; gap: 16px; z-index: 5;
}
.sbx-lb-scope { flex: 1; min-width: 0; }
.sbx-lb-count { font-family: 'Host Grotesk', sans-serif; font-size: var(--text-base); font-weight: 600; letter-spacing: 0; line-height: 1.25; color: var(--text-primary); }
.sbx-lb-count b { color: var(--accent); font-weight: 600; }
.sbx-lb-detail { font-size: var(--text-xs); color: var(--text-secondary); margin-top: 2px; line-height: 1.35; }
.sbx-lb-muted { color: var(--text-tertiary); }
.sbx-lb-warn { color: var(--negative); }
.sbx-lb-launch { height: 32px; padding: 0 14px; font-size: 12px; }
.sbx-lb-launch svg { width: 14px; height: 14px; }
.sbx-lb-launch:disabled { opacity: 0.5; cursor: default; }

/* ---------- sidebar-tree cart checkbox (Studio page only) ---------- */
.st-check {
  flex: 0 0 auto; width: 16px; height: 16px; margin-right: 8px; border-radius: 0;
  border: 1.5px solid var(--border-default); background: transparent;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; cursor: pointer; transition: border-color var(--transition-fast), background var(--transition-fast);
}
.st-check:hover { border-color: var(--accent); }
.st-check:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.st-check i, .st-check svg { width: 11px; height: 11px; stroke-width: 3; }
.st-check--checked, .st-check--indeterminate { background: var(--accent); border-color: var(--accent); }

/* ---------- scrape history (past launches → batches) ----------
   A group under the plan, above the launch bar. Each batch is a reused .card
   whose header is the collapsed rollup row; clicking it reveals the cascade.
   Visual language echoes the sbx cards + the style-reference .badge atoms;
   nesting is shown by inset (the --d depth var), matching the plan forest. */
.sbx-history { margin: 32px 0 8px; }
.sbx-history-head { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; }
.sbx-history-ic { display: inline-flex; color: var(--text-tertiary); }
.sbx-history-ic svg { width: 16px; height: 16px; stroke-width: 1.6; }
.sbx-history-title { font-family: 'Host Grotesk', sans-serif; font-size: var(--text-md); font-weight: 600; letter-spacing: -0.02em; color: var(--text-primary); }
.sbx-history-n { margin-left: 0; }
.sbx-history-list { display: flex; flex-direction: column; gap: 8px; }
.sbx-history-batch { padding: 0; overflow: hidden; border-radius: 0; }

/* collapsed rollup row = the card header (a full-width button) */
.sbx-history-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 16px; border: none; background: transparent; cursor: pointer;
  font-family: inherit; text-align: left; color: var(--text-primary);
  transition: background var(--transition-fast);
}
.sbx-history-row:hover { background: var(--accent-subtle); }
.sbx-history-caret { flex: 0 0 auto; display: inline-flex; color: var(--text-tertiary); }
.sbx-history-caret svg { width: 16px; height: 16px; stroke-width: 1.8; transition: transform var(--transition-fast); }
.sbx-history-row.is-open .sbx-history-caret svg { transform: rotate(90deg); }
.sbx-history-when { flex: 0 0 auto; font-family: 'Host Grotesk', sans-serif; font-size: var(--text-sm); font-weight: 500; letter-spacing: -0.01em; white-space: nowrap; }
.sbx-history-scope { flex: 1; min-width: 0; color: var(--text-secondary); font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sbx-history-cards { flex: 0 0 auto; font-family: 'Host Grotesk', sans-serif; font-size: var(--text-sm); color: var(--text-tertiary); white-space: nowrap; }
.sbx-history-stats { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.sbx-history-chip { font-size: 10.5px; }

/* expanded cascade body */
.sbx-history-cascade { border-top: 1px solid var(--border-subtle); padding: 8px 0; background: var(--page-bg); }
.sbx-history-msg { padding: 8px 16px; color: var(--text-tertiary); font-size: var(--text-sm); }
.sbx-casc-row {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 16px 5px calc(16px + var(--d, 0) * 20px);
}
.sbx-casc-container .sbx-casc-ic { flex: 0 0 auto; display: inline-flex; color: var(--text-tertiary); }
.sbx-casc-container .sbx-casc-ic svg { width: 14px; height: 14px; stroke-width: 1.6; }
.sbx-casc-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-primary); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sbx-casc-kindtag { flex: 0 0 auto; font-size: 10px; font-weight: 600; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
.sbx-casc-leaf { gap: 8px; }
.sbx-casc-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--text-muted); }
.sbx-casc-dot.is-queued { background: var(--text-muted); }
.sbx-casc-dot.is-claimed,
.sbx-casc-dot.is-running { background: var(--warning, #d6a200); }
.sbx-casc-dot.is-success { background: var(--positive); }
.sbx-casc-dot.is-failed { background: var(--negative); }
.sbx-casc-term { font-size: var(--text-sm); color: var(--text-primary); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sbx-casc-term.is-deleted { color: var(--text-tertiary); font-style: italic; }
.sbx-casc-status { flex: 0 0 auto; margin-left: auto; font-size: 11px; font-weight: 500; text-transform: capitalize; color: var(--text-tertiary); }
.sbx-casc-status.is-success { color: var(--positive); }
.sbx-casc-status.is-failed { color: var(--negative); }
.sbx-casc-status.is-running, .sbx-casc-status.is-claimed { color: var(--warning, #d6a200); }
.sbx-casc-cards { flex: 0 0 auto; font-family: 'Host Grotesk', sans-serif; font-size: 11.5px; color: var(--text-tertiary); white-space: nowrap; }

@media (max-width: 560px) {
  .sbx-attrs, .sbx-adv { padding-left: 16px; }
  .sbx-name { max-width: none; }
  .sbx-library-cue {
    position: relative; left: auto; top: auto; width: auto; max-width: 320px; text-align: center;
    padding-top: 0;
  }
  .sbx-library-cue svg { display: none; }
  /* drop the scope text on narrow widths so the date + status rollup stay */
  .sbx-history-scope { display: none; }
}
