/* ============================================================================
   Directors Collection — Operator Console · Theme + Component Layer
   ----------------------------------------------------------------------------
   Layers on TOP of Bootstrap 5.3 (which Shiny already ships) + Bootstrap Icons.
   Load order in the app head:
       1. Bootstrap 5.3 (shipped by Shiny)
       2. bootstrap-icons.css (CDN)
       3. colors_and_type.css   ← design tokens
       4. dc-theme.css          ← THIS FILE
   Dark mode uses Bootstrap's native  <html data-bs-theme="dark">.
   ============================================================================ */

/* ─────────────────────────────────────────────────────────────────────────
   1 · Map design tokens onto Bootstrap's CSS variables.
   This is what makes stock Bootstrap components (.btn, .badge, .form-control,
   .alert…) adopt the refined palette without touching their markup.
   ───────────────────────────────────────────────────────────────────────── */
:root {
  --bs-primary: var(--dc-primary);
  --bs-primary-rgb: 47, 109, 240;            /* #2f6df0 */
  --bs-success: var(--dc-ok);
  --bs-warning: var(--dc-warn);
  --bs-danger:  var(--dc-danger);
  --bs-body-bg: var(--dc-bg);
  --bs-body-color: var(--dc-ink);
  --bs-border-color: var(--dc-line);
  --bs-border-radius: var(--dc-radius);
  --bs-border-radius-sm: var(--dc-radius-sm);
  --bs-border-radius-lg: var(--dc-radius-lg);
  --bs-font-sans-serif: var(--dc-font-sans);
  --bs-body-font-size: var(--dc-fs-base);
  --bs-link-color: var(--dc-primary);
  --bs-link-hover-color: color-mix(in oklch, var(--dc-primary) 80%, black);
}
:root[data-bs-theme="dark"] {
  --bs-primary-rgb: 110, 150, 245;
  --bs-body-bg: var(--dc-bg);
  --bs-body-color: var(--dc-ink);
  --bs-border-color: var(--dc-line);
  --bs-emphasis-color: var(--dc-ink);
  --bs-secondary-color: var(--dc-muted);
  --bs-tertiary-bg: var(--dc-panel-2);
}

body { font-family: var(--dc-font-sans); font-size: var(--dc-fs-base); color: var(--dc-ink); background: var(--canvas); }
code, kbd, samp, .font-monospace, .dc-mono { font-family: var(--dc-font-mono); }

/* Buttons keep Bootstrap's structure; we just tighten the default size to the
   operator-dense rhythm and add a "dashed line" variant used for lazy actions. */
/* Project-wide rule (operator, 2026-08-03): a real flex gap between a
   button's icon and its label. Text nodes become anonymous flex items, so
   icon-only and text-only buttons render exactly as before (single item,
   no gap applied) — no per-page space characters needed. */
.btn { border-radius: var(--dc-radius); font-weight: var(--dc-fw-semi);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
/* …with one exception the rule above cannot reach on its own: Shiny's
   `ui.input_action_button()` wraps ALL of its content in a single
   `<span class="action-label">`, so the button has exactly one flex item and
   the gap has nothing to sit between — every icon+label action button in the
   app rendered with the icon touching its label (found 2026-08-10 on
   Encoding's "Generate previews"). Giving the wrapper the same treatment
   restores the project-wide 6px there too. */
.btn > .action-label { display: inline-flex; align-items: center; gap: 6px; }
.btn-sm { font-size: var(--dc-fs-sm); }
.dc-btn-line {
  background: var(--dc-panel); color: var(--dc-muted);
  border: 1px dashed var(--dc-line-2);
}
.dc-btn-line:hover { color: var(--dc-ink); border-color: var(--dc-faint); }

/* ═══════════════════════════════════════════════════════════════════════════
   2 · APP SHELL  —  fixed sidebar + scrolling main, fullscreen (no page scroll)
   ═══════════════════════════════════════════════════════════════════════════ */
/* `ui.page_fluid()` wraps the whole app in Bootstrap's `.container-fluid`,
   which carries a default 0.75rem (12px) left/right padding — invisible
   under the old floating-card sidebar (its own 8px margin sat on top of it
   regardless), but it blocks the flush-to-viewport-edge rail below from
   ever reaching x:0. This app has exactly one `.container-fluid` (the
   fullscreen shell) and no other page uses side padding from it, so
   zeroing it here (scoped via :has to only this shell, not any other
   possible container-fluid usage) is safe. */
.container-fluid:has(.dc-app) { padding-left: 0; padding-right: 0; }

.dc-app { display: flex; height: 100vh; overflow: hidden; background: var(--canvas); }

.dc-sidebar {
  --rail: 216px;
  width: var(--rail);
  flex: 0 0 var(--rail);
  /* height comes from flex-stretch in .dc-app (100vh); no explicit height needed.
     Flush rail (operator feedback, replaces the shell-Phase-1 floating card from
     e11b00f): no margin/border-radius/shadow — full height and width of its
     rail, flush against the viewport's top/left/bottom edges. The ONLY border
     is a single right-side seam against .dc-main, using the standard line
     token. */
  margin: 0;
  background: var(--surface);
  border: none;
  border-right: 1px solid var(--dc-line);
  border-radius: 0;
  display: flex; flex-direction: column;
  padding: var(--dc-space-4);
  overflow: hidden;
  transition: width var(--dc-dur) var(--dc-ease), flex-basis var(--dc-dur) var(--dc-ease);
  z-index: 1040;
}
/* Compact-only rail (operator-approved 2026-07-21, "compact-only (bold)"):
   the icon rail IS the sidebar — there is no expanded desktop state and no
   collapse toggle. `overflow: visible` lets the hover-title tooltip escape
   the 60px rail (it was clipped before). */
.dc-sidebar.is-collapsed { --rail: 60px; overflow: visible; }

.dc-main {
  flex: 1 1 auto; min-width: 0; height: 100vh; overflow: hidden;
  display: flex; flex-direction: column;
}
.dc-main__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px 24px; }

/* ── Brand header ── */
.dc-brand {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  padding: var(--dc-space-4) var(--dc-space-2) var(--dc-space-3);
  /* no border-bottom — floating card removes internal dividers */
}
.dc-brand__logo {
  display: block;
  height: 60px;
  width: auto;
  max-width: 100%;
  /* invert token: 0 in light (black logo on grey surface), 1 in dark (white) */
  filter: invert(var(--logo-invert));
}
.dc-brand__mark-img { display: none; height: 32px; width: 32px; }
.dc-brand__sub { font-size: 9.5px; font-weight: var(--dc-fw-bold); letter-spacing: var(--dc-track-label); text-transform: uppercase; color: var(--dc-faint); }

/* ── Nav ── */
/* sidebar padding (8px) handles the horizontal inset; nav only needs vertical */
.dc-nav { flex: 1 1 auto; overflow-y: auto; padding: 6px 0 4px; }
.dc-nav__section {
  font-size: 9.5px; font-weight: var(--dc-fw-bold); letter-spacing: var(--dc-track-label);
  text-transform: uppercase; color: var(--dc-faint);
  padding: 9px 6px 3px;
}
.dc-nav__link {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 8px; border-radius: 0;
  color: var(--dc-muted); font-weight: var(--dc-fw-medium); font-size: 13px;
  text-decoration: none; cursor: pointer; position: relative;
  white-space: nowrap; transition: background var(--dc-dur-fast), color var(--dc-dur-fast);
}
.dc-nav__link + .dc-nav__link { margin-top: 1px; }
/* Shiny's ui.input_action_link wraps the link content in an extra
   <span class="action-label">, which means the icon + label aren't
   direct children of .dc-nav__link — so the outer flex `gap: 9px`
   skips them. Propagate the same flex layout to .action-label so the
   gap reaches the icon/label pair.                                    */
.dc-nav__link > .action-label {
  display: flex; align-items: center; gap: 9px;
  flex: 1; min-width: 0;
}
.dc-nav__icon { flex: none; width: 20px; text-align: center; font-size: 15px; line-height: 1; color: var(--dc-faint); transition: color var(--dc-dur-fast); }
.dc-nav__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.dc-nav__link:hover { background: color-mix(in oklch, var(--dc-ink) 5%, transparent); color: var(--dc-ink); }
.dc-nav__link:hover .dc-nav__icon { color: var(--dc-muted); }
.dc-nav__link.is-active {
  background: transparent; color: var(--dc-primary); font-weight: var(--dc-fw-semi);
}
.dc-nav__link.is-active .dc-nav__icon { color: var(--dc-primary); }
.dc-nav__link.is-active::before {           /* the state-edge motif, reused */
  content: ""; position: absolute; left: 0; top: 7px; bottom: 7px;
  width: 3px; border-radius: 0; background: var(--dc-primary);
}
.dc-nav__badge { margin-left: auto; font-family: var(--dc-font-mono); font-size: 11px; color: var(--dc-faint); }

/* ── Sidebar footer — single-row: avatar · username · [controls at right] ── */
.dc-sidebar__footer {
  /* subtle top spacing; no border-top — floating card aesthetic has no dividers */
  padding-top: var(--dc-space-4);
  margin-top: var(--dc-space-3);
  display: flex;
  align-items: center;
  gap: var(--dc-space-3);
}
.dc-user__avatar {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  background: var(--dc-ink); color: var(--surface);
  display: grid; place-items: center;
  font-size: 10px; font-weight: var(--dc-fw-bold);
}
/* username — hidden in collapsed state; see collapsed rule below */
.dc-user__name {
  font-size: 12px; font-weight: var(--dc-fw-semi);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
  flex: 1 1 auto;
}
/* controls pushed to the far right */
.dc-sidebar__controls { display: flex; flex-direction: row; gap: 2px; margin-left: auto; }
/* ── Icon-only footer buttons — minimal, no border, transparent bg ── */
.dc-iconbtn {
  appearance: none; flex: 0 0 auto;
  width: 26px; height: 26px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: none;
  border-radius: 6px;
  color: var(--dc-muted); font-size: 14px;
  padding: 0; cursor: pointer; white-space: nowrap;
  transition: background var(--dc-dur-fast), color var(--dc-dur-fast);
  text-decoration: none;
}
.dc-iconbtn:hover { background: color-mix(in oklch, var(--dc-ink) 8%, transparent); color: var(--dc-ink); }
.dc-iconbtn i { font-size: 14px; }

/* ── Collapsed (icon rail) state ── */
/* Brand: crop the logo to the heart-mark (left portion) — no image swap */
.dc-sidebar.is-collapsed .dc-brand {
  align-items: center;
  justify-content: center;
  /* Sidebar padding-top + this block = strip + table header, so the brand
     ends on the same y as the main pane's first horizontal line and the
     nav bands below fall on the table rows (full-screen composite,
     2026-07-20). Was a fixed 60px (8 + 60 = 34 + 34); since the strip grew
     to 48px (2026-09-14, operator: "the menu's logo should align with top
     strip and table header") it is derived from the tokens: 48 + 34 - 8 =
     74px. */
  height: calc(var(--dc-strip-h) + var(--dc-topbar-h) - var(--dc-space-4));
  box-sizing: border-box;
  padding: 0;
}
.dc-sidebar.is-collapsed .dc-brand__logo { display: none; }  /* compact uses the mark */
.dc-sidebar.is-collapsed .dc-brand__mark-img {
  display: block; height: 26px; width: 26px;
  filter: invert(var(--logo-invert));
}
.dc-sidebar.is-collapsed .dc-brand__sub { display: none; }
/* Hide all text labels in the nav and footer.
   NOTE: .dc-iconbtn span is intentionally NOT included here — Shiny's
   input_action_link wraps the icon in <span class="action-label">, so
   targeting `span` inside .dc-iconbtn would hide the logout icon itself.
   No .dc-iconbtn in this markup has a standalone text span. */
.dc-sidebar.is-collapsed .dc-brand__text,
.dc-sidebar.is-collapsed .dc-nav__label,
.dc-sidebar.is-collapsed .dc-nav__badge,
.dc-sidebar.is-collapsed .dc-user__name { display: none; }
/* Nav section labels: hidden via height:0 + overflow:hidden + zero margin
   so every icon is evenly spaced (no per-section group gap in rail mode) */
.dc-sidebar.is-collapsed .dc-nav__section {
  padding: 0; border: none; margin: 0; height: 0; overflow: hidden;
}
/* Nav: drawer-language bands — full-width edge-to-edge dividers on the
   34px grid. The nav cancels the sidebar's 8px horizontal padding so the
   dividers run the full rail width; `overflow: visible` (not auto) so the
   hover-title tooltips aren't clipped. */
.dc-sidebar.is-collapsed .dc-nav {
  padding: 0;
  margin: 0 calc(-1 * var(--dc-space-4));
  overflow: visible;
}
/* Nav items: centred icon only, one 34px band per page */
.dc-sidebar.is-collapsed .dc-nav__link {
  justify-content: center;
  padding: 0;
  height: var(--dc-topbar-h);
  /* No horizontal dividers (operator 2026-08-10: "on the sidebar lets remove
     the horizontal dividers, we keep everything else as is"). The bands were
     already legible from their own height + the active fill and edge; the
     rules just added chrome. Everything else about the band is unchanged. */
}
.dc-sidebar.is-collapsed .dc-nav__link + .dc-nav__link { margin-top: 0; }
/* Active band: panel-2 fill + primary icon + square 3px primary left edge
   (inset shadow, not the ::before pill — the edge must span the full band). */
.dc-sidebar.is-collapsed .dc-nav__link.is-active {
  background: var(--dc-panel-2);
  box-shadow: inset 3px 0 0 var(--dc-primary);
}
.dc-sidebar.is-collapsed .dc-nav__link.is-active::before { display: none; }
/* Shiny's input_action_link wraps content in <span class="action-label">
   so .dc-nav__link's `justify-content: center` only centers the wrapper,
   not the icon inside it. Propagate centering down one DOM level.       */
.dc-sidebar.is-collapsed .dc-nav__link > .action-label { justify-content: center; }
.dc-sidebar.is-collapsed .dc-nav__icon { font-size: 17px; }
/* Footer: stack vertically; controls column; avatar centred */
.dc-sidebar.is-collapsed .dc-sidebar__footer {
  flex-direction: column;
  gap: var(--dc-space-2);
  align-items: center;
}
.dc-sidebar.is-collapsed .dc-sidebar__controls {
  margin-left: 0;
  flex-direction: column;
}
/* Tooltip on hover when collapsed */
.dc-sidebar.is-collapsed .dc-nav__link::after {
  content: attr(data-label); position: absolute; left: calc(100% + 10px); top: 50%; transform: translateY(-50%);
  background: var(--dc-ink); color: var(--canvas); font-size: 12px; font-weight: var(--dc-fw-semi);
  padding: 4px 9px; border-radius: 6px; white-space: nowrap; pointer-events: none;
  opacity: 0; transition: opacity var(--dc-dur-fast); z-index: 50;
}
.dc-sidebar.is-collapsed .dc-nav__link:hover::after { opacity: 1; }

/* ── Mobile top bar + off-canvas sidebar ── */
.dc-topbar { display: none; }
.dc-backdrop { display: none; }

@media (max-width: 860px) {
  .dc-topbar {
    display: flex; align-items: center; gap: 12px; flex: none;
    height: 54px; padding: 0 14px; background: var(--dc-panel);
    border-bottom: 1px solid var(--dc-line); z-index: 1030;
  }
  .dc-topbar__title { font-weight: var(--dc-fw-bold); font-size: 15px; }
  .dc-hamburger {
    appearance: none; background: none; border: none; color: var(--dc-ink);
    font-size: 22px; line-height: 1; padding: 4px 6px; cursor: pointer; border-radius: 6px;
  }
  .dc-hamburger:hover { background: color-mix(in oklch, var(--dc-ink) 6%, transparent); }

  .dc-sidebar {
    position: fixed; left: 0; top: 0; --rail: 280px;
    /* remove float margin + rounded corners for the off-canvas slide-in */
    margin: 0; border-radius: 0;
    /* explicit height required for fixed-positioned element */
    height: 100vh;
    padding: var(--dc-space-4) var(--dc-space-6);  /* more breathing room on mobile */
    transform: translateX(-100%); box-shadow: var(--dc-shadow-lg);
  }
  .dc-sidebar.is-open { transform: translateX(0); }
  .dc-sidebar.is-collapsed { --rail: 280px; }    /* never rail-collapse on mobile */
  /* restore all text labels in mobile off-canvas (collapsed class is ignored on mobile) */
  .dc-sidebar.is-collapsed .dc-nav__label,
  .dc-sidebar.is-collapsed .dc-nav__section,
  .dc-sidebar.is-collapsed .dc-user__name { display: revert; }
  .dc-sidebar.is-collapsed .dc-brand {
    align-items: flex-start;
    padding: var(--dc-space-4) 0 var(--dc-space-3);
    justify-content: flex-start;
    height: auto;
  }
  .dc-sidebar.is-collapsed .dc-brand__logo {
    height: 60px; width: auto; object-fit: unset; max-width: 100%;
  }
  .dc-sidebar.is-collapsed .dc-brand__sub { display: block; }
  .dc-sidebar.is-collapsed .dc-nav__section {
    padding: 9px 6px 3px; border: none; margin: 0; height: auto; overflow: visible;
  }
  /* undo the desktop band treatment — mobile off-canvas is a labelled list */
  .dc-sidebar.is-collapsed .dc-nav { margin: 0; padding: 6px 0 4px; overflow-y: auto; }
  .dc-sidebar.is-collapsed .dc-nav__link {
    justify-content: flex-start; padding: 8px 10px;
    height: auto; border-bottom: none;
  }
  .dc-sidebar.is-collapsed .dc-nav__link:first-of-type { border-top: none; }
  .dc-sidebar.is-collapsed .dc-nav__link + .dc-nav__link { margin-top: 1px; }
  .dc-sidebar.is-collapsed .dc-nav__link.is-active { background: transparent; box-shadow: none; }
  .dc-sidebar.is-collapsed .dc-nav__link.is-active::before { display: block; }
  .dc-sidebar.is-collapsed .dc-nav__link::after { display: none; }  /* no hover tooltips on touch */
  .dc-sidebar.is-collapsed .dc-sidebar__footer {
    flex-direction: row; gap: var(--dc-space-3); align-items: center;
  }
  .dc-sidebar.is-collapsed .dc-sidebar__controls { margin-left: auto; flex-direction: row; }

  .dc-backdrop.is-open {
    display: block; position: fixed; inset: 0; z-index: 1035;
    background: color-mix(in oklch, black 45%, transparent);
  }
  .dc-main__scroll { padding: 16px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   3 · PAGE PRIMITIVES
   ═══════════════════════════════════════════════════════════════════════════ */
.dc-page-header {
  display: flex; align-items: flex-end; gap: 16px;
  padding-bottom: 12px; margin-bottom: 16px; border-bottom: 1px solid var(--dc-line);
}
.dc-page-header__titles { flex: 1 1 auto; min-width: 0; }
.dc-page-header__title { font-size: var(--dc-fs-xl); font-weight: var(--dc-fw-bold); line-height: 1.1; letter-spacing: -0.02em; margin: 0; }
.dc-page-header__sub { color: var(--dc-muted); font-size: var(--dc-fs-sm); margin-top: 3px; }
.dc-page-header__actions { display: flex; gap: 8px; align-items: center; flex: none; }

.dc-stat-row { display: flex; gap: 10px; margin-bottom: 16px; flex-wrap: wrap; }
.dc-stat {
  flex: 1 1 0; min-width: 120px; background: var(--dc-panel);
  border: 1px solid var(--dc-line); border-radius: var(--dc-radius); padding: 12px 14px;
}
.dc-stat__value { font-size: 22px; font-weight: var(--dc-fw-bold); line-height: 1.1; font-variant-numeric: tabular-nums; }
.dc-stat__label { font-size: 11px; color: var(--dc-faint); text-transform: uppercase; letter-spacing: var(--dc-track-label); margin-top: 4px; }

.dc-card { background: var(--dc-panel); border: 1px solid var(--dc-line); border-radius: var(--dc-radius); }

/* ── Login / invite card (.dc-login) ──
   drawer.css maps every `.dc-card` Shiny control onto the drawer's flush
   edit register (28px inputs, zero field margin). Right for a key/value
   grid inside a drawer; on the sign-in card it stacked label-input-label-
   input with no air (operator 2026-09-14: "the login looks squeezed").
   These win on specificity and put a form's spacing back on that one card. */
.dc-card.dc-login .shiny-input-container { margin-bottom: 16px; }
.dc-card.dc-login .form-label { margin-bottom: 6px; font-size: 12.5px; color: var(--dc-muted); }
.dc-card.dc-login .form-control { min-height: 36px; padding: 6px 10px; font-size: 13.5px; }
.dc-card.dc-login .btn { min-height: 38px; }

/* ── Step strip (compressed wizard progress; reused across drawers) ── */
.dc-steps { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dc-step { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: var(--dc-fw-semi); color: var(--dc-faint); padding: 5px 10px; border-radius: var(--dc-radius-pill); background: var(--dc-panel-2); border: 1px solid var(--dc-line); white-space: nowrap; cursor: default; }
.dc-step__n { width: 17px; height: 17px; border-radius: 50%; display: grid; place-items: center; font-size: 10.5px; background: var(--dc-line-2); color: var(--dc-panel); }
.dc-step.is-done { color: color-mix(in oklch, var(--dc-ok) 60%, black); background: var(--dc-ok-soft); border-color: color-mix(in oklch, var(--dc-ok) 30%, white); }
.dc-step.is-done .dc-step__n { background: var(--dc-ok); }
.dc-step.is-current { color: var(--dc-primary); background: var(--dc-primary-soft); border-color: var(--dc-primary-line); }
.dc-step.is-current .dc-step__n { background: var(--dc-primary); }
.dc-steps__sep { color: var(--dc-line-2); font-size: 11px; }
:root[data-bs-theme="dark"] .dc-step.is-done { color: color-mix(in oklch, var(--dc-ok) 35%, white); }

/* ── Help popover (replaces always-on helper paragraphs to save space) ──
   <span class="dc-help"><button class="dc-help__btn"><i class="bi bi-info-circle"></i></button>
     <span class="dc-help__pop">explanation…</span></span>
   Shows on hover (desktop) and on tap via a .show toggle (mobile). */
.dc-help { position: relative; display: inline-flex; vertical-align: middle; }
.dc-help__btn { appearance: none; background: none; border: none; color: var(--dc-faint); cursor: pointer; padding: 0 2px; font-size: 0.62em; line-height: 1; display: inline-flex; }
.dc-help__btn:hover { color: var(--dc-primary); }
.dc-help__pop { position: absolute; top: calc(100% + 6px); left: 0; z-index: 40; width: max-content; max-width: 280px; background: var(--dc-ink); color: var(--dc-bg); font-size: 12px; font-weight: var(--dc-fw-normal); line-height: 1.45; padding: 8px 11px; border-radius: 7px; box-shadow: var(--dc-shadow); opacity: 0; visibility: hidden; transform: translateY(-3px); transition: opacity .12s, transform .12s; }
.dc-help:hover .dc-help__pop, .dc-help.show .dc-help__pop { opacity: 1; visibility: visible; transform: translateY(0); }

/* ── Pills (status) ── */
.dc-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: var(--dc-fw-bold); padding: 2px 9px; border-radius: var(--dc-radius-pill); white-space: nowrap; }
.dc-pill--decision { background: var(--dc-primary-soft); color: color-mix(in oklch, var(--dc-primary) 72%, black); }
.dc-pill--locked   { background: var(--dc-ok-soft);      color: color-mix(in oklch, var(--dc-ok) 62%, black); }
.dc-pill--running  { background: var(--dc-warn-soft);    color: color-mix(in oklch, var(--dc-warn) 55%, black); }
.dc-pill--pending  { background: color-mix(in oklch, var(--dc-ink) 8%, transparent); color: var(--dc-muted); }
.dc-pill--danger   { background: var(--dc-danger-soft);  color: color-mix(in oklch, var(--dc-danger) 62%, black); }
:root[data-bs-theme="dark"] .dc-pill--decision { color: color-mix(in oklch, var(--dc-primary) 30%, white); }
:root[data-bs-theme="dark"] .dc-pill--locked   { color: color-mix(in oklch, var(--dc-ok) 35%, white); }
:root[data-bs-theme="dark"] .dc-pill--running  { color: color-mix(in oklch, var(--dc-warn) 40%, white); }

/* ── Chips (mono metadata / profiles) ── */
.dc-chip { font-family: var(--dc-font-mono); font-size: 12px; background: var(--dc-panel-2); border: 1px solid var(--dc-line); border-radius: var(--dc-radius-sm); padding: 1px 7px; color: var(--dc-ink); white-space: nowrap; }
.dc-chip--rec { border-color: var(--dc-primary-line); background: var(--dc-primary-soft); }
.dc-chip--imdb { background: #F5DE50; color: #111; border-color: #e3c200; font-weight: var(--dc-fw-semi); }

/* ── State-edge list rows (the core list motif) ── */
.dc-row { position: relative; display: flex; align-items: center; gap: 12px; background: var(--dc-panel); border: 1px solid var(--dc-line); border-radius: var(--dc-radius); padding: 10px 14px 10px 16px; overflow: hidden; }
.dc-row + .dc-row { margin-top: 8px; }
.dc-row__edge { position: absolute; left: 0; top: 0; bottom: 0; width: var(--dc-edge-width); }
.dc-row--decision .dc-row__edge { background: var(--dc-edge-decision); }
.dc-row--locked   .dc-row__edge { background: var(--dc-edge-locked); }
.dc-row--locked   { background: color-mix(in oklch, var(--dc-ok) 5%, var(--dc-panel)); }
.dc-row--running  .dc-row__edge { background: var(--dc-edge-running); }
.dc-row--pending  .dc-row__edge { background: var(--dc-edge-pending); }
.dc-row__title { font-weight: var(--dc-fw-semi); }
.dc-row__spec { font-family: var(--dc-font-mono); font-size: var(--dc-fs-sm); color: var(--dc-muted); }
.dc-row--locked-line { padding: 7px 12px 7px 16px; }

/* ── Dense table ── */
.dc-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; }
.dc-table thead th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: var(--dc-track-label); color: var(--dc-faint); font-weight: var(--dc-fw-bold); padding: 8px 12px; border-bottom: 1px solid var(--dc-line); white-space: nowrap; position: sticky; top: 0; background: var(--dc-panel-2); z-index: 1; }
.dc-table tbody td { padding: 9px 12px; border-bottom: 1px solid var(--dc-line); }
.dc-table tbody tr:hover { background: var(--dc-panel-2); cursor: pointer; }
.dc-table tbody tr.is-selected { background: var(--dc-primary-soft); }
.dc-table .dc-mono { font-family: var(--dc-font-mono); font-size: 12px; color: var(--dc-muted); }

/* ── Inputs ── */
.form-control, .form-select { border-radius: var(--dc-radius); border-color: var(--dc-line-2); background: var(--dc-panel); color: var(--dc-ink); }
.form-control:focus, .form-select:focus { border-color: var(--dc-primary-line); box-shadow: var(--dc-shadow-focus); }

/* ── Selectize widgets (shipped with Shiny; used by ui.input_selectize) ──
   Shiny's selectize.css uses fixed greys. Re-theme so multi-select chips
   adopt the DC palette in both modes.                                     */
.selectize-control .selectize-input,
.selectize-input.input-active {
  background: var(--dc-panel);
  color: var(--dc-ink);
  border: 1px solid var(--dc-line-2);
  border-radius: var(--dc-radius);
  font-family: var(--dc-font-sans);
  font-size: var(--dc-fs-sm);
  box-shadow: none;
}
.selectize-input.focus {
  border-color: var(--dc-primary-line);
  box-shadow: var(--dc-shadow-focus);
}
.selectize-input > input::placeholder { color: var(--dc-faint); }
.selectize-dropdown,
.selectize-dropdown-content {
  background: var(--dc-panel);
  color: var(--dc-ink);
  border: 1px solid var(--dc-line-2);
  border-radius: var(--dc-radius);
  font-size: var(--dc-fs-sm);
}
.selectize-dropdown .active,
.selectize-dropdown [data-selectable]:hover {
  background: var(--dc-primary-soft);
  color: var(--dc-ink);
}
.selectize-input .item {
  background: var(--dc-primary-soft);
  color: color-mix(in oklch, var(--dc-primary) 72%, black);
  border-radius: var(--dc-radius-sm);
  font-size: 12px;
  padding: 1px 7px;
  border: none;
}
:root[data-bs-theme="dark"] .selectize-input .item {
  color: color-mix(in oklch, var(--dc-primary) 30%, white);
}

/* ── Bootstrap nav-tabs (used by the film detail drawer) ──
   Underline-only style; active = primary colour + 2px bottom border.      */
.nav-tabs { border-bottom: 1px solid var(--dc-line); gap: 2px; }
.nav-tabs .nav-link {
  color: var(--dc-muted);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 14px;
  font-size: var(--dc-fs-sm);
  font-weight: var(--dc-fw-semi);
  border-radius: 0;
  transition: color var(--dc-dur-fast), border-color var(--dc-dur-fast);
}
.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus {
  color: var(--dc-ink);
  /* Classic alpha-overlay hover. We tried color-mix with --dc-panel
     before, but in dark mode .split-detail flips to --dc-panel-2 (one
     step lighter than --dc-panel), so the mix-against-panel result was
     LOWER lightness than the surface the tab actually sits on →
     visually invisible. Explicit rgba in light + a dark-theme override
     gives a clearly-different hover overlay regardless of which panel
     token sits behind the drawer.                                      */
  background-color: rgba(0, 0, 0, 0.06);
  border-bottom-color: var(--dc-line-2);
}
:root[data-bs-theme="dark"] .nav-tabs .nav-link:hover,
:root[data-bs-theme="dark"] .nav-tabs .nav-link:focus {
  background-color: rgba(255, 255, 255, 0.07);
}
.nav-tabs .nav-link.active {
  color: var(--dc-primary);
  background: transparent;
  border-bottom: 2px solid var(--dc-primary);
}
:root[data-bs-theme="dark"] .nav-tabs .nav-link.active {
  color: color-mix(in oklch, var(--dc-primary) 35%, white);
  border-bottom-color: var(--dc-primary);
}
.tab-content { padding-top: 14px; }

/* ── Bootstrap dropdown-menu (View / Columns / etc.) ── */
.dropdown-menu {
  background: var(--dc-panel);
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius);
  box-shadow: var(--dc-shadow);
  color: var(--dc-ink);
}
.dropdown-item { color: var(--dc-ink); font-size: var(--dc-fs-sm); }
.dropdown-item:hover,
.dropdown-item:focus { background: var(--dc-primary-soft); color: var(--dc-ink); }

/* ── Bootstrap outline-secondary buttons (More filters / View / Columns)
   Tighten to token greys + DC rhythm.                                     */
.btn-outline-secondary {
  --bs-btn-color:              var(--dc-muted);
  --bs-btn-border-color:       var(--dc-line-2);
  --bs-btn-hover-color:        var(--dc-ink);
  --bs-btn-hover-bg:           color-mix(in oklch, var(--dc-ink) 5%, transparent);
  --bs-btn-hover-border-color: var(--dc-line-2);
  --bs-btn-active-color:       var(--dc-ink);
  --bs-btn-active-bg:          color-mix(in oklch, var(--dc-ink) 8%, transparent);
  --bs-btn-active-border-color: var(--dc-line-2);
  font-weight: var(--dc-fw-semi);
  border-radius: var(--dc-radius);
}

/* ── Shiny render.DataGrid theming ──
   render.DataGrid renders as <shiny-data-frame> containing
   `.shiny-data-grid.shiny-data-grid-grid` (or `-table` for non-grid mode).
   The widget injects its own CSS at runtime via JS that scopes defaults
   to `shiny-data-frame { … }`. Declaring our overrides on the SAME
   `shiny-data-frame` selector matches the widget's specificity, so source
   order in this file wins. The :root pattern lost the cascade race.

   The widget's geometry (border-collapse:separate; each cell gets
   border-right + border-bottom + first-child border-left) means:
     • horizontal lines  = cell `border-bottom`
     • vertical lines    = cell `border-right` and first-child `border-left`
   We keep `--gridlines-style: solid` so horizontals render, then null out
   `border-left-style` and `border-right-style` on cells to kill verticals.
                                                                          */
/* Custom-property overrides for the DataGrid.
   The widget appends its own `<style>` block AS A CHILD of every
   `<shiny-data-frame>` element at custom-element connectedCallback
   time. That style block has rules at specificity 0,0,1 like
   `shiny-data-frame { --shiny-datagrid-font-size: 0.9em; ... }`. It
   lands in the DOM AFTER our linked stylesheet, so at identical
   specificity it WINS source order. To beat it we prepend `body` here
   (0,0,2 > 0,0,1) and the override applies regardless of source order.

   The header bg uses color-mix (var(--dc-panel-2) at oklch 0.985 reads
   as "still white" in light mode) so the table head has visible
   contrast against the page bg. Dark mode resolves naturally via the
   same token chain.                                                    */
body shiny-data-frame,
body .shiny-data-frame {
  /* CHEATSHEET §3B: body = 14px BUT table cell = 13px.
     The DataGrid's --shiny-datagrid-font-size applies to the table cells,
     so we set it to 13px (NOT --dc-fs-base which is 14px).               */
  --shiny-datagrid-font-size:   13px;
  --shiny-datagrid-padding-x:   12px;
  --shiny-datagrid-padding-y:   9px;

  --shiny-datagrid-grid-header-bgcolor:
    color-mix(in oklch, var(--dc-ink) 6%, var(--dc-panel));
  --shiny-datagrid-grid-header-gridlines-color:     var(--dc-line);
  --shiny-datagrid-grid-header-gridlines-style:     solid;
  --shiny-datagrid-grid-header-selected-bgcolor:    var(--dc-primary-soft);

  --shiny-datagrid-grid-gridlines-color:            var(--dc-line);
  --shiny-datagrid-grid-gridlines-style:            solid;   /* horizontals KEPT */

  --shiny-datagrid-grid-body-hover-bgcolor:
    color-mix(in oklch, var(--dc-ink) 6%, transparent);
  --shiny-datagrid-grid-body-selected-bgcolor:      var(--dc-primary-soft);
  --shiny-datagrid-grid-body-selected-color:        var(--dc-ink);

  --shiny-datagrid-table-bottom-border:             1px solid var(--dc-line);
  --shiny-datagrid-table-header-bottom-border:      1px solid var(--dc-line);
  --shiny-datagrid-table-top-border:                none;

  --shiny-datagrid-table-cell-edit-background-color:     var(--dc-warn-soft);
  --shiny-datagrid-table-cell-edit-success-bgcolor:      var(--dc-ok-soft);
  --shiny-datagrid-table-cell-edit-success-border-color: var(--dc-ok);
  --shiny-datagrid-table-cell-edit-failure-bgcolor:      var(--dc-danger-soft);
  --shiny-datagrid-table-cell-edit-failure-border-color: var(--dc-danger);
}

/* Wrapper styling — separate rule because the widget never sets these
   properties on shiny-data-frame itself, so identical specificity is
   fine (no source-order race to lose).                                 */
shiny-data-frame,
.shiny-data-frame {
  display: block;
  background: var(--dc-panel);
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius);
  overflow: hidden;
  font-family: var(--dc-font-sans);   /* inherited by every cell      */
  color: var(--dc-ink);
}

/* Header typography — design-system spec for table heads
   (10.5px UPPERCASE bold faint with letter-spacing).                     */
shiny-data-frame .shiny-data-grid > table > thead > tr > th {
  font-size: 10.5px;
  font-weight: var(--dc-fw-bold);
  letter-spacing: var(--dc-track-label);
  text-transform: uppercase;
  color: var(--dc-faint);
}

/* Kill ONLY vertical gridlines on the grid view (most common path).
   Widget injects its CSS via JS at custom-element registration time,
   which lands AFTER our linked stylesheets in the document head — so on
   identical specificity, the widget wins source order. We prepend `body`
   to bump specificity by 1 element (widget: 0,3,5 → ours: 0,3,6) so we
   win cleanly without `!important`. Bottom borders stay intact and
   continue to render the horizontal row dividers.                      */
body shiny-data-frame .shiny-data-grid.shiny-data-grid-grid > table > thead > tr > th,
body shiny-data-frame .shiny-data-grid.shiny-data-grid-grid > table > thead > tr > th:first-child,
body shiny-data-frame .shiny-data-grid.shiny-data-grid-grid > table > tbody > tr > td,
body shiny-data-frame .shiny-data-grid.shiny-data-grid-grid > table > tbody > tr > td:first-child {
  border-left-style: none;
  border-right-style: none;
}

/* Same for the non-grid (table) view, just in case future pages use it. */
body shiny-data-frame .shiny-data-grid.shiny-data-grid-table > table > thead > tr > th,
body shiny-data-frame .shiny-data-grid.shiny-data-grid-table > table > tbody > tr > td {
  border-left-style: none;
  border-right-style: none;
}

/* Body row text colour — explicit so it adopts var(--dc-ink) in both modes.
   We do NOT set background-color on td: an opaque cell bg shadows the
   tr:hover background underneath, so hover would silently never show.
   The wrapper rule (shiny-data-frame { background: var(--dc-panel) })
   gives the table its baseline panel surface.                          */
shiny-data-frame .shiny-data-grid > table > tbody > tr > td {
  color: var(--dc-ink);
}

/* Summary footer ("N rows" line)                                        */
shiny-data-frame .shiny-data-grid-summary {
  font-size: var(--dc-fs-sm);
  color: var(--dc-muted);
  padding: 6px 12px;
  border-top: 1px solid var(--dc-line);
  background: var(--dc-panel-2);
}

/* ── Filter rail (pages use the .dc-filter-rail class on the row wrapper)
   Subtle panel-2 surface + hairline border. The page passes utility
   classes (d-flex gap-2 p-2 …) for layout; this just paints the surface
   so it flips with the theme.                                             */
.dc-filter-rail {
  background: var(--dc-panel-2);
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius);
  color: var(--dc-ink);
}
.dc-filter-rail .form-control,
.dc-filter-rail .form-select {
  background: var(--dc-panel);
  color: var(--dc-ink);
  border-color: var(--dc-line-2);
}

/* ── Drawer header (used inside .split-detail / .dc-drawer) ── */
.dc-drawer__head {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding-bottom: 12px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--dc-line);
}
.dc-drawer__head h4,
.dc-drawer__head .h4 {
  font-size: var(--dc-fs-md);
  font-weight: var(--dc-fw-bold);
  color: var(--dc-ink);
  line-height: 1.2;
  margin: 0;
}
.dc-drawer__head small,
.dc-drawer__head .text-muted {
  color: var(--dc-muted) !important;
  font-size: var(--dc-fs-sm);
}

/* ── Split.js master-detail drawer (.split-detail wrapper owned by app.py)
   App.py's inline CSS owns the layout (height, min-width, flex, scroll
   gutter). This rule owns the surface so it flips with the theme.

   In light mode the drawer is the brightest surface (panel = #fff) sitting
   on the slightly-tinted page bg, which gives clean elevation. In dark
   mode the gap between page bg (0.205 L) and panel (0.248 L) is only
   0.04 L — reads as "black on black". Lift the drawer to panel-2
   (0.285 L) in dark mode so it has the same perceived elevation as in
   light mode.                                                            */
.split-detail {
  background: var(--dc-panel);
  /* No border, radius, or shadow (2026-07-21): the Split.js gutter now owns
     BOTH seam borders (.ig-rail-gutter language — see app.py's .gutter rule),
     so a drawer-side border would double it; flush square panel otherwise. */
  border: none;
  border-radius: 0;
  box-shadow: none;
}
:root[data-bs-theme="dark"] .split-detail {
  background: var(--dc-panel-2);
  border-color: var(--dc-line-2);
}
.split-detail .detail-close {
  background: var(--dc-panel);
  border: 1px solid transparent;
  color: var(--dc-muted);
  font-size: 1.25rem;
  line-height: 1;
  border-radius: var(--dc-radius-sm);
}
.split-detail .detail-close:hover {
  background: color-mix(in oklch, var(--dc-ink) 6%, transparent);
  color: var(--dc-ink);
}

/* ── Bootstrap card surfaces — make sure they flip with the theme ── */
.card { background-color: var(--dc-panel); border-color: var(--dc-line); color: var(--dc-ink); }
.card-header { background-color: var(--dc-panel-2); border-bottom-color: var(--dc-line); color: var(--dc-ink); }

/* ── Master-detail drawer (mirrors wizard_shell.py chrome) ── */
.dc-drawer { display: flex; flex-direction: column; height: 100%; min-height: 0; background: var(--dc-panel); border: 1px solid var(--dc-line-2); border-radius: var(--dc-radius-lg); box-shadow: var(--dc-shadow); overflow: hidden; }
.dc-drawer__chrome { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--dc-line); background: var(--dc-panel-2); flex: none; }
.dc-drawer__chrome-right { display: flex; align-items: center; gap: 8px; }
.dc-drawer__close { display: none; appearance: none; background: none; border: none; color: var(--dc-muted); font-size: 16px; line-height: 1; padding: 5px 8px; border-radius: 6px; cursor: pointer; }
.dc-drawer__close:hover { background: color-mix(in oklch, var(--dc-ink) 8%, transparent); color: var(--dc-ink); }
.dc-drawer__body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 16px 20px;
  /* Container Query foundation — Phase 1.
     Marking the drawer body as a query container lets ALL descendants
     react to the drawer's WIDTH (which changes when the operator drags
     the Split.js gutter), not the viewport. Specific layout rules below
     query `drawer` by name so they only fire in this context. Native
     CSS, no JS, reflows instantly during drag.                          */
  container-type: inline-size;
  container-name: drawer;
}
.dc-drawer__details { border: 1px solid var(--dc-line); border-radius: var(--dc-radius); background: var(--dc-panel-2); margin-bottom: 16px; }
.dc-drawer__details summary { cursor: pointer; padding: 10px 14px; font-size: 13px; font-weight: var(--dc-fw-semi); list-style: none; }
.dc-drawer__details summary .dc-hint { color: var(--dc-faint); font-weight: var(--dc-fw-normal); margin-left: 4px; }
.dc-drawer__footer { flex: none; display: flex; align-items: center; gap: 10px; padding: 11px 20px; background: var(--dc-panel); border-top: 1px solid var(--dc-line); box-shadow: 0 -4px 10px -6px color-mix(in oklch, var(--dc-ink) 30%, transparent); }
.dc-drawer__footer .dc-spacer { flex: 1 1 auto; }

/* ── Master-detail resize gutter (mirrors app.py Split.js gutter) ── */
.dc-gutter { flex: none; width: 6px; align-self: stretch; position: relative; cursor: col-resize; touch-action: none; }
/* Grip: the bare 5-dot column, identical to Split.js's `.gutter` and to
   `.ig-rail-gutter` (operator 2026-08-10: "the drag to resize should be the
   same as on encoding (dotted handle) this goes for all pages including the
   drawer handle"). This used to be a 6×38 rounded bar with dots ON it, which
   is why Scheduling's handle read as a different control from Encoding's. */
.dc-gutter { background: var(--dc-panel-2);
  border-left: 1px solid var(--dc-line); border-right: 1px solid var(--dc-line); }
.dc-gutter::after { content: ""; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%); width: 2px; height: 25px;
  /* FIVE DISTINCT dots — 2px dot on a 5px pitch, matching .ig-rail-gutter's
     real <span> dots exactly. The previous `radial-gradient(c 1px, transparent
     1.1px)` had a 0.1px falloff, which anti-aliased into a continuous wavy
     column rather than dots, and a 23px height cut the last tile in half. */
  background-image: radial-gradient(circle at center, var(--dc-faint) 0 1px, transparent 1.4px);
  background-size: 2px 5px; background-position: center;
  transition: background-color var(--dc-dur-fast); }
.dc-gutter:hover, .dc-gutter.is-dragging { background: var(--dc-panel); }

/* ── Preview video ──
   Native <video controls> needs at least 240×135 to keep its control bar usable
   (below that the bar clips and fullscreen is only reachable via right-click).
   So 240×135 is the HARD FLOOR for any preview; the recommended/default preview
   should be rendered larger than the compare previews. */
.dc-video { display: block; width: 100%; aspect-ratio: 16 / 9; min-width: 240px; min-height: 135px; background: #000; border-radius: var(--dc-radius-sm); border: 1px solid var(--dc-line-2); }

/* ── Progress ── */
.dc-progress { height: 6px; background: color-mix(in oklch, var(--dc-ink) 8%, transparent); border-radius: var(--dc-radius-pill); overflow: hidden; }
.dc-progress__fill { height: 100%; background: var(--dc-warn); }

/* ── Empty state ── */
.dc-empty { text-align: center; padding: 48px 24px; border: 1px dashed var(--dc-line-2); border-radius: var(--dc-radius); background: var(--dc-panel-2); color: var(--dc-muted); }
.dc-empty__icon { font-size: 30px; color: var(--dc-faint); }

/* micro-label utility */
.dc-label { font-size: 11px; font-weight: var(--dc-fw-bold); letter-spacing: var(--dc-track-label); text-transform: uppercase; color: var(--dc-faint); }

/* ═══════════════════════════════════════════════════════════════════════
   STREAMLINED INTAKE WIZARD COMPONENTS
   (per Import Drawer - streamlined.html reference in the design system)
   Used inside .dc-drawer__body for the merged draft / form_sent /
   form_received state of the Import Groups page. Values copied verbatim
   from the reference's inline <style> block.
   ═════════════════════════════════════════════════════════════════════ */

/* ── Task heading inside a drawer body (panel title) ── */
.task-h {
  font-size: 18px;
  font-weight: var(--dc-fw-bold);
  margin: 16px 0 16px;
  display: flex;
  align-items: center;
  gap: 7px;
}

/* ── Form file card — surfaces the batch's intake-form xlsx ── */
.form-card {
  display: flex; align-items: center; gap: 14px;
  border: 1px solid var(--dc-line-2);
  border-radius: var(--dc-radius);
  padding: 14px 16px;
  background: var(--dc-panel-2);
}
.form-card__icon {
  width: 42px; height: 42px; border-radius: 9px;
  background: var(--dc-ok-soft);
  color: color-mix(in oklch, var(--dc-ok) 55%, black);
  display: grid; place-items: center;
  font-size: 22px; flex: none;
}
:root[data-bs-theme="dark"] .form-card__icon {
  color: color-mix(in oklch, var(--dc-ok) 35%, white);
}
.form-card__name { font-weight: var(--dc-fw-semi); font-size: 14px; }
.form-card__meta {
  font-family: var(--dc-font-mono);
  font-size: 11.5px;
  color: var(--dc-muted);
  margin-top: 2px;
}
.form-card__actions { margin-left: auto; display: flex; gap: 8px; }

/* ── Audit timeline — vertical progression for the merged intake page ── */
.audit { margin-top: 18px; display: flex; flex-direction: column; gap: 0; }
.audit__step { display: flex; gap: 12px; }
.audit__rail {
  display: flex; flex-direction: column; align-items: center; flex: none;
}
.audit__dot {
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 13px; flex: none;
  border: 2px solid var(--dc-line-2);
  color: var(--dc-faint);
  background: var(--dc-panel);
}
.audit__line {
  width: 2px; flex: 1;
  background: var(--dc-line);
  min-height: 18px;
}
.audit__step:last-child .audit__line { display: none; }
.audit__body { padding-bottom: 18px; flex: 1; min-width: 0; }
.audit__title { font-weight: var(--dc-fw-semi); font-size: 14px; }
.audit__hint {
  color: var(--dc-muted); font-size: 12.5px;
  margin: 2px 0 9px;
}
.audit__step.done .audit__dot {
  border-color: var(--dc-ok);
  background: var(--dc-ok);
  color: var(--dc-panel);
}
.audit__step.done .audit__line { background: var(--dc-ok); }
.audit__step.active .audit__dot {
  border-color: var(--dc-primary);
  color: var(--dc-primary);
}
.audit__step.locked { opacity: 0.55; }

/* ── Stamp pill — green chip showing a completed audit timestamp ── */
.stamp {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: var(--dc-fw-semi);
  color: color-mix(in oklch, var(--dc-ok) 55%, black);
  background: var(--dc-ok-soft);
  border: 1px solid color-mix(in oklch, var(--dc-ok) 30%, white);
  border-radius: var(--dc-radius-pill);
  padding: 4px 11px;
  white-space: nowrap;
}
:root[data-bs-theme="dark"] .stamp {
  color: color-mix(in oklch, var(--dc-ok) 35%, white);
}

/* ── Drop zone — styled file-drop area for the audit timeline ── */
.dropzone {
  border: 1.5px dashed var(--dc-primary-line);
  border-radius: var(--dc-radius);
  background: color-mix(in oklch, var(--dc-primary) 3%, var(--dc-panel));
  padding: 14px 16px;
  display: flex; align-items: center; gap: 12px;
}
.dropzone__icon { font-size: 22px; color: var(--dc-primary); }
.dropzone__t { font-weight: var(--dc-fw-semi); font-size: 13.5px; }
.dropzone__s { color: var(--dc-muted); font-size: 12px; }

/* ═══════════════════════════════════════════════════════════════════════
   FILE INTAKE WIZARD — match & approve components
   (per File Intake Drawer - match and approve.html reference)
   ═════════════════════════════════════════════════════════════════════ */

/* ── Expecting-films mini list (.expect) — scan page ── */
.expect {
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius);
  overflow: hidden;
  margin: 12px 0 16px;
}
.expect__row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 12px; font-size: 13px;
}
.expect__row + .expect__row { border-top: 1px solid var(--dc-line); }
.expect__id {
  font-family: var(--dc-font-mono);
  font-size: 12px;
  color: var(--dc-muted);
}

/* ── Stat-pills row (.sumrow) — top of the approve panel ── */
.sumrow {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin: 4px 0 14px;
}

/* ── Matched film card (.fcard) ── */
.fcard {
  border: 1px solid var(--dc-line-2);
  border-radius: var(--dc-radius);
  margin-bottom: 12px;
  overflow: hidden;
  background: var(--dc-panel);
}
.fcard.is-approved {
  border-color: color-mix(in oklch, var(--dc-ok) 45%, white);
  box-shadow: inset 3px 0 0 var(--dc-ok);
}
:root[data-bs-theme="dark"] .fcard.is-approved {
  border-color: color-mix(in oklch, var(--dc-ok) 45%, black);
}
/* Approved = locked: asset-tag selects become plain static text */
.fcard.is-approved .filerow__tags .form-select {
  border: none; background: transparent; background-image: none;
  -webkit-appearance: none; appearance: none;
  padding: 2px 4px 2px 0; min-width: 0; width: auto;
  pointer-events: none;
  color: var(--dc-ink); font-weight: var(--dc-fw-semi);
}

.fcard__head {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px;
  background: var(--dc-panel-2);
  border-bottom: 1px solid var(--dc-line);
  flex-wrap: wrap;
  cursor: pointer;
  transition: background var(--dc-dur-fast) var(--dc-ease);
}
.fcard__head:hover {
  background: color-mix(in oklch, var(--dc-ink) 5%, var(--dc-panel-2));
}
.fcard__title { font-weight: var(--dc-fw-semi); }
.fcard__title code { color: var(--dc-primary); }

/* Right cluster wrapper: file-count badge + Open folder + chevron. */
.fcard__right {
  margin-left: auto;
  display: flex; align-items: center; gap: 10px;
}
.fcard__count {
  font-family: var(--dc-font-mono);
  font-size: 11.5px;
  color: var(--dc-faint);
  white-space: nowrap;
}
.fcard__chev {
  color: var(--dc-faint);
  font-size: 12px;
  transition: transform var(--dc-dur) var(--dc-ease);
}

/* Collapse: hide all .filerow children + de-emphasise the head's
 * bottom border so the card reads as a flat line. The file-count
 * badge only renders when collapsed (hidden when open). */
.fcard.is-collapsed .fcard__head { border-bottom: none; }
.fcard.is-collapsed .fcard__chev { transform: rotate(-90deg); }
.fcard.is-collapsed .filerow { display: none; }
.fcard:not(.is-collapsed) .fcard__count { display: none; }

/* ── Approve / Skip checkbox pair inside .fcard__head ── */
.approve-toggles { display: flex; gap: 12px; }
.approve-toggles label {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px;
  color: var(--dc-muted);
  cursor: pointer;
  white-space: nowrap;
}

/* ── File row inside a .fcard (one per matched asset) ── */
.filerow {
  display: flex; gap: 11px;
  align-items: flex-start;
  padding: 10px 14px;
}
.filerow + .filerow { border-top: 1px solid var(--dc-line); }
.filerow__ic {
  font-size: 16px;
  color: var(--dc-faint);
  margin-top: 1px;
  flex: none;
}
.filerow__main { flex: 1; min-width: 0; }
.filerow__name {
  font-weight: var(--dc-fw-medium);
  font-size: 13.5px;
  word-break: break-word;
}
.filerow__name small {
  color: var(--dc-faint);
  font-weight: var(--dc-fw-normal);
  margin-left: 6px;
}
.filerow__spec {
  font-family: var(--dc-font-mono);
  font-size: 11px;
  color: var(--dc-muted);
  margin-top: 3px;
}
/* Batch-relative path (operator feedback 2026-06-10) — sits below the
 * ffprobe spec at a smaller / fainter weight so it reads as breadcrumb
 * context rather than identification. */
.filerow__path {
  font-family: var(--dc-font-mono);
  font-size: 10.5px;
  color: var(--dc-faint);
  margin-top: 2px;
  word-break: break-all;
}
/* Compact icon-only remove button on each filerow's right cluster. */
.filerow__remove {
  padding: 4px 7px;
  line-height: 1;
  flex: none;
}
.filerow__remove:hover {
  color: var(--dc-danger);
  border-color: color-mix(in oklch, var(--dc-danger) 50%, var(--dc-line-2));
}
.filerow__tags {
  display: flex; gap: 6px;
  flex: none;
  align-items: flex-start;
}
.filerow__tags .form-select {
  font-size: 12px;
  height: 31px;
  width: auto;
  min-width: 120px;
  padding: 2px 26px 2px 9px;
}

/* ── Unmatched section header (.unmatched-h) ── */
.unmatched-h {
  display: flex; align-items: center; gap: 8px;
  margin: 22px 0 10px;
}
.unmatched-h .dc-label {
  margin: 0;
  color: color-mix(in oklch, var(--dc-warn) 55%, black);
}
:root[data-bs-theme="dark"] .unmatched-h .dc-label {
  color: color-mix(in oklch, var(--dc-warn) 40%, white);
}
.unmatched-h__line {
  flex: 1; height: 1px;
  background: var(--dc-line);
}

/* ── Unmatched-folder group (.ugroup) ── */
.ugroup { margin-top: 12px; }
.ufolder {
  background: var(--dc-warn-soft);
  border: 1px solid color-mix(in oklch, var(--dc-warn) 28%, white);
  border-radius: var(--dc-radius);
  padding: 9px 12px;
  display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap;
}
:root[data-bs-theme="dark"] .ufolder {
  border-color: color-mix(in oklch, var(--dc-warn) 28%, black);
}
.ufolder__name {
  font-family: var(--dc-font-mono);
  font-size: 12.5px;
  font-weight: var(--dc-fw-semi);
}
.ufolder__assign {
  margin-left: auto;
  display: flex; align-items: center; gap: 8px;
  font-size: 12px;
  color: var(--dc-muted);
}
.ufolder .form-select,
.urow .form-select {
  font-size: 12px;
  height: 31px;
  width: auto;
  min-width: 150px;
  padding: 2px 26px 2px 9px;
}
.ugroup__children {
  margin-left: 19px;
  border-left: 2px solid color-mix(in oklch, var(--dc-warn) 40%, var(--dc-line));
}

.urow {
  position: relative;
  display: flex; gap: 11px;
  align-items: flex-start;
  padding: 10px 12px 10px 20px;
}
.urow::before {
  content: ""; position: absolute;
  left: 0; top: 21px;
  width: 13px; height: 2px;
  background: color-mix(in oklch, var(--dc-warn) 40%, var(--dc-line));
}
.urow + .urow { border-top: 1px solid var(--dc-line); }
.urow__ic {
  color: var(--dc-warn);
  font-size: 15px;
  margin-top: 1px;
  flex: none;
}
.urow__main { flex: 1; min-width: 0; }
.urow__name {
  font-weight: var(--dc-fw-medium);
  font-size: 13.5px;
  word-break: break-word;
}
.urow__name small {
  color: var(--dc-faint);
  font-weight: var(--dc-fw-normal);
  margin-left: 6px;
}
.urow__closest {
  font-size: 11.5px;
  color: var(--dc-muted);
  margin-top: 3px;
}

/* ═══════════════════════════════════════════════════════════════════════
   CONTAINER QUERY RULES — Phase 1 (drag-to-resize responsiveness)
   Container declared on .dc-drawer__body above. Rules below fire
   based on the drawer's WIDTH (not viewport), so the layouts reshuffle
   as the operator drags the Split.js gutter. Pure CSS, no JS, no reload.
   ═════════════════════════════════════════════════════════════════════ */

/* ── Narrow-ish (<= 480px): collapse 2-col grids to 1-col ──
   At this width side-by-side KV / actions rows wrap awkwardly. Stack. */
@container drawer (max-width: 480px) {

  /* Form card (intake form info row) — actions wrap below name/meta */
  .form-card {
    flex-wrap: wrap;
  }
  .form-card__actions {
    margin-left: 0;
    width: 100%;
    margin-top: 4px;
    justify-content: flex-end;
  }
}

/* ── Narrow (<= 460px): file/unmatched rows wrap their tag column ──
   Asset selects / film-assign dropdowns fall below the file name. */
@container drawer (max-width: 460px) {
  .filerow,
  .urow {
    flex-wrap: wrap;
  }
  .filerow .filerow__tags,
  .urow .filerow__tags {
    margin-left: 0;
    width: 100%;
    margin-top: 6px;
  }
  /* Unmatched folder header — assign block + Open button drop below
     the folder name/count. */
  .ufolder {
    flex-wrap: wrap;
  }
  .ufolder__assign {
    margin-left: 0;
    width: 100%;
    margin-top: 6px;
    justify-content: flex-end;
  }
}

/* ── Very narrow (<= 360px): drawer head stacks ──
   Last-resort tier so the title doesn't get squeezed under the poster. */
@container drawer (max-width: 360px) {
}
