/*
 * drawer.css — Film-detail accordion drawer design system
 *
 * Ported from dc-drawer-redesign.html (claude-design/skills/dc-skill/).
 * Namespace: .dd-* (drawer shell + shared KV/timeline/file atoms)
 *            .ddb-* (accordion body wrapper)
 *            .ddb2-* (full-width accordion sections)
 *            .ddc-* (film-head strip above accordion)
 *
 * Excluded: .ref-* scaffolding, .dd-rzwrap/.dd-rzhandle (drag-resize
 * handle — app uses shared Split.js gutter), .dc-dark (app uses
 * CSS custom properties that auto-switch via [data-bs-theme]).
 */

/* =========================================================================
   SHARED DRAWER SHELL
   ========================================================================= */

/* The drawer card itself — kept for completeness, harmless in-app */
.dd-drawer {
  /* FILLS ITS PANE. It previously carried `width:360px; height:680px` plus
     border/radius/shadow — the dimensions of the static mockup frame this was
     ported from (47cc38c, 2026-06-24), where the drawer was drawn as a
     floating card on a canvas. Those are frame dimensions, not a layout
     decision, and they shipped into the app: the drawer rendered as a fixed
     360x680 card inside a much larger pane, leaving dead space to the right
     and below on all eight pages that render a film drawer.

     dc-components.css already declared `height:100%` here, but it loads at
     app.py:123 and this file at app.py:154 — equal specificity, later file
     wins, so the correct rule never took effect. Fixed here rather than by
     reordering the stylesheets, which would change what wins app-wide.

     No surface of its own (background/border/radius/shadow): the pane owns
     that. `.split-detail` deliberately drops its border because the Split.js
     gutter owns both seam borders, and lifts to --dc-panel-2 in dark mode for
     elevation — a --dc-panel fill here painted over that lift and put the
     drawer back to "black on black". */
  width: 100%;
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: transparent;
}

/* ── Tags section — chip row ──
   Wrapping row of `.dc-chip`s. No chip styling here: .dc-chip is a component
   (dc-theme.css) and this only lays them out. */
/* Layout row itself MOVED to dc-components.css (tab-pages lock, 2026-09-02)
   — this file loads later, so the 6px-gap copy that lived here was silently
   overriding the component's 4px. */

/* Editable chips. `.dc-chip` still owns the chip itself — this only adds the
   remove control and the room for it, so a chip reads the same whether it is
   editable or not. */
.dd-tag--edit { display: inline-flex; align-items: center; gap: 4px; padding-right: 3px; }
.dd-tag__x {
  appearance: none; background: none; border: none; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: var(--dc-radius-sm);
  color: var(--dc-faint); font-size: 11px; line-height: 1; cursor: pointer;
}
.dd-tag__x:hover { background: var(--dc-danger-soft, color-mix(in oklch, var(--dc-ink) 8%, transparent)); color: var(--dc-ink); }
.dd-tags__empty { color: var(--dc-faint); font-style: italic; font-size: 12.5px; }
.dd-tags__full { color: var(--dc-faint); font-size: 11.5px; margin-top: 8px; }
.dd-tags-editor { display: flex; flex-direction: column; gap: 8px; }
.dd-tag-add { display: flex; }
/* Rounded to match the inline pickers on the table (curation-page.css). */
.dd-tag-add__input { border-radius: var(--dc-radius-sm); }

/* ── Chrome bar ──
   Base = the legacy 34px strip (still used by Export Groups' group drawer,
   frozen bugfix-only). The FILM drawer overrides it with the canonical
   68px chrome via .dd-chrome--film below. */
.dd-chrome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--dc-strip-h);
  padding: 0 var(--dc-space-6);
  border-bottom: 1px solid var(--dc-line);
  background: var(--dc-panel-2);
  flex: none;
  gap: var(--dc-space-3);
  min-height: 0;
}
.dd-chrome__left {
  display: flex; align-items: center; gap: var(--dc-space-3);
  min-width: 0; overflow: hidden;
}
.dd-chrome__id {
  font-family: var(--dc-font-mono);
  font-size: 13px;
  font-weight: var(--dc-fw-semi);
  color: var(--dc-ink);
  flex-shrink: 0;
}
.dd-chrome__sep {
  color: var(--dc-faint); font-size: 13px; flex-shrink: 0;
}
.dd-chrome__title {
  font-size: 13px; color: var(--dc-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dd-chrome__right {
  display: flex; align-items: center; gap: var(--dc-space-3); flex-shrink: 0;
}

/* ── Canonical FILM drawer chrome (2026-07-21) ──
   ONE 68px block (2 × --dc-topbar-h): title "Title · Year" + status line,
   close at the right. 68px is the same y the main pane reaches with
   view-bar (34) + table header (34), and the sidebar with padding (8) +
   brand (60), so the drawer's first line connects straight across
   (full-screen composite). */
.dd-chrome--film {
  /* Was a fixed 2 × topbar (68px). The 72×108 poster (operator
     2026-07-22) needs more — grow to fit, never below the old 68px. */
  min-height: calc(2 * var(--dc-topbar-h));
  height: auto;
  padding-top: 8px;
  padding-bottom: 8px;
  box-sizing: border-box;
}
.dd-chrome--film .dd-chrome__left {
  display: block;
}
.dd-chrome--film .dd-chrome__title {
  display: flex; align-items: center; gap: 7px;
  font-size: 14px; font-weight: 400; color: var(--dc-ink);  /* operator 2026-07-21: 600 too heavy */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dd-chrome--film .dd-chrome__status {
  margin-top: 2px;
  font-size: 11.5px; color: var(--dc-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dd-chrome--film .dd-chrome__id {
  font-family: var(--dc-font-mono);
  font-size: 11px;
  font-weight: var(--dc-fw-regular, 400);
  color: var(--dc-faint);
  flex-shrink: 0;
}
.dd-chrome--film .dd-chrome__sep {
  font-size: 11.5px;
}
.dd-close {
  appearance: none; background: none; border: none;
  color: var(--dc-faint); font-size: 15px; line-height: 1;
  padding: var(--dc-space-2) var(--dc-space-2); border-radius: var(--dc-radius-sm);
  cursor: pointer; display: inline-flex;
}
.dd-close:hover {
  background: color-mix(in oklch, var(--dc-ink) 8%, transparent);
  color: var(--dc-ink);
}

/* ── Shared footer ── */
.dd-footer {
  display: flex;
  align-items: center;
  gap: var(--dc-space-3);
  padding: 11px var(--dc-space-7);
  border-top: 1px solid var(--dc-line);
  background: var(--dc-panel-2);
  flex: none;
}
.dd-spacer { flex: 1 1 auto; }

/* ── Scrollable body ── */
.dd-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-gutter: stable;
}

/* Intake workspace drawer pane hosts the drawer via output_ui — the Shiny
   wrapper must be a flex column filling the pane (same glue app.py's
   inline CSS provides for .split-detail on Split.js pages). */
.ig-drawer-pane > .shiny-html-output {
  flex: 1 1 auto; min-height: 0; height: 100%;
  display: flex; flex-direction: column;
}
.ig-drawer-pane > .shiny-html-output > div {
  flex: 1 1 auto; min-height: 0;
}

/* =========================================================================
   SHARED KV GRID
   ========================================================================= */
/* .ig-kv language (2026-07-21, matches dc-components.css): 90px label
   column, 4px/10px gaps, normal-case faint 600 labels — the old
   uppercase 10.5px eyebrow labels were the biggest visible mismatch
   against the gallery drawer. */
.dd-kv {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 4px 10px;
  font-size: 12.5px;
}
.dd-kv__k {
  font-size: 12px;
  font-weight: var(--dc-fw-semi);
  letter-spacing: normal;
  text-transform: none;
  color: var(--dc-faint);
  display: flex; align-items: flex-start;
}
.dd-kv__v { color: var(--dc-ink); font-size: 12.5px; word-break: break-word; line-height: 1.45; }
.dd-kv__v.mono { font-family: var(--dc-font-mono); font-size: 12px; }
.dd-kv__v.muted { color: var(--dc-muted); font-style: italic; }
.dd-kv__v--warn { color: var(--dc-warn); }

/* Section label */
.dd-section-label {
  font-size: 10.5px;
  font-weight: var(--dc-fw-bold);
  letter-spacing: var(--dc-track-label);
  text-transform: uppercase;
  color: var(--dc-faint);
  margin-bottom: var(--dc-space-3);
}
.dd-section {
  margin-bottom: var(--dc-space-6);
}
.dd-section:last-child { margin-bottom: 0; }

/* Inline stat mini tiles */
.dd-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--dc-space-3);
}
.dd-stat {
  background: var(--dc-panel-2);
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius);
  padding: var(--dc-space-4) var(--dc-space-4);
  text-align: center;
}
.dd-stat__val {
  font-size: 17px; font-weight: var(--dc-fw-bold);
  font-variant-numeric: tabular-nums; color: var(--dc-ink);
  line-height: 1.1;
}
.dd-stat__lbl {
  font-size: 10px; font-weight: var(--dc-fw-bold);
  text-transform: uppercase; letter-spacing: var(--dc-track-label);
  color: var(--dc-faint); margin-top: var(--dc-space-1);
}

/* Poster stub */
.dd-poster {
  width: 64px; height: 94px; flex-shrink: 0;
  background: var(--dc-panel-2); border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius); display: flex; align-items: center; justify-content: center;
  color: var(--dc-line-2); font-size: 22px;
}

/* Film head block (poster + title + sublines) */
.dd-film-head {
  display: flex; gap: var(--dc-space-5); align-items: flex-start;
  padding: var(--dc-space-6) var(--dc-space-7);
  border-bottom: 1px solid var(--dc-line);
  flex-shrink: 0;
}
.dd-film-head__meta { flex: 1 1 0; min-width: 0; }
.dd-film-head__title {
  font-size: 15px; font-weight: var(--dc-fw-bold); color: var(--dc-ink);
  line-height: 1.3; margin-bottom: var(--dc-space-2);
}
.dd-film-head__orig {
  font-size: 12px; color: var(--dc-faint); margin-bottom: var(--dc-space-2);
  font-style: italic;
}
.dd-film-head__sub {
  font-size: 12px; color: var(--dc-muted); margin-bottom: var(--dc-space-1);
}
.dd-film-head__chips {
  display: flex; flex-wrap: wrap; gap: var(--dc-space-2); margin-top: var(--dc-space-3);
}

/* Traffic-light dot */
.dd-tl {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  flex-shrink: 0; margin-right: var(--dc-space-2);
  vertical-align: middle;
}
.dd-tl--green { background: var(--dc-ok); }
.dd-tl--amber { background: var(--dc-warn); }
.dd-tl--red   { background: var(--dc-danger); }

/* Timeline (History tab) */
.dd-tline { display: flex; flex-direction: column; }
.dd-tline-item {
  display: flex; gap: var(--dc-space-4); align-items: flex-start;
  padding-bottom: var(--dc-space-4);
}
.dd-tline-rail {
  display: flex; flex-direction: column; align-items: center;
  flex-shrink: 0; width: 20px;
}
.dd-tline-dot {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--dc-line-2); background: var(--dc-panel);
  display: flex; align-items: center; justify-content: center;
  font-size: 9px; color: var(--dc-muted); flex-shrink: 0;
}
.dd-tline-dot--ok { border-color: var(--dc-ok); color: var(--dc-ok); }
.dd-tline-dot--next { border-color: var(--dc-primary); color: var(--dc-primary); }
.dd-tline-line { flex: 1 1 auto; width: 1px; background: var(--dc-line); margin-top: 2px; min-height: 16px; }
.dd-tline-body { flex: 1 1 0; padding-top: 2px; }
.dd-tline-ev { font-size: 13px; color: var(--dc-ink); font-weight: var(--dc-fw-medium); }
.dd-tline-sub { font-family: var(--dc-font-mono); font-size: 11px; color: var(--dc-faint); margin-top: 2px; }
.dd-tline-meta { font-size: 11px; color: var(--dc-faint); margin-top: 2px; }

/* File row — MOVED to dc-components.css (tab-pages lock, 2026-09-02):
   the locked two-line Files body restyled it and the gallery must render
   the same rules the app does. */

/* Platform card */
.dd-platform-card {
  border: 1px solid var(--dc-line);
  border-radius: var(--dc-radius);
  overflow: hidden;
  margin-bottom: var(--dc-space-3);
}
.dd-platform-card:last-child { margin-bottom: 0; }
.dd-platform-card__head {
  display: flex; align-items: center; gap: var(--dc-space-3);
  padding: var(--dc-space-4) var(--dc-space-5);
  background: var(--dc-panel-2); cursor: pointer;
}
.dd-platform-card__name { font-weight: var(--dc-fw-semi); font-size: 13px; flex: 1 1 0; }
.dd-platform-card__body {
  padding: var(--dc-space-4) var(--dc-space-5);
  border-top: 1px solid var(--dc-line);
}

/* =========================================================================
   ACCORDION BODY WRAPPER
   ========================================================================= */

/* Scroll container shared by the drawer body */
.ddb-body {
  padding: var(--dc-space-5) var(--dc-space-6);
}

/* =========================================================================
   CANONICAL FILM-DRAWER SECTIONS — .ig-accordion (dc-components.css/js
   owns the shell + toggle; 2026-07-21 port). This file only adds the
   app-side extensions the static gallery doesn't need.
   ========================================================================= */

/* Empty section — dimmed, inert (dc-components.js skips is-empty clicks) */
.ig-accordion.is-empty > .ig-accordion-head { opacity: 0.5; cursor: default; }
.ig-accordion.is-empty > .ig-accordion-head .ig-accordion-edit { pointer-events: none; }
/* Edit state — head stops being a toggle (dc-components.js skips is-editing);
   no chevron while editing (gallery edit frames carry none) */
.ig-accordion.is-editing > .ig-accordion-head { cursor: default; }
.ig-accordion.is-editing .ig-accordion-head__chevron { display: none; }

/* ── .ig-kv value modifiers (gallery uses inline styles; the app needs
   reusable classes for mono/muted/warn values + links) ── */
.ig-kv-value.mono { font-family: var(--dc-font-mono); font-size: 12px; }
.ig-kv-value.muted { color: var(--dc-muted); font-style: italic; }
.ig-kv-value a { color: var(--dc-primary); text-decoration: none; }
.ig-kv-value { word-break: break-word; line-height: 1.45; }

/* Click-to-copy on read-mode values + credit names (2026-07-21).
   Scoped to `.split-detail` — the canonical film-detail drawer this was
   built for — because the copy CLICK handler itself is scoped there too
   (see pages/library.py's delegated listener: `if (!e.target.closest(
   '.split-detail')) return;`). Before this scope was added here, the CSS
   ran everywhere any .ig-accordion + .ig-kv pair exists (e.g. the System
   page's Environment tab, which has no click-to-copy wiring at all) — rows
   painted the hover highlight and a copy cursor for a click that silently
   did nothing. Found 2026-08-11 round 3: operator saw an unexplained
   full-row light-blue band on hover over the Environment tab's kv rows
   ("NAS path", "OMDB key") and correctly called it real — a prior pass had
   dismissed it as text selection on a no-interaction render, which missed
   it because it only appears ON HOVER. Kept scoped rather than removed
   outright: the affordance is genuine and wanted on every page that DOES
   use the canonical drawer (Library, Festivals, Vendors, Platforms, Logs —
   all render their .ig-accordion kv sections inside a `.split-detail`). */
/* Scoped to `.dd-drawer` (the drawer itself), NOT to `.split-detail` (the
   Split.js pane) — rescoped 2026-08-25 with the handler in dc-components.js.
   Curation, Intake and Delivery host this same drawer in `.ig-drawer-pane`,
   so a pane-scoped rule left them with no copy affordance at all. */
/* Re-anchored off `.ig-accordion` in the 2026-09-02 tab-pages lock: the pill
   shell's sections are `.dd-panel`s with no accordion ancestor, so the
   accordion-anchored selector painted no affordance anywhere in the film
   drawer while the JS handler happily copied — the exact hover-promises-
   nothing/click-works-silently split the 2026-08-11 scoping fixed in the
   other direction. `.dd-panel:not(.is-editing)` covers the pill drawer;
   the accordion selector stays for the record drawer, which still is one. */
.dd-drawer .ig-accordion:not(.is-editing) .ig-kv-value,
.dd-drawer .ig-accordion:not(.is-editing) .dd-credit-name,
.dd-drawer .dd-panel:not(.is-editing) .ig-kv-value,
.dd-drawer .dd-panel:not(.is-editing) .dd-credit-name { cursor: copy; border-radius: var(--dc-radius-sm); transition: color var(--dc-dur-fast), background var(--dc-dur-fast); }
.dd-drawer .ig-accordion:not(.is-editing) .ig-kv-value:hover,
.dd-drawer .ig-accordion:not(.is-editing) .dd-credit-name:hover,
.dd-drawer .dd-panel:not(.is-editing) .ig-kv-value:hover,
.dd-drawer .dd-panel:not(.is-editing) .dd-credit-name:hover { background: var(--dc-primary-soft); }
.ig-kv-value.is-copied, .dd-credit-name.is-copied { color: var(--dc-ok) !important; background: var(--dc-ok-soft) !important; }
.ig-kv-value.is-copied::after, .dd-credit-name.is-copied::after {
  content: " ✓ copied"; font-size: 10px; font-weight: var(--dc-fw-bold);
  letter-spacing: var(--dc-track-label); color: var(--dc-ok);
}

/* ── Edit-state kv form (.ig-kv--edit): inputs live in the value column ── */
.ig-accordion.is-editing .ig-kv { gap: var(--dc-space-3) var(--dc-space-4); align-items: center; }
.ig-kv--edit { align-items: start; row-gap: var(--dc-space-4); }
.ig-kv-value--edit { min-width: 0; }
.ig-kv-value--edit .shiny-input-container { margin-bottom: 0 !important; width: 100% !important; }
.ig-kv-value--edit .form-control,
.ig-kv-value--edit .selectize-control,
.ig-kv-value--edit .selectize-input { width: 100%; box-sizing: border-box; }
.ig-kv-value--edit .form-control { font-size: 13px; }

/* ── Logs section rows — MOVED to dc-components.css (tab-pages lock,
   2026-09-02) so the gallery and the app read one definition. This file
   loads after dc-components.css, so a copy left here would silently win. ── */

/* =========================================================================
   LEGACY FULL-WIDTH ACCORDION (.ddb2-*) — NO LONGER the film drawer.
   Still rendered by the Export Groups GROUP drawer and the old Scheduling
   Schedule section (both frozen until their visual-refresh sessions).
   Delete this block when the last ddb2 shell is gone.
   ========================================================================= */

/* Header band — full-bleed tinted, re-padded so the title stays on the gutter. */
.ddb2-head {
  display: flex; align-items: center; gap: var(--dc-space-3);
  margin: 0 calc(-1 * var(--dc-space-6));
  /* pinned to the 34px grid (2026-07-21) — padding-driven height measured
     36px and drifted the drawer sections off the table rows */
  height: var(--dc-topbar-h);
  box-sizing: border-box;
  padding: 0 var(--dc-space-6);
  background: var(--dc-panel-2);
  border-top: 1px solid var(--dc-line);
  cursor: pointer; user-select: none;
  transition: background var(--dc-dur-fast), box-shadow var(--dc-dur-fast);
}
.ddb2-group:first-child .ddb2-head { border-top: none; }
.ddb2-head:hover { background: var(--dc-panel); }  /* .ig-accordion-head hover */

/* OPEN state — flat panel tone + 3px primary left-edge + bottom hairline
   (aligned to the .ig-accordion look: no primary fill, ink title). */
.ddb2-group:not(.is-collapsed) .ddb2-head {
  background: var(--dc-panel-2);
  border-bottom: 1px solid var(--dc-line);
  box-shadow: inset 3px 0 0 var(--dc-primary);
}
/* chevron keeps a primary tint as the open affordance; title + icon stay ink */
.ddb2-group:not(.is-collapsed) .ddb2-chev { color: var(--dc-primary); }

.ddb2-icon { font-size: 14px; color: var(--dc-faint); width: 16px; text-align: center; flex-shrink: 0; }
.ddb2-title {
  font-size: 12px; font-weight: var(--dc-fw-semi); color: var(--dc-ink); flex: 1 1 0;
}
.ddb2-badge { font-size: 10.5px; color: var(--dc-faint); font-family: var(--dc-font-mono); }
.ddb2-chev { font-size: 11px; color: var(--dc-faint); transition: transform var(--dc-dur-fast); flex-shrink: 0; }
.ddb2-group.is-collapsed .ddb2-chev { transform: rotate(-90deg); }

/* Body — plain panel tone, FULL-BLEED to the drawer edge (same trick as
   .ddb2-head): negative horizontal margin pulls the body out past .ddb-body's
   space-6 gutter so its background reaches the drawer edges, then equal
   horizontal padding puts the kv content back on the gutter so it stays
   aligned with the header band text. Without the bleed, the body background
   is inset by the gutter and shows as dark strips left/right of the content
   in dark mode. Full-bleed children (fest/credit/file items) still bleed
   correctly relative to this re-padded content box. */
.ddb2-body {
  margin: 0 calc(-1 * var(--dc-space-6));
  padding: 12px var(--dc-space-6);   /* .ig-accordion-body: 12px */
  background: var(--dc-panel);
  font-size: 12.5px;
}
.ddb2-group.is-collapsed .ddb2-body { display: none; }

/* Per-panel Edit — only visible when OPEN */
.ddb2-editbtn { font-size: 11px; padding: 2px 9px; flex-shrink: 0; }
/* Pencil variant — bare 22px icon button (.ig-accordion-edit, 2026-07-21).
   Save/Cancel keep their btn-sm chrome; only the idle pencil is bare. */
.ddb2-pencil {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0;
  border: none; border-radius: var(--dc-radius);
  background: transparent; color: var(--dc-faint);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
/* Gallery parity (2026-07-21): the pencil shows on collapsed heads too
   (.ig-accordion renders it on every head). Save/Cancel only ever render
   in edit mode, where the section is forced open — so nothing else leaks
   onto collapsed heads by dropping the old hide rule. */
.ddb2-group:not(.is-collapsed) .ddb2-badge { display: none; }

/* Remove gap between film-head and first accordion band */
.ddb-body:has(> .ddb2-list) { padding-top: 0; }

/* Empty section — dim header, no cursor pointer, no hover */
.ddb2-group.is-empty .ddb2-head {
  opacity: 0.5;
  cursor: default;
  pointer-events: none;
}

/* Credits/Festivals: hide edit-mode controls when the section is in display
   mode.
   `.dd-panel` added 2026-08-26. The film drawer stopped being an
   .ig-accordion in the 2026-08-25 pills port, so NEITHER of the two
   selectors below matched it any more and every per-row Edit/Delete plus
   the Add button rendered permanently — the section read as already being
   in edit mode. The .ig-accordion and .ddb2-group selectors stay: Delivery's
   cards, the record drawer and the System page never became tabs. */
.dd-panel:not(.is-editing) .ddb2-edit-only,
.ig-accordion:not(.is-editing) .ddb2-edit-only,
.ddb2-group:not(.is-editing) .ddb2-edit-only {
  display: none !important;
}
/* The festival editor's toolbar holds only the (edit-only) Add button — in
   read mode it would render as an empty spacer row above the table, and in
   the pills shell it lands ON TOP of the section pencil, which sits at the
   same top-right corner (operator: "on festivals we have edit and add
   overlap", 2026-08-26). */
.dd-panel:not(.is-editing) .det-toolbar,
.ig-accordion:not(.is-editing) .det-toolbar { display: none; }

/* ...and in EDIT mode it must not collide either. The section's control group
   is `position:absolute; top:6px; right:8px` over the panel
   (dc-components.css .dd-section__edit), while .det-toolbar is the panel's
   first child and its `.dc-spacer` pushes Add hard right — into exactly that
   corner. Measured 2026-08-26: toolbar and control slot both at y=197.5,
   overlapping x=1462..1577.

   Dropping the spacer inside a .dd-panel left-aligns Add, so the top-right
   corner belongs to the control group alone. No magic numbers, and the
   accordion hosts (Delivery cards, record drawer, System) keep the spacer —
   they have a real head bar, so nothing floats over their body. */
.dd-panel .det-toolbar .dc-spacer { display: none; }

/* Festivals — one item per entry, ONE continuous flowing line (name ·
   section · year · award status) — see _attendance_readonly_row in
   components/festival_editor.py. */
.ddb2-fest-item {
  margin: 0 calc(-1 * var(--dc-space-6));
  padding: var(--dc-space-4) var(--dc-space-6);
  border-top: 1px solid var(--dc-line);
}
.ddb2-fest-item:first-child { border-top: none; }
.ig-accordion.is-editing .ddb2-fest-item { padding-top: var(--dc-space-5); padding-bottom: var(--dc-space-5); }
/* The line beside the (edit-mode-only) trailing action buttons.
   flex-wrap:wrap — NO truncation/ellipsis (operator correction
   2026-07-14): when name + section + year + status don't fit on one
   line, they wrap onto more lines instead of clipping. min-width:0 lets
   the wrap actually engage instead of pushing the buttons off the edge. */
.ddb2-fest-top {
  display: flex; flex-wrap: wrap; align-items: baseline;
  column-gap: var(--dc-space-2); row-gap: var(--dc-space-1);
  flex: 1 1 auto; min-width: 0;
}
.ddb2-fest-name { font-size: 13px; font-weight: var(--dc-fw-semi); color: var(--dc-ink); }
.ddb2-fest-section { font-size: 12px; color: var(--dc-muted); }
.ddb2-fest-year { font-family: var(--dc-font-mono); font-size: 11px; color: var(--dc-faint); }
.ddb2-fest-sep { color: var(--dc-faint); font-size: 11px; }

/* Platform — flat item, not a bordered card */
.ddb2-plat-item { padding: var(--dc-space-3) 0; border-top: 1px solid var(--dc-line); }
.ddb2-plat-item:first-child { border-top: none; padding-top: 0; }
.ddb2-plat-top { display: flex; align-items: center; gap: var(--dc-space-3); margin-bottom: var(--dc-space-2); }
.ddb2-plat-name { font-size: 13px; font-weight: var(--dc-fw-semi); color: var(--dc-ink); flex: 1 1 0; }

/* Credits — gallery kv language (2026-07-21 port): 90px role-label column
   + name per row, no dividers; a same-role run blanks its labels so Cast
   reads as one label with stacked names (matches the gallery's multi-line
   Cast value). */
.ddb2-credit-list { display: flex; flex-direction: column; gap: 4px; }
/* .dd-credit-row/-role/-name — MOVED to dc-components.css (tab-pages lock,
   2026-09-02) and restyled there; the click-to-copy affordance above still
   targets .dd-credit-name and is untouched. */

/* ── Edit state (legacy dd-kv — scheduling's Schedule section only; the
   film drawer's ig-kv edit rules live in the .ig-accordion block above) ── */
.ddb2-group.is-editing .dd-kv { gap: var(--dc-space-3) var(--dc-space-4); align-items: center; }
.ddb2-group.is-editing .dd-kv__k { padding-top: 0; }
[contenteditable="true"].ig-kv-value,
[contenteditable="true"].ddb2-fest-name,
[contenteditable="true"].ddb2-fest-result {
  display: block;
  border: 1px solid var(--dc-line-2);
  border-radius: var(--dc-radius-sm);
  padding: 4px 8px;
  background: var(--dc-panel);
  color: var(--dc-ink);
  outline: none;
  transition: border-color var(--dc-dur-fast), box-shadow var(--dc-dur-fast);
}
[contenteditable="true"]:focus {
  border-color: var(--dc-primary);
  box-shadow: var(--dc-shadow-focus);
}

/* ── Shiny form controls in component edit contexts render as .ig-input
   (dc-components.css — the canonical square flush control from the
   gallery's edit-state + add-row frames). Shiny emits .form-control /
   .form-select / .selectize-input, so this block maps those onto the
   .ig-input definition inside .ig-kv--edit grids and .ig-add-row grids
   (2026-07-21 — replaces an off-system ad-hoc normalization). ── */
.ig-kv--edit .form-control,
.ig-kv--edit .form-select,
.ig-kv--edit .selectize-input,
.ig-add-row .form-control,
.ig-add-row .form-select,
.ig-add-row .selectize-input,
.dc-card .form-control,
.dc-card .form-select,
.dc-card .selectize-input {
  width: 100%; box-sizing: border-box;
  /* Rounded 2026-08-31 — see the editing-register note in dc-components.css. */
  border: 1px solid var(--dc-line); border-radius: var(--dc-radius);
  background: var(--dc-panel); color: var(--dc-ink);
  font-size: 12.5px; padding: 4px 8px; min-height: 28px;
  font-family: var(--dc-font-sans);
  box-shadow: none;
}
.ig-kv--edit textarea.form-control,
.dc-card textarea.form-control { height: auto; }
.ig-kv--edit .selectize-input,
.ig-add-row .selectize-input,
.dc-card .selectize-input {
  display: flex; align-items: center; flex-wrap: wrap; gap: 2px;
  padding: 2px 8px;
}
.ig-kv--edit .selectize-input > input,
.ig-add-row .selectize-input > input,
.dc-card .selectize-input > input { font-size: 12.5px !important; }
.ig-kv--edit .form-control::placeholder,
.ig-add-row .form-control::placeholder,
.ig-kv--edit .selectize-input input::placeholder,
.ig-add-row .selectize-input input::placeholder,
.dc-card .selectize-input input::placeholder {
  color: var(--dc-faint); font-size: 12.5px;
}
.ig-kv--edit .shiny-input-container,
.ig-add-row .shiny-input-container,
.dc-card .shiny-input-container { margin-bottom: 0; width: 100% !important; }
.ig-kv--edit .form-control:focus,
.ig-add-row .form-control:focus,
.dc-card .form-control:focus,
.ig-kv--edit .selectize-input.focus,
.ig-add-row .selectize-input.focus,
.dc-card .selectize-input.focus {
  outline: none;
  border-color: var(--dc-primary-line, var(--dc-primary));
  box-shadow: 0 0 0 2px var(--dc-primary-soft);
}
.dc-card { border-radius: 0; }

/* ── Festivals edit (film drawer — .ig-accordion keyed) ── */
.ddb2-fest-edit { display: none; }
.ig-accordion.is-editing .ddb2-fest-disp { display: none; }
.ig-accordion.is-editing .ddb2-fest-edit {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: var(--dc-space-3);
  align-items: start;
}
.ddb2-fe-main { min-width: 0; display: flex; flex-direction: column; gap: var(--dc-space-3); }
.ddb2-fe-name { font-size: 13px; font-weight: var(--dc-fw-semi); color: var(--dc-ink); }
.ddb2-fe-row { display: flex; gap: var(--dc-space-2); align-items: center; }
.ddb2-fe-row .form-select-sm,
.ddb2-fe-row .form-control-sm { font-size: 12px; }
.ddb2-fe-row .form-select-sm { padding: 3px 24px 3px 8px; }
.ddb2-fe-year { flex: 0 0 62px; text-align: center; }
.ddb2-fe-section { flex: 1 1 auto; min-width: 0; }
.ddb2-fe-result { flex: 0 0 104px; }
.ddb2-fest-remove, .ddb2-file-remove { padding: 3px 8px; color: var(--dc-danger); }
.ddb2-fest-add { display: none; margin-top: var(--dc-space-4); font-size: 11px; }
.ig-accordion.is-editing .ddb2-fest-add { display: inline-flex; align-items: center; }
.ddb2-fe-name-sel { width: 100%; font-size: 13px; }
.ddb2-fe-name.mono { font-family: var(--dc-font-mono); font-size: 12px; }

/* ── Files edit ──
   Edit rows render ONLY in edit mode since the 2026-07-21 port (the read
   view is an .ig-dtable) — no CSS view-swap; each row is a plain divider
   row. */
.ddb2-fileedit {
  display: grid;
  grid-template-columns: 1fr auto;
  column-gap: var(--dc-space-3);
  align-items: start;
  padding: var(--dc-space-4) 0;
  border-top: 1px solid var(--dc-line);
}
.ddb2-fileedit:first-child { border-top: none; padding-top: 0; }
.ddb2-fe-type { flex: 0 0 132px; }
.ddb2-fe-lang { flex: 1 1 auto; min-width: 0; }

/* ── Group drawers — films-in-group list row ── */
.ddb2-film {
  display: flex; align-items: center; gap: var(--dc-space-3);
  margin: 0 calc(-1 * var(--dc-space-6));
  padding: var(--dc-space-4) var(--dc-space-6);
  border-top: 1px solid var(--dc-line);
}
.ddb2-film:first-child { border-top: none; }
.ddb2-film__ic { font-size: 15px; color: var(--dc-faint); flex-shrink: 0; }
.ddb2-film__main { flex: 1 1 0; min-width: 0; }
.ddb2-film__title {
  font-size: 12.5px; font-weight: var(--dc-fw-semi); color: var(--dc-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ddb2-film__meta { font-size: 11px; color: var(--dc-muted); font-family: var(--dc-font-mono); margin-top: 2px; }
.ddb2-film__meta a, .dd-kv__v a { color: var(--dc-primary); text-decoration: none; }
.ddb2-film .dc-pill { flex-shrink: 0; }

/* ── Group drawers — workflow step list ── */
.ddb2-step { display: flex; align-items: flex-start; gap: var(--dc-space-3); padding: var(--dc-space-3) 0; }
.ddb2-step:first-child { padding-top: 0; }
.ddb2-step__dot {
  width: 18px; height: 18px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 9px;
  border: 2px solid var(--dc-line-2); color: var(--dc-muted); background: var(--dc-panel);
}
.ddb2-step__dot--ok { border-color: var(--dc-ok); color: var(--dc-ok); }
.ddb2-step__dot--run { border-color: var(--dc-warn); color: var(--dc-warn); }
.ddb2-step__lbl { font-size: 12.5px; color: var(--dc-ink); }
.ddb2-step__sub { font-size: 11px; color: var(--dc-faint); margin-top: 1px; }

/* ── Generic sub-entity list row ── */
.ddb2-lrow {
  display: flex; align-items: center; gap: var(--dc-space-3);
  margin: 0 calc(-1 * var(--dc-space-6));
  padding: var(--dc-space-4) var(--dc-space-6);
  border-top: 1px solid var(--dc-line);
}
.ddb2-lrow:first-child { border-top: none; }
.ddb2-lrow__main { flex: 1 1 0; min-width: 0; }
.ddb2-lrow__title { font-size: 12.5px; font-weight: var(--dc-fw-semi); color: var(--dc-ink); }
.ddb2-lrow__title .dc-pill { margin-left: var(--dc-space-2); }
.ddb2-lrow__meta { font-size: 11px; color: var(--dc-muted); margin-top: 2px; word-break: break-word; }
.ddb2-lrow__meta.mono { font-family: var(--dc-font-mono); }
.ddb2-lrow__act { display: flex; gap: var(--dc-space-2); flex-shrink: 0; }
.ddb2-rowbtn { padding: 2px 7px; font-size: 11px; }
.ddb2-rowbtn--danger { color: var(--dc-danger); }
.ddb2-additem { margin-top: var(--dc-space-3); font-size: 11px; display: inline-flex; align-items: center; }
.ddb2-help { font-size: 11px; color: var(--dc-faint); margin-top: var(--dc-space-3); line-height: 1.5; }

/* ── Schedule drawer — form bits + warning banner ── */
.ddb2-form-row { margin-bottom: var(--dc-space-4); }
.ddb2-form-row:last-child { margin-bottom: 0; }
.ddb2-form-label {
  font-size: 10.5px; font-weight: var(--dc-fw-bold); text-transform: uppercase;
  letter-spacing: var(--dc-track-label); color: var(--dc-faint);
  margin-bottom: var(--dc-space-2); display: block;
}
.ddb2-form-val { font-size: 13px; color: var(--dc-ink); }
.ddb2-form-val.ro { color: var(--dc-muted); font-family: var(--dc-font-mono); }
.ddb2-form-2 { display: flex; gap: var(--dc-space-2); }
.ddb2-form-2 .form-control-sm { font-size: 12px; }
.ddb2-warn {
  display: flex; gap: var(--dc-space-3); align-items: flex-start;
  background: var(--dc-warn-soft);
  border: 1px solid color-mix(in oklch, var(--dc-warn) 35%, var(--dc-line));
  border-radius: var(--dc-radius); padding: var(--dc-space-3) var(--dc-space-4);
  font-size: 12px; color: color-mix(in oklch, var(--dc-warn) 55%, black);
  margin-top: var(--dc-space-4); line-height: 1.45;
}
:root[data-bs-theme="dark"] .ddb2-warn { color: color-mix(in oklch, var(--dc-warn) 35%, white); }
.ddb2-warn .bi { flex-shrink: 0; margin-top: 1px; }

/* =========================================================================
   FILM-HEAD STRIP (poster/icon + title + sublines, above the accordion)
   LEGACY: removed from the film drawer 2026-07-21 (the 68px .dd-chrome--film
   carries title/status now; Core metadata carries the rest). Still rendered
   by Export Groups' group drawer (frozen bugfix-only) — keep until its
   visual refresh session.
   ========================================================================= */
.ddc-head {
  display: flex; gap: var(--dc-space-4); align-items: flex-start;
  padding: var(--dc-space-6) var(--dc-space-6);
  border-bottom: 1px solid var(--dc-line);
  background: var(--dc-panel);
  flex-shrink: 0;
}
.ddc-head__text { flex: 1 1 0; min-width: 0; }
.ddc-head__title {
  font-size: 14px; font-weight: var(--dc-fw-bold); color: var(--dc-ink);
  line-height: 1.35; margin-bottom: var(--dc-space-2);
}
.ddc-head__sub { font-size: 12px; color: var(--dc-muted); line-height: 1.5; margin-bottom: var(--dc-space-1); }
.ddc-head__chips {
  display: flex; gap: var(--dc-space-2); flex-wrap: wrap; margin-top: var(--dc-space-3);
}
