/* ────────────────────────────────────────────────────────────────────────
 * dc-table.css — dc_table (Tabulator 6.5) theme override layer.
 *
 * Skins Tabulator's base tabulator.min.css (vendor/) onto the dc-* design
 * tokens (--dc-*). Loaded AFTER vendor/tabulator.min.css so these rules
 * win the cascade. Dark mode follows the same `[data-bs-theme="dark"]`
 * attribute every other dc-* stylesheet in this app keys off (see
 * dc-theme.css) — the tokens themselves flip value under that selector,
 * so almost nothing here needs a dark-specific override.
 *
 * Typography rule (design system): cap font-weight at 600, hierarchy via
 * colour / size / caps-tracking — never anything above 600 in this file.
 * ──────────────────────────────────────────────────────────────────────── */

/* Tabulator adds its own `.tabulator` class directly onto THIS SAME div
   (`<div id="..." class="dc-table-output shiny-bound-output tabulator">`),
   not onto a nested child — so every rule below is `.dc-table-output
   .tabulator-X`, never `.dc-table-output .tabulator .tabulator-X`. A
   descendant selector with that redundant middle `.tabulator` segment
   matches nothing (bug caught in review 2026-07-13: the theme layer wasn't
   applying at all — vendor grey tableholder, 14px non-uppercase headers).
   Root-level Tabulator chrome (background/border/font) is folded into the
   base `.dc-table-output` rule below for the same reason. */
.dc-table-output {
  flex: 1 1 auto;
  min-height: 0;
  height: 100%;
  overflow: hidden;
  background: transparent;
  border: none;
  font-family: var(--dc-font-sans);
  font-size: 13px;
  color: var(--dc-ink);
}

/* ── Header ─────────────────────────────────────────────────────────── */

/* panel-2 header band (was panel) — .ig-films-table spec, 2026-07-21
   Library migration: `thead th { background: var(--dc-panel-2) }`. */
/* Option B (operator 2026-11-02): two tones — the top strip is --dc-panel-2,
   the header row a shade off it (4% ink mix of the same colour, so it follows
   light and dark alike). */
:root { --dc-hdr-bg: color-mix(in oklch, var(--dc-panel-2) 96%, var(--dc-ink)); }
.dc-table-output .tabulator-header {
  background: var(--dc-hdr-bg);
  border-bottom: 1px solid var(--dc-line);
}

.dc-table-output .tabulator-header .tabulator-col {
  background: var(--dc-hdr-bg);
  border-right: none;
}

/* ── Single-row headers (2026-07-13 operator feedback, round 2 + round 3) ──
   Tabulator stacks the column title above the header filter by default —
   two rows per header. Every filtered column here carries its name on the
   filter control itself instead (an `input`'s placeholder, or a
   dcMultiSelectPicker button's label — see pages/library.py column defs
   + the `dcMultiSelectPicker` widget in this file's JS twin), so the
   title text is redundant there.
   Round 3 fix: the flex-row layout below used to be scoped to
   `:has(.tabulator-header-filter)` only, so an unfiltered column (Runtime)
   kept the vendor's default stacked layout with DIFFERENT padding —
   its title sat at a different vertical position than every other
   column's label, and used a different font-weight (700, over the
   design system's 600 cap). Applying the row layout + ONE shared label
   typography to every column (not just filtered ones) puts every header
   label — static title, input placeholder, or picker button label — on
   the same row, same baseline, same font. */
/* NOTE the 4-class selector. Vendor tabulator.min.css ships
   `.tabulator .tabulator-header .tabulator-col .tabulator-col-content
   { padding: 4px }` — four class steps. The 2-step selector this rule used
   to carry lost on specificity, so its `padding: 0 8px` never applied and
   every header cell sat at the vendor's 4px: the check column's box landed
   4px from the rail edge while the search box below it sat at 8px, and the
   sort arrows inherited the same inconsistency (operator 2026-08-10: "check
   box same margin left as search bar and platform dropdown ... title and
   relaese label and arrow should have consistent padding"). Matching the
   vendor's specificity and loading after it is what makes this win. */
.dc-table-output .tabulator-header .tabulator-col .tabulator-col-content {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 8px;
  /* exactly one 34px grid row — view-bar (34) + this header (34) = 68,
     the same y where the sidebar's first nav band and the drawer's chrome
     end, so the first horizontal line connects across the whole console
     (full-screen composite, 2026-07-20). 33px content + the header's 1px
     border-bottom = 34 total (verified via getBoundingClientRect — a plain
     34px here measured 35 and drifted every row 1px off the sidebar bands).
     Was 32px min + 5px v-padding. */
  /* Option B: --hdr-h (34px) less the header's 1px border-bottom. */
  min-height: calc(var(--hdr-h) - 1px);
  box-sizing: border-box;
}

.dc-table-output .tabulator-col-title-holder {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}

/* Shared header-label typography — the ONE style every header-row label
   uses, whichever control carries it (static title text, an `input`'s
   placeholder, or a dcMultiSelectPicker button's label). Design system
   typography rule: cap font-weight at 600 (was 700 pre-round-3 on both
   the title and the picker label — fixed here). */
.dc-table-output .tabulator-col-title,
.dc-table-output .tabulator-header-filter input::placeholder,
.dc-hf-btn__lbl {
  font-family: var(--dc-font-sans);
  /* 10.5px / 0.08em tracking per the .ig-films-table header spec
     (2026-07-21; was 10px / 0.06em). Weight stays 600 — the spec's 700
     exceeds this file's design-system cap (operator feedback, round 3). */
  /* Option B (2026-11-02): the top strip's label — 11px / 500 / sentence
     case / no tracking (was 10.5px uppercase, 0.08em). */
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
  /* NOT BOLD (operator 2026-08-31: "theyre all bold I dont like bold outside
     of film titles"). Was 600. A column name is a label, and the row content
     under it is the thing worth reading — 600 across a twelve-column header
     put the loudest type on the page furthest from the point.
     `--dc-muted` rather than `--dc-faint` to buy back the legibility the
     weight was carrying at 10.5px. */
  font-weight: var(--dc-fw-medium);
  color: var(--dc-muted);
  white-space: nowrap;
}
/* A bare title (no pill) lines up with the pill labels: pill border 1px +
   the strip's 14px side padding. */
.dc-table-output .tabulator-col:not(:has(.tabulator-header-filter)) .tabulator-col-title {
  padding-left: calc(var(--dc-pill-px) + 1px);
}

/* Round 9 (operator feedback, "remove hover on column headers"): headers
   must stay visually inert on plain mouse-over — no background reveal.
   `cursor: pointer` stays (it's a functional affordance, not visual
   chrome — the column is still click-to-sort).

   Round 11 (operator re-test): the background reveal SURVIVED on the four
   sortable columns (Film/Year/Director/Runtime) despite round 9's fix,
   because it isn't ours — vendor/tabulator.min.css ships its own hover
   rule, `.tabulator .tabulator-header .tabulator-col.tabulator-sortable
   .tabulator-col-sorter-element:hover{background-color:#cdcdcd}`, gated to
   sortable columns via a THIRD class (`tabulator-col-sorter-element`,
   added by Tabulator's own JS to every sortable column — confirmed live via
   DOM inspection) that this file's override never matched. That vendor
   selector chains 6 class/pseudo-class steps
   (.tabulator .tabulator-header .tabulator-col .tabulator-sortable
   .tabulator-col-sorter-element :hover) — equal specificity to the 6-step
   selector below (`.tabulator` and `.tabulator-header` are real ancestors
   of `.tabulator-col` here, same as in the vendor rule; `.dc-table-output`
   IS the `.tabulator` element per the note atop this file), so this
   override wins purely on source order (loaded after vendor CSS). The
   generic 4-step `.dc-table-output .tabulator-col.tabulator-sortable:hover`
   selector above is LOWER specificity than the vendor's 6-step one and
   never set a background anyway, so it never neutralized this — kept only
   for the `cursor: pointer` declaration on any future sortable column that
   doesn't carry `tabulator-col-sorter-element`. */
.dc-table-output .tabulator-col.tabulator-sortable:hover {
  cursor: pointer;
}
.dc-table-output .tabulator-header
  .tabulator-col.tabulator-sortable.tabulator-col-sorter-element:hover {
  background: var(--dc-hdr-bg);   /* option B: headers stay inert on hover */
  cursor: pointer;
}

/* Option B (operator 2026-11-02): NO sort triangles anywhere — "we have them
   within the pills already". Sorting lives in the pill (a "Sort ascending /
   descending" menu, dc-table.js `_dcSortAttach`); a bare title still sorts on
   click. The sorted column shows a small ↑ / ↓ (see `.dc-sort-ind` below). */
.dc-table-output .tabulator-col-sorter {
  display: none !important;
}
.dc-table-output .tabulator-col-content:has(.tabulator-header-filter)
  .tabulator-col-title-holder {
  display: none !important;
}
/* The sorted-direction mark. Plain column: after the title. Pill column: a
   child of `.tabulator-header-filter`, so it sits inside the pill's right end
   (before the chevron). */
.dc-table-output .tabulator-col-title::after {
  font-weight: var(--dc-fw-medium);
  margin-left: 6px;
  color: var(--dc-ink);
}
.dc-table-output .tabulator-col[aria-sort="ascending"] .tabulator-col-title::after { content: "\2191"; }
.dc-table-output .tabulator-col[aria-sort="descending"] .tabulator-col-title::after { content: "\2193"; }

/* Consistent label-left / arrow-right across every sortable header cell
   (operator 2026-08-10: "title and relaese label and arrow should have
   consistent padding").

   The two kinds of header cell were laid out differently and it showed:
   a FILTERED column (Title) renders as [filter input, flex:1][sorter], so
   its arrow lands at the column's right edge; an UNFILTERED column
   (Release) renders as [title-holder, flex:0 0 auto] with the sorter
   absolutely positioned INSIDE that holder — so its arrow sat wherever the
   title text happened to end (measured 12px vs 27px from their respective
   column edges). Letting the unfiltered holder grow puts its absolute
   sorter on the same right edge, so both read the same. */
.dc-table-output .tabulator-header
  .tabulator-col:not(:has(.tabulator-header-filter)) .tabulator-col-title-holder {
  flex: 1 1 auto;
  min-width: 0;
}

.dc-table-output .tabulator-col-content:has(.tabulator-header-filter)
  .tabulator-col-title {
  display: none;
}
.dc-table-output .tabulator-col-content:has(.tabulator-header-filter)
  .tabulator-header-filter {
  flex: 1 1 auto;
  min-width: 0;
  padding-top: 0;
  margin: 0;

}

/* Column resize handle — stays invisible even on hover (round 9, "headers
   inert on mouse-over"); the drag zone is still there and still functional
   (vendor CSS gives it `cursor: ew-resize` on its own :hover), just without
   the colour reveal that used to fire on hovering anywhere in the header. */
.dc-table-output .tabulator-col-resize-handle {
  background: transparent;
}

/* Column show/hide + any other header menu popup */
.dc-table-output .tabulator-header-popup-button {
  color: var(--dc-muted);
}
.dc-table-output .tabulator-header-popup-button:hover {
  color: var(--dc-ink);
}

/* ── Header filters (Tabulator's built-in per-column filter row) ─────────
   Rendered inside the same header cell, in the single-row layout above.
   The TYPED value stays normal-case/readable (this rule); the EMPTY-state
   placeholder gets the shared header-label typography instead (see the
   `::placeholder` selector folded into the shared rule above) — same
   height (22px) and vertical centring as the dcMultiSelectPicker buttons
   so every header control's label lands on the same baseline.

   Round 6 (operator feedback, "header visual consistency"): every column
   header must read as ONE system — same flat/quiet chrome as the mockup's
   plain `<th>` (claude-design/skills/dc-skill/dc-library.html has no box
   around its header text at all), with the filter TYPE as the only
   differentiator (this input's placeholder text vs the picker button's
   icon+label vs Runtime's bare sort arrow — see `.dc-hf-btn` below for the
   picker half of this pair). The input/select box itself is transparent by
   default (matches Runtime's chrome-less label) and only takes on
   form-control styling (background + border) on focus, or once it actually
   holds a typed value — `:not(:placeholder-shown)` is a CSS-only way to
   detect "this column has an active filter" without any JS change,
   mirroring the picker button's persistent `.on` state below.

   Round 9 (operator feedback, "remove hover on headers"): dropped the
   :hover rule that used to reveal this same chrome on mouse-over — headers
   now only pick up visible chrome on FOCUS (typing needs the affordance)
   or once a value/selection is actually active, never on a passing
   mouse-over. */
.dc-table-output .tabulator-header-filter {
  padding-top: 0;
  display: flex;
  align-items: center;
}
.dc-table-output .tabulator-header-filter input,
.dc-table-output .tabulator-header-filter select {
  width: 100%;
  height: var(--hdr-ctl-h);
  line-height: 1;
  font-size: 11px;
  font-weight: var(--dc-fw-medium);
  text-transform: none;
  letter-spacing: normal;
  color: var(--dc-ink);
  background: transparent;
  border: 1px solid transparent;
  /* ROUNDED 2026-08-31 (operator: "the inputs are still boxy no rounded
     corners"). Round 12 squared these on the reasoning that the whole
     header/popover system is flush — but that rule is about the SHELL, and
     the editing register (anything you type into) was rounded the same day
     across the modals and the drawer. `--dc-radius-sm`, not `--dc-radius`:
     these are 22px in-table controls, which is exactly what the sm token is
     documented for. The popover PANEL stays square — it is chrome that
     floats, not a control. */
  border-radius: var(--dc-radius-sm);
  padding: 0 var(--dc-pill-px);   /* the strip pill's side padding (option B, 2026-11-02) */
  box-sizing: border-box;
  transition: background 120ms ease, border-color 120ms ease;
}
.dc-table-output .tabulator-header-filter input:focus,
.dc-table-output .tabulator-header-filter select:focus {
  outline: none;
  border-color: var(--dc-primary);
  background: var(--dc-panel);
}
/* Option B (operator 2026-11-02): every header pill FILLED with the top
   strip's colour and a quiet outline, empty or holding a value — like a
   search box that holds "Berlin". Focus keeps the primary ring. */
.dc-table-output .tabulator-header-filter input:not(:focus),
.dc-table-output .tabulator-header-filter input:placeholder-shown:not(:focus),
.dc-table-output .tabulator-header-filter select:not(:focus) {
  background: var(--dc-panel-2);
  border-color: var(--dc-line-2);
}

/* Header cue (2026-11-02, operator: "you can't tell if a column header is
   searchable or a dropdown" — then "we use icons already for categories",
   so no magnifier). A usable header wears a quiet outline; a plain column
   is bare text. The outline spans the column, less the sort arrow
   (operator, same day: "as wide as the column itself minus the arrow").
   A dropdown is outlined label + category icon + chevron at the right end;
   a search box is the outlined label alone. */
.dc-table-output .tabulator-header-filter .dc-hf-btn {
  width: 100%;
  min-width: 0;
}
.dc-table-output .tabulator-header-filter .dc-hf-btn__chev {
  margin-left: auto;
}
/* A narrow column shortens the label with "…" rather than pushing the
   chevron out of the outline. */
.dc-table-output .tabulator-header-filter .dc-hf-btn { overflow: hidden; }
.dc-table-output .tabulator-header-filter .dc-hf-btn__lbl {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dc-table-output .tabulator-header-filter .dc-hf-btn > i { flex: none; }
.dc-hf-btn > i:not(.dc-hf-btn__chev) { font-size: 11px; }

/* ── Custom header-filter picker widget (dc-table.js
   DC_TABLE_HEADER_FILTERS) — a small trigger button in the header cell +
   a checklist popover positioned via fixed coordinates (see dc-table.js
   dcMultiSelectPicker). Generic naming (.dc-hf-*) — not Library/Festivals
   specific; every enumerable column (Genre/Country/Tags/Festivals) reuses
   this one widget (generalized 2026-07-13, operator feedback) instead of
   Tabulator's native "list" header filter, so `.tabulator-edit-list*`
   (the vendor multiselect popup) is unused now — removed rather than left
   as dead CSS. */
/* Round 6: flat by default (no border/background), matching the header
   text-input's chrome-less default above — the SAME one-system treatment,
   the icon+label is the only thing that differentiates a picker column
   from a text-search column. Chrome (border+background) only appears
   persistently once a selection is active (`.on`) — round 9 dropped the
   :hover reveal that used to also show it on mouse-over (operator
   feedback: headers must stay visually inert on plain hover). The
   popover-open state doesn't need its own rule here: the button's `.on`
   class already tracks "has an active selection" independently of
   hover/open, which is the state this rule needs to survive. */
.dc-hf-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--dc-line-2);
  background: var(--dc-panel-2);   /* filled whether empty or on (option B) */
  /* Rounded 2026-08-31 with the text-filter input above — this button is the
     picker-column equivalent of that input, same one-system treatment. */
  border-radius: var(--dc-radius-sm);
  padding: 0 var(--dc-pill-px);
  height: var(--hdr-ctl-h);
  box-sizing: border-box;
  cursor: pointer;
  color: var(--dc-muted);
  line-height: 1;
  white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease;
}
/* Active picker (2026-11-02, operator: "we don't need the blue outline and
   the badge with the counter"): no blue, no count — the outline darkens
   and the label goes to full ink, the same quiet step a typed search box
   takes. */
.dc-hf-btn.on {
  border-color: var(--dc-muted);
  background: var(--dc-panel-2);
}
.dc-hf-btn.on .dc-hf-btn__lbl { color: var(--dc-ink); }
.dc-hf-btn__cnt { display: none; }
/* .dc-hf-btn__lbl's font-size/weight/case/tracking/color come from the
   shared header-label rule above (same declaration as .tabulator-col-title
   and the header-filter input placeholder) — this button carries the
   column's name exactly like a filter input's placeholder does, so it
   must look identical, not a separate one-off style. */
.dc-hf-btn__cnt {
  background: var(--dc-primary);
  color: #fff;
  border-radius: 999px;
  font-size: 10px;
  padding: 0 5px;
  /* 600, not 700 — this file's documented cap. It keeps some weight because
     it is 10px reversed out of a filled pill, where 400 stops being legible. */
  font-weight: 600;
  line-height: 15px;
}
/* Round 9 (operator feedback): a dropdown affordance chevron, trailing the
   label (after the count badge, if any — always the last element so it
   reads as a fixed "this opens a picker" cue regardless of selection
   state). Sized/coloured to match `.tabulator-col-sorter`'s sort arrow
   (var(--dc-faint), a few px tall) rather than inheriting `.dc-hf-btn`'s
   own --dc-muted or the `.on` state's --dc-primary — this is a static
   affordance icon, not a value that should shift with selection state,
   same as the sort arrow never changes colour just because a filter is
   active on a sortable column. */
.dc-hf-btn__chev {
  /* 2026-11-02 (operator: "you can't tell if a column header is searchable
     or a dropdown"): 9px faint → 10px muted, so the chevron reads as
     "this opens a list" at a glance (kept muted, back to 9px). */
  font-size: 10px;
  color: var(--dc-muted);
  margin-left: auto;
}

/* Round 10 (operator feedback): flush against the header column, same
   flush language as the sidebar/view-switcher — no border-radius, and the
   popover's top edge meets the header row's bottom edge directly (see the
   JS positioning in DC_TABLE_HEADER_FILTERS.dcMultiSelectPicker, which
   used to add a 4px gap before `r.bottom` and no longer does). Left edge
   stays aligned to the column (unchanged from an earlier round). */
.dc-hf-pop {
  z-index: 4000;
  background: var(--dc-panel);
  border: 1px solid var(--dc-line);
  border-radius: 0;
  box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.35);
  padding: 6px;
  width: 240px;
}
/* Search box (operator feedback, round 8) — top of every dcMultiSelectPicker
   popover (Genre/Country/Tags/Festivals share this one component, so this
   styles all four at once). Same visual language as the header-filter
   input/picker-button chrome: quiet border, dc tokens, focus ring in
   --dc-primary — but ALWAYS has its chrome visible (unlike the flat-until-
   active header controls) since this is inside an already-open popover,
   not sitting in the quiet header row. */
.dc-hf-pop__search {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--dc-line-2);
  /* Rounded 2026-08-31 with the header inputs — it is a control you type
     into. The popover it sits in stays square: that is chrome that floats. */
  border-radius: var(--dc-radius-sm);
  background: var(--dc-panel-2);
  padding: 5px 8px;
  margin-bottom: 6px;
}
.dc-hf-pop__search:focus-within {
  border-color: var(--dc-primary);
  background: var(--dc-panel);
}
.dc-hf-pop__search i {
  font-size: 12px;
  color: var(--dc-faint);
  flex: none;
}
.dc-hf-pop__search-input {
  flex: 1 1 auto;
  min-width: 0;
  border: none;
  background: none;
  outline: none;
  font-size: 12px;
  font-weight: 400;
  color: var(--dc-ink);
  padding: 0;
}
.dc-hf-pop__search-input::placeholder { color: var(--dc-faint); }
.dc-hf-pop__nomatch {
  padding: 10px 6px;
  text-align: center;
  font-size: 12px;
  color: var(--dc-muted);
}
.dc-hf-pop__list { max-height: 220px; overflow-y: auto; }
.dc-hf-check {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 6px;
  border-radius: var(--dc-radius-sm, 5px);
  font-size: 12px;
  cursor: pointer;
  color: var(--dc-ink);
}
.dc-hf-check:hover { background: var(--dc-panel-2); }
.dc-hf-check__box {
  width: 14px;
  height: 14px;
  border: 1.5px solid var(--dc-line-2);
  border-radius: 4px;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 9px;
  flex-shrink: 0;
}
.dc-hf-check.on .dc-hf-check__box { background: var(--dc-primary); border-color: var(--dc-primary); }
.dc-hf-check__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dc-hf-check__count { font-size: 11px; color: var(--dc-faint); flex-shrink: 0; }
.dc-hf-pop__foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--dc-line);
  font-size: 11px;
  color: var(--dc-muted);
}
.dc-hf-pop__hint { font-size: 11px; color: var(--dc-muted); }
.dc-hf-pop__link {
  color: var(--dc-primary);
  cursor: pointer;
  background: none;
  border: none;
  font-size: 12px;
  font-weight: 600;
  padding: 0;
}
.dc-hf-pop__link:hover { text-decoration: underline; }

/* Range popover (dcRangePicker, 2026-11-02) -- From / To side by side, the
   same bordered-input look as the picker's search box. */
.dc-hf-pop--range { width: 232px; }
.dc-hf-range { display: flex; gap: 8px; }
.dc-hf-range__field { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 3px; margin: 0; }
.dc-hf-range__cap {
  font-size: 10.5px; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--dc-muted); font-weight: 400;
}
.dc-hf-range__input {
  width: 100%; min-width: 0; box-sizing: border-box;
  border: 1px solid var(--dc-line-2); border-radius: var(--dc-radius-sm);
  background: var(--dc-panel-2); color: var(--dc-ink);
  font-size: 12px; padding: 5px 7px; outline: none;
}
.dc-hf-range__input:focus { border-color: var(--dc-primary); background: var(--dc-panel); }
.dc-hf-range__input::placeholder { color: var(--dc-faint); }
.dc-hf-pop--range .dc-hf-pop__foot { margin-top: 8px; }

/* ── Body / rows / cells ────────────────────────────────────────────── */

.dc-table-output .tabulator-tableholder {
  background: transparent;
}

/* Vendor's base CSS sets color/background directly on `.tabulator-table`
   via `.tabulator .tabulator-tableholder .tabulator-table` — a 3-class
   selector. `.tabulator` is the SAME element as `.dc-table-output` (see
   the note atop this file), so a single-class `.dc-table-output { color }`
   loses to that 3-class vendor rule regardless of load order: found live
   in dark-mode verification (2026-07-13 review fix) as near-invisible
   (#333) cell text over a stray white table background. Match the vendor
   selector's shape 1:1 (swap `.tabulator` → `.dc-table-output`, same
   specificity) so the later-loaded override actually wins. */
.dc-table-output .tabulator-tableholder .tabulator-table {
  background-color: transparent;
  color: var(--dc-ink);
}

.dc-table-output .tabulator-row {
  background: var(--dc-panel);
  border-bottom: 1px solid var(--dc-line);
  cursor: pointer;
}

.dc-table-output .tabulator-row.tabulator-row-even {
  background: var(--dc-panel);
}

.dc-table-output .tabulator-row:hover {
  background: color-mix(in srgb, var(--dc-panel-2) 80%, transparent);
}

.dc-table-output .tabulator-row.is-sel {
  background: var(--dc-primary-soft) !important;
}

/* Scheduling bulk-selection highlight (checkbox path, managed by _dcSchedSelSet) */
.dc-table-output .tabulator-row.is-selected {
  background: var(--dc-primary-soft) !important;
}

/* ── `.dc-table--gallery` — the taller, content-driven row ────────────────
   Opt-in modifier on `.dc-table-output`. Rows size to their content instead
   of the dense 34px grid below, which is what a poster column and a stacked
   title/original-title cell need.

   Introduced on the Curation page (2026-08-24/25, scoped `.cur-page`),
   generalised here on 2026-08-26 when the operator asked for the Library
   catalogue to match it. Two pages sharing a row/cell rule makes it table
   styling, not page styling.

   THE CAVEAT, carried over verbatim because it is still real: Tabulator's
   vertical virtual DOM is happiest with uniform rows. It measures variable
   ones, but scroll behaviour wants checking at LENGTH. Verified clean at 34
   rows; re-check when a batch that size lands, and if it jitters the
   fallback is a fixed height at the 72px worst case rather than reverting
   to 34.

   NO `display:flex` on the cells. An earlier version set it to stretch them,
   and it worked visually while quietly changing the row's hit area —
   Tabulator lays its own cells out, and overriding that left a strip of row
   that looked clickable and was not. The cells already stretch via their own
   `align-items`, so the row only needs a floor. */
/* Row size (operator 2026-10-29): Compact · Comfortable · Large, picked
   with the button in the poster column's header (dc-table.js
   `dcRowSize`), remembered per browser, set as `data-dc-row-size` on
   <html>. THE PIXEL VALUES LIVE HERE ONLY — the script reads the poster
   width back from `--dc-gallery-poster-w`. Rows are a floor, not a cap:
   a row whose pills wrap still grows. Poster width ≈ (row − 1) × 2/3. */
:root {
  --dc-gallery-row-h: 48px;
  --dc-gallery-poster-w: 38px;
}
:root[data-dc-row-size="comfortable"] {
  --dc-gallery-row-h: 72px;
  --dc-gallery-poster-w: 48px;
}
:root[data-dc-row-size="large"] {
  --dc-gallery-row-h: 104px;
  --dc-gallery-poster-w: 69px;
}

.dc-table-output.dc-table--gallery .tabulator-cell {
  height: auto;
  min-height: calc(var(--dc-gallery-row-h) - 1px);
  white-space: normal;      /* the pills need to wrap; at 34px they could not */
  padding-top: 6px;
  padding-bottom: 6px;
  align-items: center;
}
.dc-table-output.dc-table--gallery .tabulator-row { min-height: var(--dc-gallery-row-h); }
.dc-table-output.dc-table--gallery .film-cell { align-items: center; }
.dc-table-output.dc-table--gallery .tags { row-gap: 2px; }
/* The poster fills the row's full height. Inside the film cell it floated
   against a two- or three-line cell instead of filling it, which is why it
   moved out into its own column (operator 2026-08-24). */
.dc-table-output.dc-table--gallery .tabulator-cell.cur-poster-col {
  padding: 0;
  align-items: stretch;
}
/* The row-size button in the poster column's header. */
.dc-table-output .dc-rowsize {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border: 0; border-radius: 4px;
  background: transparent; color: var(--dc-muted); cursor: pointer;
  font-size: 13px;
}
.dc-table-output .dc-rowsize:hover { background: var(--dc-panel-2); color: var(--dc-ink); }

/* Dense 34px rows (.ig-films-table spec, 2026-07-21 Library migration):
   cell height 33px + the row's 1px border-bottom = one 34px grid row, so
   table rows stay in phase with the sidebar bands and drawer sections.
   inline-flex centres single-line content vertically (the vendor cell is
   inline-block + padding-sized, which drifts with content height). */
.dc-table-output .tabulator-cell {
  height: 33px;
  /* 8px, matching the header cell's own inner padding (see the 4-class
     `.tabulator-col-content` rule above). They were 10 vs 4, so a column's
     header content and its body content never sat on the same x — most
     visibly the check column, whose header box and row boxes were 8px
     apart. Operator 2026-08-10: "check, title and status consistant
     spacing". */
  padding: 0 8px;
  border-right: none;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  overflow: hidden;
  box-sizing: border-box;
  font-size: 13px;
  color: var(--dc-muted);   /* quiet row content — the title carries the ink */
}

/* Selection strip on the FIRST cell (Library has no checkbox column —
   gx-nocheck variant of the .ig-films-table spec): a 4px state edge that
   fills with primary on the click-selected row. Padding drops 10 → 8 so
   content keeps its visual left position. `.is-selected` (Scheduling's
   checkbox bulk path) intentionally NOT included — its strip belongs on
   the cell after the checkbox and is that page's migration, not this one. */
.dc-table-output .tabulator-cell:first-child {
  border-left: 4px solid transparent;
  padding-left: 8px;
}
.dc-table-output .tabulator-row.is-sel .tabulator-cell:first-child {
  border-left-color: var(--dc-primary);
}

/* Row state edges (IMPORT_GROUPS.md §11) — rows carrying `_rowClass` in
   their data get these via dc-table.js's rowFormatter. Selection (.is-sel)
   wins via source order below. */
.dc-table-output .tabulator-row.row-locked   .tabulator-cell:first-child { border-left-color: var(--dc-edge-locked); }
.dc-table-output .tabulator-row.row-decision .tabulator-cell:first-child { border-left-color: var(--dc-edge-decision); }
.dc-table-output .tabulator-row.row-running  .tabulator-cell:first-child { border-left-color: var(--dc-edge-running); }
.dc-table-output .tabulator-row.row-danger   .tabulator-cell:first-child { border-left-color: var(--dc-danger); }
.dc-table-output .tabulator-row.row-pending  .tabulator-cell:first-child { border-left-color: var(--dc-edge-pending); }
.dc-table-output .tabulator-row.is-sel       .tabulator-cell:first-child { border-left-color: var(--dc-primary) !important; }

/* Year used to be forced center here too (`[tabulator-field="year"]`) as a
   leftover from being modeled on the destination-view status columns — but
   Year is ordinary row content like Film/Director, not a centered status
   icon (same class of fix as the Festivals `dc-col-c` removal, round 10).
   Dropped (operator feedback, round 11): `.tabulator-cell` has no
   `text-align` override of its own, so Year now falls back to the browser
   default (left), matching every other catalogue column. `.dc-col-c` stays
   — it's still the deliberate opt-in for the destination-view status
   columns, which ARE meant to stay centered. */
.dc-table-output .tabulator-cell.dc-col-c {
  text-align: center;
  justify-content: center;   /* cells are inline-flex now — text-align alone no longer centres */
}

/* Mono value columns (Year — `font-family: mono; font-size: 12px` in the
   .ig-films-table spec). Opt-in via cssClass on the column def. */
.dc-table-output .tabulator-cell.dc-col-mono {
  font-family: var(--dc-font-mono);
  font-size: 12px;
}

/* Orig. Title column — italic mono muted (.ig-film-orig-col). */
.dc-table-output .tabulator-cell.dc-col-orig {
  font-family: var(--dc-font-mono);
  font-size: 12px;
  font-style: italic;
}

/* ── Empty state ────────────────────────────────────────────────────── */

.dc-table-output .tabulator-placeholder {
  color: var(--dc-muted);
  font-size: 13px;
}

/* Vendor's empty-state text colour is set on the nested `.tabulator-
   placeholder-contents` element via a 4-class selector
   (`.tabulator .tabulator-tableholder .tabulator-placeholder
   .tabulator-placeholder-contents`) — same specificity-mismatch issue as
   `.tabulator-table` above. Match the shape 1:1. */
.dc-table-output .tabulator-tableholder .tabulator-placeholder .tabulator-placeholder-contents {
  color: var(--dc-muted);
  font-size: 13px;
  font-weight: 400;
}

.dc-table-empty {
  padding: 32px 12px;
  text-align: center;
  color: var(--dc-muted);
  font-size: 13px;
}

/* ── Header menu dropdown (column show/hide) ───────────────────────── */

.tabulator-menu {
  background: var(--dc-panel);
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius, 7px);
  box-shadow: 0 12px 30px -14px rgba(0, 0, 0, 0.4);
  padding: 5px;
}

.tabulator-menu .tabulator-menu-item {
  padding: 7px 8px;
  font-size: 13px;
  color: var(--dc-ink);
  border-radius: var(--dc-radius-sm, 5px);
}

.tabulator-menu .tabulator-menu-item:hover {
  background: var(--dc-panel-2);
}

/* ── Reused cell content classes (ported verbatim from library-page.css
   .ltable rules — same markup, now rendered inside a tabulator-cell) ──── */

/* Dense title cell (dcTitle formatter) — `font-weight: 500; color: ink`
   per the .ig-films-table spec; the only ink-weighted content in the row.
   (The old two-line .film-cell/.poster/.film-name/.film-sub block was
   removed with the 2026-07-21 dense migration — dcFilm renders it but no
   dc_table page uses dcFilm anymore; restore from git history if a
   tall-row view ever returns.) */
.dc-table-output .film-title {
  font-weight: 400;   /* operator 2026-07-21: 500 read too heavy */
  color: var(--dc-ink);
  overflow: hidden;
  text-overflow: ellipsis;
}

.dc-table-output .tags { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.dc-table-output .tag {
  font-size: 10px;
  border: 1px solid var(--dc-line-2);
  border-radius: 4px;
  padding: 0 5px;
  color: var(--dc-muted);
  white-space: nowrap;
}

.dc-table-output .festcnt {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--dc-ink);
}
.dc-table-output .festcnt i { color: var(--dc-warn); }
.dc-table-output .festcnt.zero { color: var(--dc-faint); }
.dc-table-output .festcnt.zero i { color: var(--dc-faint); }

.dc-table-output .st {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  font-size: 12px;
  white-space: nowrap;
}
.dc-table-output .st i { font-size: 15px; }
.dc-table-output .st--done { color: var(--dc-ok); }
.dc-table-output .st--pend { color: var(--dc-faint); }
.dc-table-output .st--warn { color: var(--dc-warn); }
.dc-table-output .st--live { color: var(--dc-ok); font-weight: 600; }
.dc-table-output .st--priv { color: var(--dc-muted); }
.dc-table-output .st__lbl { font-size: 11px; font-weight: 600; }

/* Links out of a table cell (Library › YouTube's YouTube ID and Published,
   2026-10-20): the ID reads as a link; the pill keeps its look plus an
   "opens elsewhere" arrow, and underlines its label on hover. */
.dc-ext-link {
  color: var(--dc-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.dc-ext-link:hover { text-decoration-thickness: 2px; }
.dc-ext-link--pill { text-decoration: none; color: inherit; }
.dc-ext-link--pill:hover .dc-pill { text-decoration: underline; text-underline-offset: 2px; }
.dc-ext-link__icon { font-size: 9px; margin-left: 2px; opacity: .75; }

/* Frozen rows (`frozen_row_ids`, e.g. Acquisitions' "All vendors") go UNDER
   the column headers. Tabulator lays the holder out inline-block, which put
   the row beside the headers: the row was hidden and the header grew to 48px
   (operator 2026-11-02, "the margins are off"). */
.dc-table-output.tabulator .tabulator-header .tabulator-frozen-rows-holder { display: block; padding-top: 0; }   /* outranks the vendor rule (which also adds 1em top padding) */

/* ── Sorting lives in the pill (option B, 2026-11-02) ─────────────────────
   The sorted column shows a small arrow inside its pill, before the chevron;
   a search-box pill gets a trailing chevron that opens a mini menu with the
   same "Sort ascending / descending" lines every picker popover carries.
   JS twin: dc-table.js `_dcSortAttach`. */
.dc-table-output .tabulator-header-filter { position: relative; }
.dc-sort-ind {
  display: none;
  position: absolute; top: 50%; transform: translateY(-50%);
  right: calc(var(--dc-pill-px) + 16px);   /* clear of the 10px chevron */
  font-size: 11px; line-height: 1; color: var(--dc-ink);
  pointer-events: none;
}
.dc-table-output .tabulator-col[aria-sort="ascending"] .dc-sort-ind,
.dc-table-output .tabulator-col[aria-sort="descending"] .dc-sort-ind { display: block; }
.dc-table-output .tabulator-col[aria-sort="ascending"] .dc-sort-ind::before { content: "\2191"; }
.dc-table-output .tabulator-col[aria-sort="descending"] .dc-sort-ind::before { content: "\2193"; }
/* Room for the arrow so a long label ellipsises before reaching it. */
/* Any sorted pill (picker OR From/To) makes room for its arrow — the range
   pill missed this and its arrow sat on the label (2026-11-02). */
.dc-table-output .tabulator-col[aria-sort="ascending"] .dc-hf-btn,
.dc-table-output .tabulator-col[aria-sort="descending"] .dc-hf-btn { padding-right: calc(var(--dc-pill-px) + 14px); }
/* A column whose cells ARE the order (Acquisitions "#") shows no arrow. */
.dc-table-output .tabulator-col.dc-no-sortmark .dc-sort-ind { display: none !important; }
.dc-table-output .tabulator-col.dc-no-sortmark .dc-hf-btn { padding-right: var(--dc-pill-px) !important; }
.dc-table-output .tabulator-col[aria-sort="ascending"] .dc-hf--textsort input,
.dc-table-output .tabulator-col[aria-sort="descending"] .dc-hf--textsort input { padding-right: calc(var(--dc-pill-px) + 44px); }
/* The text-search pill's chevron (opens the sort menu). */
.dc-hf-sortbtn {
  position: absolute; top: 0; bottom: 0; right: 0;
  width: calc(var(--dc-pill-px) + 18px);
  display: flex; align-items: center; justify-content: flex-end;
  padding: 0 var(--dc-pill-px) 0 0;
  border: 0; background: transparent; cursor: pointer;
  font-size: 10px; color: var(--dc-muted);
}
.dc-hf-sortbtn:hover { color: var(--dc-ink); }
.dc-hf--textsort input { padding-right: calc(var(--dc-pill-px) + 28px); text-overflow: ellipsis; }

/* Sort lines at the top of every header popover. */
.dc-hf-sort { display: flex; flex-direction: column; padding-bottom: 6px; margin-bottom: 6px; border-bottom: 1px solid var(--dc-line); }
.dc-hf-sort__item {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 5px 8px; border: 0; background: transparent;
  border-radius: var(--dc-radius-sm); cursor: pointer; text-align: left;
  font-size: 11px; font-weight: var(--dc-fw-medium); line-height: 1; color: var(--dc-ink);
}
.dc-hf-sort__item:hover { background: var(--dc-panel-2); }
.dc-hf-sort__item i { font-size: 11px; color: var(--dc-muted); flex: none; }
.dc-hf-sort__item.on { color: var(--dc-ink); }
.dc-hf-sort__item.on i { color: var(--dc-ink); }
.dc-hf-sort__item--clear { color: var(--dc-muted); }
.dc-hf-pop--sort { width: 168px; }
.dc-hf-pop--sort .dc-hf-sort { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }

/* Header search boxes: Tabulator writes `padding: 4px` onto the input as an
   inline style, which beat the pill padding above — labels sat 4px from the
   edge (operator 2026-11-02, "not enough padding for pill labels"). A text
   box with the sort chevron keeps room for it on the right. */
.dc-table-output .tabulator-header-filter input { padding: 0 var(--dc-pill-px) !important; }
.dc-table-output .tabulator-header-filter.dc-hf--textsort input {
  padding-right: calc(var(--dc-pill-px) + 20px) !important;
}

/* Control-only headers (2026-11-02, operator: "the check box and the scale
   button are moved to the right too far"). The bare-title inset above is for
   words; a header that holds a control gets none of it.
   - Tick box: 12px in = the row cell's 8px padding + the checkbox's own 4px
     default margin, so header and row boxes sit on one vertical line.
   - Row-size button: centred in its (poster) column. */
.dc-table-output .tabulator-col:not(:has(.tabulator-header-filter)) .tabulator-col-title:has(input, button) {
  padding-left: 0;
}
.dc-table-output .tabulator-header .tabulator-col:has(.tabulator-col-title input[type=checkbox]) .tabulator-col-content {
  padding-left: 12px; padding-right: 0;
}
.dc-table-output .tabulator-header .tabulator-col:has(.dc-rowsize) .tabulator-col-content {
  justify-content: center; padding-left: 0; padding-right: 0;
}
.dc-table-output .tabulator-header .tabulator-col:has(.dc-rowsize) .tabulator-col-title-holder {
  flex: 0 0 auto;
}
