:root {
  --bg: #ffffff;
  --bg-muted: #fafafa;
  --bg-hover: #f3f4f6;
  --border: #e5e7eb;
  --border-strong: #d1d5db;
  --text: #111827;
  --text-muted: #6b7280;
  --text-soft: #9ca3af;
  --accent: #2563eb;
  --accent-soft: #eff6ff;
  --danger: #dc2626;
  --success: #16a34a;
  --warning: #d97706;
  --radius: 10px;
  --radius-sm: 6px;
  --shadow-sm: 0 1px 2px rgba(17, 24, 39, 0.04);
  --font-sans: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* Authentic Instagram brand gradient — used ONLY by the IG account finder
     so that one feature reads unmistakably as "Instagram, separate tool". */
  --ig-gradient: linear-gradient(45deg, #feda75 0%, #fa7e1e 24%, #d62976 52%, #962fbf 76%, #4f5bd5 100%);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.app-shell {
  display: flex;
  /* Viewport-locked shell: each pane (sidebar, content) owns its own
     scroll. Without a fixed height the whole page would scroll and the
     sidebar's single-scroll behaviour below couldn't work. */
  height: 100vh;
  overflow: hidden;
}

/* Sidebar */
.sidebar {
  width: 256px;
  flex-shrink: 0;
  border-right: 1px solid var(--border);
  background: var(--bg-muted);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  /* ONE overall scroll for the whole sidebar. Sections inside never
     scroll on their own — they just grow as topics/creators are added
     and the entire sidebar scrolls as a single unit. */
  overflow-y: auto;
  overflow-x: hidden;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 8px 18px;
  text-decoration: none;
  color: inherit;
}

.brand:hover .brand-name {
  color: var(--accent);
}

.sidebar-section-title {
  text-decoration: none;
  color: var(--text-soft);
}

.sidebar-section-title:hover {
  color: var(--text);
}

.brand-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

/* Pulses only while work is in flight. Idle = solid accent (never
   grey — the dot is a "the app is alive" signal, not a job indicator). */
.brand-dot.is-busy {
  animation: brand-dot-pulse 1.2s ease-in-out infinite;
}

@keyframes brand-dot-pulse {
  0%, 100% { transform: scale(1);   opacity: 1; }
  50%      { transform: scale(0.7); opacity: 0.55; }
}

/* Brand name + status sit on a single line, like "Randm.Reels Watching".
   Status borrows the brand-name's size for visual continuity but stays
   regular-weight + muted so the eye lands on the name first. */
.brand-text {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}

.brand-name {
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -0.01em;
}

.brand-status {
  font-size: 15px;
  font-weight: 400;
  color: var(--text-soft);
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.brand-status.is-busy {
  color: var(--accent);
}

.brand-status.is-link {
  cursor: pointer;
}

.sidebar-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}

.sidebar-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-soft);
  font-weight: 600;
}

.sidebar-section-title {
  user-select: none;
}

.sidebar-new {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #fff;
  text-decoration: none;
  line-height: 1;
  transition: background-color 0.1s ease, transform 0.1s ease, box-shadow 0.1s ease;
  box-shadow: 0 1px 2px rgba(37, 99, 235, 0.25);
}

.sidebar-new svg {
  width: 12px;
  height: 12px;
}

.sidebar-new:hover {
  background: #1d4ed8;
  border-color: #1d4ed8;
  box-shadow: 0 2px 4px rgba(37, 99, 235, 0.35);
}

.sidebar-new:active {
  transform: scale(0.95);
}

/* Topics / Watchlist grow with their content — no internal scroll, no
   space-splitting. A hairline rule + extra top padding splits them away
   from the section above so they read as distinct sections instead of
   one long blurred list. The whole sidebar (.sidebar) is the single
   scroll container; these just get taller as rows are added. */
.sidebar-section-grow {
  border-top: 1px solid var(--border);
  padding-top: 18px;
  margin-top: 6px;
}

.topics-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding-right: 2px;
}

/* Hairline divider between consecutive (non-active) topic rows. Looks
   like a subtle group inside the sidebar instead of a wall of text;
   the active row sits on the accent-soft background so it visually
   stands out without needing the divider. */
.topics-list .topic-row + .topic-row {
  border-top: 1px solid var(--border);
}

.topics-list .topic-row.is-active,
.topics-list .topic-row.is-active + .topic-row {
  border-top-color: transparent;
}

.sidebar-empty {
  padding: 8px 12px;
  font-size: 12px;
  color: var(--text-soft);
  font-style: italic;
}

.topic-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 9px 10px;
  /* No corner radius: the row-to-row hairline (border-top below) is
     drawn on this box, so a radius made the divider ends curve. Flush
     rows = straight dividers. */
  border-radius: 0;
  border-top: 1px solid transparent;   /* keeps height stable when divider toggles on/off */
  color: var(--text);
  text-decoration: none;
  font-size: 13px;
  transition: background-color 0.1s ease;
}

.topic-row:hover {
  background: var(--bg-hover);
}

.topic-row.is-active {
  background: var(--accent-soft);
  color: var(--accent);
}

.topic-row-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topic-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: var(--text-soft);
}

.topic-row-icon svg {
  width: 14px;
  height: 14px;
}

.topic-row.is-active .topic-row-icon {
  color: var(--accent);
}

.topic-row-title-text {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topic-row-meta {
  font-size: 11px;
  color: var(--text-soft);
  font-weight: 400;
}

.topic-row.is-active .topic-row-meta {
  color: var(--accent);
  opacity: 0.7;
}

.topic-mini-badge {
  display: inline-flex;
  align-items: center;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.5;
}

.topic-mini-badge.is-paused {
  background: #fef3c7;
  color: #92400e;
}

/* "+N new since you last opened this topic" — the most actionable
   signal in the list, so it borrows the accent so the eye lands on
   topics that have fresh videos waiting. */
.topic-mini-badge.is-new {
  background: var(--accent-soft);
  color: var(--accent);
}

/* Schedule line under the query: "every 6h · in 3h" / "· due now" /
   "· paused". Same muted treatment as the query meta line. */
.topic-row-sched {
  font-size: 11px;
  color: var(--text-soft);
  font-weight: 400;
}

.topic-row.is-active .topic-row-sched {
  color: var(--accent);
  opacity: 0.7;
}

/* Drag-to-reorder + live scrape indicator (sidebar). The row becomes a
   [grip | body] flex; the body keeps the original stacked layout. */
.topic-row {
  flex-direction: row;
  align-items: flex-start;
  gap: 7px;
  cursor: grab;
}

.topic-row-grip {
  flex-shrink: 0;
  width: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 1px;
  font-size: 11px;
  line-height: 1;
  letter-spacing: -1px;
  color: var(--text-soft);
  opacity: 0.45;
  cursor: grab;
  user-select: none;
}

.topic-row:hover .topic-row-grip {
  opacity: 0.8;
}

.topic-row-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.topic-row.is-dragging {
  opacity: 0.45;
  cursor: grabbing;
  background: var(--bg-hover);
}

.topic-row-sched.is-scraping {
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--accent);
  font-weight: 600;
}

.topic-row-sched .scrape-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
  animation: brand-dot-pulse 1s ease-in-out infinite;
}

.nav {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Tools are explicit buttons: a raised white surface with a border and
   shadow — deliberately unlike the flat, borderless topic rows below,
   so the two sections never read as one continuous list. */
.nav-item {
  display: flex;
  align-items: center;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  color: var(--text);
  text-decoration: none;
  font-weight: 500;
  font-size: 13.5px;
  transition: background-color 0.1s ease, color 0.1s ease,
    border-color 0.1s ease, box-shadow 0.1s ease, transform 0.05s ease;
}

.nav-item:hover {
  background: var(--bg-hover);
  border-color: var(--border-strong);
  color: var(--text);
}

.nav-item:active {
  transform: translateY(1px);
  box-shadow: none;
}

.nav-item.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.sidebar-footer {
  margin-top: auto;
  display: flex;
  justify-content: flex-start;
}

.mode-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Main */
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.topbar {
  height: 56px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 28px;
  background: var(--bg);
}

.topbar-title {
  font-size: 15px;
  font-weight: 600;
}

.topbar-status {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text-muted);
  font-size: 12.5px;
}

/* (Activity indicator moved to the sidebar brand area — see .brand-dot
   and .brand-status above. The topbar chip is gone.) */

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-soft);
}

.status-dot.is-ok {
  background: var(--success);
}

.status-dot.is-err {
  background: var(--danger);
}

.content {
  flex: 1;
  padding: 28px;
  /* Vertical scroll only. If this were `overflow: auto` the whole
     content pane (topic head, stat tiles, scrape-state) would scroll
     sideways together with the wide videos table on narrow screens —
     "разъезжается". Horizontal overflow is owned exclusively by
     `.vt-scroll` so only the table moves. */
  overflow-y: auto;
  overflow-x: hidden;
  min-width: 0;
}

/* Page header */
.page-header {
  margin-bottom: 24px;
}

.page-title {
  font-size: 22px;
  font-weight: 600;
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}

.page-subtitle {
  color: var(--text-muted);
  font-size: 13.5px;
  margin: 0;
}

/* Empty state */
.empty {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  padding: 40px 28px;
  text-align: center;
  color: var(--text-muted);
  background: var(--bg-muted);
}

.empty-title {
  font-weight: 600;
  color: var(--text);
  margin-bottom: 6px;
}

/* Form */
.card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px 24px;
  box-shadow: var(--shadow-sm);
  max-width: 720px;
}

.card + .card {
  margin-top: 16px;
}

.card-title {
  font-size: 14px;
  font-weight: 600;
  margin: 0 0 4px;
}

.card-hint {
  font-size: 12.5px;
  color: var(--text-muted);
  margin: 0 0 18px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}

.field-label {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-muted);
}

.field input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
  transition: border-color 0.1s ease, box-shadow 0.1s ease;
}

.field input:focus {
  outline: none;
}

body.input-keyboard .field input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
  line-height: 1.2;
  transition: background-color 0.1s ease, border-color 0.1s ease, opacity 0.1s ease, box-shadow 0.1s ease, transform 0.1s ease;
}

.btn-lg {
  padding: 11px 22px;
  font-size: 14px;
  font-weight: 600;
  gap: 8px;
}

.btn-lg svg {
  width: 14px;
  height: 14px;
}

.btn-primary.btn-lg {
  box-shadow: 0 2px 6px rgba(37, 99, 235, 0.25);
}

.btn-primary.btn-lg:hover:not(:disabled) {
  box-shadow: 0 3px 10px rgba(37, 99, 235, 0.32);
  transform: translateY(-1px);
}

.btn:hover:not(:disabled) {
  background: var(--bg-hover);
}

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.btn-primary:hover:not(:disabled) {
  background: #1d4ed8;
  border-color: #1d4ed8;
}

/* First-run call-to-action: the topic was just created and has no
   scrape yet, so "Start scraping" gets a soft pulsing accent ring to
   pull the eye. Same brand colour (accent stays reserved for primary
   actions) — only the halo signals "do this next". Drops to a normal
   primary button the moment there's any scrape history. */
.btn-primary.is-cta {
  animation: btn-cta-pulse 1.35s ease-in-out infinite;
}

.btn-primary.is-cta:hover:not(:disabled) {
  animation: none;
}

/* Expanding ring + a small lift/brighten so it actually reads as
   "press me" across the room, not a barely-there halo. */
@keyframes btn-cta-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.55);
    transform: scale(1);
    background: var(--accent);
  }
  50% {
    box-shadow: 0 0 0 12px rgba(37, 99, 235, 0);
    transform: scale(1.045);
    background: #1d4ed8;
  }
  100% {
    box-shadow: 0 0 0 0 rgba(37, 99, 235, 0);
    transform: scale(1);
    background: var(--accent);
  }
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.inline-msg {
  font-size: 12.5px;
  color: var(--text-muted);
}

.inline-msg.is-ok {
  color: var(--success);
}

.inline-msg.is-err {
  color: var(--danger);
}

.text-err {
  color: var(--danger);
}

/* Spending card */
.cost-headline {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-muted);
}

.cost-headline.is-over {
  border-color: var(--danger);
  background: #fef2f2;
}

.cost-headline-label {
  font-size: 12.5px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}

.cost-headline-value {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.cost-headline.is-over .cost-headline-value {
  color: var(--danger);
}

.cost-of {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-soft);
}

/* Daily-spend mini chart (inline SVG, stacked Apify + HikerAPI) */
.cost-chart-wrap {
  margin: 12px 0 4px;
  position: relative;
}
.cost-chart {
  display: block;
  width: 100%;
  height: 84px;
}
.cost-bar-apify { fill: var(--accent); }
.cost-bar-hiker { fill: #f59e0b; }
.cost-bar-sc { fill: #10b981; }
.cost-chart-legend {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--text-muted);
}
.cost-chart-legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.cost-chart-span {
  margin-left: auto;
  color: var(--text-soft);
}
.cost-dot {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: inline-block;
}
.cost-dot-apify { background: var(--accent); }
.cost-dot-hiker { background: #f59e0b; }
.cost-dot-sc { background: #10b981; }
.cost-dot-other { background: var(--text-soft); }

/* Transparent full-height hover targets, one per day column. */
.cost-hit {
  fill: transparent;
  cursor: default;
}
.cost-hit:hover {
  fill: var(--accent);
  fill-opacity: 0.07;
}

/* Custom hover tooltip over the daily-spend chart. */
.cost-tip {
  position: absolute;
  z-index: 6;
  pointer-events: none;
  min-width: 132px;
  padding: 7px 9px;
  border-radius: 8px;
  background: var(--text);
  color: #fff;
  font-size: 11.5px;
  line-height: 1.5;
  box-shadow: 0 6px 18px rgba(17, 24, 39, 0.22);
}
.cost-tip[hidden] { display: none; }
.cost-tip-day {
  font-weight: 700;
  margin-bottom: 3px;
}
.cost-tip-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.cost-tip-row > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  opacity: 0.85;
}
.cost-tip-row > b { font-variant-numeric: tabular-nums; }
.cost-tip-total {
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
  opacity: 1;
}

.cost-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 12px;
  font-size: 13px;
}

.cost-table th,
.cost-table td {
  padding: 7px 10px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

.cost-table th {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-soft);
  font-weight: 600;
}

.cost-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.cost-table tfoot td {
  font-weight: 700;
  border-bottom: none;
}

.cost-empty {
  color: var(--text-soft);
  font-style: italic;
}

.cost-limit-field {
  margin-top: 16px;
}

.cost-limit-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cost-limit-row input {
  width: 120px;
}

.cost-limit-row .btn {
  flex-shrink: 0;
}

.btn-sm {
  padding: 5px 12px;
  font-size: 12px;
}

.field-validate {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.tg-subtoggles {
  margin: 12px 0 0 34px;
  padding-left: 14px;
  border-left: 2px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: opacity 0.1s ease;
}

.tg-subtoggles.is-disabled {
  opacity: 0.45;
}

.danger-card {
  border-color: #fecaca;
}

.danger-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.danger-row-title {
  font-weight: 600;
  font-size: 13.5px;
}

.danger-row-note {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 2px;
  max-width: 520px;
}

.danger-row .btn-danger {
  flex-shrink: 0;
}

.danger-divider {
  height: 1px;
  background: var(--border);
  margin: 14px 0;
}

.shutdown-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 100vh;
  text-align: center;
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  font-family: var(--font-sans);
}

.shutdown-screen span {
  font-size: 13px;
  font-weight: 400;
  color: var(--text-muted);
}

.muted {
  color: var(--text-soft);
}

/* Settings → Scrapers section */

.scraper-row {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 14px;
  align-items: start;
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}

.scraper-row:last-child {
  border-bottom: none;
}

.scraper-toggle {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  position: relative;
}

.scraper-toggle input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.scraper-toggle-track {
  display: inline-block;
  width: 36px;
  height: 20px;
  border-radius: 999px;
  background: var(--bg-hover);
  border: 1px solid var(--border);
  position: relative;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

.scraper-toggle-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
  transition: transform 0.14s ease;
}

.scraper-toggle input[type="checkbox"]:checked + .scraper-toggle-track {
  background: var(--accent);
  border-color: var(--accent);
}

.scraper-toggle input[type="checkbox"]:checked + .scraper-toggle-track .scraper-toggle-knob {
  transform: translateX(16px);
}

body.input-keyboard .scraper-toggle input[type="checkbox"]:focus + .scraper-toggle-track {
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.scraper-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.scraper-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
}

.scraper-note {
  font-size: 12px;
  color: var(--text-muted);
}

.scraper-status {
  font-size: 11.5px;
  color: var(--text-muted);
  margin-top: 4px;
}

/* Downloads */

.downloads-form-card {
  max-width: none;
}

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

.downloads-form input,
.downloads-form select {
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
}

.downloads-form input {
  flex: 1;
  min-width: 0;   /* allow shrink when the form is narrow */
}
/* (.downloads-form select layout lives near the chevron styling
   further down, so flex / width / min-width sit alongside the
   appearance overrides instead of competing across two blocks.) */

.downloads-form input:focus,
.downloads-form select:focus {
  outline: none;
}

body.input-keyboard .downloads-form input:focus,
body.input-keyboard .downloads-form select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.downloads-list {
  margin-top: 22px;
  display: grid;
  /* Smaller cards — ~5 per row on a normal laptop instead of 3. */
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px;
}

.dl-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-sm);
}

.dl-media {
  position: relative;
  display: block;
  width: 100%;
  /* Vertical-first: most content is 9:16 reels. Let the full portrait
     ratio show (the old 360px cap squashed it toward square on wide
     cards). The taller cap only kicks in on unusually wide columns. */
  aspect-ratio: 9 / 16;
  max-height: 460px;
  background: #0f172a;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
}

.dl-media.is-clickable {
  cursor: pointer;
}

.dl-media img,
.dl-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.dl-media video {
  opacity: 0;
  transition: opacity 0.15s ease;
}

.dl-media.is-hoverable:hover video {
  opacity: 1;
}

.thumb-placeholder {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
}

.dl-overlay {
  position: absolute;
  left: 10px;
  top: 10px;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  max-width: calc(100% - 20px);
}

.dl-status,
.quality-badge,
.platform-badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  font-size: 10.5px;
  font-weight: 600;
  border-radius: 999px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.4;
}

.dl-status {
  background: rgba(15, 23, 42, 0.78);
  color: #fff;
  backdrop-filter: blur(6px);
}

.dl-status.is-done {
  background: rgba(22, 163, 74, 0.95);
  color: #fff;
}

.dl-status.is-failed {
  background: rgba(220, 38, 38, 0.95);
  color: #fff;
}

.dl-status.is-active {
  background: rgba(37, 99, 235, 0.92);
  color: #fff;
}

.quality-badge {
  background: rgba(255, 255, 255, 0.85);
  color: var(--text);
  backdrop-filter: blur(6px);
}

.quality-badge.quality-best {
  background: rgba(15, 23, 42, 0.78);
  color: #fff;
}

/* Static / carousel downloads: a "photo" / "N slides" badge in the
   media overlay, and a clickable slide strip in the card body. */
.dl-kind-badge {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  background: rgba(15, 23, 42, 0.78);
  color: #fff;
  backdrop-filter: blur(6px);
}

/* Carousel pager — flip slides inside the preview. The slide img/video
   fills the media box via the existing .dl-media img/video rules. */
.dl-car-track {
  position: absolute;
  inset: 0;
}
.dl-car-track > a {
  display: block;
  width: 100%;
  height: 100%;
}
.dl-car-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.55);
  color: #fff;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
}
.dl-car-nav:hover {
  background: rgba(15, 23, 42, 0.82);
}
.dl-car-prev { left: 8px; }
.dl-car-next { right: 8px; }
.dl-car-count {
  position: absolute;
  bottom: 8px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.72);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
}

.platform-badge {
  gap: 5px;
  padding-left: 8px;
  padding-right: 10px;
  color: #fff;
}

.platform-badge svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

.platform-badge.platform-youtube {
  background: #ff0000;
}

.platform-badge.platform-tiktok {
  background: #111;
}

.platform-badge.platform-instagram {
  background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%);
}

.platform-badge.platform-unknown {
  background: #475569;
}

/* Read-only network tag (topic list cards + detail header) — a quiet
   pill with a brand-colored icon. Not interactive. */
.net-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  background: var(--bg-hover);
  color: var(--text-muted);
}
.net-tag svg { width: 12px; height: 12px; flex-shrink: 0; }
.net-tag.platform-tiktok svg { color: #111; }
.net-tag.platform-instagram svg { color: #cc2366; }

/* Icon-only network marker for the sidebar rows. */
.net-mini {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.net-mini svg { width: 13px; height: 13px; }
.net-mini.platform-tiktok svg { color: #111; }
.net-mini.platform-instagram svg { color: #cc2366; }

.dl-body {
  flex: 1;
  padding: 14px 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.dl-title {
  font-size: 16px;
  color: var(--text);
  font-weight: 600;
  line-height: 1.3;
  word-break: break-word;
  /* No max-height / no auto-shrink: long titles wrap onto extra lines.
     Action rows still line up across the row via .dl-card flex layout
     and `.dl-actions { margin-top: auto }`. */
}

/* Captions clamp to 2 lines so chatty posts can't blow up the grid row's
   height. The "See more" toggle (JS) removes this class to reveal the
   full text. */
.dl-title.is-clamped {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.dl-caption-toggle {
  align-self: flex-start;
  margin-top: -4px;
  padding: 0;
  border: none;
  background: none;
  color: var(--accent, #2563eb);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.dl-caption-toggle:hover { text-decoration: underline; }

.dl-tags {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.35;
  max-height: 30px;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.dl-meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 12px;
  font-size: 12px;
  color: var(--text-muted);
  align-items: center;
}

.dl-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
  color: inherit;
  text-decoration: none;
}

.dl-meta-item svg {
  width: 13px;
  height: 13px;
  color: var(--text-soft);
  flex-shrink: 0;
}

.dl-meta-item.is-link {
  color: var(--text);
}

.dl-meta-item.is-link:hover {
  color: var(--accent);
}

.dl-meta-item.is-link:hover svg {
  color: var(--accent);
}

.dl-error {
  font-size: 12px;
  color: var(--danger);
  background: #fef2f2;
  border: 1px solid #fecaca;
  border-radius: var(--radius-sm);
  padding: 6px 8px;
}

.dl-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: auto;
  min-height: 30px;
  align-items: flex-end;
}

.dl-actions .btn {
  padding: 6px 12px;
  font-size: 12.5px;
}

.btn-ghost-danger {
  color: var(--danger);
}

.btn-ghost-danger:hover:not(:disabled) {
  background: #fef2f2;
  border-color: #fecaca;
}

.btn-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

.btn-danger:hover:not(:disabled) {
  background: #b91c1c;
  border-color: #b91c1c;
}

/* Modal */

.app-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.48);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  animation: app-modal-fade 0.12s ease-out;
}

@keyframes app-modal-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.app-modal {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 24px 48px rgba(15, 23, 42, 0.18);
  width: 100%;
  max-width: 420px;
  margin: 0 24px;
  padding: 22px 24px 18px;
  animation: app-modal-pop 0.14s ease-out;
}

@keyframes app-modal-pop {
  from { transform: translateY(6px) scale(0.98); opacity: 0; }
  to { transform: translateY(0) scale(1); opacity: 1; }
}

.app-modal-title {
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
}

.app-modal-body {
  margin-top: 8px;
  font-size: 13.5px;
  color: var(--text-muted);
  line-height: 1.45;
  /* Honour explicit \n in the message string — used to break the refresh
     confirmation into a few scannable lines instead of a wall of text. */
  white-space: pre-line;
}

/* Optional label/value list used in confirm dialogs that summarise a
   paid action (refresh, etc). Label sits muted, value is bold and
   inherits the body text colour so the value is what your eye lands
   on first. */
.app-modal-details {
  margin: 12px 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13.5px;
  line-height: 1.5;
}

.app-modal-detail {
  display: flex;
  gap: 6px;
  align-items: baseline;
}

.app-modal-detail dt {
  color: var(--text-muted);
  font-weight: 400;
  margin: 0;
}

.app-modal-detail dd {
  margin: 0;
  color: var(--text);
  font-weight: 600;
}

.app-modal-actions {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
}

.field-hint {
  font-size: 11.5px;
  color: var(--text-soft);
}

.field select {
  width: 100%;
  padding: 9px 32px 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M3 5l3 3 3-3'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px;
}

/* Same chrome (chevron, padding, etc.) as `.field select` but the
   downloads form is a flex row, not a vertical field, so width must
   stay `auto` — picking it up from the generic rule was outcompeting
   the URL input's `flex: 1` and squashing the input to nothing. */
.downloads-form select {
  width: auto;
  flex: 0 0 auto;
  min-width: 170px;
  padding: 9px 32px 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-family: inherit;
  background: var(--bg);
  color: var(--text);
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M3 5l3 3 3-3'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px;
}

.field select:focus {
  outline: none;
}

body.input-keyboard .field select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 14px;
}

/* Topics list page */

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

.topic-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.1s ease, box-shadow 0.1s ease;
}

.topic-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-sm);
}

.topic-card-head {
  display: flex;
  gap: 6px;
  align-items: center;
}

.topic-card-status {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
}

.topic-card-status.status-active {
  background: rgba(22, 163, 74, 0.12);
  color: #15803d;
}

.topic-card-status.status-paused {
  background: #fef3c7;
  color: #92400e;
}


.topic-card-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}

.topic-card-query {
  font-size: 12.5px;
  color: var(--text-muted);
}

.topic-card-meta {
  font-size: 11.5px;
  color: var(--text-soft);
  margin-top: 2px;
}

/* Create-tile: always the first card in the topics index grid.
   Dashed outline + centered '+' so it reads as a positive CTA
   rather than placeholder noise. */
.topic-card-create {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 24px 18px;
  border: 1px dashed var(--border-strong);
  background: var(--bg-muted);
  color: var(--text-muted);
  text-align: center;
  min-height: 144px;
  transition: border-color 0.1s ease, color 0.1s ease, background-color 0.1s ease;
}

.topic-card-create:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: var(--shadow-sm);
}

.topic-card-create-plus {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text-muted);
  margin-bottom: 2px;
  transition: background-color 0.1s ease, color 0.1s ease, border-color 0.1s ease;
}

.topic-card-create-plus svg {
  width: 18px;
  height: 18px;
}

.topic-card-create:hover .topic-card-create-plus {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.topic-card-create-label {
  font-size: 14px;
  font-weight: 600;
}

.topic-card-create-sub {
  font-size: 11.5px;
  color: var(--text-soft);
}

.topic-card-create:hover .topic-card-create-sub {
  color: var(--accent);
  opacity: 0.7;
}

/* Topic detail page */

.topic-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}

.topic-head-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.topic-head-meta {
  display: flex;
  gap: 6px;
  align-items: center;
}

/* Inline-editable text fields (topic name + keyword query).
   The display element and the edit input share the *exact* box model
   (same padding + same 1px border) so swapping them in place doesn't
   shift anything below by even a pixel. The display border is
   transparent; the input border is the neutral --border. Accent halo
   is only shown to keyboard users (input-keyboard body class) because
   for mouse users the click itself already says "I'm editing this". */

.topic-head-name,
.topic-head-name-edit {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-family: inherit;
  line-height: 1.25;
  margin: 2px 0 0;
  margin-left: -5px;
  padding: 2px 4px;
  border-radius: 6px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text);
}

.topic-head-name {
  display: inline-block;
  cursor: text;
  transition: background-color 0.1s ease;
}

/* The [hidden] attribute would normally apply `display: none` via UA
   styles, but a class-level `display: inline-block` here has higher
   specificity and was leaving both the <h1> and the edit <input>
   visible at the same time. Re-assert hidden explicitly. */
.topic-head-name[hidden],
.topic-head-name-edit[hidden],
.topic-head-query[hidden],
.topic-head-query-edit[hidden] {
  display: none;
}

.topic-head-name:hover {
  background: var(--bg-muted);
}

.topic-head-name-edit {
  background: var(--bg-muted);
  border-color: var(--border);
  outline: none;
  width: 100%;
  max-width: 540px;
}

body.input-keyboard .topic-head-name-edit:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}

/* Inline keyword query — same UX as name, smaller font / muted colour
   because it's secondary to the topic title. */

.topic-rules-query {
  display: flex;
  align-items: center;
  gap: 8px;
}

.topic-head-query,
.topic-head-query-edit {
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
  line-height: 1.25;
  padding: 3px 8px;
  margin-left: -8px;
  border-radius: 6px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text);
}

.topic-head-query {
  display: inline-block;
  cursor: text;
  transition: background-color 0.1s ease;
}

.topic-head-query:hover {
  background: var(--bg-muted);
}

.topic-head-query-edit {
  background: var(--bg-muted);
  border-color: var(--border);
  outline: none;
  width: 100%;
  max-width: 420px;
}

body.input-keyboard .topic-head-query-edit:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}

.topic-rules-hint {
  font-size: 11.5px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* Sound topic: the two reference videos (searched / original) as small
   preview cards under the sound — a thumbnail makes the one you
   searched by instantly recognisable. Not rows in the results table. */
/* Sound header: title + sound id on one line (id muted, to the side). */
.sound-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
}

.sound-id {
  font-size: 11.5px;
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}

.sound-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
}

.sound-card {
  display: flex;
  align-items: stretch;
  gap: 12px;
  /* Content-sized, not stretched — two compact cards sit side by side
     instead of each ballooning to fill the row. */
  flex: 0 0 auto;
  width: 340px;
  max-width: 100%;
  padding: 10px;
  padding-right: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  text-decoration: none;
  transition: border-color 0.1s ease, box-shadow 0.1s ease;
}

.sound-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-sm);
}

.sound-card-thumb {
  position: relative;
  width: 50px;
  aspect-ratio: 9 / 16;
  flex-shrink: 0;
  border-radius: 6px;
  overflow: hidden;
  background: #0f172a;
}

.sound-card-thumb .vt-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.sound-card-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-width: 0;
}

.sound-card-tag {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-soft);
}

.sound-card.is-original .sound-card-tag {
  color: var(--accent);
}

.sound-card-who {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sound-card-when {
  font-size: 11px;
  color: var(--text-muted);
}

/* Compact metrics row on the Searched / Original preview cards —
   reuses .vt-growth / .vt-status colours but shrinks them to fit. */
.sound-card-stats {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 3px;
}

.sound-card-stats .sc-stat {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}

.sound-card-stats .vt-growth,
.sound-card-stats .vt-status {
  padding: 1px 7px;
  font-size: 10.5px;
  font-weight: 700;
  gap: 3px;
  border-radius: 999px;
}

/* Rules panel: networks + search-rule chips with inline add input. */

.topic-rules {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 10px;
}

.topic-rules-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.topic-rules-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  font-weight: 600;
}

.topic-rules-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.topic-rules-add {
  display: flex;
  gap: 8px;
  margin-top: 4px;
  max-width: 420px;
}

.topic-rules-add-input {
  flex: 1;
  padding: 7px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
  outline: none;
}

.topic-rules-add-input:focus {
  border-color: var(--accent);
}

/* Rule chips. Same Primary-signal metrics as Status/Download pills
   (12.5 px, weight 700, padding 5×13, 1px border) so they sit visually
   on the same "decision-relevant state" tier. The × button is a hover
   affordance; clicking it removes the rule via the API. */

.rule-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 13px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

/* × button: flex-centered so the icon sits on the same baseline as the
   chip text regardless of font metrics. SVG is 12 px square. Pushed
   a touch to the right within the chip (negative right margin pulls it
   closer to the chip's right edge; small left margin keeps it visually
   separated from the tag text). */
.rule-chip-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: 2px;
  margin-right: -7px;
  border: none;
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  padding: 0;
  border-radius: 999px;
}

.rule-chip-x svg {
  width: 10px;
  height: 10px;
  display: block;
}

.rule-chip-x:hover {
  color: var(--danger);
  background: rgba(220, 38, 38, 0.08);
}

/* + add affordance: small accent-filled circle that occupies the same
   slot as the inline-add input after click. Sized to align vertically
   with the hashtag chips (chip height = 1.2*12.5 + 5+5 + 1+1 = ~27 px). */
.rule-chip-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 27px;
  height: 27px;
  border-radius: 999px;
  border: none;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  padding: 0;
  transition: background-color 0.1s ease, transform 0.05s ease;
}

.rule-chip-add:hover {
  background: #1d4ed8;
}

.rule-chip-add:active {
  transform: scale(0.94);
}

.rule-chip-add svg {
  width: 14px;
  height: 14px;
  display: block;
}

.rule-chip-add-input {
  height: 27px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-muted);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  font-family: inherit;
  line-height: 1.2;
  outline: none;
  min-width: 140px;
}

body.input-keyboard .rule-chip-add-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.18);
}

/* Brand network chips on topic detail + creation form.
   Active chip uses the saturated brand color (TikTok #111, Instagram
   gradient, YouTube #ff0000). Locked / unselected chips are fully
   neutral — no brand color at all, just a faint grey outline — so
   they read as "available, not picked" rather than "soft-tinted
   version of the real thing". The user adds color back by selecting. */

.platform-badge-selected {
  /* brand colors come from .platform-tiktok / -youtube / -instagram */
}

/* Locked (coming later, e.g. YouTube): neutral + non-interactive. */
.platform-badge-locked {
  background: transparent !important;
  color: var(--text-soft) !important;
  border: 1px solid var(--border);
  cursor: not-allowed;
}
.platform-badge-locked svg {
  opacity: 0.4;
}

/* Available but not selected: clearly clickable — brand-tinted outline +
   brand icon, readable text, pointer and a subtle hover lift. Distinct
   from the greyed-out locked chip. */
.platform-badge-muted:not(.platform-badge-locked) {
  background: transparent !important;
  color: var(--text) !important;
  border: 1px solid var(--border-strong);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease, transform 0.12s ease;
}
.platform-badge-muted:not(.platform-badge-locked):hover {
  background: var(--bg-hover) !important;
  transform: translateY(-1px);
}
/* Brand-colored icon + border per network so the choice reads at a glance. */
.platform-badge-muted:not(.platform-badge-locked).platform-tiktok {
  border-color: #111;
}
.platform-badge-muted:not(.platform-badge-locked).platform-tiktok svg {
  color: #111;
}
.platform-badge-muted:not(.platform-badge-locked).platform-instagram {
  border-color: #cc2366;
}
.platform-badge-muted:not(.platform-badge-locked).platform-instagram svg {
  color: #cc2366;
}

.platform-soon {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-soft);
}

/* Network chips on the topic page (and creation form) are larger and
   less uppercase-y than the preview-overlay variant from downloads —
   they're in the main content flow, not overlaid on a thumbnail. */
.topic-rules-chips .platform-badge {
  font-size: 12px;
  padding: 6px 12px 6px 10px;
  gap: 6px;
  letter-spacing: 0.02em;
}

.topic-rules-chips .platform-badge svg {
  width: 14px;
  height: 14px;
}

.topic-head-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.topic-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.stat {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px;
  background: var(--bg);
}

.stat-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  font-weight: 600;
}

.stat-value {
  font-size: 14.5px;
  font-weight: 600;
  margin-top: 2px;
  color: var(--text);
}

.stat-input {
  margin-top: 2px;
  width: 100%;
  padding: 4px 18px 4px 6px;
  border: 1px solid transparent;
  background: transparent;
  border-radius: 4px;
  font-size: 14.5px;
  font-weight: 600;
  font-family: inherit;
  color: var(--text);
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M3 5l3 3 3-3'/></svg>");
  background-repeat: no-repeat;
  background-position: right 4px center;
  background-size: 10px;
}

.stat-input:hover {
  border-color: var(--border);
  background-color: var(--bg);
}

/* Scrape state under the topic head */

.scrape-state {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.scrape-state.is-running {
  background: var(--accent-soft);
  border-color: var(--accent);
}

.scrape-state.is-done {
  background: #f0fdf4;
  border-color: #86efac;
}

.scrape-state.is-partial {
  background: #fef3c7;
  border-color: #fcd34d;
}

.scrape-state.is-failed {
  background: #fef2f2;
  border-color: #fecaca;
}

.scrape-state-summary {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-transform: capitalize;
  color: var(--text);
}

.scrape-state-count {
  font-size: 11.5px;
  color: var(--text-soft);
  font-weight: 500;
  margin-top: -2px;
}

.scrape-state-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.scrape-run-direction {
  display: inline-flex;
  align-items: center;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text);
  min-width: 80px;
  padding: 2px 0;
}

.scrape-state-runs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  flex: 1;
}

.scrape-run {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text-muted);
}

.scrape-run-running {
  border-color: var(--accent);
  color: var(--accent);
}

.scrape-run-done {
  border-color: #86efac;
  color: #166534;
}

.scrape-run-failed {
  border-color: #fecaca;
  color: var(--danger);
}

.scrape-run-skipped {
  border-style: dashed;
}

/* Transient Apify hiccup (network/DNS/5xx) — already retried once and
   self-heals next scrape. Soft amber, not the alarming red of a real
   failure. */
.scrape-run-temporary {
  border-color: #fcd9a8;
  color: var(--warning);
}

.scrape-state-err {
  font-size: 12px;
  color: var(--danger);
}

/* Topic videos table (Creative-Center style) */

/* Tabs */

.vt-tabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 14px;
}

.vt-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 14px;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  font-family: inherit;
}

.vt-tab:hover:not(:disabled) {
  color: var(--text);
}

.vt-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.vt-tab:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.vt-tab-count {
  font-size: 11px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
}

.vt-tab.is-active .vt-tab-count {
  background: var(--accent-soft);
  color: var(--accent);
}

.vt-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.vt-counts {
  font-size: 12.5px;
  color: var(--text-muted);
}

.vt-counts strong {
  color: var(--text);
  font-weight: 600;
}

.vt-toolbar-hint {
  font-size: 11.5px;
  color: var(--text-soft);
}

.vt-scroll {
  /* The single horizontal scroller for the videos table. max-width
     pins it to the content pane so a 1500px table scrolls *inside*
     this card instead of widening the page. */
  overflow-x: auto;
  overflow-y: hidden;
  max-width: 100%;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

.vt-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  /* Fits the consolidated ~10-column table on a normal screen without the
     horizontal scroll clipping the right columns (was 1500px for the old
     14-column layout, which pushed Age/Actions off-pane). */
  min-width: 1180px;
  table-layout: fixed;
}

.vt-table thead th {
  background: var(--bg-muted);
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  /* Above the pinned body columns (z-index 2) so the header row
     stays on top when scrolling vertically; corners override to 4. */
  z-index: 3;
  white-space: nowrap;
}

.vt-sortable {
  cursor: pointer;
  user-select: none;
  transition: color 0.1s ease;
}

.vt-sortable:hover {
  color: var(--text);
}

.vt-sortable.is-active {
  color: var(--accent);
}

.vt-th-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.vt-num .vt-th-label {
  justify-content: flex-end;
}

.vt-arrow {
  display: inline-flex;
  align-items: center;
  width: 10px;
  height: 10px;
  opacity: 0.35;
  transition: opacity 0.1s ease;
}

.vt-sortable:hover .vt-arrow {
  opacity: 0.7;
}

.vt-arrow.is-active {
  opacity: 1;
  color: var(--accent);
}

.vt-sort-arrow {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
}

.vt-table th.vt-num,
.vt-table td.vt-num {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.vt-table tbody tr {
  border-bottom: 1px solid var(--border);
  transition: background-color 0.08s ease;
}

.vt-table tbody tr:last-child {
  border-bottom: none;
}

.vt-table tbody tr:hover {
  background: var(--bg-muted);
}

.vt-table td {
  padding: 12px 14px;
  vertical-align: middle;
  color: var(--text);
}

.vt-table td strong {
  font-weight: 700;
  font-size: 14px;
  color: var(--text);
}

/* Preview cell */

.vt-col-preview {
  width: 168px;
}

.vt-preview {
  position: relative;
  display: block;
  width: 144px;
  height: 192px;
  border-radius: 10px;
  overflow: hidden;
  background: #0f172a;
  text-decoration: none;
}

.vt-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Media-kind badge (image / carousel) — top-left corner of the preview.
   Plain videos render no badge, so this only appears on IG photos and
   carousels. Sits above the cover/video layers. */
.vt-media-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 6px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.78);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  pointer-events: none;
  backdrop-filter: blur(2px);
}
.vt-media-badge svg {
  width: 12px;
  height: 12px;
}

/* Paid-partnership pill next to the author (IG, from apidojo). */
.vt-paid-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(234, 179, 8, 0.16);
  color: #a16207;
  border: 1px solid rgba(234, 179, 8, 0.4);
  font-size: 11px;
  font-weight: 600;
  vertical-align: middle;
}

.vt-thumb-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.18s ease;
  /* Transparent, not solid dark: if it's ever painted before a frame
     exists it must not blot out the cover underneath. */
  background: transparent;
}

/* Reveal the video only when it actually has footage (`vt-has-frame`,
   set by JS on loadeddata/playing). Hovering alone no longer flips the
   cell to an empty dark <video>; the cover stays, dimmed with the
   spinner, until the real frame fades in over it. */
.vt-preview.has-video.vt-has-frame:hover .vt-thumb-video {
  opacity: 1;
}

/* Loading overlay: while the CDN-direct mp4 is still buffering after
   the user hovers, dim the thumbnail and show a spinner so the cell
   doesn't look frozen. Cleared on `playing` or on play() error. */
.vt-preview.is-loading::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
  z-index: 2;
}

.vt-preview.is-loading::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 28px;
  height: 28px;
  margin: -14px 0 0 -14px;
  border: 3px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: vt-spin 0.8s linear infinite;
  z-index: 3;
}

@keyframes vt-spin {
  to { transform: rotate(360deg); }
}

/* ===== Account-search results (Track-a-creator by keyword) ===== */
.wl-sr {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 10px;
  border-top: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color 0.1s ease;
}
.wl-sr:first-child { border-top: none; }
/* Whole row is clickable (opens the IG profile) — hover like a sidebar item. */
.wl-sr:hover { background: var(--bg-hover); }
.wl-sr-av {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: var(--bg-hover);
  overflow: hidden;
  display: inline-flex;
}
.wl-sr-av img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.wl-sr-av-ph { display: inline-flex; }
.wl-sr-body { flex: 1 1 auto; min-width: 0; }
.wl-sr-handle { font-size: 13.5px; font-weight: 600; }
.wl-sr-handle a { color: var(--text); text-decoration: none; }
.wl-sr-handle a:hover { color: var(--accent); }
.wl-sr-verified {
  margin-left: 5px;
  color: var(--accent);
  font-size: 12px;
  font-weight: 700;
}
.wl-sr-sub {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Instagram account finder — identical to a standard .card in every way
   EXCEPT the border, which is Instagram's brand gradient instead of the grey
   1px. That ring is the ONLY distinctive touch; everything inside uses the
   normal design system (field label, inputs, .btn-primary, .wl-sr rows). */
.ig-finder {
  max-width: 620px;
  margin-top: 16px;
  padding: 22px 24px;
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  /* Gradient border: solid card on padding-box, IG gradient on border-box. */
  border: 2px solid transparent;
  background:
    linear-gradient(var(--bg), var(--bg)) padding-box,
    var(--ig-gradient) border-box;
}
/* The finder's search field fills the row — Settings' .cost-limit-row keeps
   its compact 120px because this is scoped to .ig-finder. */
.ig-finder .cost-limit-row input {
  width: auto;
  flex: 1 1 auto;
  min-width: 0;
}

/* ===== Associated tab — collapsible advertiser-network cards =====
   Each linked account is a card: header (caret · name · why · Track) + body.
   Expanded → the full ads table; collapsed → a tight grid of small previews. */
.assoc-group {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 12px 12px;
  margin-bottom: 12px;
  background: var(--bg);
}
.assoc-group.is-collapsed {
  background: var(--bg-muted);
  padding-bottom: 8px;
}
/* Full collapse: header only, body hidden entirely. Drop the head's
   bottom margin so the single row sits centered between the 8px top/bottom
   padding (otherwise it's 8px above vs 16px below — looks top-heavy). */
.assoc-group.is-collapsed .assoc-body {
  display: none;
}
.assoc-group.is-collapsed .assoc-head {
  margin-bottom: 0;
}
.assoc-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.assoc-toggle {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  font-size: 11px;
  line-height: 22px;
  text-align: center;
  border-radius: var(--radius-sm);
}
.assoc-toggle:hover {
  background: var(--bg-hover);
  color: var(--text);
}
.assoc-head-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.assoc-head .vt-author {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.assoc-why {
  font-size: 12px;
  color: var(--text-muted);
}
.assoc-empty {
  font-size: 12px;
  color: var(--text-soft);
  padding: 2px 0 4px;
}

/* ===== Compact grid view (Videos / Ads / Associated) ===== */
/* List ⇄ grid toggle in the toolbar (right side, beside the count/actions). */
.vt-toolbar-right {
  display: flex;
  align-items: center;
  gap: 12px;
}
.vt-view-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  flex: 0 0 auto;
}
.vt-view-btn {
  width: 30px;
  height: 26px;
  padding: 0;
  border: none;
  background: var(--bg);
  color: var(--text-soft);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.vt-view-btn + .vt-view-btn {
  border-left: 1px solid var(--border);
}
.vt-view-btn:hover {
  background: var(--bg-hover);
  color: var(--text);
}
.vt-view-btn.is-active {
  background: var(--accent-soft);
  color: var(--accent);
}
.vt-view-btn svg {
  width: 15px;
  height: 15px;
}

/* The preview wall: each cell is a 9:16 thumb + one caption line. */
.vt-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(124px, 1fr));
  gap: 14px 12px;
}
.vt-grid-cell {
  min-width: 0;
}
.vt-grid-thumb {
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-sm);
}
.vt-grid-cap {
  margin-top: 5px;
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Author + caption column */

.vt-caption-col {
  max-width: 360px;
  min-width: 220px;
}

.vt-author-row {
  margin-bottom: 2px;
}

.vt-author {
  font-size: 12.5px;
  color: var(--text-muted);
  font-weight: 500;
  text-decoration: none;
}

.vt-author:hover {
  color: var(--accent);
}

.vt-author.muted {
  color: var(--text-soft);
}

.vt-title {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.vt-title.muted {
  color: var(--text-soft);
  font-weight: 400;
}

.vt-tags {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.35;
  margin-top: 2px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.vt-music {
  font-size: 11px;
  color: var(--text-soft);
  margin-top: 4px;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Status pill */

/* Two pill scales across the topic table:
   - "Primary signal" (Status, Quality, Downloaded): 12.5 px, weight
     600, mixed case, ~5×13 padding. Reads as a decision-relevant
     state.
   - "Soft tag" (Match, Age, Scrapers): 11 px, weight 500, soft tint,
     ~2×9 padding. Reads as contextual metadata.
   Keep these two and only these two; new pills go into one bucket. */

.vt-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 13px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;          /* match .btn so pill height == button height */
  letter-spacing: 0;
  text-transform: none;
  border-radius: 999px;
  border: 1px solid transparent;   /* invisible — matches .btn's 1px border so heights align */
  white-space: nowrap;
}

.vt-status-icon {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}

/* Status pill palette — variant A (stock-chart / TikTok-flame).
   The pill answers two orthogonal questions: how hot is the trend
   right now, and have we even seen this video long enough to know.
   Hot/Growing carry the strongest signal (red flame, green growth),
   New is a soft yellow "look at this" while we wait for the second
   scrape to refine it, and the cool/decline states use desaturated
   complements. Pending stays quietly grey. */

.vt-status.is-pending {
  background: var(--bg-hover);
  color: var(--text-soft);
}

.vt-status.is-new {
  background: #fde68a;   /* yellow-200 */
  color: #854d0e;        /* yellow-800 */
}

.vt-status.is-stable {
  background: var(--bg-hover);
  color: var(--text);
}

.vt-status.is-growing {
  background: #16a34a;   /* green-600 */
  color: #fff;
}

.vt-status.is-hot {
  background: #dc2626;   /* red-600 */
  color: #fff;
}

.vt-status.is-cooling {
  background: #dbeafe;   /* blue-100 */
  color: #1e40af;        /* blue-800 */
}

.vt-status.is-declining {
  background: #fecaca;   /* red-200 */
  color: #991b1b;        /* red-800 */
}

.vt-status.is-failed {
  background: var(--bg);
  color: var(--text-soft);
  border: 1px dashed var(--border-strong);
}

/* Freshness pill */

.vt-fresh {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  background: var(--bg-hover);
  color: var(--text-muted);
  white-space: nowrap;
}

.vt-fresh.is-fresh {
  background: rgba(22, 163, 74, 0.12);
  color: #166534;
}

.vt-fresh.is-warm {
  background: #fef3c7;
  color: #92400e;
}

.vt-fresh.is-old,
.vt-fresh.is-stale {
  background: var(--bg-hover);
  color: var(--text-soft);
}

.vt-scrapers {
  display: inline-flex;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--bg-hover);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* Scrapers badge moved inline into the author row (its column was merged away). */
.vt-scrapers-inline {
  margin-left: 6px;
  padding: 1px 7px;
  vertical-align: middle;
}

/* Merged engagement cell: likes · comments · rate, stacked compactly. */
.vt-eng-cell {
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-size: 12px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  line-height: 1.25;
}
.vt-eng-cell .vt-eng-pct {
  color: var(--text);
  font-weight: 600;
}

/* Duration overlay on the preview thumbnail (its column was merged away). */
.vt-dur-badge {
  position: absolute;
  right: 6px;
  bottom: 6px;
  z-index: 3;
  padding: 1px 6px;
  border-radius: 6px;
  background: rgba(15, 23, 42, 0.78);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}

.vt-col-actions {
  /* Wide enough for the "✓ Downloaded" pill (~119px), not just the
     narrower "Download" button — at 130px the fixed-layout column
     clipped the pill against the sticky right edge. */
  width: 152px;
  text-align: right;
}

/* Pinned columns. A 14-column table is wider than most screens, so
   the Preview (left) and Actions/Download (right) columns stick to
   the edges of the .vt-scroll viewport — you can always see *which*
   video and reach Download without scrolling the table all the way
   across. Sticky cells need an opaque background or the scrolling
   columns show through; they mirror the row's normal / hover /
   expanded background. */
.vt-table th.vt-col-preview,
.vt-table td.vt-col-preview {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--bg);
}

.vt-table th.vt-col-actions,
.vt-table td.vt-col-actions {
  position: sticky;
  right: 0;
  z-index: 2;
  background: var(--bg);
}

/* Header corners sit above both the sticky body columns and the
   sticky header row. */
.vt-table thead th.vt-col-preview,
.vt-table thead th.vt-col-actions {
  z-index: 4;
  background: var(--bg-muted);
}

/* Follow the row state so the pinned cells don't look detached. */
.vt-table tbody tr:hover .vt-col-preview,
.vt-table tbody tr:hover .vt-col-actions {
  background: var(--bg-muted);
}

.vt-row.is-expanded > td.vt-col-preview,
.vt-row.is-expanded > td.vt-col-actions {
  background: var(--bg-muted);
}

/* Edge shadows make the pinned columns read as floating above the
   scrolling middle. */
.vt-table th.vt-col-preview,
.vt-table td.vt-col-preview {
  box-shadow: 6px 0 6px -6px rgba(15, 23, 42, 0.12);
}

.vt-table th.vt-col-actions,
.vt-table td.vt-col-actions {
  box-shadow: -6px 0 6px -6px rgba(15, 23, 42, 0.12);
}

.vt-dl {
  padding: 5px 13px;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
}

/* Pill variants for Downloaded / Downloading — same Primary-signal
   metrics as Status, just rendered as <a>/<span>. */
.vt-pill {
  display: inline-flex;
  align-items: center;
  padding: 5px 13px;
  border-radius: 999px;
  border: 1px solid transparent;   /* match .btn's 1px border so height aligns with Download */
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  text-decoration: none;
}

.vt-pill-done {
  background: rgba(22, 163, 74, 0.95);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.1s ease;
}

.vt-pill-done:hover {
  background: rgba(22, 163, 74, 1);
}

.vt-pill-active {
  background: rgba(37, 99, 235, 0.92);
  color: #fff;
}

.vt-firstseen {
  font-size: 11.5px;
  color: var(--text-muted);
  white-space: nowrap;
}

.vt-growth {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.vt-growth.is-positive {
  color: #15803d;
}

.vt-growth.is-negative {
  color: #b91c1c;
}

.vt-growth.is-neutral {
  color: var(--text-muted);
  font-weight: 500;
}

/* Match column — Soft-tag scale (same metrics as Age / Scrapers). */

.vt-match {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}

.vt-match.is-strong  { background: rgba(22,163,74,0.14);  color: #166534; }
.vt-match.is-medium  { background: rgba(234,179,8,0.18);  color: #854d0e; }
.vt-match.is-weak    { background: rgba(148,163,184,0.18); color: #475569; }
.vt-match.is-empty   { color: var(--text-soft); background: transparent; }

/* Score column */

.vt-score {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 13px;
  color: var(--text);
  display: inline-block;
  min-width: 28px;
}

.vt-score.is-empty {
  color: var(--text-soft);
  font-weight: 400;
}

/* Status pill rendered as a button for evidence-expand. */

.vt-status-button {
  /* border + padding + font inherit from .vt-status. Do NOT use `font: inherit`
     here — the shorthand resets font-size / font-weight / line-height to body
     (14px) and blows away the 12.5px / 700 / 1.2 set on .vt-status, which
     makes the pill render visibly taller than the Download button. Only override
     the bits a default <button> brings in (font-family + background reset). */
  font-family: inherit;
  background: none;
  cursor: pointer;
}

.vt-row.is-expanded > td {
  background: var(--bg-muted);
}

.vt-row.is-expanded .vt-status-button {
  box-shadow: 0 0 0 2px rgba(15, 23, 42, 0.18);
}

/* Evidence drawer row */

.vt-evidence-row td {
  padding: 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-muted);
}

.vt-evidence-list {
  list-style: none;
  margin: 0;
  padding: 12px 18px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 8px 24px;
}

.vt-evidence-list li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 12.5px;
  color: var(--text);
}

.vt-evidence-key {
  font-weight: 600;
  color: var(--text-muted);
  min-width: 72px;
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.04em;
}

.vt-evidence-text {
  flex: 1;
}

.vt-evidence-weight {
  font-size: 11px;
  color: var(--text-muted);
  background: var(--bg);
  border: 1px solid var(--border);
  padding: 1px 7px;
  border-radius: 999px;
}

.vt-evidence-empty {
  padding: 12px 18px;
  font-size: 12.5px;
  color: var(--text-soft);
}

.stat-input:focus {
  outline: none;
}

body.input-keyboard .stat-input:focus {
  border-color: var(--accent);
  background-color: var(--bg);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* --- Link Analysis (Phase 10) — new-topic "From links" panel --- */
.token-textarea {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 13px;
  line-height: 1.45;
  background: var(--bg);
  color: var(--text);
  resize: vertical;
  box-sizing: border-box;
  min-height: 240px;
}
.token-textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.links-tabs {
  display: flex;
  gap: 6px;
  margin: 14px 0 10px;
  border-bottom: 1px solid var(--border);
}
.links-tab {
  appearance: none;
  border: none;
  background: none;
  padding: 7px 12px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.links-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.links-pane[hidden] { display: none; }

.la-qrow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
/* The links panel is a `.field`, so the global `.field input
   { width:100%; padding; border }` cascades onto BOTH the checkbox and
   the query input — blowing the checkbox into a full-width box and
   hiding the text. Reset both explicitly (these 2-class selectors
   out-specify `.field input`). */
.la-qrow .la-qpick {
  flex: 0 0 auto;
  width: auto;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  box-shadow: none;
}
.la-qrow .la-qtext {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 13px;
  background: var(--bg);
  color: var(--text);
}
.la-qrow .la-qtext:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Settings — growth thresholds editor */
.thr-group { margin-bottom: 16px; }
.thr-group:last-child { margin-bottom: 0; }
.thr-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

/* ===== Watchlist (Phase 11) ===== */
.wl-avatar {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-hover);
  color: var(--text-muted);
  font-weight: 700;
}
.wl-avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.wl-avatar-fallback { line-height: 1; }
.wl-avatar-sm { width: 26px; height: 26px; font-size: 11px; }
.wl-avatar-md { width: 40px; height: 40px; font-size: 15px; }
.wl-avatar-lg { width: 64px; height: 64px; font-size: 24px; }

.wl-card-id {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 2px 0 6px;
}

.wl-head {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 14px;
}
.wl-head-body { min-width: 0; }
.wl-head-sub {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 2px;
}
.wl-head-sub a { color: var(--accent); text-decoration: none; }
.wl-head-about {
  font-size: 12px;
  color: var(--text-soft);
  margin-top: 2px;
}
.wl-bio {
  font-size: 13px;
  color: var(--text-soft);
  margin-top: 6px;
  max-width: 640px;
  white-space: pre-line;   /* keep the bio's own line breaks, like IG */
  line-height: 1.45;
}
.wl-head-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 6px;
  font-size: 13px;
  color: var(--text-muted);
}
.wl-head-counts b {
  color: var(--text);
  font-weight: 600;
}
.wl-verified {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  margin-left: 7px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  vertical-align: middle;
}
.wl-bio-links {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 14px;
  margin-top: 6px;
  font-size: 13px;
}
.wl-bio-links a {
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
}
.wl-bio-links a::before {
  content: "🔗";
  margin-right: 4px;
  font-size: 11px;
  opacity: 0.75;
}
.wl-bio-links a:hover { text-decoration: underline; }

/* "Automatically track" control — IG-only switches (add form + creator page). */
.wl-track {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 20px;
}
/* In the add form it's a field-rhythm block; in the creator header it sits
   inline in the actions row with extra room before Refresh now / Delete. */
#wl-form .wl-track { margin: 14px 0; }
.topic-head-actions .wl-track { margin-right: 16px; }
.wl-track-label { font-size: 13px; font-weight: 600; color: var(--text); }
.wl-track-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 13.5px;
  color: var(--text);
  user-select: none;
}
.wl-track-name { font-weight: 500; }
.wl-switch-input { position: absolute; opacity: 0; width: 0; height: 0; }
.wl-switch {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
  border-radius: 999px;
  background: var(--border-strong);
  transition: background-color 0.15s ease;
  flex: 0 0 auto;
}
.wl-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px rgba(17, 24, 39, 0.25);
  transition: transform 0.15s ease;
}
.wl-switch-input:checked + .wl-switch { background: var(--accent); }
.wl-switch-input:checked + .wl-switch::after { transform: translateX(16px); }
.wl-switch-input:focus-visible + .wl-switch { box-shadow: 0 0 0 3px var(--accent-soft); }

/* Archived-stories grid (creator detail → Stories tab). */
.wl-stories-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 12px;
}
.wl-story-card { text-decoration: none; color: var(--text); display: block; }
.wl-story-thumb {
  position: relative;
  display: block;
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg-hover);
  border: 1px solid var(--border);
}
.wl-story-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wl-story-card:hover .wl-story-thumb { border-color: var(--border-strong); }
.wl-story-badge {
  position: absolute;
  left: 6px;
  top: 6px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  border-radius: 4px;
  padding: 0 6px;
  font-size: 11px;
  line-height: 18px;
}
.wl-story-when {
  display: block;
  font-size: 11.5px;
  color: var(--text-muted);
  margin-top: 4px;
}

/* Watchlist detail reuses the Topics head/stats classes
   (.topic-head / .topic-head-actions / .topic-stats / .stat /
   .stat-input) so it looks identical — no watchlist-specific
   controls/stats styles needed. */

/* The watchlist videos table reuses the Topics .vt-* table styles
   verbatim (.vt-scroll / .vt-table / colgroup / .vt-sortable /
   .vt-status / .vt-evidence-row / .vt-fresh …) so it is visually
   identical — no watchlist-specific table CSS. */
.wl-banner {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin: 16px 0 4px;
  padding: 12px 14px;
  border: 1px solid #fcd9a8;
  background: #fff8ef;
  border-radius: var(--radius);
  font-size: 13px;
  color: #92400e;
  line-height: 1.5;
}
.wl-banner-icon { flex: 0 0 auto; font-size: 15px; line-height: 1.4; }
.wl-banner-title { font-weight: 600; color: var(--warning); }

/* ===== Hook Cutter ===== */
.dl-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
.dl-tab {
  appearance: none;
  background: none;
  border: none;
  padding: 8px 14px;
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.dl-tab:hover { color: var(--text); }
.dl-tab.is-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.hook-rename-input {
  width: 100%;
  font: inherit;
  font-weight: 600;
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
}

.cutter-modal {
  max-width: 760px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.cutter-body { display: flex; flex-direction: column; gap: 14px; }
.cutter-video {
  width: 100%;
  max-height: 48vh;
  background: #0f172a;
  border-radius: var(--radius-sm);
}
.cutter-timeline {
  position: relative;
  height: 34px;
  display: flex;
  align-items: center;
}
.cutter-track {
  position: absolute;
  left: 0; right: 0;
  height: 6px;
  border-radius: 3px;
  background: var(--bg-hover);
}
.cutter-range {
  position: absolute;
  height: 6px;
  border-radius: 3px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  box-sizing: border-box;
  pointer-events: none;
}
/* Two transparent range inputs stacked over the track act as the
   start/end handles; only their thumbs are visible. */
.cutter-handle {
  position: absolute;
  left: 0; right: 0;
  width: 100%;
  margin: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  pointer-events: none;
}
.cutter-handle::-webkit-slider-thumb {
  -webkit-appearance: none;
  pointer-events: auto;
  width: 14px;
  height: 22px;
  border-radius: 4px;
  background: var(--accent);
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.35);
  cursor: ew-resize;
}
.cutter-handle::-moz-range-thumb {
  pointer-events: auto;
  width: 14px;
  height: 22px;
  border-radius: 4px;
  background: var(--accent);
  border: 2px solid #fff;
  cursor: ew-resize;
}
.cutter-handle::-webkit-slider-runnable-track { background: none; }
.cutter-handle::-moz-range-track { background: none; }
.cutter-fields {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.cutter-fields .field-label,
.cutter-body > .field-label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
}
.cutter-fields input,
.cutter-fields select,
.cutter-body > .field-label input {
  font: inherit;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
}
.cutter-dur { font-weight: 600; padding: 6px 0; }
