/* Bulma 1.0.4 is loaded from CDN in each page's <head>.
   Bulma derives every shade of a color from its hue/saturation/lightness parts,
   so overriding those parts here restyles buttons, tags, notifications, etc.
   in both light and dark mode. Dark mode itself is Bulma's own, keyed off the
   data-theme="dark" attribute that js/theme.js sets on <html>. */

:root {
  /* Theme palette (Simple Bulma Theme Color Picker):
     primary #d783ff · link #3273dc · info #209cee · success #23d160
     warning #ffdd57 · danger #ff7e79 (light/dark/black/white = Bulma defaults). */
  --bulma-primary-h: 281deg;
  --bulma-primary-s: 100%;
  --bulma-primary-l: 76%;
  --bulma-link-h: 217deg;
  --bulma-link-s: 71%;
  --bulma-link-l: 53%;
  --bulma-info-h: 204deg;
  --bulma-info-s: 86%;
  --bulma-info-l: 53%;
  --bulma-success-h: 141deg;
  --bulma-success-s: 71%;
  --bulma-success-l: 48%;
  --bulma-warning-h: 48deg;
  --bulma-warning-s: 100%;
  --bulma-warning-l: 67%;
  --bulma-danger-h: 2deg;
  --bulma-danger-s: 100%;
  --bulma-danger-l: 74%;

  /* Resolved here, against the theme active on :root, for components whose own
     scope re-declares Bulma's text variables (see .navbar below). */
  --app-text: var(--bulma-text);
  --app-text-strong: var(--bulma-text-strong);
}

/* Inline SVG icon sprite (see public/icons.php). Untitled UI icons are
   stroke-based and inherit currentColor; Simple Icons brand logos are fill. */
.ic { width: 1.25em; height: 1.25em; stroke: currentColor; fill: none;
      stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
      vertical-align: -0.15em; flex-shrink: 0; }
.ic-brand { stroke: none; fill: currentColor; }
.ic-sm { width: 1em; height: 1em; }
.ic-lg { width: 2em; height: 2em; }

/* Fixed navbar clearance */
body {
  padding-top: 3.25rem;
}

/* ── Uniform page gutters ─────────────────────────────────────────────────────
   Every page lays its content out in `.container.is-fullhd` wrappers (thumbnail,
   titles, notes, hrs, role headers, search/pagination …). Below the fullhd
   breakpoint that container is full-width with no side padding, so on smaller
   desktops the content ran flush to the viewport edges. Give every such wrapper
   the same 1.5rem gutters the database page already applied by hand via `px-5`
   (the data-table header/search still carry px-5, which resolves to the same
   value, so nothing doubles up). Tables are deliberately full-bleed: they live
   in `.table-container`, which carries no `.container` class, so they are never
   caught by this rule. */
.container.is-fullhd {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}

/* Neutral navbar: a shade darker than the page background in either theme.
   Derived from Bulma's scheme variables rather than a fixed colour, so it
   tracks the theme automatically (white page -> light grey bar; near-black
   page -> darker bar). Bulma keeps deriving the item text colour from the same
   scheme, so contrast holds without hardcoding it. */
.navbar {
  --bulma-navbar-background-color: hsl(
    var(--bulma-scheme-h),
    var(--bulma-scheme-s),
    calc(var(--bulma-scheme-main-l) - 6%)
  );
  border-bottom: 1px solid var(--bulma-border);
}

/* Bulma re-declares its text variables inside .navbar under a
   prefers-color-scheme media query, which data-theme cannot override — so
   inside the navbar, var(--bulma-text) yields the OS's colour rather than the
   chosen theme's, and the text ended up unreadable in one theme or the other.
   Capturing the colours at :root pins them to the active theme (custom
   properties are substituted where they are declared), and the navbar then
   inherits an already-resolved value. */
/* Selectors match Bulma's own a.navbar-item specificity, which a bare
   .navbar-item would lose to. */
.navbar a.navbar-item,
.navbar .navbar-link {
  color: var(--app-text);
}

.navbar a.navbar-item:hover,
.navbar .navbar-link:hover,
.navbar a.navbar-item.is-active,
.navbar .navbar-link.is-active {
  color: var(--app-text-strong);
}

/* Center the primary nav items rather than letting them hug the brand.
   Bulma's .navbar-start only pushes everything else right, so it needs to be
   told to fill the space before its contents can be centred within it. */
.navbar-menu .navbar-start {
  flex-grow: 1;
  justify-content: center;
}

/* ── Responsive navbar ───────────────────────────────────────────────────────
   Three layouts share one markup:
     • Desktop (≥1024px): the horizontal menu. If it would overflow beside the
       brand, js/navbar adds .is-collapsed and it folds into the "more" dropdown.
     • Tablet (769–1023px): a compact icon-only horizontal bar with floating
       dropdowns (see the media query below).
     • Mobile (≤768px): a single "more" button opening a full-screen panel.
   We force the navbar into a horizontal flex at all widths (Bulma otherwise
   stacks it below 1024px) so the overflow measurement is consistent. */
.navbar {
  display: flex;
  align-items: stretch;
}
.navbar-menu { display: flex; }
.navbar-collapsed-menu { display: none; }
.navbar.is-collapsed .navbar-menu { display: none; }
.navbar.is-collapsed .navbar-brand { flex-grow: 1; }
.navbar.is-collapsed .navbar-collapsed-menu {
  display: flex;
  margin-left: auto; /* push the dots trigger to the far right of the brand row */
}
.navbar-collapsed-menu .navbar-link.is-arrowless::after { display: none; }

/* The "more" dropdown: a right-anchored floating panel (used when the desktop
   menu collapses; the mobile media query re-styles it into a full-screen panel).
   Opened by click via .is-active (js/navbar). */
.navbar-collapsed-menu .navbar-dropdown {
  display: none;
  position: absolute;
  top: 100%;
  right: 0.5rem;
  left: auto;
  min-width: 15rem;
  max-width: calc(100vw - 1rem);
  background-color: var(--bulma-navbar-dropdown-background-color, var(--bulma-scheme-main));
  border: 1px solid var(--bulma-border);
  border-radius: 0 0 var(--bulma-radius-large, 8px) var(--bulma-radius-large, 8px);
  box-shadow: 0 8px 16px hsla(0, 0%, 0%, 0.15);
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  z-index: 30;
}
.navbar-collapsed-menu.is-active .navbar-dropdown { display: block; }

/* Accordions inside the "more" dropdown (Projects / Menu). */
.navbar-accordion-toggle { display: flex; align-items: center; cursor: pointer; font-weight: 600; position: relative; padding-inline-end: 2.5em; }
.navbar-accordion-toggle .acc-label { flex-grow: 1; }
/* The expand indicator uses the same Bulma dropdown-arrow ::after as the navbar
   links (not an SVG chevron); it flips up when the section is expanded. */
.navbar-accordion-toggle .acc-chevron { display: none; }
.navbar-accordion-toggle::after {
  content: " "; display: block; position: absolute; pointer-events: none;
  width: 0.625em; height: 0.625em;
  border: 3px solid var(--bulma-navbar-dropdown-arrow); border-top: 0; border-inline-end: 0; border-radius: 2px;
  top: 50%; inset-inline-end: 1.125em; margin-top: -0.375em;
  transform: rotate(-45deg); transform-origin: center; transition: transform .15s ease;
}
.navbar-accordion-toggle[aria-expanded="true"]::after { margin-top: -0.125em; transform: rotate(135deg); }
.navbar-accordion-content .navbar-item { padding-left: 2.25rem; }  /* indent under a header */

/* Starred projects live inline on desktop; the copy inside the PROJECTS dropdown
   only surfaces on tablet (see the tablet media query). */
.projects-dd-starred { display: none; }

/* ── Compact navbar (≤1023px): tablet & phone ────────────────────────────────
   Same three-section layout as the desktop bar — brand (left) · navbar-start
   (centred) · navbar-end (right) — all on one vertically-centred row. The menu
   stays visible at every width down to the smallest phone; it never folds into
   the dots menu here. Labels collapse to their icons and dropdowns open on
   click (Bulma's hover-open is neutralised to kill the flicker/arrow artefact). */
@media screen and (max-width: 1023px) {
  /* The real menu stays; the dots "more" button is desktop-overflow-only. */
  .navbar .navbar-collapsed-menu { display: none !important; }
  .navbar.is-collapsed .navbar-menu { display: flex !important; }

  .navbar { align-items: center; }
  .navbar .navbar-menu {
    display: flex !important;
    flex-grow: 1;
    align-items: center;
    padding: 0;
    background: transparent;
    box-shadow: none;
  }
  /* Bulma's `.navbar.is-fixed-top .navbar-menu` forces overflow:auto + a
     max-height at touch widths, which clipped the open dropdown to the bar's
     height. Override at equal specificity so the dropdown can escape the bar. */
  .navbar.is-fixed-top .navbar-menu,
  .navbar.is-fixed-bottom .navbar-menu {
    overflow: visible;
    max-height: none;
  }
  .navbar-menu .navbar-start,
  .navbar-menu .navbar-end { display: flex; align-items: center; }
  .navbar-menu .navbar-start { flex-grow: 1; justify-content: center; }

  /* Vertically centre every item (and its icon) within the bar. */
  .navbar-brand .navbar-item,
  .navbar-menu .navbar-item,
  .navbar-menu .navbar-link { display: flex; align-items: center; }

  /* Floating dropdowns (Bulma expands them inline at touch widths). */
  .navbar-menu .navbar-item.has-dropdown { position: relative; }
  .navbar-menu .navbar-dropdown {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 14rem;
    background-color: var(--bulma-navbar-dropdown-background-color, var(--bulma-scheme-main));
    border: 1px solid var(--bulma-border);
    border-radius: 0 0 var(--bulma-radius-large, 8px) var(--bulma-radius-large, 8px);
    box-shadow: 0 8px 16px hsla(0, 0%, 0%, 0.15);
    padding: 0.5rem 0;
    z-index: 30;
  }
  .navbar-menu .navbar-dropdown.is-right { left: auto; right: 0; }
  /* Open on click only: neutralise Bulma's hover-open (the flicker source) … */
  .navbar-menu .navbar-item.has-dropdown:hover > .navbar-dropdown { display: none; }
  /* … then reveal on .is-active, set by the click handler in js/navbar. */
  .navbar-menu .navbar-item.has-dropdown.is-active > .navbar-dropdown { display: block; }

  /* Icon-only: hide the text labels, keep the icons (DATABASE, PROJECTS …). */
  .navbar-menu .navbar-item > strong,
  .navbar-menu .navbar-link > strong { display: none; }

  /* Brand stays untouched on tablet (wordmark + Admin/Guest tag). On phones the
     wordmark is dropped but the role tag is kept — see the ≤768 block below. */

  /* Keep the starred projects inline in the centre (titles capped globally —
     see .nav-proj-title). The dropdown copy stays hidden. */
  #starredProjectsContainer { display: flex !important; }
  .projects-dd-starred { display: none; }
}

/* Every project title (starred or in a dropdown) is capped at 160px with an
   ellipsis at all window sizes ("Long title co…"). */
.nav-proj-title {
  display: inline-block; max-width: 160px; vertical-align: bottom;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Phone (≤768px): keep dropdowns on-screen ────────────────────────────────
   A centred trigger's dropdown would spill off the right edge on a narrow phone.
   Anchor every open dropdown to the navbar's right edge instead (only one is
   ever open at a time) and cap it to the viewport. Making the trigger `static`
   lets the panel position against the fixed navbar rather than the trigger. */
@media screen and (max-width: 768px) {
  /* ── Apple-style phone navbar ──────────────────────────────────────────────
     LEFT: the "Somogyi Aliz Casting" wordmark + the Admin/Guest tag.
     RIGHT: the avatar — tapping it opens a full-screen scrollable menu. */
  .navbar { display: flex; align-items: center; }
  .navbar .navbar-brand { flex: 1 1 auto; min-width: 0; }
  .navbar .navbar-menu { flex: 0 0 auto; justify-content: flex-end; }

  /* Keep the wordmark; only the avatar stays in the bar on the right. */
  .navbar-brand-text { display: inline; }
  .navbar-menu .navbar-start { display: none !important; }
  .navbar-menu .navbar-end { display: flex; }

  /* No separate dots trigger — the avatar is the trigger. Keep the collapsed
     menu's container (it holds the full-screen panel) but hide its button. */
  .navbar .navbar-collapsed-menu { display: flex !important; }
  .navbar-collapsed-trigger { display: none !important; }

  /* The avatar shows the dropdown arrow (it's the menu trigger on phones). */
  .navbar-menu .navbar-link:not(.is-arrowless) { padding-inline-end: 2.5em; }
  .navbar-menu .navbar-link:not(.is-arrowless)::after {
    display: block;
    border-color: var(--bulma-navbar-dropdown-arrow);
    inset-inline-end: 1.125em;
    margin-top: -0.375em;
  }

  /* The menu panel: full width + height, scrollable, left-aligned big rows. */
  .navbar-collapsed-menu .navbar-dropdown {
    position: fixed; inset: var(--navbar-h, 3.25rem) 0 0 0;
    width: 100vw; max-width: none; height: auto;
    max-height: calc(100vh - var(--navbar-h, 3.25rem));
    overflow-y: auto; border: none; border-radius: 0; box-shadow: none;
    padding: 1rem 1.5rem 3rem;
  }
  .navbar-collapsed-menu .navbar-dropdown .navbar-item,
  .navbar-collapsed-menu .navbar-dropdown .navbar-accordion-toggle {
    justify-content: flex-start; text-align: left;
    font-size: 1.15rem; padding: 0.7rem 0;
  }
  .navbar-collapsed-menu .navbar-accordion-content .navbar-item { padding-left: 1.5rem; font-size: 1.05rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   DATA-TABLE COMPONENT STYLES
   Everything from here down styles the reusable data-table core and its
   collaborators: the table + sortable headers + drag/select affordances
   (components/data-table.php, js/data-table.js), the scheme editor
   (components/scheme-modal.php, js/scheme.js), and the actor card
   (actor-card.php, js/actor-card.js) — plus the shared checkbox/toggle/skeleton/
   date-picker/tag-select widgets they use. Kept in this shared stylesheet (loaded
   on every page) rather than a separate file, so the cascade order is preserved;
   edit here to restyle the component everywhere it is mounted.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Scroll behaviour: collapsing title header + sticky search ────────────────
   On scroll the title header (data-dt-header) collapses away while the search
   bar (data-dt-search) sticks just under the fixed navbar (3.25rem tall), so it
   reads like the search field is pinned to the navbar. Scrolling back to the
   top restores the title header. `body.dt-scrolled` is toggled by the scroll
   handler in js/data-table.js. */
.data-table [data-dt-header] {
  max-height: 4rem;
  transition: max-height .25s ease, opacity .2s ease,
              margin-bottom .25s ease, padding-top .25s ease;
}
body.dt-scrolled .data-table [data-dt-header] {
  max-height: 0;
  opacity: 0;
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  padding-top: 0;
  padding-bottom: 0;
  pointer-events: none;
}
/* The search bar lives outside the scrolling .table-container, so it is always
   visible; once the title header collapses it simply rises to sit flush under
   the fixed navbar — no sticky positioning required (and sticky would misbehave
   anyway: .db-shell's `overflow:hidden` makes it the sticky containing block and
   adds a spurious top offset). The box-shadow on scroll gives it a pinned feel. */
.data-table [data-dt-search] {
  z-index: 20;
  background-color: var(--bulma-body-background-color, var(--bulma-scheme-main));
  padding-top: .75rem;
  padding-bottom: .75rem;
  transition: box-shadow .2s ease;
}

/* Outline the whole table, not just the cell grid. --bulma-border resolves
   against the active theme, so this holds up in light and dark. */
.table {
  border: 1px solid var(--bulma-border);
  border-radius: var(--bulma-radius);
  overflow: hidden;
}

.table td, .table th {
  vertical-align: middle !important;
  cursor: pointer;
}

.field-column {
  min-width: 175px;
}

/* Drag-and-drop affordances for the sortable cast sheet tables */
.drag-handle {
  cursor: grab !important;
  color: var(--bulma-text-weak, #999);
}

td.drag-handle .ic,
td.drag-disabled .ic {
  display: block;
  margin: 0 auto;
}

.drag-handle:hover {
  color: var(--app-text);
}

.drag-handle:active {
  cursor: grabbing;
}

/* ── Sortable column headers ─────────────────────────────────────── */

.sortable-col {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.sortable-col:hover,
.sortable-col.is-sorted {
  color: var(--bulma-title-color) !important;
}

/* Header hover background — themed: lighter in light mode, darker in dark mode. */
.sortable-col:hover {
  background-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), 92%) !important;
}
:root[data-theme="dark"] .sortable-col:hover {
  background-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), 17%) !important;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .sortable-col:hover {
    background-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), 17%) !important;
  }
}

.sort-ind {
  font-size: 0.7em;
  opacity: 0.85;
}

/* Category-column sort+filter dropdown. */
.filter-col { position: relative; }
.sortable-col.is-filtered { color: var(--bulma-primary) !important; }
.dt-filter-panel {
  position: absolute; top: 100%; left: 0; z-index: 40; margin-top: 4px;
  min-width: 180px; max-height: 380px; overflow-y: auto;
  background: var(--app-panel, var(--bulma-scheme-main)); color: var(--app-text);
  border: 1px solid var(--bulma-border); border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0,0,0,.25); padding: .4rem;
  cursor: default; font-weight: 400; white-space: normal;
}
.dt-filter-sort { display: flex; gap: .4rem; margin-bottom: .4rem; }
.dt-filter-sort button {
  flex: 1 1 0; display: flex; align-items: center; justify-content: center;
  padding: .3rem .4rem; cursor: pointer;
  background: var(--bulma-scheme-main-bis); color: var(--app-text);
  border: 1px solid var(--bulma-border); border-radius: 4px;
}
.dt-filter-sort button.is-on { background: var(--bulma-primary); color: #fff; border-color: var(--bulma-primary); }
/* Reuse the actor-card chip selector, but stacked one option per row. */
.dt-filter-opts.tag-select-container { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: .3rem; }
.dt-filter-opts .tag-select-label { display: block; text-align: center; }

.is-placeholder {
  opacity: 0.5;
}

/* ── Compact toggle switch for field visibility ──────────────────── */

.switch { display: inline-flex; align-items: center; cursor: pointer; flex-shrink: 0; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track { width: 34px; height: 18px; border-radius: 999px; background: #555;
  display: inline-block; position: relative; transition: background .15s; flex-shrink: 0; }
.switch-thumb { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
  border-radius: 50%; background: #fff; transition: transform .15s; }
.switch input:checked + .switch-track { background: var(--bulma-success); }
.switch input:checked + .switch-track .switch-thumb { transform: translateX(16px); }
.switch input:focus-visible + .switch-track { outline: 2px solid var(--bulma-link); outline-offset: 2px; }

/* ── Custom checkboxes (getcssscan "checkbox-4" style) ────────────────
   The real <input> is hidden and a sibling .cbx4-box is styled instead — the
   same approach the source example uses, because styling <input> directly
   (pseudo-elements / :checked background) is unreliable in WebKit. Faithful to
   the example: rounded box, #07f fill when checked, a white check that draws
   in via stroke-dashoffset, and a subtle "wave" scale on toggle. */
.cbx4 {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  user-select: none;
  vertical-align: text-bottom;
  margin-left: 0.25rem;
}

.cbx4 > input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  margin: 0;
}

.cbx4-box {
  position: relative;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  border: 1px solid #cccfdb;
  border-radius: 4px;
  background: #fff;
  box-shadow: 0 1px 1px rgba(0, 16, 75, 0.05);
  transition: background 0.2s ease, border-color 0.2s ease;
}

.cbx4-box svg {
  position: absolute;
  top: 3px;
  left: 2px;
  width: 12px;
  height: 10px;
  fill: none;
  stroke: #fff;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 16px;
  stroke-dashoffset: 16px;
  transition: stroke-dashoffset 0.3s ease 0.1s;
}

.cbx4-text {
  padding-left: 8px;
  line-height: 18px;
}

.cbx4:hover .cbx4-box {
  border-color: #07f;
}

.cbx4 > input:checked + .cbx4-box {
  background: #07f;
  border-color: #07f;
  animation: cbx-wave 0.4s ease;
}

.cbx4 > input:checked + .cbx4-box svg {
  stroke-dashoffset: 0;
}

.cbx4 > input:focus-visible + .cbx4-box {
  outline: 2px solid #07f;
  outline-offset: 2px;
}

@keyframes cbx-wave {
  50% { transform: scale(0.9); }
}

/* ── Scheme modal card rows ─────────────────────────────────────── */

/* The scheme modal has no footer now (its actions live inside each section),
   so round the body's bottom corners to match the header. */
.modal-card-body:last-child {
  border-bottom-left-radius: var(--bulma-radius-large, 8px);
  border-bottom-right-radius: var(--bulma-radius-large, 8px);
}

.scheme-field-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--bulma-border);
}

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

.scheme-drag-handle {
  cursor: grab;
  color: var(--bulma-text-weak, #999);
  flex-shrink: 0;
}

.scheme-drag-handle:active {
  cursor: grabbing;
}

.scheme-drag-handle svg {
  display: block;
  margin: 0 auto;
}

.scheme-remove-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--bulma-danger);
  opacity: 0.7;
  flex-shrink: 0;
}

.scheme-remove-btn:hover {
  opacity: 1;
}

.scheme-field-info {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

.scheme-field-name {
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.scheme-field-row-start, .scheme-field-row-end {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1rem;
}

.scheme-field-row-end {
  justify-content: flex-end;
  gap: 0.5rem; /* tighter than the row's 1rem so the two control columns line up under the labels */
}

/* Fixed-width, centred control cells so the Search / Visible column labels
   line up above them. */
.scheme-field-row-end > .scheme-search-cbx,
.scheme-field-row-end > .switch {
  width: 2.75rem;
  justify-content: center;
  margin: 0;
}

/* Column labels above the field list (Search = checkbox, Visible = toggle). */
.scheme-list-header {
  display: flex;
  justify-content: flex-end;
  gap: 1rem;
  padding: 0 1.75rem 0.4rem;
}

.scheme-col-label {
  width: 2.75rem;
  text-align: center;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bulma-text-weak);
}

/* Selected/focused field row — visible in both light and dark themes via a
   translucent link tint plus a solid left accent bar. */
.scheme-field-row.is-selected {
  background-color: hsla(var(--bulma-link-h), var(--bulma-link-s), var(--bulma-link-l), 0.14);
  box-shadow: inset 3px 0 0 0 var(--bulma-link);
  cursor: default;
}

.scheme-field-row:not(.is-selected):hover {
  background-color: var(--bulma-background);
}

.scheme-edit-section {
  display: none;
}

.scheme-edit-section.is-active {
  display: block;
}

/* ── Chip-style subcategory pills ───────────────────────────────── */

.scheme-chip-container {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-bottom: 0.5rem;
}

.scheme-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.2rem 0.6rem;
  border-radius: var(--bulma-radius);
  color: hsl(var(--bulma-info-h), var(--bulma-info-s), calc(var(--bulma-info-l) - 45%));
  font-size: 0.8rem;
}

.scheme-chip button {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.15s ease;
}

.scheme-chip button:hover {
  opacity: 1;
}

.scheme-add-sub {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.scheme-add-sub .input {
  min-width: 120px;
}

.card-tab-panel.is-hidden {
  display: none;
}

.tabs li.is-disabled a {
  opacity: 0.4;
  pointer-events: none;
}

.card-photo-placeholder {
  height: 100%;
  border-radius: var(--bulma-radius);
  background: var(--bulma-scheme-main-ter);
  color: var(--bulma-title-color);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-weight: 600;
  border: 2px dashed;
  border-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), calc(var(--bulma-scheme-l) - 10%));
}


.card-name-edit-wrap {
  width: 100%;
}

/* In edit mode the hero inputs carry their own left icon, so hide the
   standalone leading display icons (toggled via #cardTabProfile.primary-editing). */
.primary-editing .hero-lead-icon {
  display: none;
}

.card-name-input-strong {
  font-weight: 700;
  text-transform: uppercase;
}

.hero-field-input {
  font-size: 0.95rem;
}

.hero-field-input:focus {
  outline: none;
  color: var(--app-text);
  text-decoration: none;
}

.icon-link {
  cursor: pointer;
  color: var(--bulma-link);
}

.save-status { font-size: .78rem; font-weight: 400; color: var(--bulma-text-weak, #999); margin-left: .5rem; }
.hero-open-link { cursor: pointer; color: var(--bulma-link); }

.card-media-placeholder {
  height: 160px;
  border-radius: var(--bulma-radius);
  border: 1px dashed var(--bulma-border);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  color: var(--bulma-text-weak, #999);
}

/* ── Hero field display (read-only clickable text) ─────────────── */

.hero-field-display {
  flex: 1;
  cursor: pointer;
  padding: 0.2em 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--app-text);
  text-decoration: underline;
  text-underline-offset: 0.12em;
}

.hero-field-display:hover {
  opacity: 0.8;
}

.actor-count-spinner {
  display: inline-block;
  width: 0.9em;
  height: 0.9em;
  margin-right: 0.35em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 999px;
  animation: actor-count-spin 0.75s linear infinite;
  vertical-align: -0.1em;
}

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

/* ═══════════════════════════════════════════════════════════════════════════
   PROJECT-PAGE COMPONENTS (notes, role-sheets, etc.)
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Flex utilities ──────────────────────────────────────────────── */

.d-flex { display: flex !important; }
.justify-space-between { justify-content: space-between !important; }
.align-center { align-items: center !important; }
.gap-2 { gap: 0.5rem !important; }

/* ── Notes grid ──────────────────────────────────────────────────── */

.notes-grid {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
}

/* Note skeletons: three cards share one row equally, same shimmer tone as
   every other placeholder (driven by the base `.skeleton` class). */
.skeleton-note-card {
  flex: 1 1 0;
  min-width: 0;
  min-height: 160px;
  border-radius: var(--bulma-radius-large);
}

.note-card {
  /* Grow to fill the row like the skeletons: 2 notes split the row, 3 split it,
     a 4th wraps to the next row. The ~340px basis is the wrap threshold. */
  flex: 1 1 340px;
  min-width: 340px;
  max-width: 100%;
  /* Fixed height so every card is uniform; the editor scrolls inside, and the
     expand button opens the modal for notes too long to read here. */
  height: 22rem;
  display: flex;
  flex-direction: column;
  border-radius: var(--bulma-radius-large);
  overflow: hidden;
  background: var(--bulma-scheme-main);
  border: 1px solid var(--bulma-border-subtle, var(--bulma-border));
}

/* The header and toolbar keep their natural height; the editor fills the rest
   of the fixed-height card and scrolls. */
.note-card .rich-editor {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

.note-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.4rem 0.6rem;
  background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), calc(var(--bulma-scheme-l) + 8%));
  border-bottom: 1px solid var(--bulma-border-subtle, var(--bulma-border));
}

.note-toolbar-left {
  display: flex;
  gap: 0.2rem;
}

.note-toolbar-right {
  display: flex;
  gap: 0.25rem;
  align-items: center;
}

.note-toolbar-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.15rem 0.3rem;
  color: var(--bulma-text-weak);
  border-radius: var(--bulma-radius);
  transition: color .12s, background .12s;
}

.note-toolbar-btn:hover {
  color: var(--app-text);
  background: var(--bulma-background);
}

.note-toolbar-btn.active {
  color: var(--bulma-link);
}

.note-delete-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: hsl(348, 72%, 55%);
  opacity: 0.5;
  padding: 0.15rem;
  transition: opacity .12s;
}

.note-delete-btn:hover {
  opacity: 1;
}

.note-toolbar-sep {
  width: 1px;
  height: 1.2em;
  background: var(--bulma-border);
  margin: 0 0.15rem;
}

.note-body {
  min-height: 140px;
  max-height: 360px;
  overflow-y: auto;
  padding: 0.9rem 1rem;
  background: var(--bulma-scheme-main);
  color: var(--app-text);
  line-height: 1.6;
}

.note-body:empty::before {
  content: "Note text comes here...";
  color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), calc(var(--bulma-scheme-l) + 25%));
  pointer-events: none;
}

.note-body h1 { font-size: 1.15rem; font-weight: 700; margin: 0 0 0.4rem; }
.note-body b, .note-body strong { font-weight: 600; }
.note-body a { color: var(--bulma-link); text-decoration: underline; }

/* ── Inline-edit input overlay ───────────────────────────────────── */

.is-inline-edit {
  display: inline-block !important;
  min-width: 8rem;
  max-width: 24rem;
  vertical-align: middle;
  font-size: inherit;
  font-weight: inherit;
}

/* ── Role-sheets section ─────────────────────────────────────────── */

.role-sheets-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.role-count-badge {
  font-size: 0.85em;
  padding: 0.2em 0.6em;
  border-radius: var(--bulma-radius);
}

.actor-count-badge {
  font-size: 0.85em;
  padding: 0.2em 0.6em;
  border-radius: var(--bulma-radius);
}

.role-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .8rem 1rem;
  margin-bottom: 0.25rem;
  background: var(--bulma-scheme-main-bis);
  transition: border-color .12s;
  border-radius: var(--bulma-radius-large);
}



/* ── Role title bar (matches the draft) ─────────────────────────── */
.role-row-left {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}
.role-row-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

.role-title {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
  margin: 0;
  color: var(--bulma-text-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.role-title-input {
  font-size: 1.35rem;
  font-weight: 700;
  max-width: 18rem;
  height: auto;
}

/* Uniform count pill used everywhere on the page (header roles/actors count,
   per-role actor count, …). Only sizing/shape/weight are set here; the
   background and text colour come from Bulma's own .tag colour modifiers
   (is-info, is-warning, …) so those stay user-controllable. */
.count-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.32em;
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.4;
  height: auto;
  border-radius: 999px;
  padding: 0.28em 0.75em;
  flex-shrink: 0;
}
.count-pill .count-value { font-variant-numeric: tabular-nums; }

/* Vertical split between the action buttons and the collapse chevron. */
.role-divider {
  width: 1px;
  height: 1.4rem;
  background: var(--bulma-border);
  margin: 0 0.15rem;
}

/* Recolour swatches shown on the right while renaming a role. */
.role-swatches { margin-right: 0.35rem; }

/* Role title-bar tint — a translucent wash of the theme colour so it stays
   visible on any palette in both light and dark. `[data-theme]` gives the
   selector enough weight to beat the dark-mode `.role-row` background rule. */

/* ── Role row drag handle icon (hidden by default, shown in reorder mode) ── */
.drag-handle-icon svg { display: block; margin: 0 auto; color: var(--bulma-text-weak); cursor: grab; }
.drag-handle-icon:active svg { cursor: grabbing; }

/* Reorder / remove-role modes disable a role's own action buttons. */
body.reorder-active .role-row-right .button,
body.remove-role-active .role-row-right .button { opacity: 0.4; pointer-events: none; }

/* The ✕ shown per role while in remove-role mode. */
.role-remove-x {
  background: none; border: none; cursor: pointer; padding: 0 .35rem 0 0;
  color: var(--bulma-danger); display: inline-flex; align-items: center;
}
.role-remove-x .ic { width: 1.15em; height: 1.15em; }
/* Red spinner shown in place of the ✕ while a role is being removed. */
.role-remove-spinner {
  display: inline-block; width: 1.05em; height: 1.05em;
  border: 2px solid var(--bulma-danger); border-right-color: transparent;
  border-radius: 999px; animation: actor-count-spin 0.75s linear infinite; vertical-align: -0.15em;
}
.role-remove-x:hover { color: hsl(var(--bulma-danger-h), var(--bulma-danger-s), calc(var(--bulma-danger-l) - 12%)); }

/* ── Notes rich-text editor (low-key H1 / bold / italic / link) ──── */

/* Toolbar: a thin row whose height fits the buttons, with a divider below. */
.rt-toolbar {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.5rem;
  /* A raised, theme-aware surface (the old --bulma-scheme-l was undefined in
     Bulma 1.0, so this quietly rendered transparent). */
  background: var(--bulma-scheme-main-ter, var(--bulma-background));
  border-bottom: 1px solid var(--bulma-border);
}

.rt-group {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

/* Vertical split between button clusters. */
.rt-divider {
  width: 1px;
  align-self: stretch;
  margin: 0.15rem 0.15rem;
  background: var(--bulma-border);
}

/* The editable note body — this is the tall box, not the toolbar. */
.rich-editor {
  min-height: 14rem;
  max-height: 24rem;
  overflow-y: auto;
  padding: 0.75rem 0.9rem;
  background: var(--bulma-scheme-main);
  line-height: 1.5;
  color: var(--app-text);
  outline: none;
}

/* ── Note colour swatches (bulma theme picker) ─────────────────── */
.note-swatches {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}

.note-swatch {
  width: 1.05rem;
  height: 1.05rem;
  padding: 0;
  border-radius: 5px;
  border: 1px solid rgba(0, 0, 0, 0.15);
  cursor: pointer;
  transition: transform .1s;
}
.note-swatch:hover { transform: scale(1.15); }

.note-swatch-primary { background: var(--bulma-primary); }
.note-swatch-info    { background: var(--bulma-info); }
.note-swatch-warning { background: var(--bulma-warning); }
.note-swatch-danger  { background: var(--bulma-danger); }
.note-swatch-clear {
  background: var(--bulma-scheme-main);
  position: relative;
}
.note-swatch-clear::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top left, transparent 43%, var(--bulma-danger) 45%, var(--bulma-danger) 55%, transparent 57%);
}

/* Outlined state for the currently selected swatch (roles + notes).
   Higher specificity than Bulma's own .note-swatch rules so it wins even
   when combined classes like note-swatch-primary are present. */
div.note-swatches .note-swatch.is-selected {
  outline: 2px solid var(--bulma-link) !important;
  outline-offset: 1px;
  box-shadow: 0 0 0 1px var(--bulma-link) !important;
}

/* Ordered list of roles (visual ordering indicator). */
.role-row[draggable="true"] {
  border-left: 3px solid var(--bulma-link);
}

/* Soft theme tint applied to a coloured note card. Prefixed with .notes-grid so
   these win over the dark-mode `.note-card` background rule (higher specificity). */
:root .notes-grid .note-card.note-color-primary { background: hsl(var(--bulma-primary-h), var(--bulma-primary-s), calc(var(--bulma-primary-l) + 18%)); }
:root .notes-grid .note-card.note-color-info    { background: hsl(var(--bulma-info-h), var(--bulma-info-s), calc(var(--bulma-info-l) + 30%)); }
:root .notes-grid .note-card.note-color-warning { background: hsl(var(--bulma-warning-h), var(--bulma-warning-s), calc(var(--bulma-warning-l) + 20%)); }
:root .notes-grid .note-card.note-color-danger  { background: hsl(var(--bulma-danger-h), var(--bulma-danger-s), calc(var(--bulma-danger-l) + 16%)); }
:root .notes-grid .note-card[class*="note-color-"] .rich-editor { background: transparent; color: #1a1a1f; }
.notes-grid .note-card[class*="note-color-"] .rt-toolbar,
.notes-grid .note-card[class*="note-color-"] .note-header { background: rgba(0,0,0,0.06); }

.rich-editor h1 {
  font-size: 1.2rem;
  font-weight: 700;
  margin: 0 0 0.5rem;
}

.rich-editor a {
  color: var(--bulma-link);
  text-decoration: underline;
}

/* Placeholder shown only while the editor is truly empty. */
.rich-editor:empty::before {
  content: attr(data-placeholder);
  color: var(--bulma-text-weak);
  pointer-events: none;
}

/* Link dialog (shared style, sits above the actor-card modal). */
.link-dialog-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.link-dialog-box {
  background: var(--bulma-scheme-main);
  border: 1px solid var(--bulma-border);
  border-radius: 8px;
  padding: 1.25rem 1.5rem;
  width: min(400px, 90vw);
  color: var(--app-text);
}

.link-dialog-box h3 {
  margin: 0 0 0.75rem;
  font-size: 1rem;
  font-weight: 600;
}

.link-dialog-box label {
  display: block;
  margin-bottom: 0.6rem;
  font-size: 0.82rem;
  color: var(--bulma-text-weak);
}

.link-dialog-box .dialog-row {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin-top: 1rem;
}

/* ── Database app-shell: one scroll region so the table header stays pinned ──
   The page fills the viewport below the fixed navbar and does not scroll itself;
   the table body is the only scroll area, so #actorsTableHead (sticky, below)
   stays pinned under the toolbar while rows scroll. mt-6 (3rem) + navbar
   (3.25rem) are subtracted so main lines up exactly to the viewport bottom. */
.db-shell {
  height: calc(100vh - 3.25rem - 3rem);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.db-shell > .section {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* ── Table container with scroll ───────────────────────────────── */

.table-container {
  flex: 1 1 auto;   /* fill the space between the toolbar and the pagination bar */
  min-height: 0;    /* allow the flex child to shrink so it, not the page, scrolls */
  overflow-y: auto;
  overflow-x: auto;
}

/* The table carries overflow:hidden, which sits between the sticky <th> and the
   scrolling .table-container and silently disables the sticky header. Clear it
   so #actorsTableHead can pin while rows scroll. */
.table-container > table {
  overflow: visible;
}

/* ── Minimalist tag-select (category chips) ─────────────────────── */

.tag-select-container {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.tag-select-option {
  cursor: pointer;
  user-select: none;
}

.tag-select-option input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.tag-select-label {
  display: inline-block;
  padding: 0.3em 0.75em;
  border: 2px solid var(--bulma-border);
  border-radius: var(--bulma-radius);
  font-size: 0.85rem;
  color: var(--app-text);
  background: transparent;
  transition: background .12s, color .12s, border-color .12s;
}

.tag-select-option input[type="checkbox"]:checked + .tag-select-label {
  background: var(--bulma-primary);
  color: hsl(var(--bulma-primary-h), var(--bulma-primary-s), calc(var(--bulma-primary-l) - 30%));
  border-color: var(--bulma-primary);
}

.tag-select-option input[type="checkbox"]:focus-visible + .tag-select-label {
  outline: 2px solid var(--bulma-link);
  outline-offset: 2px;
}

.tag-select-label:hover {
  border-color: var(--bulma-text-weak);
}

/* ── Date picker input wrapper ─────────────────────────────────── */

.date-picker-wrapper {
  position: relative;
  width: 100%;
}

.card-date-input {
  padding-right: 2.5rem;
  cursor: pointer;
}

.date-picker-trigger {
  position: absolute;
  right: .375rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1.75rem;
  height: 1.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--bulma-text-weak);
  border-radius: var(--bulma-radius);
  transition: background .12s, color .12s;
}

.date-picker-trigger:hover {
  background: var(--bulma-background);
  color: var(--app-text);
}

/* ── Date picker popup calendar ───────────────────────────────── */

.date-picker-popup {
  position: fixed;   /* fixed + JS-positioned so the modal's overflow can't clip it */
  z-index: 1000;
  background: var(--bulma-scheme-main);
  border: 1px solid var(--bulma-border);
  border-radius: var(--bulma-radius);
  padding: .75rem;
  width: 240px;
  box-shadow: 0 .5em 2em -0.375em hsla(var(--bulma-scheme-h), var(--bulma-scheme-s), 16%, .25);
}

.dp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: .5rem;
}

.dp-month-year {
  font-size: .825rem;
  font-weight: 600;
  color: var(--app-text);
}

.dp-nav {
  background: none;
  border: none;
  cursor: pointer;
  width: 1.75rem;
  height: 1.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--bulma-radius);
  color: var(--app-text);
  font-size: .85rem;
  transition: background .12s;
}

.dp-nav:hover {
  background: var(--bulma-background);
}

.dp-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0;
  margin-bottom: .125rem;
}

.dp-weekdays span {
  text-align: center;
  font-size: .65rem;
  font-weight: 600;
  color: var(--bulma-text-weak);
  text-transform: uppercase;
}

.dp-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.dp-day {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .78rem;
  border-radius: var(--bulma-radius);
  cursor: pointer;
  color: var(--app-text);
  transition: background .1s;
}

.dp-day:hover:not(.dp-past):not(.dp-future) {
  background: var(--bulma-background);
}

.dp-day.is-selected {
  background: var(--bulma-primary);
  color: hsl(var(--bulma-primary-h), var(--bulma-primary-s), calc(var(--bulma-primary-l) - 30%));
  font-weight: 600;
}

.dp-day.is-today:not(.is-selected) {
  border: 1.5px solid var(--bulma-link);
}

.dp-day.dp-past, .dp-day.dp-future {
  color: var(--bulma-text-weak);
  opacity: .4;
  cursor: default;
}

/* Clickable month/year header label (zooms out to month / year views). */
.dp-label {
  background: none;
  border: none;
  cursor: pointer;
  font-size: .825rem;
  font-weight: 600;
  color: var(--app-text);
  border-radius: var(--bulma-radius);
  padding: .15rem .5rem;
  transition: background .12s;
}

button.dp-label:hover {
  background: var(--bulma-background);
}

/* Month / year grid (3 columns). */
.dp-grid-my {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
}

.dp-cell {
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .8rem;
  border-radius: var(--bulma-radius);
  cursor: pointer;
  color: var(--app-text);
  transition: background .1s;
}

.dp-cell:hover {
  background: var(--bulma-background);
}

.dp-cell.is-selected {
  background: var(--bulma-primary);
  color: hsl(var(--bulma-primary-h), var(--bulma-primary-s), calc(var(--bulma-primary-l) - 30%));
  font-weight: 600;
}

.dp-cell.is-today:not(.is-selected) {
  border: 1.5px solid var(--bulma-link);
}

.dp-cell.dp-muted {
  color: var(--bulma-text-weak);
  opacity: .5;
}

/* ── Skeleton loading placeholders (à la zalog/placeholder-loading) ─ */

@keyframes ph-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.skeleton {
  display: block;
  border-radius: var(--bulma-radius);
  background-color: var(--bulma-border-weak, #edeff2);
  background-image: linear-gradient(
    90deg,
    var(--bulma-border-weak, #edeff2) 0,
    var(--bulma-background, #f6f8fa) 40%,
    var(--bulma-border-weak, #edeff2) 80%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: ph-shimmer 1.3s ease-in-out infinite;
}

/* Prefer motion-free placeholders when the user asks for reduced motion. */
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
}

.skeleton-line {
  height: 0.85em;
  margin: 0.35em 0;
}

/* Skeleton cell used inside table rows while actors load. */
.skeleton-cell {
  height: 0.85em;
  width: 70%;
}

.skeleton-block {
  height: 2.25rem;
  width: 100%;
}

/* ── Sticky, tinted table header + frozen first column ─────────────
   Applies to the reusable data-table core. The header pins under the
   toolbar/search bar while rows scroll; the checkbox column is frozen to
   the left edge (Google-Docs-style freeze), non-configurable by design. */

.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 5;
  color: var(--bulma-text-strong);
  /* Light mode: a solid light-grey header, clearly darker than the white body.
     Fixed lightness (not calc on a maybe-missing var) guarantees it's opaque. */
  background-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), 86%);
}

/* Dark mode: a solid mid-grey header, clearly lighter than the near-black body. */
:root[data-theme="dark"] .data-table thead th {
  background-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), 27%);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .data-table thead th {
    background-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), 27%);
  }
}

/* Navbar dropdowns get a card-like shadow. --bulma-card-shadow is only defined
   inside .card, so it resolves to nothing here — use explicit, theme-aware
   values: a dark drop on light, and on dark a deeper drop plus a light 1px ring
   so the panel still separates from the near-black chrome. */
.navbar-dropdown {
  box-shadow: 0 0.5em 1em -0.125em rgba(10, 10, 10, 0.2), 0 0 0 1px rgba(10, 10, 10, 0.05) !important;
}
:root[data-theme="dark"] .navbar-dropdown {
  box-shadow: 0 0.5em 1em -0.125em rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.14) !important;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .navbar-dropdown {
    box-shadow: 0 0.5em 1em -0.125em rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.14) !important;
  }
}

.data-table thead th .sort-ind {
  color: inherit;
}

.data-table thead th.field-column {
  min-width: 175px;
}

/* Freeze the first (checkbox) column against the left edge. */
.data-table th:first-child,
.data-table td:first-child {
  position: sticky;
  left: 0;
}
/* Header's first cell must win on both axes. */
.data-table thead th:first-child {
  z-index: 6;
}
/* Body cells need an opaque background so scrolled content passes underneath. */
.data-table tbody td:first-child {
  z-index: 3;
  background-color: var(--bulma-scheme-main);
}

/* ═══════════════════════════════════════════════════════════════════════════
   PHASE 8: Light/Dark theme polish for all new components
   ═══════════════════════════════════════════════════════════════════════════ */

/* Note cards in dark mode — ensure text is readable on scheme-main bg */
@media (prefers-color-scheme: dark) {
  :root[data-theme="dark"] .note-card {
    background: var(--bulma-scheme-invert, #1a1a1f);
    border-color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), calc(var(--bulma-scheme-l) - 10%));
  }
  :root[data-theme="dark"] .note-toolbar {
    background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), calc(var(--bulma-scheme-l) - 3%));
  }
  :root[data-theme="dark"] .note-body {
    color: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), calc(var(--bulma-scheme-l) + 70%));
  }
}

/* Role rows — default to a subtle contrasting bar; a chosen swatch tints it. */
.role-row {
  background: var(--bulma-scheme-main-ter);
}
.role-row:hover { border-color: var(--bulma-link); }

/* Swatch colour tints — match the lighter note-card palette so the selected
  role row reads as a soft tinted surface instead of a saturated block. */
#roleRowsContainer .role-row.role-color-primary { background: hsl(var(--bulma-primary-h), var(--bulma-primary-s), calc(var(--bulma-primary-l) + 18%)); }
#roleRowsContainer .role-row.role-color-info    { background: hsl(var(--bulma-info-h), var(--bulma-info-s), calc(var(--bulma-info-l) + 30%)); }
#roleRowsContainer .role-row.role-color-warning { background: hsl(var(--bulma-warning-h), var(--bulma-warning-s), calc(var(--bulma-warning-l) + 20%)); }
#roleRowsContainer .role-row.role-color-danger  { background: hsl(var(--bulma-danger-h), var(--bulma-danger-s), calc(var(--bulma-danger-l) + 16%)); }
/* The swatch colours are light, so keep the title dark and readable on them. */
#roleRowsContainer .role-row[class*="role-color-"] .role-title { color: #1a1a1f; }

/* ── Finalist / Selected status ──────────────────────────────────────────────
   Row-wide outline (not a filled background): a 2px inset shadow drawn on the
   row's cells — top/bottom on every cell, plus the left edge on the first cell
   and the right edge on the last. Finalist = blue (link), Selected = green
   (success). --tier-c carries the colour so the shared cell rules stay DRY. */
.actor-row.is-finalist-row        { --tier-c: var(--bulma-link, #485fc7); }
.actor-row.is-status-selected-row { --tier-c: var(--bulma-success, #48c78e); }

.actor-row.is-finalist-row > td,
.actor-row.is-status-selected-row > td {
  box-shadow: inset 0 2px 0 var(--tier-c), inset 0 -2px 0 var(--tier-c);
}
.actor-row.is-finalist-row > td:first-child,
.actor-row.is-status-selected-row > td:first-child {
  box-shadow: inset 0 2px 0 var(--tier-c), inset 0 -2px 0 var(--tier-c), inset 2px 0 0 var(--tier-c);
}
.actor-row.is-finalist-row > td:last-child,
.actor-row.is-status-selected-row > td:last-child {
  box-shadow: inset 0 2px 0 var(--tier-c), inset 0 -2px 0 var(--tier-c), inset -2px 0 0 var(--tier-c);
}

/* The role header goes green-outlined once the role has its Selected actor. */
.role-row.role-is-cast { box-shadow: inset 0 0 0 2px var(--bulma-success, #48c78e); }

/* Badge contrast — ensure text is readable on badge bg */
.role-count-badge,
.actor-count-badge {
  font-weight: 500;
}

/* Add actor from DB modal table rows */
#addActorFromDBModal .table td {
  vertical-align: middle !important;
  padding: 0.5rem 0.75rem;
}

/* Collapse toggle button hover effect */
.role-collapse-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--bulma-text-weak);
  padding: 0.15rem;
  border-radius: var(--bulma-radius);
  transition: color .12s, background .12s;
}
.role-collapse-btn:hover {
  color: var(--app-text);
  background: var(--bulma-background);
}

/* Ensure note card placeholder text adapts to theme */
.note-body::before {
  color: var(--bulma-text-weak);
}

/* Star indicator — orange filled star matching design sketch */
.star-indicator svg {
  fill: hsl(var(--bulma-warning-h), var(--bulma-warning-s), var(--bulma-warning-l));
  stroke: none;
}

/* Star toggle button in the title bar. Outline star when unstarred, filled
   warning-orange when starred. */
.star-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.25rem;
  background: none;
  border: none;
  cursor: pointer;
  border-radius: var(--bulma-radius);
  color: var(--bulma-text-weak);
  transition: color .12s, background .12s;
}
.star-toggle-btn:hover { background: var(--bulma-background); color: var(--bulma-text-strong); }
.star-toggle-btn.is-starred {
  color: var(--bulma-text-strong);
}
.star-toggle-btn.is-starred svg { fill: currentColor; stroke: none; }

/* Project pages open the SHARED scheme modal but may only reorder fields and
   toggle their visibility — adding, renaming, retyping or removing fields is
   done in the main database only. Hide those controls when the body is locked. */
body.scheme-locked #schemeAddSection,
body.scheme-locked #schemeEditSection,
body.scheme-locked #schemeEditTopRule,
body.scheme-locked #schemeEditBottomRule {
  display: none !important;
}
/* Locked rows aren't selectable for editing — don't hint that they are. */
body.scheme-locked .scheme-field-row { cursor: default; }

/* "Set scheme to default" footer — only on project pages (scheme-locked). */
.scheme-project-only { display: none; }
body.scheme-locked .scheme-project-only { display: flex; }

/* Action dropdown button styling */
#roleActionDropdown .button.is-success {
  background: var(--bulma-success);
  color: var(--bulma-success-invert, #fff);
  border-color: var(--bulma-success);
}

/* Inline edit input — matches surrounding text size/weight */
input.is-inline-edit {
  min-width: 10rem;
  font-size: inherit;
  font-weight: inherit;
  background: var(--bulma-scheme-main-invert, #fff);
  border-color: var(--bulma-link);
  padding: 0.2em 0.5em;
}

/* Add actor modal search input styling */
#actorSearchInput {
  background: var(--bulma-scheme-main);
  color: var(--app-text);
}

/* ── Autosave-status indicator (next to section titles) ──────────── */

.autosave-status {
  font-size: .75rem;
  font-weight: 400;
  color: var(--bulma-text-weak, #999);
  min-width: 3.5em;
  transition: color .12s;
}

.autosave-status.is-active {
  color: var(--bulma-link);
}

/* ── Skeleton enhancements for project page ─────────────────────── */

.skeleton-icon {
  width: 2rem;
  height: 2rem;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  border-radius: var(--bulma-radius);
  background-color: var(--bulma-border-weak, #edeff2);
  background-image: linear-gradient(
    90deg,
    var(--bulma-border-weak, #edeff2) 0,
    var(--bulma-background, #f6f8fa) 40%,
    var(--bulma-border-weak, #edeff2) 80%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: ph-shimmer 1.3s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-icon { animation: none; }
}

.skeleton-tag {
  min-width: 5rem !important;
  background-color: var(--bulma-border-weak, #edeff2);
  background-image: linear-gradient(
    90deg,
    var(--bulma-border-weak, #edeff2) 0,
    var(--bulma-background, #f6f8fa) 40%,
    var(--bulma-border-weak, #edeff2) 80%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: ph-shimmer 1.3s ease-in-out infinite;
  color: transparent !important;
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-tag { animation: none; }
}

.skeleton-role-row {
  height: 3rem;
  border-radius: var(--bulma-radius);
  background-color: var(--bulma-border-weak, #edeff2);
  background-image: linear-gradient(
    90deg,
    var(--bulma-border-weak, #edeff2) 0,
    var(--bulma-background, #f6f8fa) 40%,
    var(--bulma-border-weak, #edeff2) 80%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: ph-shimmer 1.3s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-role-row { animation: none; }
}

.flex-column { flex-direction: column !important; }
.gap-2 { gap: 0.5rem !important; }

/* Navbar skeleton bar shown where starred project title(s) will appear. */
.skeleton-navbar-star {
  display: inline-block;
  width: 5.5rem;
  height: 1rem;
  border-radius: var(--bulma-radius);
  vertical-align: middle;
}

/* ── Notes reorder drag handle ─────────────────────────────────── */

.note-drag-handle {
  cursor: grab !important;
  color: var(--bulma-text-weak) !important;
  opacity: 0.5 !important;
}

.note-drag-handle:active {
  cursor: grabbing;
}

/* ── Rich-toolbar button styling for notes (actor-card style) ───── */

.rt-spacer { flex: 1; }

/* Red trash button on the right of the note toolbar. */
.note-del-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.2rem;
  border-radius: var(--bulma-radius);
  color: var(--bulma-danger);
  transition: background .12s;
}
.note-del-btn:hover { background: hsl(var(--bulma-danger-h), var(--bulma-danger-s), calc(var(--bulma-danger-l) + 40%)); }

.rt-toolbar button.link-btn svg {
  width: .9em;
  height: .9em;
}

.rt-toolbar button.button.is-small {
  font-size: .78rem;
  padding: 0.2rem 0.45rem;
}

/* ── Note-card header: title (left) + actions (right), above the toolbar ─────── */
.note-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.5rem 0.4rem 0.85rem;
  background: var(--bulma-scheme-main-ter, var(--bulma-background));
  border-bottom: 1px solid var(--bulma-border);
}
.note-title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 1.2rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--app-text-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Placeholder when a note has no title yet. */
.note-title:empty::before {
  content: 'Untitled note';
  color: var(--bulma-text-weak);
  font-weight: 500;
}
.note-title-input {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 1.05rem;
}
.note-header-actions {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  flex-shrink: 0;
}
.note-hdr-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.3rem;
  border-radius: var(--bulma-radius);
  color: var(--bulma-text-weak);
  transition: background .12s, color .12s;
}
.note-hdr-btn:hover {
  background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), calc(var(--bulma-scheme-l) + 8%));
  color: var(--app-text-strong);
}
.note-hdr-btn.has-text-danger { color: var(--bulma-danger); }
.note-hdr-btn.is-active { color: var(--bulma-primary); }
.note-hdr-btn.has-text-danger:hover {
  background: hsl(var(--bulma-danger-h), var(--bulma-danger-s), calc(var(--bulma-danger-l) + 40%));
}
.note-header .note-drag-handle {
  display: inline-flex;
  align-items: center;
  padding: 0.3rem;
}
/* Vertical split between header action clusters. */
.note-hdr-divider {
  width: 1px;
  align-self: stretch;
  margin: 0.2rem 0.15rem;
  background: var(--bulma-border);
}
/* Keep header text/icons dark on a light-tinted coloured note (matches the
   rich-editor colour rule), so they stay legible in both themes. */
:root .notes-grid .note-card[class*="note-color-"] .note-title,
:root .notes-grid .note-card[class*="note-color-"] .note-hdr-btn { color: #1a1a1f; }

/* ── Expanded-note modal: a taller editing surface for one note ──────────────── */
.note-expand-card { width: min(760px, 96vw); }
.note-expand-body { display: flex; flex-direction: column; }
/* Toolbar + editor read as one bordered note, like the cards on the page. */
#noteExpandToolbar {
  border: 1px solid;
  border-bottom: none;
  border-radius: var(--bulma-radius-large) var(--bulma-radius-large) 0 0;
  border-color: rgba(0,0,0,0.28);
}
.note-expand-editor {
  min-height: 50vh;
  max-height: 70vh;
  border: 1px solid var(--bulma-border);
  border-top: none;
  border-radius: 0 0 var(--bulma-radius-large) var(--bulma-radius-large);
}
/* Coloured note reflected in the modal — mirrors the card tints, and the tint
   can be changed live from the modal's own swatches. */
:root #noteExpandBody.note-color-primary { background: hsl(var(--bulma-primary-h), var(--bulma-primary-s), calc(var(--bulma-primary-l) + 18%)); }
:root #noteExpandBody.note-color-info    { background: hsl(var(--bulma-info-h), var(--bulma-info-s), calc(var(--bulma-info-l) + 30%)); }
:root #noteExpandBody.note-color-warning { background: hsl(var(--bulma-warning-h), var(--bulma-warning-s), calc(var(--bulma-warning-l) + 20%)); }
:root #noteExpandBody.note-color-danger  { background: hsl(var(--bulma-danger-h), var(--bulma-danger-s), calc(var(--bulma-danger-l) + 16%)); }
:root #noteExpandBody[class*="note-color-"] .note-expand-editor { background: transparent; color: #1a1a1f; }
#noteExpandBody[class*="note-color-"] .rt-toolbar { background: rgba(0,0,0,0.06); }

/* Tint the expand-modal header to match the note colour (same palette). */
:root #noteExpandModal .modal-card-head.note-color-primary { background: hsl(var(--bulma-primary-h), var(--bulma-primary-s), calc(var(--bulma-primary-l) + 18%)); }
:root #noteExpandModal .modal-card-head.note-color-info    { background: hsl(var(--bulma-info-h), var(--bulma-info-s), calc(var(--bulma-info-l) + 30%)); }
:root #noteExpandModal .modal-card-head.note-color-warning { background: hsl(var(--bulma-warning-h), var(--bulma-warning-s), calc(var(--bulma-warning-l) + 20%)); }
:root #noteExpandModal .modal-card-head.note-color-danger  { background: hsl(var(--bulma-danger-h), var(--bulma-danger-s), calc(var(--bulma-danger-l) + 16%)); }
:root #noteExpandModal .modal-card-head[class*="note-color-"] .modal-card-title { color: #1a1a1f; }

/* On a colour-tinted note the borders/dividers must read against the light tint
   (the tint is always light, in both themes) — darken them like the dark theme. */
.notes-grid .note-card[class*="note-color-"] .rt-toolbar,
#noteExpandBody[class*="note-color-"] .rt-toolbar { border-bottom-color: rgba(0,0,0,0.28); }

/* Dark theme, default (un-tinted) notes: the toolbar blends into the card, so
   give it a full border to define it (light theme already reads fine). */
:root[data-theme="dark"] .notes-grid .note-card:not([class*="note-color-"]) .rt-toolbar,
:root[data-theme="dark"] #noteExpandBody:not([class*="note-color-"]) .rt-toolbar { border: 1px solid var(--bulma-border); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .notes-grid .note-card:not([class*="note-color-"]) .rt-toolbar,
  :root:not([data-theme="light"]) #noteExpandBody:not([class*="note-color-"]) .rt-toolbar { border: 1px solid var(--bulma-border); }
}
.notes-grid .note-card[class*="note-color-"] .rt-divider,
#noteExpandBody[class*="note-color-"] .rt-divider { background: rgba(0,0,0,0.3); }
.notes-grid .note-card[class*="note-color-"] .note-header { border-bottom-color: rgba(0,0,0,0.22); }
.notes-grid .note-card[class*="note-color-"] .note-hdr-divider { background: rgba(0,0,0,0.28); }
/* On tinted notes the forced dark colour kills the hover feedback — restore it
   with an opacity shift instead (.7 default → full on hover). */
.notes-grid .note-card[class*="note-color-"] .note-hdr-btn { opacity: 0.7; transition: opacity .12s; }
.notes-grid .note-card[class*="note-color-"] .note-hdr-btn:hover { opacity: 1; }
.notes-grid .note-card[class*="note-color-"] { border-color: rgba(0,0,0,0.22); }
:root #noteExpandBody[class*="note-color-"] .note-expand-editor { border-color: rgba(0,0,0,0.28); }
:root #noteExpandModal .modal-card-head[class*="note-color-"] { border-bottom-color: rgba(0,0,0,0.24); }

/* ── Notes grid reorder visual feedback ─────────────────────────── */

#notesContainer .note-card.is-placeholder {
  opacity: 0.5;
  border: 2px dashed var(--bulma-link);
}

#notesContainer .note-card,
#roleRowsContainer .role-row {
  position: relative;
}


/* ── Disabled nav / dropdown items (greyed, non-interactive) ─────── */
.navbar-item.is-disabled,
.dropdown-item.is-disabled {
  opacity: .45;
  pointer-events: none;
  cursor: default;
}

/* ── Projects grid: reorder handle (card-header, right) ──────────── */
.project-drag-handle {
  padding: .15rem;
  background: none;
  border: none;
  cursor: grab;
  color: var(--bulma-text-weak, #999);
}
.project-drag-handle:hover { color: var(--bulma-text-strong); }
.project-drag-handle:active { cursor: grabbing; }
/* Dragged card gets the same dashed outline as a dragged note. The card's own
   box-shadow is dropped so the dashed border reads clearly. */
#projectsGrid .column.is-placeholder .card {
  opacity: 0.5;
  border: 2px dashed var(--bulma-link);
  box-shadow: none;
}

/* ── Project action dropdown: centered rows, width = longest label ─── */
#projectActionMenu { min-width: 0; }
#projectActionMenu .dropdown-content { min-width: 0; width: max-content; }
#projectActionMenu .dropdown-item {
  display: flex;
  align-items: center;
  gap: .5rem;
  white-space: nowrap;
  padding-right: 1.25rem;
}
#projectActionMenu .dropdown-item .icon { margin: 0; }

/* ── Role action dropdown: centered rows, width = longest label ─── */
#roleActionDropdown { min-width: 0; }
#roleActionDropdown .dropdown-content { min-width: 0; width: max-content; }
#roleActionDropdown .dropdown-item {
  display: flex;
  align-items: center;
  gap: .5rem;
  white-space: nowrap;
  padding-right: 1.25rem;
}
#roleActionMenu .dropdown-item .icon { margin: 0; }

/* ── Toast alerts (slide in from right, fade out) ─────────────────── */
#notification-container { display: flex; flex-direction: column; gap: .6rem; }
.app-toast {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: .75rem;
  min-width: 300px; max-width: 420px;
  padding: .8rem .9rem;
  border-radius: .65rem;
  background: var(--bulma-scheme-main, #fff);
  color: var(--bulma-text-strong);
  border: 1px solid var(--bulma-border, #e5e7eb);
  box-shadow: 0 4px 12px rgba(0,0,0,.10);
  font-size: .875rem;
  line-height: 1.35;
  animation: toast-in .28s cubic-bezier(.2,.8,.2,1);
}
.app-toast.is-leaving { animation: toast-out .35s forwards; }
.app-toast .toast-icon { color: var(--tone, currentColor); display: flex; align-self: start; margin-top: .1rem; }
.app-toast .toast-msg { min-width: 0; }
.app-toast .toast-close {
  background: none; border: none; cursor: pointer;
  color: var(--bulma-text-weak); padding: .15rem; display: flex; align-self: start;
  border-radius: .3rem;
}
.app-toast .toast-close:hover { color: var(--bulma-text-strong); background: var(--bulma-background); }

/* Every modal close button styled like the notification close: a clean themed
   X, no grey Bulma circle. Applies site-wide without touching each modal. */
.modal .delete, .modal-card-head .delete, .modal .modal-close {
  background-color: transparent;
  color: var(--bulma-text-weak);
  height: 1.75rem; width: 1.75rem; max-height: none; max-width: none;
  border-radius: .3rem;
}
.modal .delete::before, .modal .delete::after,
.modal-card-head .delete::before, .modal-card-head .delete::after {
  background-color: currentColor;
}
.modal .delete:hover, .modal-card-head .delete:hover, .modal .modal-close:hover {
  background-color: var(--bulma-background);
  color: var(--bulma-text-strong);
}
.app-toast.is-success { --tone: #48c78e; }
.app-toast.is-danger  { --tone: #f14668; border-color: color-mix(in srgb, #f14668 45%, var(--bulma-border, #e5e7eb)); }
.app-toast.is-danger .toast-msg { color: #f14668; }
.app-toast.is-warning { --tone: #f5a623; }
.app-toast.is-info    { --tone: #3e8ed0; }
@keyframes toast-in  { from { opacity: 0; transform: translateX(120%); } to { opacity: 1; transform: translateX(0); } }
@keyframes toast-out { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(120%); } }
@media (prefers-reduced-motion: reduce) {
  .app-toast, .app-toast.is-leaving { animation: none; }
}

/* ── Dashed list mode for rich-text note editors ─────────────────── */
.rich-editor ul { list-style: none; padding-left: 1.25rem; margin: .3rem 0; }
.rich-editor ul li { position: relative; }
.rich-editor ul li::before {
  content: "–"; position: absolute; left: -1rem;
  color: var(--bulma-text-weak, #999);
}

/* ── Project card title truncation ────────────────────────────────── */
.project-card {
  border: 1px solid var(--bulma-border-subtle, var(--bulma-border));
}

.project-card .card-header-title {
  overflow: hidden;
  white-space: nowrap;
  max-width: 240px;
  text-overflow: ellipsis;
  display: block;
}

/* ── Users page: associated-projects picker inside the edit modal ─────────────
   A scrollable checkbox list so a long project list can't blow out the modal. */
.user-projects-list {
  max-height: 220px;
  overflow-y: auto;
}
.user-projects-list .checkbox.is-block { display: block; }
.users-table td { vertical-align: middle; }

/* ── Role tag (admin / guest) ─────────────────────────────────────────────────
   Solid mid-tone backgrounds with white text so the tag is legible in BOTH the
   light and dark themes (the previous is-light variant vanished in light mode).
   Used next to the navbar brand and in the Users table. */
.tag.role-tag {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.65rem;
}
.tag.role-admin { background-color: hsl(275, 55%, 55%); color: #fff; }
.tag.role-guest { background-color: hsl(210, 12%, 46%); color: #fff; }

/* Navbar user avatar (replaces the gear/Settings label). Admin = primary,
   guest = the same grey as the guests' role tag. */
.navbar-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: 50%;
  font-size: 0.78rem; font-weight: 700; color: #fff; line-height: 1;
}
.navbar-avatar.is-admin { background-color: var(--bulma-primary, hsl(275, 55%, 55%)); }
.navbar-avatar.is-guest { background-color: hsl(210, 12%, 46%); }

/* User avatar-colour swatches (edit form). */
.user-color-swatches { display: flex; gap: 0.5rem; }
.user-swatch {
  width: 1.6rem; height: 1.6rem; padding: 0; border-radius: 50%;
  border: 2px solid transparent; cursor: pointer; background: var(--bulma-border);
}
.user-swatch.is-none { background: var(--bulma-scheme-main, #fff); border: 2px dashed var(--bulma-border); }
.user-swatch.is-selected { border-color: var(--bulma-text, #333); box-shadow: 0 0 0 2px var(--bulma-scheme-main, #fff); }

/* General page: the activity log scrolls within a fixed height, paginated. */
.general-log-scroll { max-height: 300px; }

/* Audio tiles: an icon + filename; click opens a small player overlay. */
.media-thumb.is-audio {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.3rem; padding: 0.5rem; text-align: center;
  background: var(--bulma-scheme-main-bis, var(--bulma-scheme-main));
}
.media-thumb.is-audio .media-audio-icon { color: var(--bulma-primary); }
.media-thumb.is-audio .media-audio-name {
  font-size: 0.68rem; line-height: 1.15; max-width: 100%;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  color: var(--bulma-text-weak, var(--app-text));
}
.media-lightbox.is-audio .media-audio-player {
  background: var(--bulma-scheme-main, #fff); padding: 1.25rem; border-radius: var(--bulma-radius);
  min-width: min(90vw, 420px); text-align: center;
}
.media-lightbox.is-audio .media-audio-title { font-weight: 600; margin-bottom: 0.75rem; }
.media-lightbox.is-audio audio { width: 100%; }
/* Audio as a lightGallery HTML slide. */
.lg-audio-slide {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1rem; height: 100%; padding: 2rem; text-align: center;
}
.lg-audio-slide .lg-audio-title { color: #fff; font-weight: 600; }
.lg-audio-slide audio { width: min(90vw, 560px); }

/* Media reorder: show where the dragged tile will land (Sortable ghostClass). */
.media-thumb.is-placeholder {
  opacity: .5;
  outline: 2px dashed var(--bulma-link);
  outline-offset: -2px;
  background: transparent;
}
.media-thumb.is-placeholder > * { visibility: hidden; }

/* ── Add-Actor-from-DB modal: pin the search field to the top of the scrolling
   modal body so it stays reachable while the actor list scrolls underneath. The
   solid background (and padding, not margin) leaves no transparent strip for
   rows to peek through. */
#addActorFromDBModal .modal-card-body > .field.is-grouped {
  position: sticky;
  top: 0;
  z-index: 5;
  margin-bottom: 0;
  padding: 0.25rem 0 0.75rem;
  background-color: var(--bulma-scheme-main);
}

/* ── Modal open: lock page scroll while any modal is showing ──────────────────
   js/modals.js toggles body.modal-open whenever a modal is/left open. */
body.modal-open {
  overflow: hidden;
}

/* ── Selected-row highlight (main data-table) ────────────────────────────────
   Same yellow affordance as the Add-Actor-from-DB table. Applied to every cell
   (incl. the frozen first column, which otherwise paints its own opaque bg) via
   a td:first-child selector that outranks the freeze rule regardless of order.
   Toggled by js/data-table.js (updateSelectedInfo → .is-selected-row). */
.data-table tbody tr.is-selected-row td,
.data-table tbody tr.is-selected-row td:first-child {
  background-color: var(--bulma-warning);
  color: hsl(var(--bulma-warning-h), var(--bulma-warning-s), 22%);
}

/* ── Media gallery (images) ──────────────────────────────────────────────────
   Mounted on the actor card and each role. Drag-and-drop dropzone + thumbnail
   grid + upload progress + lightbox. Theme-aware via Bulma scheme variables. */
.media-gallery { position: relative; }
.media-gallery.is-dragover .media-dropzone { border: 2px dashed var(--bulma-primary); border-radius: var(--bulma-radius); }

.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 0.6rem;
}
.media-thumb {
  position: relative;
  margin: 0;
  aspect-ratio: 1 / 1;
  border-radius: var(--bulma-radius);
  overflow: hidden;
  border: 1px solid var(--bulma-border);
  background: var(--bulma-scheme-main-bis, var(--bulma-scheme-main));
  cursor: pointer;
  transition: transform .18s ease, box-shadow .18s ease;
}
.media-thumb:hover {
  box-shadow: 0 4px 16px rgba(0,0,0,.12);
}
.media-thumb::after {
  content: '';
  position: absolute; inset: 0;
  background: rgba(0,0,0,.18);
  opacity: 0;
  transition: opacity .18s ease;
  pointer-events: none;
}
.media-thumb:hover::after { opacity: 1; }
.media-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Corner pill marking the tile that is the owner's main photo. */
.media-main-pill {
  position: absolute; top: 6px; left: 6px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 5px;
  background: var(--bulma-primary); color: var(--bulma-primary-invert, #fff);
  border-radius: 999px; box-shadow: 0 1px 3px rgba(0,0,0,.35);
  pointer-events: none;
}
.media-main-pill .ic { width: 13px; height: 13px; }
.media-thumb.is-placeholder { opacity: 0.4; }
.media-del {
  position: absolute; top: 4px; right: 4px;
  width: 22px; height: 22px; line-height: 20px;
  border: none; border-radius: 50%;
  background: hsla(0,0%,0%,0.55); color: #fff; font-size: 15px;
  cursor: pointer; opacity: 0; transition: opacity .12s;
}
.media-thumb:hover .media-del { opacity: 1; }

.media-dropzone {
  margin-top: 0.75rem;
  padding: 1.1rem;
  border: 2px dashed var(--bulma-border);
  border-radius: var(--bulma-radius);
  text-align: center;
  color: var(--bulma-text-weak, var(--app-text));
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.media-dropzone:hover { border-color: var(--bulma-link); }
.media-empty { margin: 0.5rem 0; }

/* Actor card main-photo box: photo, admin dropzone, or hover overlay. */
.card-photo-main {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 6;
  border-radius: var(--bulma-radius);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.card-photo-img { width: 100%; height: 100%; object-fit: cover; }
/* While a (new) main photo loads, keep the previous actor's image hidden under
   the shimmer instead of flashing it before the new one paints. */
.card-photo-main.is-loading .card-photo-img { visibility: hidden; }
/* Upload indicator above the box, mirroring the media pool's progress cue. */
.card-photo-uploading {
  display: flex; align-items: center; gap: 0.4rem;
  margin-bottom: 0.5rem; font-size: 0.8rem; color: var(--bulma-text-weak, var(--app-text));
}
.card-photo-empty-label { color: var(--bulma-text-light); font-size: 0.85rem; }
.card-photo-drop {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 1rem;
  text-align: center;
  font-size: 0.85rem;
  border: 2px dashed var(--bulma-border);
  border-radius: var(--bulma-radius);
  color: var(--bulma-text-weak, var(--app-text));
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.card-photo-drop:hover,
.card-photo-main.is-dragover .card-photo-drop { border-color: var(--bulma-link); }
.card-photo-drop .main-pool-link { text-decoration: underline; cursor: pointer; color: inherit; }
.card-photo-drop-actions { display: flex; gap: 0.5rem; align-items: center; justify-content: center; }

/* Project header thumbnail (cover image + crop). Mirrors the main-photo box. */
.project-thumb {
  position: relative; width: 100%; height: 200px;
  border-radius: var(--bulma-radius); overflow: hidden;
  background: var(--bulma-dark-hsl, #1a1a1a);
  display: flex; align-items: center; justify-content: center;
}
.project-thumb-img { width: 100%; height: 100%; object-fit: cover; }
.project-thumb-empty { color: var(--bulma-text-light); font-size: 0.9rem; }
.project-thumb.is-loading .project-thumb-img { visibility: hidden; }
/* Skeleton shimmer while an existing thumbnail loads. */
.project-thumb.is-loading {
  background-color: var(--bulma-border-weak, #edeff2);
  background-image: linear-gradient(90deg, var(--bulma-border-weak, #edeff2) 0, var(--bulma-background, #f6f8fa) 40%, var(--bulma-border-weak, #edeff2) 80%);
  background-size: 200% 100%; background-repeat: no-repeat;
  animation: ph-shimmer 1.3s ease-in-out infinite;
}
.project-thumb-actions { position: absolute; right: 0.6rem; top: 0.6rem; z-index: 4; display: flex; gap: 0.4rem; }
.project-thumb:hover .card-photo-hoverbar:not(.is-hidden) { opacity: 1; }
.project-thumb.is-cropping, .project-thumb.is-cropping .project-thumb-img { cursor: grab; }
.project-thumb.is-cropping.is-grabbing, .project-thumb.is-cropping.is-grabbing .project-thumb-img { cursor: grabbing; }

/* Scheme: locked fields (not editable) show a disabled cursor. */
.scheme-field-row.is-locked { cursor: not-allowed; }

/* Database-table avatar column: a round main-photo thumbnail, or initials. */
.dt-avatar-col { width: 48px; text-align: center; vertical-align: middle; }
.dt-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: middle; flex: 0 0 auto;
  width: 2rem; height: 2rem; border-radius: 50%;
  font-size: 0.72rem; font-weight: 700; color: #fff;
  background-color: hsl(210, 12%, 46%); background-size: cover; background-position: center;
}
.dt-avatar.has-photo { color: transparent; }
/* While its thumbnail loads, an avatar shows a spinner instead of initials. */
.dt-avatar.is-loading { background-color: var(--bulma-border-weak, #edeff2); color: var(--bulma-text, #555); }
.dt-avatar .actor-count-spinner { margin-right: 0; }
.card-photo-drop .main-pool-link:hover { color: var(--bulma-primary); }
.card-photo-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  transition: opacity .12s;
}
.card-photo-main:hover .card-photo-overlay:not(.is-hidden) { opacity: 1; }
/* Skeletons: grid squares shimmer on their own (the .media-thumb base bg was
   painting over .skeleton, so the animation was invisible). Same gradient +
   ph-shimmer as the main-photo box below. */
.media-skeleton,
.media-thumb.is-loading {
  aspect-ratio: 1 / 1;
  border-radius: var(--bulma-radius);
  background-color: var(--bulma-border-weak, #edeff2);
  background-image: linear-gradient(
    90deg,
    var(--bulma-border-weak, #edeff2) 0,
    var(--bulma-background, #f6f8fa) 40%,
    var(--bulma-border-weak, #edeff2) 80%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: ph-shimmer 1.3s ease-in-out infinite;
}
/* Per-tile skeleton: hide the image until it has loaded. */
.media-thumb.is-loading img { visibility: hidden; }
.card-photo-main.is-loading::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  background-color: var(--bulma-border-weak, #edeff2);
  background-image: linear-gradient(
    90deg,
    var(--bulma-border-weak, #edeff2) 0,
    var(--bulma-background, #f6f8fa) 40%,
    var(--bulma-border-weak, #edeff2) 80%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  animation: ph-shimmer 1.3s ease-in-out infinite;
}

/* Main-photo crop (pan) mode: drag the image to set object-position. */
.card-photo-main.is-cropping,
.card-photo-main.is-cropping .card-photo-img { cursor: grab; }
.card-photo-main.is-cropping.is-grabbing,
.card-photo-main.is-cropping.is-grabbing .card-photo-img { cursor: grabbing; }
.card-photo-crop-hint {
  position: absolute; top: 0.4rem; left: 0; right: 0; z-index: 4;
  text-align: center; font-size: 0.72rem; color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .85); pointer-events: none;
}
.card-photo-crop-bar {
  position: absolute; left: 0; right: 0; top: 0; z-index: 4;
  display: flex; gap: 0.5rem; justify-content: flex-end; align-items: center;
  padding: 0.4rem;
}
/* The Change/Crop bar reuses the crop-bar look but only appears on hover. */
.card-photo-hoverbar { opacity: 0; transition: opacity .12s; }
.card-photo-main:hover .card-photo-hoverbar:not(.is-hidden) { opacity: 1; }

/* Change / Crop buttons live in the row under the photo (with Edit primary).
   Edit is always right-aligned — including when the actions group is hidden
   (no main photo yet). */
#cardMainPhotoActions { display: flex; gap: 0.5rem; }
#cardEditBtnWrap > .control { margin-left: auto; margin-bottom: 0; }

/* Lightbox video (iframe) slides: constrain to 16:9 and center so the player's
   controls hug the video instead of sitting at the bottom of the viewport. */
.lg-outer .lg-has-iframe {
  position: absolute !important;
  top: 50% !important;
  left: 50% !important;
  transform: translate(-50%, -50%) !important;
  width: min(92vw, 158vh) !important;
  max-width: 92vw !important;
  height: auto !important;
  aspect-ratio: 16 / 9;
}
.lg-outer .lg-has-iframe .lg-object,
.lg-outer .lg-has-iframe iframe {
  width: 100% !important;
  height: 100% !important;
  max-height: 100% !important;
}

.media-queue { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 0.5rem; }
.media-progress { font-size: 0.8rem; }
.media-progress-name { display: block; margin-bottom: 2px; color: var(--app-text); }
.media-progress-bar { display: block; height: 5px; border-radius: 3px; background: var(--bulma-border); overflow: hidden; }
.media-progress-bar > span { display: block; height: 100%; width: 0; background: var(--bulma-primary); transition: width .15s; }
.media-progress.is-done .media-progress-bar > span { background: var(--bulma-success); }
.media-progress.is-failed .media-progress-bar > span { width: 100% !important; background: var(--bulma-danger); }

/* Global upload manager — fixed bottom-right progress panel. */
.upload-mgr {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 60;
  width: 320px; max-width: calc(100vw - 2rem);
  background: var(--app-panel, var(--bulma-scheme-main)); color: var(--app-text);
  border: 1px solid var(--bulma-border); border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0,0,0,.28); overflow: hidden;
}
.upload-mgr-head {
  display: flex; align-items: center; gap: .5rem;
  padding: .6rem .8rem; background: var(--bulma-scheme-main-bis);
  border-bottom: 1px solid var(--bulma-border);
}
.upload-mgr-title { flex: 1 1 auto; font-weight: 600; font-size: .9rem; }
.upload-mgr-clear {
  flex: 0 0 auto; background: none; border: none; cursor: pointer;
  color: var(--bulma-link, #3b82f6); font-size: .8rem; padding: .15rem .3rem;
}
.upload-mgr-clear:hover { text-decoration: underline; }
.upload-mgr-clear.is-hidden { display: none; }
.upload-mgr-collapse, .upload-mgr-close {
  flex: 0 0 auto; background: none; border: none; cursor: pointer;
  color: var(--app-text); font-size: 1rem; line-height: 1; padding: .15rem .3rem;
}
.upload-mgr-close[disabled] { opacity: .35; cursor: default; }
.upload-mgr.is-collapsed .upload-mgr-collapse { transform: rotate(180deg); }
.upload-mgr-list { max-height: 260px; overflow-y: auto; }
.upload-mgr.is-collapsed .upload-mgr-list { display: none; }
.upload-mgr-row {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: .1rem .5rem;
  padding: .5rem .8rem; border-bottom: 1px solid var(--bulma-border-weak, var(--bulma-border));
}
.upload-mgr-row:last-child { border-bottom: none; }
.upload-mgr-name {
  grid-column: 1; font-size: .82rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.upload-mgr-meta { grid-column: 1; display: flex; align-items: center; gap: .5rem; }
.upload-mgr-meta .upload-mgr-bar { flex: 1 1 auto; }
.upload-mgr-size { flex: 0 0 auto; font-size: .72rem; color: var(--bulma-text-weak, #999); white-space: nowrap; }
.upload-mgr-state { grid-column: 2; grid-row: 1 / span 2; font-size: .8rem; min-width: 1.4rem; text-align: right; color: var(--bulma-text-weak, #999); }
.upload-mgr-row[data-state="done"] .upload-mgr-state { color: var(--bulma-success); }
.upload-mgr-row[data-state="failed"] .upload-mgr-state { color: var(--bulma-danger); }
.upload-mgr-bar { grid-column: 1; display: block; height: 5px; border-radius: 3px; background: var(--bulma-border); overflow: hidden; }
.upload-mgr-bar > span { display: block; height: 100%; width: 0; background: var(--bulma-primary); transition: width .15s; }
.upload-mgr-row[data-state="processing"] .upload-mgr-bar > span {
  width: 100% !important; background-color: var(--bulma-warning);
  background-image: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent);
  background-size: 40% 100%; background-repeat: no-repeat; background-position: -40% 0;
  animation: upload-mgr-shimmer 1.15s linear infinite;
}
@keyframes upload-mgr-shimmer {
  0%   { background-position: -40% 0; }
  100% { background-position: 140% 0; }
}
.upload-mgr-row[data-state="done"] .upload-mgr-bar > span { background: var(--bulma-success); }
.upload-mgr-row[data-state="failed"] .upload-mgr-bar > span { width: 100% !important; background: var(--bulma-danger); }
.upload-mgr-retry { background: none; border: none; cursor: pointer; color: var(--bulma-danger); font-size: 1rem; padding: 0; }
.upload-mgr-cancel {
  background: none; border: none; cursor: pointer; color: var(--bulma-text-weak, #999);
  line-height: 1; padding: 0 .1rem; border-radius: 3px;
}
.upload-mgr-cancel:hover { color: var(--bulma-danger); background: var(--bulma-scheme-main-bis); }
/* Every panel icon renders at one consistent size regardless of its button. */
.upload-mgr .ic { width: 16px; height: 16px; }

.media-lightbox {
  position: fixed; inset: 0; z-index: 100;
  display: none; align-items: center; justify-content: center;
  background: hsla(0,0%,0%,0.85); cursor: zoom-out; padding: 2rem;
}
.media-lightbox.is-active { display: flex; }
.media-lightbox img { max-width: 95vw; max-height: 92vh; object-fit: contain; border-radius: var(--bulma-radius); }

/* Phase 3 — video tiles + iframe lightbox */
.media-thumb.is-video { position: relative; background: #000; }
.media-thumb .media-video-blank { width: 100%; height: 100%; background:
  repeating-linear-gradient(45deg, #1f1f1f, #1f1f1f 10px, #262626 10px, #262626 20px); }
.media-play-badge {
  position: absolute; inset: 0; margin: auto; width: 2.6rem; height: 2.6rem;
  display: flex; align-items: center; justify-content: center; border-radius: 50%;
  background: rgba(0,0,0,0.55); color: #fff; font-size: 1.1rem; pointer-events: none;
}
.media-processing {
  position: absolute; inset: auto 0 0 0; padding: 3px 6px; font-size: 0.7rem;
  text-align: center; background: rgba(0,0,0,0.6); color: #fff; pointer-events: none;
}
.media-failed {
  position: absolute; inset: auto 0 0 0; padding: 3px 6px; font-size: 0.7rem;
  text-align: center; background: rgba(150,20,20,0.78); color: #fff; pointer-events: none;
}
/* Big live Bunny transcode % centred on a processing video tile. */
.media-vid-pct {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 1.9rem; font-weight: 700; color: #fff; text-shadow: 0 1px 4px rgba(0,0,0,.6);
  pointer-events: none; z-index: 2;
}
.media-lightbox.is-video { display: none; }
.media-lightbox.is-video.is-active {
  display: flex; align-items: center; justify-content: center;
  position: fixed; inset: 0; z-index: 1000; background: rgba(0,0,0,0.85);
}
.media-video-frame { width: min(90vw, 1280px); aspect-ratio: 16 / 9; }
.media-video-frame iframe { width: 100%; height: 100%; border: 0; }

.border-radius-button { border-radius: var(--bulma-radius); }