/*
 * The shared components' look (docs/goals/platform/one-look/plan.md). Every state is a step of the
 * glaze on :root: a plate at rest, one step brighter under the pointer, brighter again held down, and
 * at the top step when selected. The only lines are the keyboard's and a dashed one. A screen lays
 * these components out and never draws a control itself.
 */

/* ── Icons, and text for the screen reader alone ─────────────────────────────────────────────── */
.ui-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.ui-icon {
  display: block;
  width: 16px;
  height: 16px;
  fill: currentColor;
  color: currentColor;
}

/* ── Button ──────────────────────────────────────────────────────────────────────────────────── */
.ui-btn {
  --ui-btn-h: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  position: relative;
  box-sizing: border-box;
  flex-shrink: 0;
  height: var(--ui-btn-h);
  padding: 0 12px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.ui-btn:hover:not(:disabled) { background: var(--plate-hover); }
.ui-btn:active:not(:disabled) { background: var(--plate-down); }
.ui-btn.selected:not(:disabled) { background: var(--plate-selected); }
.ui-btn:disabled { opacity: 0.4; cursor: default; }
.ui-btn:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }

.ui-btn-sm { --ui-btn-h: 24px; padding: 0 9px; font-size: 11px; }
.ui-btn-xs { --ui-btn-h: 20px; padding: 0 6px; font-size: 11px; border-radius: var(--r-chip); }
.ui-btn-icon { width: var(--ui-btn-h); padding: 0; font-size: 15px; }

/* The one main action. */
.ui-btn-main { background: var(--ui-btn-color, var(--accent)); color: var(--ink); }
.ui-btn-main:hover:not(:disabled) { background: color-mix(in srgb, var(--ui-btn-color, var(--accent)) 82%, white); }
.ui-btn-main:active:not(:disabled) { background: color-mix(in srgb, var(--ui-btn-color, var(--accent)) 88%, black); }
.ui-btn-main.selected:not(:disabled) { background: color-mix(in srgb, var(--ui-btn-color, var(--accent)) 88%, black); }

/* What cannot be undone: red, and solid only while the pointer is over it. */
.ui-btn-danger { background: color-mix(in srgb, var(--pgm) 16%, transparent); color: var(--pgm); }
.ui-btn-danger:hover:not(:disabled) { background: var(--pgm); color: var(--on-fill); }
.ui-btn-danger:active:not(:disabled) { background: color-mix(in srgb, var(--pgm) 86%, black); color: var(--on-fill); }
.ui-btn-danger.selected:not(:disabled) { background: color-mix(in srgb, var(--pgm) 24%, var(--plate)); color: var(--pgm); }

/* Recording is a tally, with the same shade steps rather than a destructive action's solid fill. */
.ui-btn-record { background: color-mix(in srgb, var(--pgm) 16%, var(--plate)); color: var(--pgm); }
.ui-btn-record:hover:not(:disabled) { background: color-mix(in srgb, var(--pgm) 26%, var(--plate-hover)); color: var(--text); }
.ui-btn-record:active:not(:disabled) { background: color-mix(in srgb, var(--pgm) 34%, var(--plate-down)); color: var(--text); }
.ui-btn-record.selected:not(:disabled) { background: color-mix(in srgb, var(--pgm) 30%, var(--plate-selected)); color: var(--text); }

/* No plate until the pointer comes, as a row in a list has none. */
.ui-btn-quiet,
.ui-btn-remove { background: transparent; color: var(--muted); }
.ui-btn-quiet:hover:not(:disabled),
.ui-btn-remove:hover:not(:disabled) { background: var(--plate); color: var(--text); }
.ui-btn-quiet:active:not(:disabled),
.ui-btn-remove:active:not(:disabled) { background: var(--plate-down); }
.ui-btn-quiet.selected:not(:disabled),
.ui-btn-remove.selected:not(:disabled) { background: var(--plate-selected); color: var(--text); }
.ui-btn-remove:hover:not(:disabled) { color: var(--pgm); }

/* An event tag is a small neutral toggle in the Events editor. */
.ui-event-tag {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: var(--r-chip);
  background: transparent;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}
.ui-event-tag.active,
.ui-event-tag.ui-btn.selected:not(:disabled) { background: var(--text); color: var(--ink); }
.ui-event-tag.ui-btn.selected:hover:not(:disabled) { background: var(--on-fill); color: var(--ink); }
.ui-event-tag.ui-btn.selected:active:not(:disabled) { background: color-mix(in srgb, var(--text) 85%, var(--muted)); }

/* A glyph that says what a transport does. */
.ui-btn[data-glyph="play"]:not(:disabled) { color: var(--pst); }
.ui-btn[data-glyph="warning"]:not(:disabled) { color: var(--on); }

/* ── Chip: one choice of a few ───────────────────────────────────────────────────────────────── */
.ui-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  box-sizing: border-box;
  height: 24px;
  min-width: 0;
  padding: 0 10px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--muted);
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.ui-chip:hover:not(:disabled) { background: var(--plate-hover); color: var(--text); }
.ui-chip:active:not(:disabled) { background: var(--plate-down); }
.ui-chip.selected { background: var(--plate-selected); color: var(--text); }
.ui-chip:disabled { opacity: 0.4; cursor: default; }
.ui-chip:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }

/* A colour choice is its colour, with the chosen state marked inside it. */
.ui-swatch {
  --ui-swatch-size: 22px;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 var(--ui-swatch-size);
  width: var(--ui-swatch-size);
  height: var(--ui-swatch-size);
  padding: 0;
  border: 0;
  border-radius: var(--r-chip);
  background: var(--ui-swatch-color);
  color: white;
  cursor: pointer;
  transition: filter 0.1s, transform 0.1s;
}
.ui-swatch:hover:not(:disabled) { filter: brightness(1.12); transform: scale(1.06); }
.ui-swatch:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 2px; }
.ui-swatch:disabled { opacity: 0.4; cursor: default; }
.ui-swatch-mark { font-size: 12px; font-weight: 900; line-height: 1; text-shadow: 0 0 2px var(--bg); }

/* Configuration colours use one palette and one optional custom choice in properties. */
.ui-colour-properties { display: flex; flex-direction: column; gap: 10px; min-width: 0; margin-bottom: 20px; }
.ui-colour-heading { color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; }
.ui-colour-swatches { display: flex; flex-wrap: wrap; gap: 6px; }
.ui-colour-options { display: flex; align-items: center; gap: 10px; }
.ui-colour-custom { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); font-size: 11px; cursor: pointer; }
.ui-card-colour { position: absolute; top: 6px; right: 30px; z-index: 4; opacity: 0; pointer-events: none; }
.cfg-link-card:hover .ui-card-colour,
.cfg-link-card:focus-within .ui-card-colour { opacity: 1; pointer-events: auto; }
.cfg-link-card:has(.inline-rename-input) .ui-card-colour { visibility: hidden; }
@media (hover: none) {
  .cfg-link-card .ui-card-colour { opacity: 1; pointer-events: auto; }
  .admin-node-card .ui-card-colour, .admin-stage-card .ui-card-colour { opacity: 1; pointer-events: auto; }
}

/* A status badge: the same pill at rest, with colour for a state that has meaning. */
.ui-badge {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  min-height: 22px;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: var(--muted);
  font: inherit;
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.6px;
  line-height: 1.2;
  text-transform: uppercase;
}
.ui-icon-spin { animation: ui-icon-spin 1s linear infinite; }
@keyframes ui-icon-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .ui-icon-spin { animation: none; } }
.ui-badge-good { background: color-mix(in srgb, var(--pst) 16%, var(--plate)); color: var(--pst); }
.ui-badge-accent { background: color-mix(in srgb, var(--accent) 16%, var(--plate)); color: var(--accent); }
.ui-badge-warning { background: color-mix(in srgb, var(--on) 16%, var(--plate)); color: var(--on); }
.ui-badge-danger { background: color-mix(in srgb, var(--pgm) 16%, var(--plate)); color: var(--pgm); }

/* ── Field: where you type ───────────────────────────────────────────────────────────────────── */
.ui-field {
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  height: 28px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--field);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  line-height: 1.2;
}
.ui-field:hover:not(:disabled):not(:focus) { background: var(--field-hover); }
.ui-field:focus { outline: 2px solid var(--focus-line); outline-offset: 1px; }
.ui-field:disabled { opacity: 0.45; }
.ui-field::placeholder { color: color-mix(in srgb, var(--muted) 55%, transparent); opacity: 1; }
.ui-field::selection { background: color-mix(in srgb, var(--accent) 40%, transparent); color: var(--text); }
.ui-color-input {
  box-sizing: border-box;
  width: 46px;
  height: 26px;
  padding: 2px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  cursor: pointer;
}
.ui-color-input:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }
.ui-color-input:disabled { opacity: 0.45; cursor: default; }
.ui-textarea { height: auto; min-height: 56px; padding: 6px 8px; line-height: 1.4; resize: vertical; }
.ui-select {
  appearance: none;
  padding-right: 26px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238a96a6' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  cursor: pointer;
}

/* ── Range: a blue progress track, keyboard focus, and no platform-default white trough ───────── */
.ui-range {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 1 256px;
  width: 256px;
  min-width: 88px;
  height: 20px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: pointer;
  touch-action: pan-y;
}
.ui-range::-webkit-slider-runnable-track {
  height: var(--ui-range-track-height, 6px);
  border-radius: 999px;
  background: linear-gradient(to right, var(--accent) 0%, var(--accent) var(--ui-range-progress), var(--plate) var(--ui-range-progress), var(--plate) 100%);
}
.ui-range:hover::-webkit-slider-runnable-track {
  background: linear-gradient(to right, var(--accent) 0%, var(--accent) var(--ui-range-progress), var(--plate-hover) var(--ui-range-progress), var(--plate-hover) 100%);
}
.ui-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: var(--ui-range-thumb-size, 14px);
  height: var(--ui-range-thumb-size, 14px);
  margin-top: calc((var(--ui-range-track-height, 6px) - var(--ui-range-thumb-size, 14px)) / 2);
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: var(--ui-range-thumb-shadow, 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent));
}
.ui-range::-moz-range-track {
  height: var(--ui-range-track-height, 6px);
  border-radius: 999px;
  background: var(--plate);
}
.ui-range::-moz-range-progress { height: var(--ui-range-track-height, 6px); border-radius: 999px; background: var(--accent); }
.ui-range::-moz-range-thumb {
  width: var(--ui-range-thumb-size, 14px);
  height: var(--ui-range-thumb-size, 14px);
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: var(--ui-range-thumb-shadow, 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent));
}
.ui-range:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 2px; }
.ui-range:disabled { opacity: 0.4; cursor: default; }

/* ── Rows and cards: layout belongs to the screen, their plate and states do not ──────────────── */
.ui-row,
.ui-card {
  min-width: 0;
  border-radius: var(--r-control);
  transition: background 0.1s;
}
.ui-row.ui-interactive,
.ui-card.ui-interactive { cursor: pointer; }
.ui-row.ui-interactive:hover { background: var(--plate); }
.ui-row.ui-selected { background: var(--plate-selected); }
.ui-row:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }
.ui-card {
  box-sizing: border-box;
  border: 0;
  border-radius: var(--r-card);
  background: var(--plate);
  color: inherit;
  font: inherit;
  text-align: left;
}
.ui-card.ui-interactive:hover { background: var(--plate-hover); }
.ui-card.ui-selected,
.ui-card.selected { background: var(--plate-selected); }
.ui-card:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }

/* Programmatic focus scopes route editor shortcuts; their child controls own keyboard focus. */
.ui-focus-scope:focus { outline: none; }

/* Timeline markers share their shape and states; editor layouts place them. */
.ui-timeline-playhead { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--playhead-color, var(--accent)); pointer-events: none; z-index: 2; }
.ui-timeline-playhead.has-head::before { content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 14px; height: 12px; background: var(--playhead-color, var(--accent)); clip-path: polygon(0 0, 100% 0, 50% 100%); }
.ui-timeline-keyframe { position: absolute; top: 50%; width: 9px; height: 9px; transform: translate(-50%, -50%) rotate(45deg); background: var(--text); border: 0; border-radius: var(--r-chip); cursor: ew-resize; touch-action: none; z-index: 1; }
.ui-timeline-keyframe:hover, .ui-timeline-keyframe.at-playhead, .ui-timeline-keyframe.selected { background: var(--accent); }
.ui-timeline-keyframe.selected { transform: translate(-50%, -50%) rotate(45deg) scale(1.2); }
.ui-timeline-keyframe.dot { width: 10px; height: 10px; border-radius: 50%; transform: translate(-50%, -50%); }
.ui-timeline-keyframe.dot.selected { transform: translate(-50%, -50%) scale(1.2); }
.ui-timeline-keyframe.summary { width: 6px; height: 6px; background: var(--muted); pointer-events: none; }
.ui-timeline-keyframe.summary.at-playhead { background: var(--accent); }
.ui-timeline-keyframe:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 2px; }

/* ── Floating layer: one soft surface for a menu, picker list, or popover ──────────────────────── */
.ui-popover {
  min-width: 0;
  border: 0;
  border-radius: var(--r-card);
  background: var(--float);
  -webkit-backdrop-filter: var(--float-blur);
  backdrop-filter: var(--float-blur);
  box-shadow: var(--float-shadow);
}

/* A modal uses the same floating surface, inside one shared dimmed scrim and semantic dialog. */
.ui-dialog-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
}
.ui-dialog {
  box-sizing: border-box;
  width: min(420px, calc(100vw - 32px));
  max-height: calc(100vh - 32px);
  overflow: auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  border: 0;
  border-radius: var(--r-card);
  background: var(--float);
  -webkit-backdrop-filter: var(--float-blur);
  backdrop-filter: var(--float-blur);
  box-shadow: var(--float-shadow);
}
.ui-dialog h3 { margin: 0; font-size: 15px; font-weight: 600; }

/* ── Menu option: a flat row, brighter when pointed at or chosen, with an optional color dot ──── */
.ui-menu-item {
  box-sizing: border-box;
  flex: none;
  width: 100%;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 8px;
  border: 0;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  transition: background 0.1s;
}
.ui-menu-item:hover:not(:disabled) { background: var(--plate); }
.ui-menu-item.ui-selected { background: var(--plate-selected); }
.ui-menu-item.ui-menu-multi.ui-selected { background: var(--plate); }
.ui-menu-item.ui-menu-multi:hover:not(:disabled) { background: var(--plate-hover); }
.ui-menu-item:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }
.ui-menu-item:disabled { opacity: 0.4; cursor: default; }
.ui-menu-marker {
  flex: 0 0 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ui-menu-marker);
}
.ui-menu-check {
  position: relative;
  flex: 0 0 14px;
  width: 14px;
  height: 14px;
  border-radius: var(--r-chip);
  background: var(--plate);
}
.ui-menu-item.ui-selected .ui-menu-check { background: var(--accent); color: var(--ink); }
.ui-menu-item.ui-selected .ui-menu-check::after {
  content: '✓';
  position: absolute;
  inset: -1px 0 0;
  font-size: 10px;
  font-weight: 800;
  line-height: 14px;
  text-align: center;
}

/* ── Segmented choice: a few side by side, the selected one lit ──────────────────────────────── */
.ui-seg {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border-radius: var(--r-control);
  background: var(--field);
}
.ui-seg-btn {
  height: 24px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--r-chip);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.ui-seg-btn:hover:not(:disabled):not(.selected) { background: var(--plate); color: var(--text); }
.ui-seg-btn:active:not(:disabled):not(.selected) { background: var(--plate-down); }
.ui-seg-btn.selected,
.ui-seg-btn.selected:hover:not(:disabled),
.ui-seg-btn.selected:active:not(:disabled) { background: var(--ui-seg-color, var(--accent)); color: var(--ink); }
.ui-seg-btn:disabled { opacity: 0.35; cursor: default; }
.ui-seg-btn.selected:disabled { opacity: 1; }
.ui-seg-btn:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }
/* In a bar, at the bar's height. */
.ui-seg-compact { padding: 1px; gap: 1px; }
.ui-seg-compact .ui-seg-btn { height: 20px; padding: 0 7px; font-size: 11px; font-weight: 800; }
/* Optional removal stays inside the choice plate without nesting one button in another. */
.ui-seg-item { position: relative; display: inline-flex; color: var(--muted); }
.ui-seg-item.selected { color: var(--ink); }
.ui-seg-item .ui-seg-btn { padding-right: 30px; }
.ui-seg-item .ui-seg-remove { position: absolute; right: 0; top: 0; opacity: 0; pointer-events: none; }
.ui-seg-item .ui-seg-remove:not(:hover) { color: inherit; }
.ui-seg-item:hover .ui-seg-remove,
.ui-seg-item:focus-within .ui-seg-remove { opacity: 1; pointer-events: auto; }
.ui-seg-item:has(.inline-rename-input) .ui-seg-remove { visibility: hidden; }
.ui-seg-compact .ui-seg-item .ui-seg-btn { padding-right: 24px; }
@media (hover: none) {
  .ui-seg-item .ui-seg-remove { opacity: 1; pointer-events: auto; }
}

/* ── Fold: a part of a screen that folds to its head ─────────────────────────────────────────── */
/* A band the width of what holds it, a rung above it, with a hairline under: chevron, name, and what
   it says folded or open. The controls at its right edge are beside the fold, not in it. */
.ui-fold { position: relative; min-width: 0; }
.ui-fold-head {
  display: flex;
  align-items: center;
  min-width: 0;
  border-bottom: 1px solid var(--line);
  background: var(--panel-2);
  color: color-mix(in srgb, var(--text) 78%, var(--muted));
}
.ui-fold-head:hover { color: var(--text); background: color-mix(in srgb, var(--text) 6%, var(--panel-2)); }
.ui-fold-toggle {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 6px 10px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  user-select: none;
}
.ui-fold-toggle:focus-visible { outline: 2px solid var(--focus-line); outline-offset: -2px; }
.ui-fold-chevron { flex: 0 0 10px; font-size: 10px; }
.ui-fold-title { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.ui-fold-summary {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The grip says a band can be dragged up or down, as the rundown's sections say it. */
.ui-fold-grip {
  flex: none;
  padding: 0 10px 0 0;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: -2px;
  opacity: 0;
  cursor: grab;
}
.ui-fold-head:hover .ui-fold-grip { opacity: .8; }
.ui-fold-head[draggable="true"]:active { cursor: grabbing; }
/* Where a band being moved would land: a dashed line before this one or after it. */
.ui-fold.drop-before::before,
.ui-fold.drop-after::after {
  content: '';
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  border-top: 2px dashed color-mix(in srgb, var(--text) 45%, transparent);
  pointer-events: none;
}
.ui-fold.drop-before::before { top: -1px; }
.ui-fold.drop-after::after { bottom: -1px; }
.ui-fold-live { color: var(--pst); font-weight: 800; }
.ui-fold-warn { color: var(--pgm); font-weight: 800; }
.ui-fold-actions { display: flex; flex: 0 0 auto; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 6px; min-width: 0; padding: 3px 10px 3px 0; }
/* Keep the content one step below its head, including inside raised or floating panels.
   Inheriting the panel's background can make a folding band disappear into its contents. */
.ui-fold-body, .rd-rail-section-body { background: var(--panel); }
.ui-fold-body { padding: 6px 10px 10px; }
/* Put in a narrow side panel, what it holds scrolls sideways rather than being cut off. */
.rd-rail-body .ui-fold-body,
.rd-aside-sections .ui-fold-body { overflow-x: auto; }
/* What it holds is bands of their own, and each stands in a step from its parent's edge. */
.ui-fold-flush > .ui-fold-body { padding: 0; }
.ui-fold .ui-fold .ui-fold-toggle { padding-left: 24px; }
.ui-fold .ui-fold .ui-fold .ui-fold-toggle { padding-left: 38px; }
.ui-fold .ui-fold .ui-fold .ui-fold .ui-fold-toggle { padding-left: 52px; }
/* The rundown's sections are not Folds, but a band in one stands in a step from its edge as well. */
.rd-rail-section .ui-fold > .ui-fold-head .ui-fold-toggle { padding-left: 24px; }
.rd-rail-section .ui-fold .ui-fold > .ui-fold-head .ui-fold-toggle { padding-left: 38px; }
.ui-fold-body[hidden] { display: none; }
/* A band named as its author wrote it, or by a route it draws (PLAY → billie), not by a word of the
   screen: in the case it was written in, cut with an ellipsis when long, and what it says at its right edge. */
.ui-fold-as-written > .ui-fold-head .ui-fold-title { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 700; letter-spacing: 0; text-transform: none; }
.ui-fold-as-written > .ui-fold-head .ui-fold-summary { flex: 1 0 auto; overflow: visible; text-align: right; }
/* Open, it takes the height its parent leaves, and what it holds scrolls there. */
.ui-fold-fill { display: flex; flex-direction: column; min-height: 0; }
.ui-fold-fill.open { flex: 1 1 0; }
.ui-fold-fill > .ui-fold-body { display: flex; flex: 1 1 0; flex-direction: column; min-height: 0; padding: 0; }

/* ── Add with a choice: the add card, and under it a menu of the ways a new one can start ───────── */
.ui-add-choice { position: relative; display: flex; min-width: 0; }
.ui-add-choice > .cfg-link-card { flex: 1 1 auto; }
.ui-add-choice-menu { position: fixed; top: 0; left: 0; z-index: 1000; width: 280px; max-width: calc(100vw - 16px); max-height: calc(100vh - 16px); box-sizing: border-box; overflow-y: auto; padding: 7px; display: flex; flex-direction: column; }
/* The menu scrolls as a whole, so the picker's list in it is as long as it is. */
.ui-add-choice-menu .te-combo-list { max-height: none; overflow: visible; }
.ui-add-choice-menu > .te-combo-list:first-child { margin-top: 0; }

/* Quantities share one quiet pill and one right edge, open or folded. */
.ui-fold-counts { display: inline-flex; align-items: center; justify-content: flex-end; gap: 4px; flex: 0 0 auto; margin-left: auto; }
.ui-count.ui-badge { justify-content: center; min-width: 18px; min-height: 18px; padding: 1px 6px; font-size: 10px; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ui-count-prefix { color: var(--muted); font-size: 9px; margin-right: 3px; }
.ui-fold:has(> .ui-fold-head .ui-fold-counts) > .ui-fold-head .ui-fold-summary { flex: 0 1 auto; min-width: 0; overflow: hidden; }

/* A pane keeps the same header height with or without a count badge; nested bands stay compact. */
.ui-pane-head { min-height: 32px; box-sizing: border-box; }
/* A pane's × and grip open at the right edge while its head has the pointer or the keyboard; at rest
   they take no room, so its count stands at the right edge, as every count does. */
.ui-pane-controls { display: grid; grid-template-columns: 0 0; align-items: center; column-gap: 0; flex: none; padding: 0; overflow: hidden; transition: grid-template-columns .12s ease, column-gap .12s ease, padding .12s ease; }
:is(.ui-fold-head, .rd-rail-section-head, .rd-column-tools):is(:hover, :focus-within) > .ui-pane-controls { grid-template-columns: 20px 12px; column-gap: 4px; padding: 0 8px 0 4px; }
.ui-pane-controls > .ui-pane-close { grid-column: 1; width: 20px; min-width: 20px; padding: 0; margin: 0; color: var(--muted); opacity: 0; pointer-events: none; }
:is(.ui-fold-head, .rd-rail-section-head, .rd-column-tools):is(:hover, :focus-within) > .ui-pane-controls > .ui-pane-close { opacity: 1; pointer-events: auto; }
@media (hover: none) {
  .ui-pane-controls { grid-template-columns: 20px 12px; column-gap: 4px; padding: 0 8px 0 4px; }
  .ui-pane-controls > .ui-pane-close { opacity: 1; pointer-events: auto; }
}
.ui-pane-controls > .ui-pane-grip { grid-column: 2; width: 12px; padding: 0; margin: 0; text-align: center; }

.ui-preview-popover { position: fixed; z-index: 10000; padding: 6px; pointer-events: none; animation: ui-preview-arrive .12s ease-out; }
.ui-chip-hover-popover { overflow: hidden; }
.ui-chip-hover-card { display: flex; flex-direction: column; gap: 7px; padding: 2px; font-size: 12px; line-height: 1.35; }
.ui-chip-hover-action { display: flex; min-width: 0; width: 100%; color: var(--text); }
.ui-chip-hover-action.is-disabled { opacity: .5; }
.ui-chip-hover-action .rd-chip-route { min-height: 25px; }
.ui-chip-hover-action .rd-chip-token { max-width: none; }
.ui-chip-hover-action .rd-chip-kind { margin-left: auto; }
.ui-event-identity.action-parts-surface { display: flex; align-items: center; box-sizing: border-box; min-width: 0; min-height: 25px; gap: 6px; container: event-identity / inline-size; background: color-mix(in srgb, var(--kind-color, var(--panel-2)) 30%, var(--panel-2)); }
.ui-event-identity .rd-chip-token { max-width: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-event-identity .kind-mark { flex-shrink: 0; }
/* In the rundown, the item's mark starts where the words of the action chips under it do: their frame
   and inset, 1 + 6 px: measured, the two then start on the same pixel. */
.rd-part > .ui-event-identity.action-parts-surface { padding-left: 7px; }
.ui-event-details { display: flex; align-items: center; gap: 4px; min-width: 0; margin-left: auto; }
.ui-event-status { display: inline-flex; flex: none; }
.rd-chip-status { display: inline-flex; align-items: center; justify-content: center; min-width: 11px; height: 11px; padding: 0 2px; font-family: inherit; font-size: 9px; font-weight: 700; line-height: 1; border-radius: var(--r-chip); background: color-mix(in srgb, var(--panel-2) 82%, transparent); }
.rd-chip-status-glyph { white-space: nowrap; }
.rd-chip-status-idle, .rd-chip-status-pending { background: none; }
.rd-chip-status-error { background: color-mix(in srgb, var(--pgm) 22%, var(--panel-2)); }
.ui-event-identity .ui-event-details :is(.rd-inherit-badge, .rd-trim-summary, .rd-duration-chip) { flex: none; margin: 0; height: 16px; box-sizing: border-box; padding: 0 5px; border-radius: var(--r-control); background: var(--plate); color: var(--text); line-height: 16px; font-variant-numeric: tabular-nums; }
.ui-event-identity .ui-event-details .rd-trim-summary { flex-shrink: 1; }
.ui-event-identity .rd-trim-summary b { color: inherit; }
.ui-event-identity:has(.rd-chip-status-error) { background: color-mix(in srgb, var(--pgm) 30%, var(--panel-2)); }
.ui-event-identity.action-parts-surface:hover { background: color-mix(in srgb, var(--kind-color, var(--panel-2)) 38%, var(--panel-2)); }
@container event-identity (max-width: 260px) { .ui-event-details .rd-trim-summary { display: none; } }
@container event-identity (max-width: 150px) { .ui-event-details .rd-inherit-badge { display: none; } }
@container event-identity (max-width: 96px) { .ui-event-details .rd-duration-chip { display: none; } }
.ui-chip-hover-media { min-width: 0; border-radius: var(--r-control); overflow: hidden; }
.ui-chip-hover-actions { display: flex; flex-direction: column; gap: 3px; }
.ui-chip-hover-footer { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 11px; padding: 1px 4px; }
.ui-chip-hover-status { margin-left: auto; }
.ui-chip-hover-status.is-good { color: var(--pst); }
.ui-chip-hover-status.is-warning { color: var(--warn); }
.ui-chip-hover-status.is-danger, .ui-chip-hover-message.is-danger { color: var(--pgm); }
.ui-chip-hover-message { padding: 0 4px 2px; font-size: 11px; overflow-wrap: anywhere; }
.ui-chip-hover-more { color: var(--muted); font-size: 11px; }
.ui-duration-readout { display: inline-flex; flex: 0 1 auto; flex-direction: row-reverse; flex-wrap: wrap; justify-content: flex-end; align-content: flex-start; align-items: center; column-gap: 5px; box-sizing: border-box; max-width: 100%; height: 18px; padding: 2px 0; overflow: hidden; color: var(--text); white-space: nowrap; line-height: 14px; }
.ui-duration-readout > span { flex: 0 0 auto; }
.ui-duration-edge { height: 14px; margin-left: -5px; }
.ui-duration-value { font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
.ui-duration-kind { color: var(--muted); font-size: 8px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
.ui-duration-name { color: var(--muted); font-size: 9px; }
.ui-duration-icon .ui-icon { width: 11px; height: 11px; color: var(--muted); }
.ui-chip-hover-status .rd-chip-status { position: static; margin: 0; }
@media (max-height: 500px) { .ui-chip-hover-media { max-height: 28vh; } }
@keyframes ui-preview-arrive { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .ui-preview-popover { animation: none; } }

/* A thing lifted larger on hover (HoverEnlarge): on the glass above the screen, its place kept. */
.ui-hover-enlarge { position: relative; min-width: 0; display: flow-root; }
.ui-hover-enlarged { z-index: 10000; padding: 0; border: 0; display: flex; flex-direction: column; overflow: hidden; cursor: grab; background: var(--bg); container-type: inline-size; }
.ui-hover-enlarged:active { cursor: grabbing; }
.ui-hover-enlarged::backdrop { background: transparent; pointer-events: none; }
/* Its one control of its own, the close, shows with the picture's controls: while the pointer is on it. */
.ui-hover-enlarged > .ui-picture-close { position: absolute; z-index: 20; top: 6px; right: 6px; flex: none; border-radius: var(--r-pill); background: color-mix(in srgb, var(--bg) 70%, transparent); color: var(--text); opacity: 0; transition: opacity .12s ease; }
.ui-hover-enlarged:hover > .ui-picture-close, .ui-hover-enlarged > .ui-picture-close:focus-visible { opacity: 1; }
.ui-hover-enlarged .graphics-picture-area { width: 100%; }
.ui-hover-enlarged > video { border-radius: var(--r-card); }
.ui-hover-enlarged > * { flex: 1 1 auto; min-height: 0; }
/* Without its glass while a list is open from it, so the list is placed on the window, not on it. */
.ui-hover-enlarged:has(.te-combo-pop) { -webkit-backdrop-filter: none; backdrop-filter: none; }

/* What a HoverPopover listens on when its trigger is not an element of its own (HoverPopover.tsx). */
.ui-hover-trigger { display: contents; }

/* How far a picture is zoomed (ZoomReadout.tsx), in the corner of whatever holds it. */
.ui-zoom-readout {
  position: absolute;
  right: 10px;
  bottom: 8px;
  z-index: 6;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  color: var(--muted);
  pointer-events: none;
}

/* The box dragged across a timeline to pick chips (useMarquee.tsx): a glaze over what it covers,
   no line, so the chips it lights read through it. */
.ui-marquee {
  position: fixed;
  z-index: 1000;
  pointer-events: none;
  background: color-mix(in srgb, var(--plate-selected) 60%, transparent);
  border-radius: var(--r-chip);
}

/* A column's edge (EdgeGrip.tsx): dragged to widen it, as a floating panel's edge is. */
.ui-edge-grip { position: absolute; z-index: 6; top: 0; bottom: 0; width: 6px; cursor: col-resize; touch-action: none; }
.ui-edge-grip-right { right: 0; }
.ui-edge-grip-left { left: 0; }
.ui-edge-grip:hover { background: var(--plate-hover); }
.ui-edge-grip:focus-visible { outline: 2px solid var(--focus-line); outline-offset: -2px; }
:root {
  /* One look (docs/goals/platform/one-look). The ground is three steps of blue-grey: the
     ground behind everything, the panel a rail or a screen stands on, and the raised step. */
  --bg: #0e1218;
  --panel: #161c26;
  --panel-2: #1d2532;
  --line: #2a3342; /* a hairline, where a list needs a divider: never an outline */
  --text: #d7dee8;
  --muted: #8a96a6;
  --ink: #06111d; /* text on a bright plate */
  --on-fill: #ffffff; /* text on a saturated fill: red under the pointer */
  --accent: #3aa0ff; /* the main action, default selected choice, switch and keyboard's line */
  --pgm: #ff3b3b;
  --pst: #2ecc71;
  --on: #ff9f1c;
  --warn: #ffcc00;
  --category-mixer: #2dd4bf; /* teal: apart from Graphics' violet */
  --category-shortcuts: #dcc39a; /* keycap beige: the keys, their own colour, not a clip's */
  --category-rundowns: #ee8ca5;
  --category-admin: #c7d0dc;
  --category-node: #ff8a6b; /* coral: this node, in Settings' rail, unlike any set's colour */
  --category-preset: #b7bec9; /* neutral slate: remembered profile choices */
  --category-layout: #c4e85a; /* lime: how the screen is arranged, unlike any tab's colour */
  --event-camera: #4aa3ff;
  --event-live: #36d677;
  --event-clip: #20d6d6;
  --event-voiceover: #d986ff;
  --event-gfx: #a78bfa;
  --event-pause: #ffcf4a;
  --event-automation: #8b95a5;
  --event-group: #c084fc;
  --group-stage: #f0883e;
  /* Source and domain colors for small tags, meters and log labels. */
  --source-gvg: var(--accent);
  --source-sony: #b48cff;
  --source-obs: #42a5ff;
  --source-calrec: var(--pst);
  --source-studer: var(--warn);
  --source-dhd: #d58cff;
  --source-fxmotion: #ef7dff;
  --source-telemetrics: #ff7ac8;
  --source-vizengine: #66e0a3;
  --source-mse: #5db7ff;
  --source-bigviz: #f45b69;
  --source-lottie: #c08bff;
  --source-airspeed: var(--event-clip);
  --source-quantel: #35d0ff;
  --source-mos: #a0d468;
  --source-templates: var(--on);
  --source-settings: #c7d0dc;
  --source-system: var(--muted);
  --source-cloud: #d89a1e;
  --source-mcp: var(--accent);
  --source-flows: var(--source-settings);
  --domain-video-mixer: var(--source-obs);
  --domain-audio-mixer: var(--pst);
  --domain-video-server: var(--event-clip);
  --domain-graphics: var(--source-lottie);
  --domain-robotics: var(--source-fxmotion);
  --domain-newsroom: var(--source-mos);
  --domain-hotkey: var(--on);
  --domain-rundown: #ffb84d;
  --domain-event: var(--on);
  --domain-settings: var(--source-settings);
  --domain-transport: #8796ff;
  --domain-system: var(--muted);
  --meter-track: rgb(255 255 255 / 0.045);
  --meter-safe: rgb(64 205 118 / 0.76);
  --meter-warn: rgb(240 196 25 / 0.82);
  --meter-clip: rgb(235 87 70 / 0.88);
  --canvas-checker-a: #11151c;
  --canvas-checker-b: #0f1319;
  --canvas-grid: rgb(138 150 166 / 0.10);
  --canvas-guide: #35e0d2;
  /* A plate is a glaze: white laid thin over what holds it, so it takes the colour it sits on. Each
     state is one step brighter: at rest, the pointer over it, held down, selected or active. A row
     in a list has no plate at rest, so the pointer takes it to --plate and selection to the top. */
  --plate: rgb(255 255 255 / 0.08);
  --plate-hover: rgb(255 255 255 / 0.12);
  --plate-down: rgb(255 255 255 / 0.18);
  --plate-selected: rgb(255 255 255 / 0.22);
  /* Open stories use a quieter shade than the shared selected plate. */
  --plate-story-selected: color-mix(in srgb, var(--text) 9%, var(--panel-2));
  --directory-badge: rgb(0 0 0 / 0.25);
  --timeline-ground: var(--panel);
  --field: rgb(0 0 0 / 0.35); /* where you type: a shade darker than what holds it */
  --field-hover: rgb(0 0 0 / 0.28);
  /* The only lines: where the keyboard is, and (dashed) what is not there yet. A failure is a plate. */
  --focus-line: var(--accent);
  --fail-plate: rgb(255 59 59 / 0.28);
  /* What floats: the raised step over a soft blur of what is behind it. */
  --float: color-mix(in srgb, var(--panel-2) 72%, transparent);
  --float-blur: blur(24px) saturate(1.3);
  --float-shadow: 0 12px 32px rgb(0 0 0 / 0.5);
  /* Corners: a chip, a control or a row, a card or a panel, and the pill. */
  --r-chip: 3px;
  --r-control: 6px;
  --r-card: 10px;
  --r-pill: 999px;
  /* Rundown and Graphics share their library and properties proportions. */
  --editor-rail-left: 268px;
  --editor-rail-right: 272px;
}

* {
  box-sizing: border-box;
}

html,
body,
#root {
  height: 100%;
  margin: 0;
}

body {
  background: var(--bg);
  color: var(--text);
  font: 13px/1.4 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.loading {
  display: grid;
  place-items: center;
  height: 100%;
  color: var(--muted);
}

.app-crash {
  min-height: 100vh;
  display: grid;
  place-items: center;
  background: var(--bg);
  color: var(--text);
  padding: 24px;
}

.app-crash-panel {
  width: min(520px, 100%);
  padding: 24px;
}

.app-crash-kicker {
  display: block;
  color: var(--pgm);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  margin-bottom: 8px;
}

.app-crash h1 {
  margin: 0 0 10px;
  font-size: 22px;
  letter-spacing: 0;
}

.app-crash p {
  color: var(--muted);
  margin: 0 0 18px;
  overflow-wrap: anywhere;
}

.app {
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* ---- App header ---- */
.app-header {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 18px;
  padding: 0 16px;
  height: 42px;
  min-height: 42px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.app-brand {
  display: flex;
  align-items: baseline;
  gap: clamp(4px, 0.55vw, 7px);
  flex: 0 0 auto;
  user-select: none;
}
.app-brand-hi {
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent);
}
.app-brand-early-access {
  color: var(--text);
  font-size: clamp(8px, 0.68vw, 10px);
  font-style: italic;
  font-weight: 550;
  letter-spacing: 0.025em;
  line-height: 1;
  white-space: nowrap;
}
.app-brand-lo {
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--muted);
}
.app-chips {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow-x: auto;
}
.app-chip {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
  background: var(--panel-2);
  color: var(--muted);
  user-select: none;
}
.app-chip.listening { background: color-mix(in srgb, var(--accent) 12%, var(--panel-2)); color: var(--accent); }
.app-chip.connected { background: color-mix(in srgb, var(--pst) 12%, var(--panel-2)); color: var(--pst); }
.app-chip.error     { background: color-mix(in srgb, var(--pgm) 12%, var(--panel-2)); color: var(--pgm); }

.app-chip-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
  flex-shrink: 0;
}
.app-chip-dot.listening { background: var(--accent); }
.app-chip-dot.connected { background: var(--pst);    box-shadow: 0 0 4px var(--pst); }
.app-chip-dot.error     { background: var(--pgm); box-shadow: 0 0 4px var(--pgm); }
.app-chip-dot.stopped   { background: var(--muted); }
.app-chip-dot.warn      { background: var(--on); box-shadow: 0 0 4px var(--on); }

/* The segmented choice is the shared ProtocolChips (components/ui/ui.css). */
.te-prop-section .ui-seg { flex-wrap: wrap; }
/* The Mixer's deck, chosen in its bar: lit in the deck's own colour, orange for next, green for on air. */
.mx-deck-chips.next .ui-seg-btn.selected { background: var(--on); color: var(--ink); }
.mx-deck-chips.onair .ui-seg-btn.selected { background: var(--pst); color: var(--ink); }

/* ---- Transport config (inside Vision Mixer panel) ---- */
.vcfg {
  display: flex;
  flex-direction: column;
  gap: 0;
  background: color-mix(in srgb, var(--bg) 60%, var(--panel-2));
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  margin-bottom: 10px;
}
.vcfg-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 50%, transparent);
}
.vcfg-row:last-child {
  border-bottom: none;
}
.vcfg-host {
  width: 106px;
  background: var(--field);
  border: 0;
  color: var(--text);
  border-radius: var(--r-control);
  padding: 3px 6px;
  font-size: 12px;
}
.vcfg-port {
  width: 64px;
  background: var(--field);
  border: 0;
  color: var(--text);
  border-radius: var(--r-control);
  padding: 3px 6px;
  font-size: 12px;
}
.vcfg-port-sel {
  background: var(--field);
  border: 0;
  color: var(--text);
  border-radius: var(--r-control);
  padding: 3px 6px;
  font-size: 12px;
  max-width: 200px;
}
.vcfg-host:focus-visible,
.vcfg-port:focus-visible,
.vcfg-port-sel:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }

/* ---- Shared control primitives ---- */
.chk {
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  font-size: 12px;
  min-width: 58px;
}
.baud,
.detail {
  color: var(--muted);
  font-size: 11px;
}
.dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--muted);
  display: inline-block;
  flex-shrink: 0;
}
.dot.listening {
  background: var(--accent);
}
.dot.connected {
  background: var(--pst);
  box-shadow: 0 0 6px var(--pst);
}
.dot.error {
  background: var(--pgm);
}
.dot.stopped { background: var(--muted); }

/* ---- Layout ---- */
.body {
  display: flex;
  flex: 1;
  min-height: 0;
  min-width: 0;
}
.stage {
  flex: 1 1 auto;
  min-width: 0;
  overflow: auto;
  padding: 12px;
}
.sidebar {
  flex: 0 0 clamp(300px, 24vw, 360px);
  width: clamp(300px, 24vw, 360px);
  min-width: 0;
  border-left: 1px solid var(--line);
  background: var(--panel);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

@media (max-width: 980px) {
  .body {
    flex-direction: column;
  }
  .stage {
    flex: 1 1 0;
    padding: 8px;
  }
  .sidebar {
    flex: 0 0 clamp(180px, 34vh, 260px);
    width: 100%;
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}

/* ---- The vision mixers' faces (MixEffectBank, AuxPanel, DskPanel, ObsVisionPanel) ----
   Keys are plates, the tally's red and green only where they mean something, no boxes with edges, and a
   layout that gives way to a side panel's width. */
.sim-block { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sim-label { margin: 0; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.me-grid { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.me-bank { padding-bottom: 8px; border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.me-bank:last-child { padding-bottom: 0; border-bottom: 0; }
.me-bank.mixing .me-title { color: var(--on); }
.me-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.me-title { font-size: 11px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.me-meta { display: flex; gap: 8px; color: var(--muted); font-size: 10px; }
.me-meta .emem { color: var(--accent); }
.me-meta .mix-dot { color: var(--on); }

.bus { display: grid; grid-template-columns: 24px minmax(0, 1fr); align-items: start; gap: 6px; margin: 3px 0; }
.bus-name { padding-top: 4px; color: var(--muted); font-size: 9px; font-weight: 800; letter-spacing: 0.06em; }
.bus.pgm .bus-name { color: var(--pgm); }
.bus.pst .bus-name { color: var(--pst); }
.xpoints { display: grid; grid-template-columns: repeat(auto-fill, minmax(42px, 1fr)); gap: 3px; }
.xpt { padding: 3px 1px; overflow: hidden; border-radius: var(--r-chip); background: var(--plate); color: var(--muted); font-size: 10px; text-align: center; text-overflow: ellipsis; white-space: nowrap; }
.bus.pgm .xpt.active { background: var(--pgm); color: var(--on-fill); font-weight: 800; }
.bus.pst .xpt.active { background: var(--pst); color: var(--ink); font-weight: 800; }

.keyers { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.keyer { display: flex; align-items: center; gap: 5px; padding: 2px 7px; border-radius: var(--r-chip); background: var(--plate); font-size: 10px; }
.keyer.on { background: color-mix(in srgb, var(--on) 18%, var(--plate)); color: var(--on); }
.keyer .k-label { color: var(--muted); font-weight: 800; }
.keyer.on .k-label { color: inherit; }

.bus-row { display: flex; flex-wrap: wrap; gap: 8px 14px; margin-top: 8px; }
.aux-panel { flex: 1 1 150px; }
.aux-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 3px; }
.aux-tile { display: flex; flex-direction: column; padding: 3px 6px; border-radius: var(--r-chip); background: var(--plate); }
.aux-tile.set { background: color-mix(in srgb, var(--accent) 16%, var(--plate)); }
.aux-n { color: var(--muted); font-size: 9px; }
.aux-src { font-size: 11px; font-weight: 600; }
.dsk-panel { flex: 0 1 auto; }
.dsk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 96px)); gap: 3px; }
.dsk-tile { appearance: none; display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 4px 6px; border: 0; border-radius: var(--r-chip); background: var(--plate); color: inherit; cursor: pointer; font: inherit; font-size: 10px; font-weight: 800; }
.dsk-tile:hover:not(.on) { background: var(--plate-hover); }
.dsk-tile.on { background: var(--pgm); color: var(--on-fill); }
.dsk-state { color: var(--muted); font-size: 9px; font-weight: 600; }
.dsk-tile.on .dsk-state { color: color-mix(in srgb, var(--on-fill) 80%, transparent); }

/* OBS as a vision mixer: its scenes are keys, on the same plates. */
.obs-scene-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 3px; }
.obs-scene-btn { appearance: none; padding: 4px; overflow: hidden; border: 0; border-radius: var(--r-chip); background: var(--plate); color: var(--muted); cursor: pointer; font: inherit; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; transition: background 0.1s; }
.obs-scene-btn:hover { background: var(--plate-hover); }
.obs-scene-btn:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }
.obs-scene-btn.pgm { background: var(--pgm); color: var(--on-fill); font-weight: 800; }
.obs-scene-btn.pst { background: var(--pst); color: var(--ink); font-weight: 800; }
.obs-transition-row { display: flex; gap: 6px; margin-top: 6px; }
.obs-transition-row > .ui-btn { flex: 1; }
.obs-warning { color: var(--on); font-size: 11px; }
.obs-empty { color: var(--muted); font-size: 11px; }

/* ---- The activity log (ActivityLog.tsx): its feed, in a Fold that fills the sidebar ---- */
.sim-log-body {
  flex: 1;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  /* The feed keeps the reader's place itself (virtualFeed.ts); the browser must not do it a second time. */
  overflow-anchor: none;
  position: relative;
}
.sim-log-spacer {
  position: relative;
}
.sim-log-row {
  position: absolute;
  left: 0;
  right: 0;
  height: 24px;
  display: grid;
  grid-template-columns: minmax(72px, 78px) max-content max-content minmax(0, 1fr);
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 42%, transparent);
  background: var(--panel);
  font-size: 11px;
  overflow: hidden;
  contain: paint;
}
.sim-log-row:hover {
  background: var(--plate-hover);
}
.sim-log-time {
  min-width: 0;
  color: var(--muted);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sim-log-source {
  min-width: 0;
  width: auto;
  max-width: 100%;
  min-height: 16px;
  padding: 1px 5px;
  color: var(--source-color, var(--muted));
  font-weight: 800;
  font-size: 9px;
  letter-spacing: 0.3px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sim-log-level {
  width: auto;
  min-width: 0;
  max-width: none;
  min-height: 16px;
  padding: 1px 5px;
  font-size: 9px;
  letter-spacing: 0.3px;
}
.sim-log-message {
  min-width: 0;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sim-log-row.log-highlight::before {
  content: '';
  position: absolute;
  z-index: 1;
  inset: 0 auto 0 0;
  width: var(--log-highlight-stripe-width, 0px);
  background: var(--log-highlight-stripes, transparent);
  pointer-events: none;
}
.sim-log-empty {
  padding: 24px 10px;
  color: var(--muted);
  font-size: 12px;
  text-align: center;
}

@media (max-width: 520px) {
  .sim-log-row {
    grid-template-columns: minmax(64px, 72px) max-content minmax(0, 1fr);
  }
  .sim-log-source {
    display: none;
  }
}

/* ---- Sony panel: the same keys and plates, in a container that takes the width it is given ---- */
.sony-full { display: flex; flex-direction: column; gap: 10px; min-width: 0; container-type: inline-size; }
.sony-status-strip { display: flex; align-items: center; gap: 8px; }
.on-air-count { margin-left: auto; color: var(--muted); font-size: 11px; }
.sony-me-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); gap: 4px; }
.sony-me-tile { display: grid; gap: 3px; padding: 6px 8px; border-radius: var(--r-control); background: var(--plate); }
.sony-me-title { font-size: 11px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; }
.sony-bus-line { display: grid; grid-template-columns: 16px 1fr; align-items: center; gap: 6px; color: var(--muted); font-size: 11px; }
.sony-bus-line span { color: var(--accent); font-weight: 900; }
.sony-bus-line strong { overflow: hidden; color: var(--text); text-overflow: ellipsis; white-space: nowrap; }
.sony-keyer-row { display: flex; flex-wrap: wrap; gap: 3px; }
.sony-keyer-pill { max-width: 100%; padding: 1px 7px; overflow: hidden; border-radius: var(--r-pill); background: var(--plate); color: var(--muted); font-size: 10px; font-weight: 800; text-overflow: ellipsis; white-space: nowrap; }
.sony-keyer-pill.on { background: color-mix(in srgb, var(--pst) 18%, var(--plate)); color: var(--pst); }
.sony-aux-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 3px; }
.sony-aux-tile { display: grid; gap: 1px; padding: 4px 6px; border-radius: var(--r-chip); background: var(--plate); }
.sony-aux-tile.set { background: color-mix(in srgb, var(--accent) 16%, var(--plate)); }
.sony-aux-tile span { color: var(--muted); font-size: 9px; font-weight: 800; }
.sony-aux-tile strong { overflow: hidden; color: var(--text); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.tally-bank { display: flex; flex-direction: column; gap: 4px; }
.tally-bank-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.tally-bus-label { color: var(--pgm); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; }
.tally-actions { display: flex; flex-wrap: wrap; gap: 4px; margin-left: auto; }
.sony-input-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 3px; }
.sony-input-tile { appearance: none; display: grid; gap: 1px; min-width: 0; padding: 4px 6px; border: 0; border-radius: var(--r-chip); background: var(--plate); color: var(--text); cursor: pointer; font: inherit; text-align: left; }
.sony-input-tile:hover:not(.on-air) { background: var(--plate-hover); }
.sony-input-tile span { color: var(--muted); font-size: 9px; font-weight: 900; }
.sony-input-tile strong { overflow: hidden; font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.sony-input-tile.on-air { background: var(--pgm); }
.sony-input-tile.on-air span,
.sony-input-tile.on-air strong { color: var(--on-fill); }
.tally-presets { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.preset-label { margin-right: 2px; color: var(--muted); font-size: 11px; }
.sony-fault { display: flex; flex-direction: column; gap: 6px; }
.sony-delays { display: flex; flex-wrap: wrap; gap: 6px 12px; }
.sony-delays label { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 11px; }
.sony-delays .ui-field { width: 64px; }

.viz-panel,
.bigviz-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.viz-panel {
  container-type: inline-size;
}

.bigviz-panel {
  container-type: inline-size;
}

.viz-controls,
.bigviz-stage {
  padding-bottom: 8px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
}

.viz-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.viz-stat-pill,
.viz-last-label {
  flex: none;
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: var(--muted);
  font-size: 10px;
  font-weight: 850;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.ui-btn.viz-onair-btn.on-air,
.ui-btn.viz-onair-btn.on-air:hover:not(:disabled) {
  background: var(--pst);
  color: var(--ink);
}

.viz-last-text {
  min-width: 0;
  color: var(--text);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mse-tree-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.mse-tree-head,
.mse-tree-group-title,
.mse-path-form {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.mse-tree-head,
.mse-tree-group-title {
  justify-content: space-between;
  padding: 4px 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.mse-path-form .ui-field {
  flex: 1 1 auto;
  min-width: 0;
}

.mse-tree-footer {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 8px;
  min-width: 0;
}

.mse-tree-footer .mse-path-form {
  align-self: start;
}

.viz-command-line {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 7px;
  min-width: 0;
  min-height: 26px;
  padding: 2px 6px;
  border-radius: var(--r-control);
  background: var(--plate);
}

.viz-controls .viz-command-line {
  flex: 1 1 280px;
}

.mse-graphics-panel {
  min-width: 0;
  overflow: hidden;
}

.mse-graphics-head,
.mse-graphics-row {
  display: grid;
  align-items: center;
  min-width: 0;
}

.mse-graphics-head {
  grid-template-columns: 1fr auto;
  gap: 8px;
  padding: 4px 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.mse-graphics-list {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-height: 116px;
  overflow-y: auto;
}

.mse-graphics-row {
  grid-template-columns: 50px minmax(48px, 0.45fr) minmax(130px, 1.25fr) minmax(110px, 0.9fr) 74px minmax(92px, 0.7fr);
  gap: 8px;
  min-height: 28px;
  padding: 2px 0;
  border-top: 1px solid color-mix(in srgb, var(--line) 34%, transparent);
  font-size: 11px;
}

.mse-graphics-row:first-child {
  border-top: 0;
}

.mse-graphics-state,
.mse-graphics-hit {
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: var(--muted);
  text-align: center;
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.08em;
}

.mse-graphics-state.on-air,
.mse-graphics-hit.hit {
  background: color-mix(in srgb, var(--pst) 16%, var(--plate));
  color: var(--pst);
}

.mse-graphics-id {
  color: var(--accent);
  font-weight: 950;
}

.mse-graphics-name,
.mse-graphics-meta,
.mse-graphics-source,
.mse-graphics-id {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mse-graphics-name {
  color: var(--text);
  font-weight: 800;
}

.mse-graphics-meta,
.mse-graphics-source {
  color: var(--muted);
}

.mse-graphics-source {
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 10px;
}

.mse-tree-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(270px, 100%), 1fr));
  gap: 8px;
  max-height: 260px;
  overflow-y: auto;
}

.mse-tree-group {
  min-width: 0;
  overflow: hidden;
}

.mse-tree-group-title {
  border-bottom: 1px solid color-mix(in srgb, var(--line) 34%, transparent);
}

.mse-tree-row {
  display: grid;
  grid-template-columns: auto minmax(60px, 0.85fr) minmax(0, 1.35fr) auto;
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 24px;
  padding: 2px 0;
  border-top: 1px solid color-mix(in srgb, var(--line) 34%, transparent);
  font-size: 11px;
}

.mse-tree-group-title + .mse-tree-row {
  border-top: 0;
}

.mse-tree-indent {
  display: block;
  flex: 0 0 auto;
  max-width: 42px;
  height: 1px;
}

.mse-tree-name {
  min-width: 0;
  color: var(--text);
  font-weight: 800;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mse-tree-context {
  min-width: 0;
  color: var(--muted);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mse-tree-count {
  min-width: 24px;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 14%, var(--plate));
  color: var(--accent);
  text-align: right;
  font-weight: 850;
}

.mse-tree-count.empty {
  background: transparent;
  color: color-mix(in srgb, var(--muted) 50%, transparent);
}

.mse-tree-empty {
  padding: 10px 8px;
  color: var(--muted);
  font-size: 11px;
}

.mse-engine-list { display: flex; flex-direction: column; }
.mse-engine-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 8px;
  padding: 3px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  font-size: 11px;
}
.mse-engine-dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--plate-selected);
}
.mse-engine-dot.on { background: var(--pst); }
.mse-engine-name { font-weight: 600; min-width: 90px; }
.mse-engine-host { color: var(--muted); font-family: var(--mono, monospace); font-size: 11px; }
.mse-engine-onair { margin-left: auto; color: var(--muted); font-size: 11px; }
.mse-engine-row.connected .mse-engine-onair { color: var(--text); }

.cfg-viz-engines { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.cfg-viz-engines-head { display: flex; flex-direction: column; gap: 2px; }
.cfg-viz-engines-hint { font-size: 10px; color: var(--muted); opacity: 0.8; }
.cfg-viz-engine-row {
  display: grid;
  grid-template-columns: 126px minmax(0, 1fr) minmax(0, 1fr) 92px 28px;
  grid-template-areas:
    "mode name channel channel remove"
    "mode host host port remove";
  gap: 6px;
  align-items: center;
  min-width: 0;
}
.cfg-viz-engine-row .cfg-sim-toggle {
  grid-area: mode;
  min-width: 0;
}
.cfg-viz-engine-name { grid-area: name; }
.cfg-viz-engine-channel { grid-area: channel; }
.cfg-viz-engine-host { grid-area: host; }
.cfg-viz-engine-port {
  grid-area: port;
  width: 100%;
  max-width: none;
}
.cfg-viz-engine-rm {
  grid-area: remove;
  align-self: stretch;
}
.cfg-viz-engine-add { margin-top: 2px; }

@media (max-width: 900px) {
  .mse-tree-footer {
    grid-template-columns: 1fr;
  }

  .mse-tree-footer .mse-path-form {
    grid-row: auto;
  }

  .cfg-viz-engine-row {
    display: flex;
    flex-wrap: wrap;
  }

  .cfg-viz-engine-row .cfg-sim-toggle {
    flex: 1 1 142px;
  }

  .cfg-viz-engine-row .ui-field { flex: 1 1 150px; }
  .cfg-viz-engine-port { flex: 0 0 92px; }
}

.viz-catalog {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.viz-catalog-tools { display: flex; flex-wrap: wrap; gap: 4px; }

.viz-graphic-actions > .ui-btn { white-space: nowrap; }
.viz-graphic-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.viz-graphic-core {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(120px, 100%), 1fr));
  gap: 6px;
  min-width: 0;
}

.viz-graphic-attrs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr));
  gap: 6px;
  min-width: 0;
}

.viz-graphic-attr {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.viz-graphic-attr span {
  color: var(--muted);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.viz-graphic-short {
  text-transform: uppercase;
}

.viz-graphic-style {
  text-transform: capitalize;
}

.viz-catalog-error {
  padding: 6px 8px;
  border-radius: var(--r-control);
  background: var(--fail-plate);
  color: var(--text);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 11px;
  overflow-wrap: anywhere;
}

.viz-graphic-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
  max-height: 290px;
  min-width: 0;
  overflow: auto;
}

.viz-graphic-row {
  display: grid;
  flex: none;
  grid-template-columns: minmax(96px, 0.7fr) minmax(0, 1.6fr) auto auto 30px;
  align-items: center;
  gap: 6px 8px;
  min-height: 34px;
  min-width: 0;
  padding: 3px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
}

.viz-graphic-row.active {
  background: color-mix(in srgb, var(--pst) 8%, transparent);
}

.viz-graphic-id {
  min-width: 0;
  color: var(--accent);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 12px;
  font-weight: 850;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.viz-graphic-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.viz-graphic-name {
  min-width: 0;
  color: var(--text);
  font-size: 12px;
  font-weight: 850;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.viz-graphic-meta {
  min-width: 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.viz-graphic-live {
  justify-self: end;
  min-width: 52px;
  padding: 1px 8px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--pst) 16%, var(--plate));
  color: var(--pst);
  text-align: center;
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.08em;
  white-space: nowrap;
}

.viz-graphic-live.empty {
  background: var(--plate);
  color: var(--muted);
}

.viz-graphic-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 4px;
  min-width: 0;
}

.viz-graphic-rm {
  display: inline-grid;
  place-items: center;
  width: 26px;
  padding: 0;
  font-size: 16px;
  line-height: 1;
}

.viz-ref-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.viz-ref-table td {
  padding: 4px 6px 4px 0;
  border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  color: var(--muted);
  font-size: 11px;
  overflow-wrap: anywhere;
  vertical-align: top;
}

.viz-ref-cmd {
  color: var(--text);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
}

/* In a side panel the answer stands under its command, so neither is broken to fit half a row. */
@container (max-width: 420px) {
  .viz-ref-table,
  .viz-ref-table tbody,
  .viz-ref-row,
  .viz-ref-table td {
    display: block;
  }

  .viz-ref-row {
    padding: 4px 0;
    border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  }

  .viz-ref-table td {
    padding: 0;
    border-top: 0;
  }
}

.bigviz-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(240px, 300px);
  align-items: start;
  gap: 10px;
  min-width: 0;
}

.viz-output-stage {
  min-width: 0;
}

.viz-renderer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 8px;
  min-width: 0;
}

.viz-renderer-output {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 4px;
  border: 0;
  border-radius: var(--r-control);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.viz-renderer-output:hover {
  background: var(--plate);
}

.viz-renderer-output.selected {
  background: var(--plate-selected);
}

.viz-renderer-head {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 22px;
  min-width: 0;
}

.viz-renderer-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-weight: 850;
  font-size: 11px;
}

.viz-renderer-meta {
  flex: 0 0 auto;
  padding: 1px 6px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: var(--muted);
  font-family: var(--mono, monospace);
  font-size: 10px;
  line-height: 1.2;
}

.viz-renderer-monitor {
  width: 100%;
  border-radius: var(--r-control);
}

.bigviz-monitor {
  position: relative;
  min-width: 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background:
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(180deg, rgba(255,255,255,0.04) 1px, transparent 1px),
    #060b10;
  background-size: 80px 80px;
  container-type: size;
}

.bigviz-monitor.on-air {
  border-color: color-mix(in srgb, var(--pgm) 52%, var(--line));
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--pgm) 16%, transparent);
}

.bigviz-fullscreen {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  row-gap: 2cqw;
  padding: 6cqw;
  color: white;
  background:
    linear-gradient(90deg, #c11f32 0 38%, #102a43 38% 100%);
}

.bigviz-fullscreen.style-s2 {
  background:
    linear-gradient(90deg, #f4c542 0 30%, #111820 30% 100%);
  color: #f8fbff;
}

.bigviz-fullscreen.style-s3 {
  background:
    linear-gradient(90deg, #1e9a70 0 34%, #20142f 34% 100%);
}

.bigviz-bug,
.bigviz-strap,
.bigviz-footer {
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.bigviz-bug {
  justify-self: start;
  border: 0.4cqw solid currentColor;
  padding: 1.2cqw 2.2cqw;
  font-size: 3.2cqw;
}

.bigviz-strap {
  align-self: end;
  font-size: 3.2cqw;
  opacity: 0.8;
}

.bigviz-headline {
  align-self: end;
  max-width: 78%;
  font-size: 9cqw;
  line-height: 0.98;
  font-weight: 950;
}

.bigviz-footer {
  display: flex;
  justify-content: space-between;
  border-top: 0.4cqw solid currentColor;
  padding-top: 2.4cqw;
  font-size: 3cqw;
}

.bigviz-clear-frame {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: 7cqw;
  font-weight: 900;
  letter-spacing: 0.18em;
}

.viz-native-graphic {
  z-index: 2;
}

.bigviz-controls {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.bigviz-field-row,
.bigviz-style-row,
.bigviz-action-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.bigviz-field-row .ui-field {
  flex: 1 1 100%;
}

/* In a side panel the rows fold onto two lines rather than run off the edge. */
@container (max-width: 820px) {
  .bigviz-stage {
    grid-template-columns: 1fr;
  }
}
@container (max-width: 640px) {
  .viz-graphic-row {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "id live rm" "main main main" "actions actions actions";
  }
  .viz-graphic-id { grid-area: id; }
  .viz-graphic-main { grid-area: main; }
  .viz-graphic-live { grid-area: live; }
  .viz-graphic-actions { grid-area: actions; justify-content: flex-start; }
  .viz-graphic-rm { grid-area: rm; }
  .mse-graphics-row {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "state name hit" "id meta source";
  }
  .mse-graphics-row > :nth-child(1) { grid-area: state; }
  .mse-graphics-row > :nth-child(2) { grid-area: id; }
  .mse-graphics-row > :nth-child(3) { grid-area: name; }
  .mse-graphics-row > :nth-child(4) { grid-area: meta; }
  .mse-graphics-row > :nth-child(5) { grid-area: hit; }
  .mse-graphics-row > :nth-child(6) { grid-area: source; }
}

/* ── Lottie graphics simulator ─────────────────────────────────────────── */
.lottie-monitor {
  position: relative;
  min-width: 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  background:
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(180deg, rgba(255,255,255,0.04) 1px, transparent 1px),
    #060b10;
  background-size: 80px 80px;
  container-type: size;
}

.lottie-monitor.on-air {
  border-color: color-mix(in srgb, var(--pgm) 52%, var(--line));
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--pgm) 16%, transparent);
}


/* A graphics page in a frame (GraphicsPicture.tsx): seen, never touched, so no key reaches it. */
/* The frame holds the picture at 16:9 and, under it, whatever runs along its foot. */
.graphics-picture { display: flex; flex-direction: column; aspect-ratio: auto; container-type: inline-size; }
/* In the room's shape (ADR 0129), the graphic in it (ADR 0145); an upright one no taller than half the window. */
.graphics-picture-area { position: relative; flex: none; aspect-ratio: var(--picture-aspect, 16 / 9); width: min(100%, calc(50vh * var(--picture-aspect, 16 / 9))); align-self: center; }
.graphics-picture-scroll { position: absolute; inset: 0; overflow: auto; scrollbar-width: none; touch-action: pan-y; }
/* Zoomed in, a drag or a finger looks around the picture rather than scrolling the column. */
.graphics-picture-scroll.zoomed { cursor: grab; touch-action: none; }
.graphics-picture-scroll.panning { cursor: grabbing; }
.graphics-picture-scroll::-webkit-scrollbar { display: none; }
.graphics-picture-content { position: relative; min-width: 100%; min-height: 100%; }
.graphics-picture iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; pointer-events: none; background: transparent; }
.graphics-picture .lottie-clear-frame { pointer-events: none; }
/* A preview larger, while the pointer rests on it (GraphicPreview). */

/* The graphics buttons (GraphicsPicture.tsx), the same row wherever a graphic is played. */
.graphics-transport-buttons, .graphics-preview-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
/* What the graphic is doing stands on a line of its own above the buttons, there off air too, so a
   take never moves them. */
.graphics-transport { display: grid; justify-items: start; gap: 6px; }
.graphics-preview, .graphics-preview-player { display: grid; gap: 6px; }
.graphics-preview > .graphics-transport { padding-top: 6px; }
.graphics-preview:has(> .graphics-preview-fold:not(.open)) { row-gap: 0; }
.te-props .te-prop-section.te-graphics-preview-section { padding: 0; }
.te-graphics-preview-section .graphics-preview-player { padding: 6px 11px; }
.te-graphics-preview-section .graphics-transport { padding: 4px 11px 6px; }
.graphics-picture.playable { cursor: pointer; }
/* A preview's In, Loop and Out along the foot of its frame, under the picture and never over it: the
   Graphics tab's segments, as thin as a folder's mix of events (.te-folder-mix). */
.graphics-timebar { position: relative; flex: none; height: 4px; }
.graphics-timebar-track { position: absolute; inset: 0; overflow: hidden; }
.graphics-timebar .gfx-seg { top: 0; bottom: 0; padding: 0; border-radius: 0; font-size: 0; cursor: pointer; pointer-events: auto; }
.graphics-timebar .gfx-seg-in { background: var(--accent); }
.graphics-timebar .gfx-seg-loop { background: var(--pst); }
.graphics-timebar .gfx-seg-out { background: var(--on); }
.graphics-timebar .ui-timeline-playhead { top: 0; bottom: 0; }

.lottie-clear-frame {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: clamp(11px, 5cqw, 28px);
  font-weight: 900;
  letter-spacing: 0.18em;
  text-align: center;
}

.lt-bug {
  position: absolute;
  left: 4%;
  top: 7.4%;
  width: 15.6%;
  height: 10.6%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.8cqw;
  font-size: 3cqw;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.lt-bug-dot {
  width: 1.4cqw;
  height: 1.4cqw;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0.6cqw #fff;
  animation: lt-bug-pulse 1.4s ease-in-out infinite;
}
@keyframes lt-bug-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* ticker */
.lottie-template-row,
.lottie-new-styles,
.lottie-accent-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.lottie-chip-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: var(--r-chip);
  margin-right: 6px;
  background: var(--lt-accent, var(--accent));
  vertical-align: middle;
}
.lottie-chip-x {
  margin-left: 7px;
  opacity: 0.55;
  font-weight: 900;
}
.lottie-chip-x:hover { opacity: 1; color: var(--on); }
.lottie-new-chip { border-style: dashed; }

.lottie-new-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border: 1px dashed var(--line);
  border-radius: var(--r-control);
  padding: 10px;
}
.lottie-accent-input {
  width: 36px;
  height: 26px;
  padding: 3px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  cursor: pointer;
}

.lottie-accent-input:hover {
  background: var(--plate-hover);
}

.lottie-accent-input::-webkit-color-swatch-wrapper {
  padding: 0;
}

.lottie-accent-input::-webkit-color-swatch {
  border: 0;
  border-radius: var(--r-chip);
}

.lottie-field-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.lottie-field { display: flex; flex-direction: column; gap: 3px; }
.lottie-field-label {
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}

/* ── Graphics preview (cqw/cqh-scaled so text never overflows
   the monitor box, no matter how the panel is laid out — mirrors .lt-* sizing) ── */
.mse-graphic {
  position: absolute;
  inset: 0;
  color: #fff;
  text-shadow: 0 1px 4px rgba(0,0,0,0.45);
}

.mse-graphic.style-fullscreen {
  left: 16%;
  right: 8%;
  top: 28%;
  bottom: 6%;
  display: flex;
  flex-direction: column;
  gap: 2cqh;
}
.mse-fs-kicker {
  align-self: flex-start;
  background: #0a84ff;
  padding: 0.8cqh 1.4cqw;
  font-size: 2.6cqw;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-radius: var(--r-chip);
}
.mse-fs-title { max-width: 90%; font-size: 6.5cqw; line-height: 1.02; font-weight: 950; }

.mse-graphic.style-lower-third {
  top: auto;
  left: 15.5%;
  right: 5%;
  bottom: 8%;
  height: 17%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.6cqh;
  background: rgba(8, 14, 22, 0.78);
  border-left: 0.6cqw solid #c11f32;
  border-radius: var(--r-control);
  padding: 1.4cqh 1.8cqw;
}
.mse-lower-title { font-size: 5.2cqw; line-height: 1; font-weight: 950; }
.mse-lower-sub { font-size: 2.6cqw; opacity: 0.85; font-weight: 700; letter-spacing: 0.04em; }

.mse-graphic.style-bullets {
  top: 22%;
  left: 16%;
  right: 8%;
  bottom: 6%;
  display: flex;
  flex-direction: column;
  gap: 2.2cqh;
  background: rgba(8, 14, 22, 0.78);
  border-radius: var(--r-control);
  padding: 2.4cqh 2.4cqw;
}
.mse-bullets-title { font-size: 5cqw; font-weight: 950; margin-bottom: 1cqh; }
.mse-bullets-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2.4cqh; }
.mse-bullet {
  font-size: 3.1cqw;
  font-weight: 700;
  opacity: 0;
  transform: translateX(-12px);
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.mse-bullet.shown { opacity: 1; transform: translateX(0); }

.mse-graphic.style-bug {
  inset: auto;
  left: 4%;
  top: 7.4%;
  display: flex;
  align-items: center;
  gap: 0.8cqw;
  font-size: 3cqw;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: rgba(8, 14, 22, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: var(--r-control);
  padding: 0.8cqh 1.2cqw;
}

.mse-graphic.style-ticker {
  top: auto;
  left: 0;
  right: 0;
  bottom: 4%;
  height: 11.7%;
  display: flex;
  align-items: center;
  background: rgba(8, 14, 22, 0.78);
}
.mse-ticker-label {
  flex: 0 0 auto;
  height: 100%;
  display: flex;
  align-items: center;
  padding: 0 1.4cqw;
  font-weight: 900;
  font-size: 2.8cqw;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: #f4c542;
  color: #111;
}
.mse-ticker-text { padding: 0 1.4cqw; font-size: 3cqw; font-weight: 700; }

.fxmotion-panel { display: flex; flex-direction: column; gap: 8px; min-width: 0; container-type: inline-size; }
.fxmotion-loading { padding: 8px 0; color: var(--muted); font-size: 12px; }
.fxmotion-last-cmd { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; color: var(--muted); font-size: 11px; }
.fxmotion-last-type { padding: 1px 7px; border-radius: var(--r-pill); background: var(--plate); color: var(--muted); font-size: 10px; font-weight: 850; letter-spacing: 0.06em; }
.fxmotion-last-label,
.fxmotion-last-robot,
.fxmotion-last-target,
.fxmotion-robot-id { color: var(--muted); font-size: 11px; }
.fxmotion-robots { display: flex; flex-wrap: wrap; gap: 4px; }
.fxmotion-catalog { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); gap: 8px 14px; }
.fxmotion-catalog-col { min-width: 0; max-height: 240px; overflow-y: auto; }
.fxmotion-catalog-label { margin-bottom: 2px; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.fxmotion-item { display: flex; align-items: center; gap: 8px; min-height: 24px; padding: 2px 4px; border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.fxmotion-item.active { background: color-mix(in srgb, var(--pgm) 18%, transparent); }
.fxmotion-item-id { min-width: 30px; color: var(--accent); font-size: 11px; font-weight: 850; }
.fxmotion-item-caption { overflow: hidden; color: var(--text); font-size: 11px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }

/* Telemetrics: what automation has sent it. */
.telemetrics-console { display: flex; flex-direction: column; gap: 4px; }
.telemetrics-console-label { color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.telemetrics-console-empty { padding: 6px 0; color: var(--muted); font-size: 11px; font-style: italic; }
.telemetrics-console-list { display: flex; flex-direction: column; gap: 2px; max-height: 200px; overflow-y: auto; font-family: 'SF Mono', 'Fira Code', Consolas, monospace; font-size: 11px; }
.telemetrics-line { display: flex; gap: 8px; padding: 2px 4px; border-radius: var(--r-chip); }
.telemetrics-line.latest { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.telemetrics-line-time { flex: 0 0 auto; color: var(--muted); }
.telemetrics-line-cmd { color: var(--text); word-break: break-all; }

/* ---- The audio consoles (CalrecPanel, DhdPanel, StuderPanel, ObsAudioPanel): fader rows and a few keys ---- */
.calrec-loading,
.dhd-loading,
.studer-loading { padding: 8px 0; color: var(--muted); font-size: 12px; }
.calrec-panel,
.dhd-panel,
.studer-panel { display: flex; flex-direction: column; gap: 8px; min-width: 0; container-type: inline-size; }
.calrec-section,
.studer-fader-section,
.studer-gpi-section { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.calrec-section-label,
.studer-section-label { color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.calrec-aux-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 3px; }
.calrec-aux-tile { display: flex; flex-direction: column; gap: 3px; padding: 4px 6px; border-radius: var(--r-chip); background: var(--plate); }
.calrec-aux-n { color: var(--muted); font-size: 9px; font-weight: 700; text-transform: uppercase; }
.calrec-aux-bar-wrap { height: 3px; overflow: hidden; border-radius: var(--r-chip); background: var(--plate); }
.calrec-aux-bar { height: 100%; border-radius: var(--r-chip); background: var(--accent); transition: width 0.15s ease; }
.calrec-aux-pct { color: var(--muted); font-size: 9px; text-align: right; }
.studer-info { color: var(--muted); font-size: 11px; }
.studer-port-group { display: flex; align-items: center; gap: 6px; min-width: 0; margin-left: auto; }
.studer-port-select { min-width: 0; max-width: 200px; height: 22px; font-size: 11px; }
.studer-baud { color: var(--muted); font-size: 10px; font-weight: 600; }
.studer-empty-run { grid-column: 1 / -1; padding: 3px 0; color: color-mix(in srgb, var(--muted) 70%, transparent); font-size: 11px; }
.studer-gpi-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(34px, 1fr)); gap: 3px; }

/* ---- Console ---- */
.console {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.console-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.console-body {
  flex: 1;
  overflow: auto;
  font-family: 'SF Mono', ui-monospace, Menlo, monospace;
  font-size: 11px;
  margin-top: 6px;
}
.line {
  display: flex;
  gap: 8px;
  padding: 1px 0;
  white-space: nowrap;
}
.line .arrow {
  width: 18px;
}
.line.rx .arrow {
  color: var(--accent);
}
.line.tx .arrow {
  color: var(--on);
}
.line .tport {
  color: var(--muted);
  width: 38px;
}
.line .hex {
  color: var(--text);
}
.line .decoded {
  color: var(--muted);
}

/* ---- AirSpeed / OBS clip server and MOS newsroom panels (AirSpeedPanel.tsx, SimulatorsSection.tsx) ----
   Rows, pills and quiet lines as the Status panel's Machine has them, no boxes with edges. They stand in
   the rundown's side panel as well as in the wide Status panel, and take the width they are given. */
.as-panel,
.mos-panel { display: flex; flex-direction: column; gap: 8px; min-width: 0; container-type: inline-size; }
.as-loading,
.mos-loading { padding: 8px 0; color: var(--muted); font-size: 12px; }

/* The device's line at the head of what it shows: what it is, where it listens, who is connected. */
.sim-device-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; padding-bottom: 8px; font-size: 11px; }
.sim-device-where { color: var(--muted); font-family: 'SF Mono', 'Fira Code', monospace; }
.sim-device-clients { color: var(--muted); }
.sim-device-clients.live { color: var(--pst); }
.sim-device-kill { margin-left: auto; }

.as-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; color: var(--muted); font-size: 11px; }
.as-brand { font-size: 10px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; }
.as-folder-label { flex: 1 1 110px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11px; }
.as-port-range { color: var(--muted); }

/* A channel: two lines and a thin line for how far the clip has played. */
.as-channels { display: flex; flex-direction: column; }
.as-channel { display: flex; flex-direction: column; gap: 3px; min-width: 0; padding: 5px 0 6px; border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.as-ch-head { display: flex; flex-wrap: wrap; align-items: center; gap: 3px 6px; min-width: 0; }
.as-ch-head .ui-badge { flex: none; white-space: nowrap; }
.as-ch-clip { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.as-ch-num { color: var(--text); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap; }
.as-ch-port { color: var(--muted); font-size: 10px; }
.as-conn-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--plate-selected); }
.as-conn-dot.connected { background: var(--pst); }
.as-tc { flex: none; margin-left: auto; color: var(--text); font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11px; white-space: nowrap; }
.as-dur { color: var(--muted); }
.as-clip-name { flex: 1 1 auto; min-width: 0; overflow: hidden; color: var(--text); font-size: 11px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.as-no-clip { color: var(--muted); font-weight: 400; }
.as-transport { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 3px; }
.as-transport .ui-btn { width: 100%; }
@container (min-width: 460px) {
  .as-channel { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 12px; }
  .as-ch-head { grid-column: 1 / -1; }
  .as-progress { grid-column: 1 / -1; }
  .as-transport { display: flex; grid-column: 2; grid-row: 2; }
  .as-transport .ui-btn { width: var(--ui-btn-h); }
}
.as-progress { height: 2px; overflow: hidden; border-radius: var(--r-chip); background: var(--plate); }
.as-progress > span { display: block; height: 100%; background: var(--pst); transition: width 0.2s linear; }
.as-pulse { animation: as-pulse 1.4s ease-in-out infinite; }

@keyframes as-pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.55; }
}

/* The clips: rows, the id only where there is room for it. */
.as-clips { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.as-clips-head,
.mos-status-head { color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.as-add-form { display: flex; flex-wrap: wrap; gap: 6px; }
.as-input { flex: 1 1 96px; min-width: 0; }
.as-input-short { flex: 0 1 72px; }
.as-clip-list { max-height: 168px; overflow-y: auto; }
.as-clip-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 2px 8px; min-height: 24px; padding: 1px 0; border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent); font-size: 11px; }
.as-clip-row.active { background: color-mix(in srgb, var(--pst) 8%, transparent); }
.as-clip-id { display: none; overflow: hidden; color: var(--accent); font-family: 'SF Mono', 'Fira Code', monospace; font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
.as-clip-name-cell { overflow: hidden; color: var(--text); text-overflow: ellipsis; white-space: nowrap; }
.as-clip-tail { display: flex; align-items: center; gap: 6px; }
.as-clip-dur { color: var(--muted); font-family: 'SF Mono', 'Fira Code', monospace; font-size: 10px; }
.as-clip-empty { padding: 10px 0; color: var(--muted); font-size: 11px; text-align: center; }
@container (min-width: 420px) {
  .as-clip-row { grid-template-columns: 120px minmax(0, 1fr) auto; }
  .as-clip-id { display: block; }
}

/* The newsroom: what it is serving, as label and value, then the statuses it has been sent. */
.mos-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.mos-port { color: var(--muted); font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11px; }
.mos-facts { display: flex; flex-direction: column; margin: 0; }
.mos-facts > div { display: grid; grid-template-columns: 66px minmax(0, 1fr); align-items: baseline; gap: 8px; padding: 3px 0; border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent); font-size: 12px; }
.mos-facts dt { color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; }
.mos-facts dd { display: flex; align-items: baseline; gap: 8px; min-width: 0; margin: 0; }
.mos-facts strong { flex: none; max-width: 100%; overflow: hidden; color: var(--text); text-overflow: ellipsis; white-space: nowrap; }
.mos-facts small { min-width: 0; overflow: hidden; color: var(--muted); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }

/* The pretend house reference: its four numbers, in as many columns as the panel has room for. */
.ref-edges { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(112px, 100%), 1fr)); gap: 8px; }
.mos-empty-status { padding: 6px 0; color: var(--muted); font-size: 12px; }
.mos-status-list { display: flex; flex-direction: column; max-height: 220px; overflow-y: auto; }
.mos-status-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 8px; min-height: 26px; border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }
.mos-status-main { min-width: 0; overflow: hidden; color: var(--text); font-size: 12px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.mos-status-time { color: var(--muted); font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11px; white-space: nowrap; }

/* ─── Tab navigation ─────────────────────────────────────────────────────────── */

.app-tabs {
  margin-left: auto;
}
.app-tabs-choice .ui-seg-btn {
  height: 28px;
  padding: 0 14px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3px;
}

@media (max-width: 800px) {
  .app-header {
    gap: 10px;
    padding-inline: 10px;
  }
  .app-tabs-choice .ui-seg-btn {
    padding-inline: 12px;
  }
}

.tab-content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.tab-panel {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.tab-panel[hidden] {
  display: none;
}

/* ─── Mixer tab ─────────────────────────────────────────────────────────────── */

.mx-root {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  overflow: hidden;
}
.mx-top {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line);
}
.mx-top h1 {
  margin: 0;
  font-size: 15px;
  letter-spacing: .04em;
}
.mx-top > div:first-child {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.mx-top span {
  color: var(--muted);
  font-size: 13px;
}
.mx-status {
  display: flex;
  align-items: center;
  gap: 12px;
}
.mx-status span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.mx-status span::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
}
.mx-status span.live { color: var(--pst); }
.mx-status span.live::before {
  background: var(--pst);
  box-shadow: 0 0 8px var(--pst);
}
.mx-midi-main,
.mx-midi-status {
  font-size: 10px;
  font-weight: 900;
  letter-spacing: .05em;
  text-transform: uppercase;
}
.mx-midi-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.mx-workspace {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  grid-template-rows: 1fr 1fr;
  grid-template-areas:
    "video next"
    "faders onair";
  gap: 12px;
  padding: 12px 16px 16px;
  overflow: hidden;
}
.mx-control-stack,
.mx-deck-stack {
  display: contents;
}
.mx-bank-video { grid-area: video; }
.mx-bank-audio { grid-area: faders; }
.mx-mon-next { grid-area: next; }
.mx-mon-onair { grid-area: onair; }
.mx-deck-stack {
  grid-template-rows: auto auto;
  align-content: start;
  overflow-y: auto;
}
.mx-mon {
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  gap: 0;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  padding: 8px;
  border: 0;
  border-radius: var(--r-card);
  cursor: pointer;
  background: transparent;
  transition: background .1s, opacity .1s;
}
.mx-mon:hover {
  background: color-mix(in srgb, var(--panel) 42%, transparent);
}
.mx-mon:focus-visible {
  outline: 2px solid var(--focus-line);
  outline-offset: 2px;
}
.mx-mon:not(.selected) {
  opacity: .72;
}
.mx-mon:not(.selected) .mx-mon-frame {
  filter: saturate(.78) brightness(.86);
}
.mx-mon-onair.selected {
  background: linear-gradient(0deg, color-mix(in srgb, var(--pgm) 20%, transparent), color-mix(in srgb, var(--panel) 36%, transparent));
}
.mx-mon-next.selected {
  background: linear-gradient(0deg, color-mix(in srgb, var(--on) 18%, transparent), color-mix(in srgb, var(--panel) 36%, transparent));
}
.mx-mon-frame {
  position: relative;
  justify-self: center;
  align-self: center;
  height: 100%;
  width: auto;
  max-width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-card);
  overflow: hidden;
  background: var(--bg);
}
.mx-mon-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--bg);
  display: block;
}
.mx-mon-dark {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: 13px;
  letter-spacing: .05em;
}
/* A monitor of a room with no pictures from it: why, over the dark frame (Rundown and Mixer alike). */
.monitor-no-pictures {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 10px 14px;
  text-align: center;
  background: var(--bg);
  color: var(--muted);
  font-size: 11px;
  line-height: 1.4;
}
.monitor-no-pictures strong {
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--text) 86%, transparent);
}
.mx-deck-head {
  position: absolute;
  top: 8px;
  left: 8px;
  right: 8px;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity .12s ease, transform .12s ease;
}
.mx-mon:hover .mx-deck-head,
.mx-mon:focus-within .mx-deck-head {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.mx-deck-state {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--r-control);
  background: var(--panel);
  color: var(--muted);
}
.mx-mon-onair .mx-deck-state {
  background: color-mix(in srgb, var(--pgm) 22%, var(--panel));
  color: color-mix(in srgb, var(--pgm) 90%, var(--text));
}
.mx-mon-next .mx-deck-state {
  background: color-mix(in srgb, var(--on) 20%, var(--panel));
  color: color-mix(in srgb, var(--on) 90%, var(--text));
}
.mx-mon-onair.selected .mx-deck-state {
  background: var(--pgm);
  color: var(--on-fill);
}
.mx-mon-next.selected .mx-deck-state {
  background: var(--on);
  color: var(--ink);
}
.mx-deck-event {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13px;
  padding: 6px 8px;
  border-radius: var(--r-control);
  background: var(--float);
  box-shadow: var(--float-shadow);
  backdrop-filter: var(--float-blur);
}
.mx-deck-event.empty {
  flex: 0 1 auto;
  color: var(--muted);
  padding-inline: 8px;
}
.mx-event-type {
  flex: 0 0 auto;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .04em;
  padding: 2px 6px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--template-color, var(--text)) 72%, var(--text));
  color: var(--bg);
}
.mx-event-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 700;
}
.mx-event-time {
  flex: 0 0 auto;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
}
.mx-deck-manual-release {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 9px;
  font-weight: 900;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.mx-bank {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--panel);
  border-radius: var(--r-card);
  overflow: hidden;
}
.mx-bank-title {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 12px;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
}
.mx-bank-sub {
  color: color-mix(in srgb, var(--pgm) 80%, var(--text));
  font-weight: 800;
}
.mx-bank-sub.next {
  color: color-mix(in srgb, var(--on) 86%, var(--text));
}
.mx-source-grid {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  /* Each row is exactly as tall as the 16:9 tile in it. Auto rows are sized against the bank's own
     height, so once the tiles no longer fit, every row is squeezed a few pixels shorter than the
     tile it holds and each row paints over the one above it. This is a scroller: the rows keep
     their size and the overflow scrolls. */
  grid-auto-rows: min-content;
  gap: 8px;
  padding: 12px;
  align-content: start;
}
.mx-source {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  aspect-ratio: 16 / 9;
  min-height: 0;
  padding: 10px;
  border: 0;
  border-radius: var(--r-card);
  background: var(--plate);
  color: var(--text);
  font: inherit;
  font-weight: 700;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: background .1s, opacity .1s;
}
.mx-source:hover:not(.disabled) { background: var(--plate-hover); }
.mx-source.disabled { opacity: .4; cursor: not-allowed; }
.mx-source.auto {
  background: color-mix(in srgb, var(--pst) 16%, var(--plate));
}
.mx-source.manual {
  background: color-mix(in srgb, var(--pgm) 22%, var(--plate));
}
.mx-source.preview {
  background: color-mix(in srgb, var(--on) 18%, var(--plate));
}
.mx-source.midi-learning {
  background: color-mix(in srgb, var(--accent) 20%, var(--plate));
}
.mx-source-video,
.mx-source-dark {
  position: absolute;
  inset: 0;
}
.mx-source-video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: transparent;
}
.mx-source-video .signal-video:not(.has-signal) { background: transparent; }
.mx-source-video .video-preview-cell > .video-preview-caption { bottom: 40px; left: 6px; }
.mx-source-video .video-preview-cell:has(.video-preview-caption) .signal-video-status { padding: 6px 6px 58px; }
.mx-source-dark {
  display: grid;
  place-items: center;
  color: color-mix(in srgb, var(--muted) 75%, transparent);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-align: center;
  padding: 10px;
}
.mx-source-name {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 8px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 7px;
  border-radius: var(--r-control);
  /* The source's colour in the mapping, as its chips and its card in Settings have it. */
  background: color-mix(in srgb, var(--source-color, var(--muted)) 10%, var(--float));
  backdrop-filter: var(--float-blur);
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mx-source-color-dot {
  flex: 0 0 7px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--source-color, var(--muted));
}
.mx-source-tag {
  position: absolute;
  top: 5px;
  right: 6px;
  z-index: 2;
  font-size: 9px;
  font-weight: 900;
  letter-spacing: .05em;
  padding: 2px 6px;
  border-radius: var(--r-control);
  background: var(--pgm);
  color: var(--on-fill);
}
.mx-source-tag.auto { background: var(--pst); color: var(--ink); }
.mx-source-tag.preview { background: var(--on); color: var(--ink); }

/* --- shared fader track (components/FaderTrack.tsx: events editor + live mixer) ---
   Drag to set, double-click to reset, name inside the track, dB pill on the right.
   Color rides on --fader-color; per-surface rules only add state chrome around it. */
.fader-track {
  position: relative;
  display: block;
  flex: 1;
  min-width: 0;
  height: 30px;
  border-radius: var(--r-control);
  border: 0;
  background: var(--field);
  cursor: ew-resize;
  touch-action: none;
  user-select: none;
  overflow: hidden;
}
.fader-track:hover { background: var(--field-hover); }
.fader-track.readonly { cursor: default; }
.fader-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--fader-pct, 0%);
  background: color-mix(in srgb, var(--fader-color, var(--accent)) 28%, var(--panel-2));
  pointer-events: none;
}
.fader-name {
  position: absolute;
  inset: 0 56px 0 9px;
  display: flex;
  align-items: center;
  font-size: 11px;
  font-weight: 700;
  color: color-mix(in srgb, var(--text) 86%, var(--muted));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  user-select: none;
}
.fader-db {
  position: absolute;
  right: 5px;
  top: 50%;
  transform: translateY(-50%);
  min-width: 40px;
  text-align: center;
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: var(--panel-2);
  border: 0;
  border-radius: var(--r-control);
  padding: 2px 5px;
  pointer-events: none;
  user-select: none;
}

/* --- the shared fader row (components/FaderTrack.tsx, Fader) ---------------------
   The events editor's row, drawn everywhere a fader is: a status in front, the track, its switch,
   and a release, PFL or remove button behind. Colour rides on --row-color. Plates, no outlines, a
   control's height in properties: an outline says which one is being worked on (dragged), or a
   surface's state (the Mixer's on air, preview, manual), nothing else. */
.fader-row {
  --row-color: var(--accent);
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  user-select: none;
}
.fader-row .fader-track {
  height: 24px;
  border-color: transparent;
  background: color-mix(in srgb, var(--text) 6%, var(--panel-2));
  box-shadow: none;
}
.fader-row .fader-track:hover { background: color-mix(in srgb, var(--text) 9%, var(--panel-2)); }
.fader-row .fader-track.dragging { background: color-mix(in srgb, var(--row-color) 20%, var(--field)); }
.fader-row .fader-db { border: 0; }
.fader-row.off .fader-track { opacity: .72; }
.fader-row-controls {
  display: flex;
  align-items: center;
  gap: 3px;
  flex: 0 0 auto;
}
.fader-switch {
  min-width: 28px;
  height: 24px;
  padding: 0 7px;
}
/* On in the channel's colour, as mild as its fill: said, not shouted. */
.fader-switch.on {
  background: color-mix(in srgb, var(--row-color) 40%, var(--panel-2));
  color: var(--text);
}
.fader-switch.static:not(.on) { opacity: .8; }
.fader-row-button {
  min-width: 20px;
  height: 24px;
  padding: 0 5px;
}
.fader-row-button.lit { color: var(--ink); background: color-mix(in srgb, var(--warn) 30%, var(--plate-selected)); }
.fader-row-status {
  flex: 0 0 auto;
  min-width: 34px;
  padding: 3px 6px;
  border-radius: var(--r-control);
  border: 0;
  background: color-mix(in srgb, var(--text) 8%, transparent);
  color: var(--muted);
  font-size: 8px;
  font-weight: 900;
  letter-spacing: .06em;
  text-align: center;
}
.fader-row-status.lit { color: var(--ink); background: var(--warn); }
.fader-row.empty { opacity: .45; }
/* Faders side by side where there are many: a simulated console's bank. */
.fader-bank {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  gap: 3px 12px;
}

/* --- something to copy (components/CopyField.tsx): the text as code in its own box, a copy button at
   its end. Every address, link, command and credential LiveDeck shows to be copied. --- */
.copy-field {
  display: flex;
  align-items: center;
  min-width: 0;
  overflow: hidden;
}
.copy-field-text {
  flex: 1;
  min-width: 0;
  padding: 6px 9px;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 11px;
  line-height: 1.45;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-all;
  text-transform: none;
  letter-spacing: 0;
  user-select: all;
}
.copy-field-button {
  flex: 0 0 auto;
  margin-left: 4px;
}
.copy-field-button.copied { color: var(--pst); }

/* This node's properties: a label over each value, plain, no pills. */
.cfg-node-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.cfg-node-value { color: var(--text); font-size: 13px; font-weight: 600; }
.cfg-node-value.muted { color: var(--muted); font-weight: 500; }
.cfg-node-value-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.cfg-node-note { color: var(--muted); font-size: 11px; line-height: 1.45; }

.cfg-node-fields { display: flex; flex-direction: column; gap: 12px; }
/* In a properties pane the node's details wrap rather than run off its edge. */
.settings-props-body .cfg-failover-self { flex-wrap: wrap; }

/* Admin → Nodes: a card per node, as a device is in Settings; its name in its own colour. */
.admin-fleet-name { display: inline-block; padding: 2px 7px; border-radius: var(--r-control); font-weight: 750; }
.admin-node-card, .admin-stage-card { position: relative; }
/* A node and the stage wear their colour as a tenant's card does: the plate tinted by it. */
.cfg-device-card.colored { background: color-mix(in srgb, var(--link-color, var(--accent)) 24%, var(--panel)); }
.cfg-device-card.colored:hover { background: color-mix(in srgb, var(--link-color, var(--accent)) 29%, var(--panel)); }
.cfg-device-card.colored.selected { background: color-mix(in srgb, var(--link-color, var(--accent)) 34%, var(--panel)); }
.admin-node-card:hover .ui-card-colour, .admin-stage-card:hover .ui-card-colour,
.admin-node-card .ui-card-colour:focus-visible, .admin-stage-card .ui-card-colour:focus-visible { opacity: 1; pointer-events: auto; }
.admin-node-card .ui-card-colour, .admin-stage-card .ui-card-colour { right: 8px; }
.admin-stage-card { --cfg-device-card-min-height: 72px; margin-bottom: 14px; }
/* One column, the width of the tenant's Users. */
.cfg-linker.admin-superadmins { grid-template-columns: minmax(280px, 520px); }
.sync-cell { color: var(--pst); }
.sync-cell.warn { color: var(--warn); }
.sync-cell.unknown { color: var(--muted); }
.admin-node-facts { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; margin: 8px 0 14px; font-size: 12px; }
.admin-node-facts dt { color: var(--muted); }
.admin-node-facts dd { margin: 0; color: var(--text); }
.admin-sync-part.warn .admin-perm-area-head,
.admin-sync-note { color: var(--warn); }
.admin-pairing .admin-issued-row { flex-direction: column; align-items: stretch; gap: 4px; }
/* Adding a node: where it is, as a choice, then the one code or command for it and a line on what to
   do with it. A command breaks between its words where it can, not inside one. */
.admin-pairing-ways { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 6px; margin-bottom: 14px; }
.admin-pairing-ways .ui-btn { justify-content: flex-start; }
.admin-pairing-kinds { grid-template-columns: 1fr 1fr; }
.admin-pairing-kinds .ui-btn { justify-content: center; }
.admin-pairing .copy-field-text { word-break: normal; overflow-wrap: anywhere; }
.admin-pairing-note { margin: 10px 0 0; font-size: 12px; line-height: 1.5; color: var(--muted); }

/* --- a simulated device's status line (components/SimStatusBar.tsx) ---------------------------- */
.sim-status-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
.sim-status-title { font-size: 11px; font-weight: 800; letter-spacing: 0.04em; }
.sim-port-group { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.sim-port-label { color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; }
.sim-port-group .sim-port-input { width: 64px; height: 22px; padding: 0 6px; font-size: 11px; }
.sim-port-input[readonly] { color: var(--muted); }

/* --- shared WebRTC monitor chrome (components/WebrtcVideo.tsx) ----------------
   Transparent meter over the right edge, plus hover controls along the bottom. */
.monitor-video-root {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
  background: var(--bg);
  container-type: inline-size;
}
.monitor-meter {
  position: absolute;
  top: 8px;
  bottom: auto;
  right: 7px;
  width: 6px;
  height: calc(100% - 16px);
  display: block;
  pointer-events: none;
  opacity: .78;
  z-index: 2;
}
.monitor-controls {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 8px;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition: opacity .12s ease, transform .12s ease;
}
/* :focus-visible, not :focus-within — a mouse click on the volume slider or the meter button
   leaves that control focused, and :focus-within then pinned the overlay open long after the
   pointer had left the video. Keyboard focus still reveals it, which is the only thing
   :focus-within was there for. */
:is(.monitor-video-root, .monitor-fs).controls-visible .monitor-controls,
:is(.monitor-video-root, .monitor-fs):has(:active) .monitor-controls,
:is(.monitor-video-root, .monitor-fs):has(.monitor-quality-anchor > [aria-expanded="true"]) .monitor-controls,
:is(.monitor-video-root, .monitor-fs):has(:focus-visible) .monitor-controls {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
/* A monitor's quality menu: over the screen beside its button, two columns. */
.monitor-quality-anchor { display: inline-flex; }
.monitor-quality { z-index: 1000; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; max-height: 70vh; overflow-y: auto; padding: 6px; }
.monitor-quality-group { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.monitor-quality-heading { padding: 6px 8px; color: var(--muted); font-size: 11px; font-weight: 600; }
.monitor-quality .ui-menu-item { justify-content: space-between; gap: 12px; font-size: 12px; }
.monitor-quality-note { color: var(--muted); font-variant-numeric: tabular-nums; }
/* The picture and its controls lift on a second's stillness; the original keeps its size. */
.monitor-zoom { position: absolute; inset: 0; }
.monitor-zoom > .ui-hover-enlarge-body { position: absolute; inset: 0; }
.monitor-zoom video, .ui-hover-enlarged > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
/* Along the picture's top, as NEXT's item is: what a Feeds tile shows, chosen there. With the bar, on hover. */
.monitor-top {
  position: absolute; top: 8px; left: 8px; right: 8px; z-index: 5;
  display: flex; align-items: center; gap: 6px; padding: 4px 6px;
  opacity: 0; transform: translateY(-4px); pointer-events: none; transition: opacity .12s ease, transform .12s ease;
}
.monitor-top .feeds-picker { flex: 1 1 auto; min-width: 0; }
.monitor-video-root.controls-visible .monitor-top,
.monitor-video-root:has(:focus-visible) .monitor-top,
.monitor-video-root:has(.te-combo-pop) .monitor-top { opacity: 1; transform: none; pointer-events: auto; }
/* A list opened from the top is not cut off by the picture, nor placed on the strip's glass. */
.monitor-video-root:has(.te-combo-pop) { overflow: visible; }
.monitor-video-root:has(.te-combo-pop) .monitor-top { -webkit-backdrop-filter: none; backdrop-filter: none; }
/* The monitor's figures (monitorNotes.ts), in its top right corner while they are on: how late, the
   sound, the CPU. Right-aligned, onto the next line down where the picture is too narrow for them all;
   never in the way: the pointer goes through them to the picture, and what they mean is said on the i. */
.monitor-figures { position: absolute; top: 12px; right: 14px; left: 14px; z-index: 6; display: flex; flex-wrap: wrap; justify-content: flex-end; align-content: flex-start; gap: 4px; pointer-events: none; }
.monitor-figure {
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace; font-size: 10px; font-weight: 700; line-height: 1;
  padding: 4px 6px; border-radius: var(--r-chip); color: var(--text); background: color-mix(in srgb, var(--bg) 72%, transparent); white-space: nowrap;
}
.monitor-figure.warn { color: var(--on); }
.monitor-volume,
.monitor-control-group,
.video-preview-caption {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--bg) 64%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--text);
}
.monitor-volume {
  --accent: var(--text);
  --ui-range-track-height: 3px;
  --ui-range-thumb-size: 10px;
  --ui-range-thumb-shadow: none;
  flex: 0 1 112px;
  min-width: 64px;
  margin-right: auto;
  padding-right: 10px;
}
.monitor-volume .ui-range {
  flex: 1 1 auto;
  min-width: 22px;
  width: 64px;
}
:is(.monitor-volume, .monitor-control-group) .monitor-icon-control {
  border-radius: var(--r-pill);
  color: inherit;
}
:is(.monitor-volume, .monitor-control-group) .monitor-icon-control:hover:not(:disabled),
:is(.monitor-volume, .monitor-control-group) .monitor-icon-control.selected:not(:disabled) {
  background: color-mix(in srgb, var(--text) 14%, transparent);
  color: var(--text);
}
.monitor-icon-control {
  flex: 0 0 auto;
}
.monitor-icon-control svg {
  display: block;
  width: 15px;
  height: 15px;
  fill: currentColor;
}
.monitor-fs {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--bg);
  cursor: zoom-out;
  container-type: inline-size;
}
.monitor-fs > video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.monitor-fs .monitor-meter {
  top: 28px;
  bottom: auto;
  right: 18px;
  width: 8px;
  height: calc(100% - 56px);
}

/* Small monitors keep the sound switch; its volume opens beside it while the pointer is on it, or it
   has the keyboard, over the monitor's other buttons. */
@container (max-width: 280px) {
  .monitor-controls { left: 4px; right: 4px; gap: 4px; }
  .monitor-control-group { gap: 0; }
  :is(.monitor-volume, .monitor-control-group) .monitor-icon-control { --ui-btn-h: 22px; }
  .monitor-volume { flex: none; min-width: 0; padding: 3px; }
  .monitor-volume .ui-range { display: none; }
  .monitor-volume:is(:hover, :focus-within) { flex: 1 1 auto; padding-right: 10px; }
  .monitor-volume:is(:hover, :focus-within) .ui-range { display: block; }
  .monitor-controls:has(.monitor-volume:is(:hover, :focus-within)) .monitor-control-group { display: none; }
}

.mx-fader-row {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  overflow-x: hidden;
  overflow-y: auto;
}
.mx-fader {
  min-width: 0;
  min-height: 42px;
  display: flex;
  align-items: center;
  padding: 5px 8px;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  background: transparent;
}
.mx-fader > .fader-row { flex: 1; }
.mx-fader-status.none { visibility: hidden; }
.mx-fader-status {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  min-width: 34px;
  min-height: 24px;
  text-align: center;
  font-size: 8px;
  font-weight: 900;
  letter-spacing: .06em;
  border-radius: var(--r-control);
  padding: 3px 6px;
}
.mx-fader-status.air {
  background: color-mix(in srgb, var(--pgm) 86%, var(--panel));
  color: var(--on-fill);
}
.mx-fader-status.preview {
  background: color-mix(in srgb, var(--on) 28%, var(--panel));
  color: color-mix(in srgb, var(--on) 88%, var(--text));
}
.mx-fader-status.auto {
  background: color-mix(in srgb, var(--pst) 28%, var(--panel));
  color: color-mix(in srgb, var(--pst) 88%, var(--text));
}
.mx-fader.standby .fader-track { opacity: .72; }
.mx-fader-idle .fader-track { opacity: .58; }
.mx-fader-air {
  background: color-mix(in srgb, var(--pgm) 12%, var(--plate));
}
.mx-fader-preview { background: color-mix(in srgb, var(--on) 12%, var(--plate)); }
.mx-fader-auto { background: color-mix(in srgb, var(--pst) 12%, var(--plate)); }
.mx-fader-manual .fader-track {
}
.mx-fader.manual .fader-track {
}
.mx-fader.midi-learning .fader-name {
  color: color-mix(in srgb, var(--accent) 86%, var(--text));
}
.mx-fader.midi-learning .fader-track {
  background: color-mix(in srgb, var(--accent) 20%, var(--plate));
}
.mx-fader-release {
  font-size: 8px;
  font-weight: 900;
  letter-spacing: .05em;
}
.mx-empty {
  display: grid;
  place-items: center;
  min-height: 96px;
  border: 1px dashed var(--line);
  border-radius: var(--r-card);
  color: var(--muted);
  font-size: 13px;
  grid-column: 1 / -1;
}

@media (max-width: 980px) {
  .mx-root { overflow-y: auto; }
  .mx-workspace {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto auto;
    grid-template-areas: "video" "next" "faders" "onair";
    overflow: visible;
  }
  .mx-mon {
    grid-template-rows: auto auto;
  }
  .mx-mon-frame {
    height: auto;
    width: 100%;
    max-width: 560px;
  }
  .mx-fader {
    grid-template-columns: 54px minmax(120px, 1.4fr) 60px;
  }
}

@media (max-height: 720px) and (min-width: 981px) {
  .mx-top {
    padding: 7px 12px;
  }

  .mx-workspace {
    gap: 8px;
    padding: 8px 12px 10px;
  }

  .mx-control-stack,
  .mx-deck-stack {
    gap: 8px;
  }

  .mx-control-stack {
    grid-template-rows: minmax(200px, 1fr) minmax(200px, .8fr);
  }

  .mx-mon {
    gap: 5px;
  }

  .mx-mon-frame {
    max-width: 500px;
  }

  .mx-deck-head {
    gap: 7px;
  }

  .mx-deck-state {
    font-size: 10px;
    padding: 2px 7px;
  }

  .mx-deck-event {
    gap: 6px;
    font-size: 12px;
  }

  .mx-event-time {
    font-size: 11px;
  }

  .mx-bank-title {
    padding: 6px 10px;
    font-size: 10px;
  }

  .mx-source-grid {
    gap: 6px;
    padding: 8px;
    grid-template-columns: repeat(auto-fill, minmax(134px, 1fr));
  }

  .mx-source-name {
    left: 6px;
    right: 6px;
    bottom: 6px;
    padding: 4px 6px;
    font-size: 12px;
  }

  .mx-fader-row {
    gap: 5px;
    padding: 8px;
  }

  .mx-fader .fader-track {
    height: 24px;
  }

}

@media (max-height: 640px) and (min-width: 981px) {
  .mx-control-stack {
    grid-template-rows: minmax(156px, 1fr) minmax(128px, .58fr);
  }

  .mx-source-grid {
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  }

  .mx-fader .fader-track {
    height: 22px;
  }

  .mx-fader {
    grid-template-columns: 44px minmax(82px, 1.3fr) 48px;
  }

  .mx-mon-frame {
    max-width: 420px;
  }

}

.app-statusbar {
  container: app-footer / inline-size;
  min-height: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  padding: 0 12px;
  background: var(--panel);
  border-top: 1px solid var(--line);
  flex-shrink: 0;
}

/* In a narrow window the bar gives way in turn, so what stays in it stays readable and the pickers keep
   their width: first Status' figures that read as they should (one that wants reading stays, and the
   Status panel has them all), then the labels in front of the pickers and Snap, then Record's word,
   leaving its lamp and count. */
@media (max-width: 1100px) {
  .app-status-figure.ok,
  .app-status-figures:not(:has(.app-status-figure:not(.ok))) { display: none; }
}
@media (max-width: 920px) {
  .app-tenant-label, .app-room-label { display: none; }
}
@media (max-width: 800px) {
  .flow-rec-word { display: none; }
}

.app-room {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.app-room-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  white-space: nowrap;
}

.app-room .te-combo {
  width: clamp(160px, 18vw, 260px);
  flex: 0 1 260px;
}

.app-sets { flex: 1 1 480px; min-width: 180px; max-width: 720px; }
.app-sets .te-combo { width: 100%; flex: 1 1 auto; }
.app-sets .te-combo-pop { min-width: min(460px, 90vw); }
.app-sets .te-combo-list { max-height: min(520px, 70vh); }
.profile-error { padding: 4px 8px; color: var(--pgm); font-size: 11px; }
.gfx-library-list.te-list-tree { display: flex; flex-direction: column; gap: 1px; }

/* The LiveDeck on screen, named with its tenant: closed it reads "Studio 1 · TV2". Open, it lists every
   LiveDeck there is to open, each with its tenant, room and address, so it opens wider than it sits. */
.app-tenant .te-combo {
  width: clamp(160px, 16vw, 240px);
  flex: 0 1 240px;
}
.app-tenant .te-combo-pop {
  min-width: 330px;
}
.app-tenant .te-combo-list {
  max-height: 360px;
}

/* Both pickers in the status bar: one line when closed. They open upwards, as any picker does with
   no room below it. */
.app-room .te-combo-trigger,
.app-tenant .te-combo-trigger {
  min-height: 26px;
  height: 26px;
  padding: 3px 8px;
}

.app-room .te-combo-trigger-detail,
.app-tenant .te-combo-trigger-detail {
  display: none;
}

.app-room .te-combo-caret,
.app-tenant .te-combo-caret {
  transform: rotate(180deg);
}

/* The one snap of every timeline, beside each timeline it steps (SnapPicker). */
.timeline-snap {
  align-items: center;
  display: inline-flex;
  flex: 0 0 auto;
  gap: 3px;
}
.timeline-snap-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.06em;
  margin-right: 3px;
  text-transform: uppercase;
}
.timeline-snap-picker { width: 76px; }
.timeline-snap-picker .te-combo-trigger { min-height: 24px; height: 24px; padding: 0 7px; }
.timeline-snap-picker .te-combo-pop { min-width: 180px; }

/* Shortcuts' keyboard, in its pane (ShortcutsSection): as wide as the panel it stands in. */
.app-hotkeys-panel { padding: 2px 0 4px; }

.app-hotkeys-keyboard {
  min-height: 0;
  overflow: hidden;
  display: grid;
  gap: 3px;
}

.app-hotkeys-kbd-row {
  display: flex;
  gap: 3px;
  width: 100%;
  min-width: 0;
}

.app-hotkeys-kbd-key {
  position: relative;
  flex: 1 1 38px;
  min-width: 0;
  height: 40px;
  display: grid;
  grid-template-rows: 12px minmax(0, 1fr);
  gap: 2px;
  align-items: start;
  padding: 4px;
  border-radius: var(--r-control);
  background: var(--plate);
  overflow: hidden;
  /* Keys are tappable (they dispatch the bound hotkey) — manipulation kills iPad double-tap zoom. */
  cursor: pointer;
  user-select: none;
  touch-action: manipulation;
}

.app-hotkeys-kbd-key:active {
  background: var(--plate-down);
  transform: translateY(1px);
}
.app-hotkeys-kbd-key:hover { background: var(--plate-hover); }

.app-hotkeys-kbd-key.wide {
  flex: 1.35 1 52px;
}

.app-hotkeys-kbd-key.xwide {
  flex: 1.9 1 70px;
}

.app-hotkeys-kbd-key.space {
  flex: 7 1 180px;
}

.app-hotkeys-kbd-key.assigned { background: color-mix(in srgb, var(--accent) 20%, var(--panel-2)); }

.app-hotkeys-kbd-key.pressed { background: color-mix(in srgb, var(--on) 22%, var(--panel-2)); }

.app-hotkeys-key-label,
.app-hotkeys-key-action {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-hotkeys-key-label {
  color: var(--text);
  font-size: 9.5px;
  font-weight: 900;
  line-height: 1;
  white-space: nowrap;
}

.app-hotkeys-kbd-key.assigned .app-hotkeys-key-label {
  color: var(--accent);
}

.app-hotkeys-key-action {
  align-self: end;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  color: var(--text);
  font-size: 8.5px;
  font-weight: 850;
  line-height: 1.05;
  word-break: break-word;
}

.app-hotkeys-key-more {
  position: absolute;
  top: 3px;
  right: 3px;
  min-width: 14px;
  height: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 24%, var(--panel));
  color: var(--accent);
  font-size: 8px;
  font-weight: 950;
}


.app-monitor {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}
.app-monitor-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 750;
  white-space: nowrap;
}
.app-monitor-toggle .toggle-track { order: 2; }
.app-monitor-icon { order: 1; }
.app-monitor-text { order: 3; }
.app-monitor-icon { width: 15px; height: 15px; flex: 0 0 auto; }
.app-monitor-feeds { display: inline-flex; align-items: center; gap: 2px; }
.app-monitor-vol { flex: 0 0 88px; width: 88px; min-width: 88px; height: 16px; }
.app-monitor-sync {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  font-weight: 750;
  color: var(--muted);
  white-space: nowrap;
}
.app-monitor-sync .ui-range { flex: 0 0 70px; width: 70px; min-width: 70px; height: 16px; }
.app-monitor-sync-label { text-transform: uppercase; letter-spacing: .06em; }
.app-monitor-sync-value { font-variant-numeric: tabular-nums; min-width: 38px; text-align: right; }

.app-health-wrap {
  position: relative;
  flex: none;
  margin-left: auto;
}

/* More lower panels stay in the footer's single line, with overflow inside their own group. */
.app-lower-panels { display: flex; align-items: center; gap: 4px; flex: 0 1 auto; min-width: 72px; max-width: 45%; overflow-x: auto; scrollbar-width: none; }
.app-lower-panels::-webkit-scrollbar { display: none; }
.app-lower-panels > .ui-add-choice { position: sticky; left: 0; z-index: 1; background: var(--panel); }
.app-lower-panels > .ui-add-choice, .app-lower-panel-chip { flex: none; }
.app-lower-panels > .app-health-button { flex: none; }
.app-health-wrap.app-lower-panels > .app-health-button { position: sticky; right: 0; z-index: 1; }
.app-lower-panels-left > .app-profiles-button { flex: 0 1 auto; }
.app-lower-panel-chip { position: relative; display: flex; align-items: center; }
/* The panel's × takes no room at rest: on hover it opens at the button's right end and the rest of the
   button makes room for it, as a pane's head does. */
.app-lower-panel-chip > .ui-btn:first-child { white-space: nowrap; transition: padding-right .12s ease; }
.app-lower-panel-chip:is(:hover, :focus-within) > .ui-btn:first-child { padding-right: 26px; }
.app-lower-panel-close { position: absolute; right: 2px; top: 2px; opacity: 0; pointer-events: none; }
.app-lower-panel-chip:is(:hover, :focus-within) .app-lower-panel-close { opacity: 1; pointer-events: auto; }
@media (hover: none) { .app-lower-panel-chip > .ui-btn:first-child { padding-right: 26px; } .app-lower-panel-close { opacity: 1; pointer-events: auto; } }

.app-health-button {
  gap: 7px;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
}

.app-health-button.error {
  color: var(--pgm);
}

.app-health-button.standby {
  color: var(--accent);
}

/* The Runtime panel as tables (RuntimePanel.tsx, ResourceWatch.tsx): a row per thing, a check, a
   standby mark or a warning in front, its kind in its colour, and what is driven lit. */
.rt-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.rt-table th {
  text-align: left;
  color: var(--muted);
  font-size: 9px;
  font-weight: 850;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  padding: 3px 8px 3px 0;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.rt-table td {
  padding: 3px 8px 3px 0;
  height: 26px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  white-space: nowrap;
  vertical-align: middle;
}
.rt-table tbody + tbody tr:first-child td { border-top: 1px solid var(--line); }
.rt-table tr.driven td { background: color-mix(in srgb, var(--pst) 7%, transparent); }
.rt-mark { width: 22px; padding-left: 7px !important; font-weight: 900; text-align: center; }
.rt-mark.ok { color: var(--pst); }
.rt-mark.standby { color: var(--muted); }
.rt-mark.warn { color: var(--pgm); }
.rt-mark.off { color: color-mix(in srgb, var(--muted) 60%, transparent); }
.rt-name { font-weight: 750; color: var(--text); }
.rt-what { color: var(--muted); max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; }
.rt-what code { color: var(--text); font-size: 11px; margin-right: 8px; }
.rt-services { font-size: 11px; color: color-mix(in srgb, var(--pst) 75%, var(--muted)); }
.rt-state, .rt-action { width: 1%; text-align: right; }
.rt-kind-cell { width: 1%; }
.rt-kind {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 6px;
  border: 0;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--kind-color, var(--text)) 72%, var(--text));
  color: var(--bg);
  font-size: 10px;
  font-weight: 850;
}
.rt-pill {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 7px;
  border-radius: var(--r-card);
  /* A plate, no outline, as a chip's parts are. */
  background: color-mix(in srgb, var(--muted) 14%, transparent);
  color: var(--muted);
  font-size: 10px;
  font-weight: 850;
  letter-spacing: 0.3px;
}
.rt-pill.active { color: var(--pst); background: color-mix(in srgb, var(--pst) 16%, transparent); }
.rt-pill.unavailable { color: var(--pgm); background: color-mix(in srgb, var(--pgm) 16%, transparent); }
.rt-pill.auto { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }
.rt-group td { height: 22px; color: var(--text); font-size: 11px; font-weight: 800; background: color-mix(in srgb, var(--panel-2) 70%, transparent); }
.rt-group-mode { margin-left: 8px; color: var(--muted); font-weight: 600; }
.rt-group-mode.manual { color: var(--on); }
.rt-table tr.grouped .rt-name { padding-left: 12px; }
.rt-empty { margin: 4px 0; color: var(--muted); font-size: 12px; }
.rt-num { text-align: right !important; white-space: nowrap; font-variant-numeric: tabular-nums; }
.rt-machine { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: 6px 18px; margin-bottom: 6px; container-type: inline-size; }
.rt-total { display: grid; grid-template-columns: 58px minmax(60px, 1fr) auto auto; align-items: center; gap: 8px; font-size: 12px; height: 24px; }
.rt-total-label { color: var(--muted); font-weight: 700; }
.rt-total strong { font-variant-numeric: tabular-nums; white-space: nowrap; }
.rt-total-of { white-space: nowrap; }
.rt-total.warn strong { color: var(--on); }
.rt-total.critical strong { color: var(--pgm); }
.rt-total-of { color: var(--muted); }
.rt-meter { display: inline-block; height: 6px; border-radius: var(--r-chip); background: color-mix(in srgb, var(--line) 70%, transparent); overflow: hidden; }
.rt-total .rt-meter { width: 100%; }
.rt-process-table .rt-meter { width: 42px; margin-right: 6px; vertical-align: middle; }
.rt-meter > span { display: block; height: 100%; border-radius: var(--r-chip); background: var(--pst); }
.rt-meter.warn > span { background: var(--on); }
.rt-meter.critical > span { background: var(--pgm); }
.rt-reason { margin: 0 0 4px; font-size: 12px; line-height: 1.35; white-space: normal; }
.rt-reason.warn { color: var(--on); }
.rt-reason.critical { color: var(--pgm); }
/* What is slowing the machine (ResourceWatch.tsx): each program, with what it takes. */
.rt-hogs { display: flex; flex-direction: column; gap: 2px; margin: 4px 0 8px; }
.rt-hogs-title { color: var(--muted); font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; }
.rt-hog { margin: 0; font-size: 12px; line-height: 1.35; color: var(--on); }
.rt-hog strong { color: var(--text); font-weight: 600; margin-right: 6px; }
.rt-hog .ui-btn { margin-left: 8px; }
.rt-work { display: flex; flex-direction: column; gap: 2px; margin: 4px 0 8px; }
.rt-work-row { display: flex; gap: 8px; margin: 0; font-size: 12px; line-height: 1.35; color: var(--muted); }
.rt-work-row strong { color: var(--text); font-weight: 600; min-width: 64px; }
.rt-process-tables { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); align-items: start; gap: 4px 18px; container-type: inline-size; }
.rt-process-table td { height: 22px; }
.rt-process-table th:first-child, .rt-process-table td:first-child { padding-left: 7px; }
/* These stand in a side panel as well as in the wide Status panel, and take the width they are given. */
.rt-fit { container-type: inline-size; }
@container (max-width: 300px) {
  .rt-total { grid-template-columns: 52px minmax(36px, 1fr) auto; }
  .rt-total-of { display: none; }
}
@container (max-width: 340px) {
  .rt-process-table .rt-meter { display: none; }
}
/* What a row says of where it is and of how it stands, in the wide table on one line. */
@container (min-width: 441px) {
  .rt-where:not(:empty) + .rt-why:not(:empty)::before { content: ' · '; }
}
/* A table of rows, narrow, is two lines to a row: first what it is and how it stands, then what it says
   and, at the same right edge, what kind of machine it is. Every row is laid out alike, so the marks,
   the names, the texts and the plates each stand in a line. Where it is, its address, is for the wide
   table and the hover; in a side panel what one looks for is how its link stands. */
@container (max-width: 440px) {
  .rt-table.rt-stack thead { display: none; }
  .rt-table.rt-stack, .rt-table.rt-stack tbody { display: block; }
  .rt-table.rt-stack tr {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr) auto;
    grid-template-areas: 'mark name state' '. what kind' '. action action';
    align-items: center;
    gap: 2px 8px;
    padding: 6px 4px;
    border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  }
  .rt-table.rt-stack tr.driven { background: color-mix(in srgb, var(--pst) 7%, transparent); }
  .rt-table.rt-stack tr.grouped { padding-left: 16px; }
  .rt-table.rt-stack td,
  .rt-table.rt-stack tr.driven td,
  .rt-table.rt-stack tbody + tbody tr:first-child td { display: block; height: auto; padding: 0; border: 0; background: none; box-shadow: none; }
  .rt-table.rt-stack .rt-mark { grid-area: mark; width: auto; padding-left: 0 !important; }
  .rt-table.rt-stack .rt-name,
  .rt-table.rt-stack tr.grouped .rt-name { grid-area: name; padding-left: 0; overflow: hidden; text-overflow: ellipsis; }
  .rt-table.rt-stack .rt-state { grid-area: state; width: auto; justify-self: end; }
  .rt-table.rt-stack .rt-what { grid-area: what; width: auto; max-width: none; white-space: normal; overflow-wrap: anywhere; }
  .rt-table.rt-stack tr:not(:has(.rt-kind-cell)) .rt-what { grid-column: 2 / 4; }
  .rt-table.rt-stack .rt-kind-cell { grid-area: kind; width: auto; justify-self: end; align-self: start; }
  .rt-table.rt-stack .rt-action { grid-area: action; width: auto; text-align: left; margin-top: 3px; }
  .rt-table.rt-stack .rt-action:empty { display: none; }
  .rt-table.rt-stack .rt-where { display: none; }
  /* A failover group's head: its name and how it fails over, and at the right what to do about it. */
  .rt-table.rt-stack tr.rt-group { display: flex; align-items: center; gap: 8px; margin-top: 6px; border-radius: var(--r-control); background: var(--plate); border-bottom: 0; }
  .rt-table.rt-stack tr.rt-group > td:first-child { display: none; }
  .rt-table.rt-stack tr.rt-group > td:nth-child(2) { flex: 1 1 auto; min-width: 0; }
  .rt-table.rt-stack tr.rt-group .rt-action { margin-top: 0; }
  .rt-table.rt-stack tr.rt-group .rt-group-mode { display: block; margin-left: 0; font-weight: 600; }
}

/* Status in the status bar: the machine's CPU and memory in use, amber as they run short, red when
   all but gone, beside how many of the room's devices are live. */
.app-status-figures { display: inline-flex; align-items: center; gap: 8px; font-variant-numeric: tabular-nums; }
.app-status-figure { color: var(--muted); font-weight: 800; }
/* Not pinned to the bar (barPins.tsx), the machine shows there only a figure that wants reading. */
.app-status-figures.wanted .app-status-figure.ok { display: none; }
.app-status-figure.warn { color: var(--on); }
.app-status-figure.critical { color: var(--pgm); }
.app-health-count.live { color: var(--pst); }
.app-health-standby { color: var(--on); font-weight: 800; }

.app-health-divider {
  width: 1px;
  height: 14px;
  background: var(--line);
}

.app-health-count {
  color: var(--muted);
}

.app-health-button.error .app-health-count {
  color: var(--pgm);
}

.app-health-clashes { border-radius: var(--r-card); background: color-mix(in srgb, var(--on) 12%, var(--panel-2)); padding: 8px 10px; margin-bottom: 10px; }
.app-health-clash { margin: 4px 0; font-size: 12px; color: var(--on); }
/* The Status panel (StatusPanel.tsx): a layer of glass (.ui-popover) over the right of the screen. It
   covers what is under it and moves none of it. Its width is the viewer's. Its parts are bands (Fold,
   components/ui), the activity log pinned along the bottom. */
.app-main {
  position: relative;
  display: flex;
  flex: 1;
  min-height: 0;
  min-width: 0;
}
.app-main > .tab-content { flex: 1 1 0; min-width: 0; }
.app-dock {
  position: absolute;
  z-index: 50;
  right: 8px;
  bottom: 8px;
  display: flex;
  flex-direction: column;
  width: min(var(--dock-width), calc(100% - 16px));
  max-height: calc(100% - 16px);
  overflow: hidden;
}
/* This panel is opaque. A backdrop filter would also trap its fixed picker lists inside the
   scrolling panel and clip the node choices when they open above it. */
.app-dock-profiles { left: 8px; right: auto; background: var(--panel-2); -webkit-backdrop-filter: none; backdrop-filter: none; }
.app-dock-front { z-index: 51; }
/* A panel from the top bar opens under it, at the right where its button is. */
.app-dock-upper { top: 8px; bottom: auto; }
.app-dock-grip.app-dock-grip-right { left: auto; right: 0; }
.profiles-catalogue { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.profiles-preset-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 2px 10px; color: var(--muted); font-size: 11px; font-weight: 700; }
.sync-actions { display: inline-flex; align-items: center; gap: 4px; }
/* The tenant a synced set is in, after the words: in the badge's type, less loud. */
.sync-tenant { opacity: 0.75; }
.profiles-card-footer { display: flex; align-items: center; gap: 0; flex: none; margin-left: auto; }
.profiles-card-share, .profiles-card-duplicate { position: static; flex: none; }
.sync-dot { display: inline-block; width: 6px; height: 6px; flex: 0 0 6px; border-radius: 50%; }
.sync-dot { margin: 0 4px; background: var(--muted); }
.sync-dot-good { background: var(--pst); }
.sync-dot-accent { background: var(--accent); }
.sync-dot-warning { background: var(--on); }
.sync-dot-danger { background: var(--pgm); }
.profiles-section > .ui-fold-head .ui-fold-toggle, .profiles-group > .ui-fold-head .ui-fold-toggle { padding-top: 4px; padding-bottom: 4px; }
.profiles-section > .ui-fold-head .ui-fold-actions, .profiles-preset-head .ui-fold-actions, .profiles-group > .ui-fold-head .ui-fold-actions { flex-wrap: nowrap; gap: 4px; padding-top: 2px; padding-bottom: 2px; }
.node-context { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; margin-bottom: 6px; }
.node-context-tag { display: inline-flex; align-items: center; gap: 5px; min-width: 0; max-width: 100%; min-height: 28px; padding: 0 8px; border-radius: var(--r-control); background: var(--plate); font-size: 11px; }
.node-context-dot { flex: 0 0 7px; width: 7px; height: 7px; border-radius: 50%; background: var(--identity-color); }
.node-context-kind { color: var(--muted); font-size: 9px; }
.node-context-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-weight: 700; }
.node-context-local { color: var(--muted); font-size: 10px; }
.admin-ai-access, .admin-ai-nodes { display: flex; flex-direction: column; gap: 8px; }
.admin-ai-access { margin-bottom: 16px; }
.admin-mcp-steps { display: flex; flex-direction: column; gap: 8px; padding-left: 24px; }
.admin-mcp { margin-bottom: 10px; }
.admin-mcp-fields { display: flex; flex-direction: column; gap: 12px; margin: 0; }
.admin-mcp-fields dt { font-weight: 600; }
.admin-mcp-fields dd { margin: 0; overflow-wrap: anywhere; }
.admin-mcp-arrow { align-self: center; }
.admin-ai-access .ui-seg { flex-wrap: wrap; }
.admin-mcp-config > summary { padding: 8px 0; cursor: pointer; font-weight: 600; }
.settings-properties-portal { height: 100%; }
.profiles-catalogue > .profiles-grid, .profiles-configurations { padding: 4px 10px 6px; }

.video-preview-grid { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 4px; min-width: 0; width: 100%; height: 100%; }
.ui-preview-popover .video-preview-grid { height: auto; }
/* A hover's pictures and its graphics, one row of tiles: the pictures' own grid lends its tiles to it. */
.video-preview-grid-inner { display: contents; }
.video-preview-cell > .graphics-picture { border-radius: inherit; }
.ui-preview-popover .video-preview-cell { border-radius: var(--r-control); }
.video-preview-cell { position: relative; display: block; min-width: 0; overflow: hidden; }
.signal-video { position: relative; display: block; width: 100%; height: 100%; min-height: 24px; aspect-ratio: var(--picture-aspect, 16 / 9); overflow: hidden; background: var(--plate); }
.signal-video.has-signal { background: var(--bg); }
.signal-video video, .signal-video img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.signal-video img { opacity: 0; }
.signal-video img.ready { opacity: 1; }
.signal-video-status { display: flex; align-items: center; justify-content: center; height: 100%; font-size: 10px; color: var(--muted); padding: 6px; text-align: center; }
.video-preview-caption { box-sizing: border-box; gap: 6px; font-size: 10px; padding: 3px 6px; overflow: hidden; white-space: nowrap; }
.video-preview-caption > span:not(.ui-badge) { overflow: hidden; text-overflow: ellipsis; }
.video-preview-caption .ui-badge { flex: none; min-height: 14px; padding: 2px 4px; font-size: 8px; }
.video-preview-cell > .video-preview-caption { position: absolute; left: 4px; bottom: 4px; max-width: calc(100% - 8px); }
.profiles-grid { --plate-selected: var(--plate-hover); display: flex; flex-wrap: wrap; align-items: flex-start; gap: 4px; min-width: 0; }
.profiles-grid .cfg-link-card { --cfg-link-row-height: 28px; flex: 0 1 auto; flex-direction: row; align-items: center; width: auto; max-width: 100%; height: 28px; min-height: 28px; min-width: 0; padding: 3px 6px; gap: 6px; border-radius: var(--r-control); }
.profiles-grid .cfg-link-card-main { flex: 0 1 auto; min-width: 0; max-width: 180px; font-size: 11px; line-height: 16px; }
.profiles-grid .cfg-link-card-sub { display: none; }
.profiles-grid .cfg-link-card-main.inline-rename-input { height: 20px; max-width: 100%; min-width: 0; margin: 0; }
.profiles-grid .profiles-card-remove { position: static; flex: none; }
.profiles-grid .profiles-choice.colored:not(.ui-selected) { background: var(--plate); }
.profiles-grid .profiles-choice.colored:not(.ui-selected):hover { background: var(--plate-hover); }
.profiles-grid .profiles-choice.colored.ui-selected { background: color-mix(in srgb, var(--link-color) 34%, var(--panel)); }
.profiles-grid .profiles-choice.colored.ui-selected:hover { background: color-mix(in srgb, var(--link-color) 40%, var(--panel)); }
.profiles-choice .profiles-card-footer, .profiles-choice .profiles-card-remove { opacity: 0; pointer-events: none; transition: opacity .1s; }
.profiles-choice:hover .profiles-card-footer, .profiles-choice:focus-within .profiles-card-footer,
.profiles-choice:hover .profiles-card-remove, .profiles-choice:focus-within .profiles-card-remove { opacity: 1; pointer-events: auto; }
.profiles-choice > .ui-badge { flex: none; min-height: 14px; padding: 1px 4px; font-size: 8px; }
@media (hover: none) {
  .profiles-choice .profiles-card-footer, .profiles-choice .profiles-card-remove { opacity: 1; pointer-events: auto; }
}
.profiles-grid .ui-btn-icon { width: 18px; height: 18px; min-height: 18px; font-size: 12px; }
.profiles-grid .ui-add-choice { flex: 0 1 auto; max-width: 100%; }
.profiles-grid .cfg-link-add-card { flex: none; width: 28px; justify-content: center; gap: 0; }
.profiles-grid .cfg-link-add-card .cfg-link-card-main { display: none; }
.profiles-grid .cfg-link-add-card .cfg-link-drop { position: static; order: -1; min-width: 12px; padding: 0; border: 0; background: transparent; font-size: 12px; }
.profiles-node-picker { padding: 4px 0 12px; }
.profiles-node-picker .app-tenant { width: 100%; max-width: none; }
.profiles-node-picker .te-combo { width: 100%; }
.profiles-node-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.profiles-node-chips > .node-context { display: contents; }
.profiles-node-chip.app-tenant-button { width: auto; max-width: 100%; height: 28px; min-height: 28px; padding: 0 8px; border-radius: var(--r-control); background: color-mix(in srgb, var(--node-color) 34%, var(--panel)); }
.profiles-node-chip .app-tenant-name { font-size: 11px; }
.profiles-node-info, .profiles-node-partner { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0; min-height: 28px; padding: 0 8px; border-radius: var(--r-control); background: var(--plate); font-size: 11px; color: var(--muted); }
.profiles-node-partner b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.profiles-node-partner > span { font-size: 9px; }
.profiles-node-partner.selected { background: color-mix(in srgb, var(--node-color) 34%, var(--panel)); color: var(--text); }
.profiles-node-partner.warning { color: var(--on); }
.profiles-node-authority { opacity: 0; pointer-events: none; }
.profiles-node-chips:hover .profiles-node-authority, .profiles-node-chips:focus-within .profiles-node-authority { opacity: 1; pointer-events: auto; }
.profiles-node-select.app-tenant { width: auto; min-width: 0; max-width: 100%; }
.profiles-node-select > .app-tenant-label { display: none; }
.profiles-node-select .te-combo-trigger { min-height: 28px; padding: 4px 8px; }
.profiles-node-select .te-combo-trigger-label { font-size: 11px; }
@media (hover: none) { .profiles-node-authority { opacity: 1; pointer-events: auto; } }
/* The node, its tenant and the sets in use, in one line that keeps whatever fits whole and wraps the
   rest onto a second line that is never seen: a name is shown entire or not at all, the last ones
   going first as the bar narrows. Only the node's own name, which always stands, can shorten. */
.app-profiles-button { flex: 0 1 auto; min-width: 0; overflow: hidden; justify-content: flex-start; }
.app-profiles-button > .ui-badge { flex: none; }
.app-profiles-row {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 12px;
  height: 20px;
  overflow: hidden;
}
.app-profiles-row > *, .app-profile-figure { flex: none; height: 20px; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.app-profiles-node { flex: 0 1 auto; display: block; min-width: 0; max-width: 200px; overflow: hidden; text-overflow: ellipsis; line-height: 20px; color: var(--text); }
.app-profiles-tenant { margin-left: -6px; color: var(--muted); }
.app-profiles-summary { display: contents; }
.app-profile-figure { color: var(--text); }
.app-profile-lead { gap: 7px; }
/* The edge to take hold of: a shade under the pointer, the keyboard's line where it is. */
.app-dock-grip {
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  left: 0;
  width: 8px;
  cursor: col-resize;
  touch-action: none;
}
.app-dock-grip:hover { background: var(--plate-hover); }
.app-dock-grip:focus-visible { outline: 2px solid var(--focus-line); outline-offset: -2px; }
.app-dock-head {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
}
.app-dock-head h2 {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  margin: 0;
  color: var(--text);
  font-size: 13px;
  letter-spacing: 0;
}
.app-dock-head-actions { display: flex; flex: none; align-items: center; gap: 4px; }
/* As a pane's head: the count at the right edge, the panel's buttons beside it on hover; Keep open,
   while it is on, stays in sight. */
@media (hover: hover) {
  .app-dock-head:not(:hover, :focus-within) > .app-dock-head-actions > :not([aria-pressed="true"]) { display: none; }
}
/* What folds away scrolls in the height the panel has; the log, open, has a height of its own beneath,
   and folded it is a band along the bottom. */
.app-dock-scroll { flex: 0 1 auto; min-height: 0; overflow-y: auto; }
/* The log along the bottom keeps its height however tall what is above it is. */
.app-dock > .ui-fold { flex: none; }
.status-log.open { flex: none; height: clamp(200px, 34vh, 360px); }
.app-dock-scroll .app-health-clashes { margin: 8px 10px; }
.app-dock-empty { margin: 0; padding: 18px 10px; color: var(--muted); font-size: 12px; text-align: center; }
/* A section of the rundown's, drawn by the rundown into the panel: it does not fill a rail here, so what
   scrolls by itself is given a height. */
.status-slot .rd-rail-section.rd-rail-own-scroll.open { height: clamp(240px, 42vh, 460px); }
.sim-empty-note { padding: 8px 24px 12px; }

.app-health-kicker,
.app-health-section h3 {
  color: var(--muted);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 1.6px;
  text-transform: uppercase;
}

.app-health-section {
  border-radius: var(--r-card);
  background: var(--plate);
  padding: 10px;
  margin-bottom: 10px;
  min-width: 0;
}

.app-health-section h3 {
  margin: 0 0 8px;
}

.app-health-device-group + .app-health-device-group {
  margin-top: 10px;
}

.app-health-group-title {
  margin: 0 0 6px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}

.app-health-failover-list {
  display: grid;
  gap: 8px;
}

.app-health-service-failover,
.app-health-failover-head {
  display: grid;
  align-items: center;
  gap: 8px;
}

.app-health-service-failover {
  grid-template-columns: minmax(140px, 1fr) max-content;
  min-height: 30px;
  padding: 6px 8px;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--text);
  font-size: 12px;
}

.app-health-service-failover strong {
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.7px;
}

.app-health-failover-group {
  border-radius: var(--r-card);
  background: var(--plate);
  overflow: hidden;
}

.app-health-failover-head {
  grid-template-columns: minmax(0, 1fr) max-content;
  min-height: 38px;
  padding: 8px;
  background: var(--plate-hover);
  border-bottom: 1px solid var(--line);
}

.app-health-failover-head > span {
  display: grid;
  gap: 2px;
  min-width: 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}

.app-health-failover-head strong {
  color: var(--text);
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
}

.app-health-failover-head small {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
}

.app-health-failover-members {
  display: grid;
}

/* ─── Template editor ────────────────────────────────────────────────────────── */

.te-root {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg);
}

/* The bar across the top of a tab (components/PathBar.tsx): where you are, as chips with arrows,
   left to right, then saved, undo, redo and wipe all. The same on every tab that edits. */
.path-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 36px;
  padding: 4px 10px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
  flex-shrink: 0;
  min-width: 0;
}
/* Beside the tabs: hides every tab's bar at once, and shows it again. */
.path-bar-toggle {
  flex: 0 0 auto;
  width: 24px;
  margin-left: 4px;
}
.path-bar-toggle .ui-icon { width: 14px; height: 14px; transform: rotate(90deg); transition: transform 0.15s; }
/* Up while the bar shows, to fold it away; down while it is hidden, to bring it back. */
.path-bar-toggle.shown .ui-icon { transform: rotate(-90deg); }
.path-bar-steps { display: flex; align-items: center; gap: 0; min-width: 0; flex: 1 1 auto; overflow: hidden; }
.path-step-wrap { display: inline-flex; align-items: center; flex: 0 1 auto; min-width: 0; max-width: 290px; }
/* Narrowed, a step keeps its arrow, its badge and the start of its name, so every step still says what it is. */
.path-step-wrap:has(.path-step-badge) { min-width: 112px; }
/* The tenant leads, and is short: it stands whole. */
.path-step-wrap:first-child { min-width: auto; flex-shrink: 0; }
.path-step-wrap > .path-step { flex: 0 1 auto; min-width: 0; }
.path-step-wrap:last-child { max-width: min(60%, 290px); }
/* A separator, not something to press: the text's colour, quieter. */
/* What Undo or Redo would do, under the pointer: the editor's last steps, the next one first. */
.path-history { position: relative; display: inline-flex; }
.path-history-pop { position: absolute; top: calc(100% + 6px); right: 0; z-index: 40; min-width: 260px; max-width: 460px; padding: 8px 10px; display: flex; flex-direction: column; gap: 4px; font-size: 12px; }
.path-history-head, .path-history-more { color: var(--muted); font-size: 10px; letter-spacing: 0.3px; }
.path-history-step { opacity: .62; white-space: nowrap; overflow: hidden; }
.path-history-step.next { opacity: 1; font-weight: 600; }
.path-step-arrow { display: inline-flex; flex: 0 0 auto; margin: 0 5px; color: color-mix(in srgb, var(--text) 60%, transparent); }
.path-step-arrow .ui-icon { width: 13px; height: 13px; }
.path-step {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  /* A long name is cut, with its whole in the hint: no step is wider than this, and none is drawn
     over the next. */
  max-width: 100%;
  overflow: hidden;
  padding: 0 8px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 750;
  white-space: nowrap;
}
.path-step.current { color: var(--text); }

.path-step.path-step-tinted { background: color-mix(in srgb, var(--step-color) 24%, var(--panel-2)); color: var(--text); }
.path-step.path-step-tinted:hover { background: color-mix(in srgb, var(--step-color) 29%, var(--panel-2)); }
.path-step.path-step-tinted.current { background: color-mix(in srgb, var(--step-color) 34%, var(--panel-2)); }
.path-step-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; display: inline-flex; align-items: center; gap: 5px; }
/* A name alone is cut with an ellipsis; a step that holds chips keeps them whole and is cut at its edge. */
.path-step-label:not(:has(> *)) { display: block; }
.path-step-badge {
  flex: 0 0 auto;
  padding: 2px 5px;
  /* A plate in the colour of what it names, an event type, a lane, a machine; white where none is
     decided yet, so it stands out until one is. */
  border: 0;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--step-color, var(--text)) 72%, var(--text));
  color: var(--bg);
  font-size: 9px;
  font-weight: 800;
  line-height: 1;
}
/* An action said as its chip says it, inside a step. */
.path-step .rd-chip-route { gap: 4px; }
.path-step .rd-chip-token { height: 18px; font-size: 11px; }
.path-bar-actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; margin-left: auto; }
.mx-port-picker { width: 120px; min-width: 0; }
.path-save {
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
  padding: 0 4px;
}
.path-save.saving { color: var(--accent); }
.path-save.error { color: var(--pgm); }

/* Type quick-create bar inside the template list column */
.te-type-quickbar {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 6px 8px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.te-type-quick {
  flex: 1 0 52px;
  min-width: 0;
  color: var(--template-color);
  font-size: 9px;
  font-weight: 800;
  white-space: nowrap;
}

.te-template-camera { --template-color: var(--event-camera); }
.te-template-live { --template-color: var(--event-live); }
.te-template-clip { --template-color: var(--event-clip); }
.te-template-voiceover { --template-color: var(--event-voiceover); }
.te-template-gfx { --template-color: var(--event-gfx); }
.te-template-pause { --template-color: var(--event-pause); }
.te-template-automation { --template-color: var(--event-automation); }

.te-workspace {
  position: relative;
  --templates-col: 260px;
  --actions-col: 184px; /* Wide enough for "Crosspoint" beside a two-figure count. */
  --props-col: 260px;
  display: grid;
  grid-template-columns: var(--templates-col) var(--actions-col) minmax(360px, 1fr) var(--props-col);
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.te-workspace.templates-collapsed { --templates-col: 44px; }
.te-workspace.actions-collapsed { --actions-col: 44px; }
.te-workspace.props-hidden {
  grid-template-columns: var(--templates-col) var(--actions-col) minmax(360px, 1fr);
}

.te-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: var(--panel);
  border-right: 1px solid var(--line);
}
.te-col:last-child { border-right: none; }

.te-col-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 34px;
  padding: 6px 10px;
  border-bottom: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  flex-shrink: 0;
}
.te-header-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.te-collapsed-header {
  justify-content: center;
  padding: 6px 4px;
}
.te-collapsed-rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 8px 4px;
  min-height: 0;
  overflow-y: auto;
}
.te-rail-label {
  writing-mode: vertical-rl;
  text-orientation: mixed;
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.te-rail-pill {
  position: relative;
  width: 32px;
  min-height: 28px;
  padding: 3px 2px;
  color: color-mix(in srgb, var(--kind-color, var(--muted)) 70%, var(--muted));
  font-size: 9px;
  font-weight: 800;
}
.te-rail-count {
  position: absolute;
  top: -5px;
  right: -5px;
  align-items: center;
  justify-content: center;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  font-size: 9px;
  font-weight: 900;
  line-height: 1;
}
.te-icon-btn { --ui-btn-h: 22px; font-size: 14px; font-weight: 800; }
.te-icon-btn.small { font-size: 12px; }
.te-icon-btn.te-lock-filter .te-lock-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  stroke-width: 2.2;
}
.te-icon-btn.wide {
  width: 68px;
  padding: 0 8px;
  font-size: 10px;
  white-space: nowrap;
}

.te-list {
  list-style: none;
  flex: 1;
  min-height: 0;
  margin: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 5px 6px;
}
.te-list-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 3px 6px;
}
.te-list-type {
  width: 30px;
  min-height: 18px;
  justify-content: center;
  padding: 1px 0;
  /* The event kind is named on a compact badge in its chosen colour. */
  background: color-mix(in srgb, var(--template-color, var(--text)) 72%, var(--text));
  color: var(--bg);
  font-size: 9px;
  font-weight: 800;
  text-align: center;
}
.te-item-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: 12px;
}
.te-list-item.ui-selected .te-item-name {
  color: var(--text);
  font-weight: 800;
}
.te-inherit-badge {
  flex-shrink: 0;
  min-height: 18px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 800;
}
.te-rename {
  flex: 1;
  min-width: 0;
  height: 24px;
  padding: 0 6px;
  font-size: 12px;
  font-weight: inherit;
}
.te-list-item .te-rename {
  color: var(--text);
  font-weight: 800;
}
.te-folder-row .te-rename {
  color: var(--text);
  font-weight: 800;
}
/* Customer folder tree */
.te-list-tree.root-drop {
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  outline: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: -6px;
}
.te-folder-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  /* Taller than an event row: the extra bottom padding is the type-mix rule's lane, plus clear air
     between it and the folder name. Fixed rather than min-height — the tallest action button used
     to drive the height, so a row grew by 4px the moment its buttons rendered. */
  --folder-rule-lane: 9px;
  height: 34px;
  margin: 0 0 0 var(--tree-indent, 0px);
  padding: 5px 6px var(--folder-rule-lane);
  /* Folders use the same neutral surfaces as the surrounding panels. Opening one adds a small
     lift so the hierarchy stays visible alongside the event-type colour rule. */
  background: color-mix(in srgb, var(--text) 5%, var(--panel));
  user-select: none;
  color: var(--text);
}
.te-folder-row.ui-interactive:hover {
  background: color-mix(in srgb, var(--text) 9%, var(--panel));
}
.te-folder-row.open {
  background: color-mix(in srgb, var(--text) 7%, var(--panel));
}
.te-folder-row.open.ui-interactive:hover {
  background: color-mix(in srgb, var(--text) 11%, var(--panel));
}

.te-folder-row.drop-target {
  outline: 1px dashed color-mix(in srgb, var(--template-color, var(--accent)) 70%, var(--line));
  outline-offset: -2px;
  background: color-mix(in srgb, var(--accent) 20%, var(--panel-2));
}
.te-list-item.drop-target {
  outline: 1px dashed color-mix(in srgb, var(--template-color, var(--accent)) 70%, var(--line));
  outline-offset: -2px;
  background: var(--plate-hover);
}
.te-folder-row.drop-before,
.te-folder-row.drop-after,
.te-list-item.drop-before,
.te-list-item.drop-after { outline: 1px dashed var(--accent); outline-offset: -2px; }
.te-folder-row.dragging { opacity: 0.4; }
.te-list-item.locked .te-list-type { background: var(--event-automation); }
.te-folder-row.locked {
  cursor: default;
}
.te-list-item.locked {
  cursor: default;
  opacity: 0.66;
}
.te-list-item.locked.ui-selected {
  opacity: 0.82;
}
.te-folder-row.locked .te-folder-icon,
.te-folder-row.locked .te-folder-name {
  opacity: 0.72;
}
.te-folder-row.locked.open .te-folder-icon,
.te-folder-row.locked.open .te-folder-name {
  opacity: 0.86;
}
.te-folder-row.inherited-lock .te-folder-name,
.te-list-item.locked .te-item-name {
  color: var(--muted);
}
.te-lock-state {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: var(--muted);
}
.te-lock-toggle {
  width: 20px;
  flex-shrink: 0;
}
.te-lock-state {
  opacity: 0.78;
}
.te-lock-icon {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.te-lock-toggle .te-lock-icon {
  width: 21px;
  height: 21px;
  stroke-width: 2.55;
}
.te-folder-lock-icon {
  width: 16px;
  height: 16px;
  /* Match .te-lock-icon (preset locks). Must not exceed the ~20px content box
     of .te-lock-toggle, or flex-shrink crushes this viewBox SVG down to ~8px. */
  flex-shrink: 0;
  fill: color-mix(in srgb, currentColor 14%, transparent);
  stroke: currentColor;
  stroke-width: 2.35;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.te-folder-arrow {
  flex-shrink: 0;
  transform: rotate(0deg);
  transition: transform 0.15s;
}
.te-folder-arrow.open { transform: rotate(90deg); }
.te-folder-chevron {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.te-folder-icon {
  flex-shrink: 0;
  width: 28px;
  min-height: 18px;
  justify-content: center;
  padding: 1px 3px;
  background: var(--directory-badge);
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .04em;
  text-align: center;
}
.te-folder-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 12px;
  font-weight: 800;
}
.te-folder-row .te-folder-name { font-weight: 700; }
.te-folder-row.open .te-folder-name { font-weight: 800; }

/* How many events are inside, at the right edge of the folder. */
.te-folder-count {
  flex: 0 0 auto;
  margin-left: auto;
  align-self: center;
  justify-content: center;
  min-height: 18px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.te-folder-row .te-folder-count {
  background: var(--directory-badge);
  color: var(--muted);
}

/* Event-type composition of the folder, as a proportional rule inside the chip. Inset to the
   chip's own padding and fully rounded: run flush to the edges it stops reading as part of the
   chip and starts reading as a divider between rows. Horizontal rather than a left rail because
   the bar exists to show proportion, and 34px of height cannot resolve a 2-of-11 share that 250px
   of width shows plainly. */
.te-folder-mix {
  position: absolute;
  left: 6px;
  right: 6px;
  bottom: 2px;
  height: 4px;
  border-radius: var(--r-pill);
  pointer-events: none;
}
/* Every row boundary is the same 1px that .te-list already sets — folders included. Group breaks
   used to carry an extra margin, which made the rhythm jump around a folder; the depth band gives
   each row a visible surface, so the tight, uniform spacing reads cleanly on its own. */

/* Indent tree items under their group */
.te-list-tree .te-list-item {
  margin-left: var(--tree-indent, 0px);
  padding-left: 6px;
}
.te-list-tree .te-list-item:where(:not(.ui-selected):not(:hover)) {
  /* Half the folders' wash: the contrast between the two is what separates a folder from its
     events, so quieting the events lets the chips stay light without shouting. */
  background-color: color-mix(in srgb, var(--text) calc(var(--tree-band, 0) * 0.5%), transparent);
}

/* Drag states on list items (source only) */
.te-list-item[draggable] { cursor: grab; }
.te-list-item[draggable]:active { cursor: grabbing; }
.te-list-item.dragging { opacity: 0.4; }

/* "Inherits from" section drop zone */
.te-combined-section {
  flex-shrink: 0;
  border-top: 1px solid var(--line);
  padding: 8px;
  background: color-mix(in srgb, var(--panel-2) 60%, var(--panel));
}
.te-combined-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.te-combined-count {
  padding: 1px 7px;
  font-size: 10px;
}
.te-combined-empty {
  color: var(--muted);
  font-size: 11px;
  font-style: italic;
  text-align: center;
  padding: 4px 0 2px;
}
.setup-hint {
  position: relative;
  width: 100%;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--on) 14%, var(--panel));
  color: color-mix(in srgb, var(--text) 88%, var(--on));
  font-size: 12px;
  font-style: normal;
  font-weight: 650;
  line-height: 1.4;
  padding: 8px 10px 8px 28px;
  text-align: left;
}
.setup-hint::before {
  content: '!';
  position: absolute;
  left: 9px;
  top: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--on) 20%, var(--panel));
  color: var(--on);
  font-size: 9px;
  font-weight: 900;
  line-height: 1;
}
.te-combined-empty.setup-hint {
  padding: 7px 9px 7px 27px;
}
.te-combined-list { display: flex; flex-direction: column; gap: 4px; }
.te-combined-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 4px 4px 8px;
}
.te-combined-lock {
  flex-shrink: 0;
  color: var(--template-color, var(--muted));
  padding: 1px 4px;
  font-size: 9px;
  font-weight: 900;
  line-height: 1.1;
}
.te-combined-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--template-color, var(--muted));
  flex-shrink: 0;
}
.te-combined-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 11px;
}

.te-combined-section.drag-over {
  background: color-mix(in srgb, var(--accent) 10%, var(--panel-2));
  outline: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: -3px;
}
.te-combined-section.drag-over .te-combined-empty {
  color: var(--accent);
}
.te-combined-handle {
  color: var(--muted);
  font-size: 12px;
  cursor: grab;
  flex-shrink: 0;
  opacity: 0.5;
  line-height: 1;
}
.te-combined-handle:hover { opacity: 1; }
.te-combined-item[draggable] { cursor: default; }
.te-combined-item.dragging { opacity: 0.35; }
.te-combined-item.drop-target {
  outline: 1px dashed color-mix(in srgb, var(--template-color, var(--accent)) 60%, transparent);
  outline-offset: -2px;
  background: color-mix(in srgb, var(--template-color, var(--accent)) 14%, var(--panel-2));
}

.te-picker-filter {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px 8px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 11px;
  flex-shrink: 0;
}

.te-search {
  display: flex;
  gap: 6px;
  padding: 6px 8px;
  border-top: 1px solid var(--line);
  flex-shrink: 0;
}
.te-search input {
  flex: 1;
  min-width: 0;
}
.te-empty {
  padding: 16px 12px;
  color: var(--muted);
  font-size: 12px;
}

.te-action-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.te-def-group {
  padding: 8px 10px 9px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 40%, transparent);
  flex-shrink: 0;
}
.te-def-group-label {
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1.2px;
  margin-bottom: 6px;
}
.te-def-row {
  width: 100%;
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto 20px;
  align-items: center;
  gap: 5px;
  min-height: 30px;
  margin-bottom: 2px;
  padding: 3px 4px;
  color: var(--text);
  text-align: left;
}
.te-def-icon { justify-self: start; }
.te-def-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 11px;
}
.te-def-count {
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 6px;
  color: var(--accent);
  font-size: 10px;
  font-weight: 900;
  line-height: 1;
}
.te-def-plus {
  grid-column: 4;
  color: var(--muted);
  font-size: 13px;
  font-weight: 800;
}

.te-action-search {
  display: flex;
  gap: 6px;
  padding: 6px 8px;
  border-top: 1px solid var(--line);
  flex-shrink: 0;
}
.te-action-search input {
  flex: 1;
  min-width: 0;
}

.te-board { background: var(--bg); }
.te-frame-timing { display: flex; flex-direction: column; gap: 8px; font-size: 11px; }
.te-frame-timing-summary { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; color: var(--muted); }
.te-frame-timing-empty { margin: 0; color: var(--muted); }
.te-frame-timing-scroll { max-height: 180px; overflow: auto; }
.te-frame-timing table { width: 100%; border-collapse: collapse; text-align: left; font-variant-numeric: tabular-nums; }
.te-frame-timing th { color: var(--muted); font-weight: 600; }
.te-frame-timing th, .te-frame-timing td { padding: 4px 8px; white-space: nowrap; vertical-align: top; }
.te-frame-timing th:first-child, .te-frame-timing td:first-child { padding-left: 0; }
.te-frame-timing small { display: block; color: var(--muted); margin-top: 2px; }
.te-timeline-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 42px;
  padding: 7px 10px;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
  flex-shrink: 0;
}
.te-view-toggles {
  display: flex;
  gap: 6px;
  min-width: 0;
  overflow-x: auto;
}
.te-snap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}
.te-snap-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 850;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.te-timeline-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  flex-shrink: 0;
}
.te-view-toggle {
  gap: 6px;
  padding: 6px 10px;
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
}
.te-view-toggle-count {
  min-height: 16px;
  padding: 1px 5px;
  font-size: 10px;
  color: currentColor;
}
.te-view-toggle-add {
  min-height: 16px;
  padding: 1px 5px;
  font-size: 8px;
  letter-spacing: .25px;
}
.te-timeline {
  display: grid;
  grid-template-columns: repeat(var(--visible-lanes), minmax(260px, 1fr));
  gap: 10px;
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 10px;
}
.te-timeline.zooming,
.te-timeline.zooming * {
  cursor: ns-resize !important;
  user-select: none;
}
.te-op-lane {
  grid-row: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  flex-shrink: 0;
  height: 100%;
  container-type: inline-size;
}
.te-lane-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 40px;
  padding: 9px 11px;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel-2) 80%, var(--bg));
  color: var(--text);
  font-size: 14px;
  font-weight: 800;
}
.te-lane-label { flex: 0 0 auto; white-space: nowrap; }
.te-op-preview .te-lane-title { color: var(--on); }
.te-op-program .te-lane-title { color: var(--pst); }
.te-op-takeout .te-lane-title { color: var(--pgm); }
.te-op-preview.ui-selected .te-lane-title { background: color-mix(in srgb, var(--on) 10%, var(--panel-2)); }
.te-op-program.ui-selected .te-lane-title { background: color-mix(in srgb, var(--pst) 10%, var(--panel-2)); }
.te-op-takeout.ui-selected .te-lane-title { background: color-mix(in srgb, var(--pgm) 10%, var(--panel-2)); }
.te-lane-window {
  margin-left: auto;
  margin-right: 10px;
  min-height: 18px;
  padding: 1px 7px;
  font-size: 10px;
  font-weight: 800;
  white-space: nowrap;
}
.te-op-title-actions {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 7px;
}
@container (max-width: 350px) {
  .te-lane-title { gap: 6px; padding-inline: 8px; }
  .te-lane-window { display: none; }
  .te-op-title-actions { gap: 4px; }
}
.te-test-btn {
  font-size: 10px;
  font-weight: 800;
}
.te-test-btn.wide {
  width: 100%;
  margin-top: 9px;
}
.te-test-btn.compact {
  font-size: 10px;
  white-space: nowrap;
}
.te-test-all {
  min-width: 112px;
  white-space: nowrap;
}
.te-op-count {
  min-width: 38px;
  min-height: 18px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 800;
  text-align: center;
  white-space: nowrap;
}
.te-board-testbar {
  display: flex;
  justify-content: center;
  padding: 7px 10px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  flex-shrink: 0;
}
.te-timeline-track {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: auto;
  cursor: crosshair;
  background: var(--bg);
}
.te-timeline-track-inner {
  position: relative;
  width: 100%;
  min-width: 100%;
  height: max(100%, calc(58px + (var(--rows) * 50px) + var(--lane-extra, 0px)));
  min-height: calc(58px + (var(--rows) * 50px) + var(--lane-extra, 0px));
  background:
    linear-gradient(to bottom, transparent 0, transparent 36px, color-mix(in srgb, var(--line) 52%, transparent) 36px, transparent 37px),
    repeating-linear-gradient(to right, transparent 0, transparent calc(var(--tick-step) - 1px), color-mix(in srgb, var(--line) 38%, transparent) calc(var(--tick-step) - 1px), color-mix(in srgb, var(--line) 38%, transparent) var(--tick-step)),
    repeating-linear-gradient(to right, transparent 0, transparent calc(var(--snap-step) - 1px), color-mix(in srgb, var(--line) var(--snap-grid-alpha), transparent) calc(var(--snap-step) - 1px), color-mix(in srgb, var(--line) var(--snap-grid-alpha), transparent) var(--snap-step)),
    var(--bg);
}
.te-ruler {
  position: absolute;
  inset: 6px 0 auto 0;
  height: 18px;
  pointer-events: none;
  z-index: 1;
}
.te-ruler-tick {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  color: color-mix(in srgb, var(--muted) 78%, transparent);
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  text-shadow: 0 1px 0 var(--bg);
  white-space: nowrap;
}
.te-ruler-tick.edge-start {
  transform: translateX(0);
}
.te-ruler-tick.edge-end {
  transform: translateX(-100%);
}
.te-end-marker {
  position: absolute;
  top: -1px;
  z-index: 4;
  width: 14px;
  height: 12px;
  pointer-events: none;
  transform: translateX(-50%);
}
.te-end-marker::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 14px;
  height: 12px;
  background: var(--accent);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}
.te-playhead-line[data-testing='true'] {
  animation: te-cti-test-flash 0.7s ease-out;
}
/* The rows of an operation's lane: a band each, every other one a little lighter. */
.te-row-band {
  background: color-mix(in srgb, var(--panel-2) 45%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  left: 0;
  pointer-events: none;
  position: absolute;
  right: 0;
  z-index: 1;
}
.te-row-band.odd { background: color-mix(in srgb, var(--panel-2) 20%, transparent); }
/* Where an action dragged by its handle would land. */
.te-reorder-line {
  background: var(--accent);
  border-radius: var(--r-chip);
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 50%, transparent);
  height: 3px;
  left: 0;
  pointer-events: none;
  position: absolute;
  right: 0;
  z-index: 20;
}
/* The handle an action is moved up or down by; the rest of the card moves it in time. */
.te-op-card-grip {
  background-image: radial-gradient(circle, color-mix(in srgb, var(--muted) 88%, transparent) 1.15px, transparent 1.6px);
  background-position: center;
  background-size: 5px 5px;
  bottom: 4px;
  cursor: ns-resize;
  left: 3px;
  opacity: .72;
  position: absolute;
  top: 4px;
  width: 14px;
  z-index: 4;
}
.te-op-card:hover .te-op-card-grip { opacity: 1; }
.te-op-card {
  position: absolute;
  top: var(--row-top, calc(50px + (var(--row) * 50px)));
  left: var(--x);
  z-index: 3;
  width: var(--chip-width, 184px);
  max-width: calc(100% - var(--x));
  display: grid;
  grid-template-columns: minmax(0, 1fr) 56px 20px;
  align-items: center;
  gap: 7px;
  padding: 8px;
  /* In the colour of the machine it drives, lightly: its kind is said last, in the same colour. */
  background: color-mix(in srgb, var(--kind-color, var(--panel)) 8%, var(--plate));
  color: var(--text);
  font: inherit;
  line-height: 1.15;
  cursor: grab;
  text-align: left;
  user-select: none;
  touch-action: none;
  overflow: hidden;
}
.te-op-card:has(.te-op-card-grip) { padding-left: 23px; }
.te-op-card.timed {
  background: color-mix(in srgb, var(--kind-color, var(--accent)) 9%, var(--plate));
}
.te-op-card.transition {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--pst) 13%, var(--plate)),
    color-mix(in srgb, var(--accent) 15%, var(--plate))
  );
}
.te-transition-layer {
  grid-row: 1;
  position: relative;
  align-self: stretch;
  z-index: 8;
  min-width: 0;
  min-height: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}
.te-transition-seam {
  position: absolute;
  left: 50%;
  top: 41px;
  bottom: 50px;
  width: 2px;
  transform: translateX(-50%);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--accent) 56%, var(--pst));
  box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 28%, transparent);
  opacity: 0.78;
  pointer-events: none;
}
.te-op-card.seam {
  top: var(--transition-top);
  left: var(--transition-center);
  z-index: 9;
  width: var(--transition-width);
  min-width: 0;
  max-width: none;
  transform: translateX(-50%);
  grid-template-columns: minmax(0, 1fr) 44px 20px;
  pointer-events: auto;
  cursor: pointer;
}
.te-op-card.seam.resizing {
  cursor: ew-resize;
}
.te-op-card.seam .te-transition-resize {
  position: absolute;
  top: 6px;
  bottom: 6px;
  width: 10px;
  border-radius: var(--r-pill);
  cursor: ew-resize;
  background: color-mix(in srgb, var(--accent) 50%, var(--pst));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}
.te-op-card.seam:hover .te-transition-resize,
.te-op-card.seam:focus-visible .te-transition-resize,
.te-op-card.seam.resizing .te-transition-resize {
  opacity: 1;
  pointer-events: auto;
}
.te-op-card.seam .te-transition-resize.start {
  left: 0;
}
.te-op-card.seam .te-transition-resize.end {
  right: 0;
}
.te-op-card.seam .te-transition-resize::after {
  content: "";
  position: absolute;
  inset: 4px 3px;
  background: repeating-linear-gradient(90deg, transparent 0 2px, color-mix(in srgb, var(--bg) 72%, transparent) 2px 3px);
}
.te-op-card.duration-resizable .te-transition-resize {
  position: absolute;
  top: 6px;
  bottom: 6px;
  width: 10px;
  border-radius: var(--r-pill);
  cursor: ew-resize;
  background: color-mix(in srgb, var(--accent) 55%, var(--pst));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}
.te-op-card.duration-resizable:hover .te-transition-resize,
.te-op-card.duration-resizable:focus-visible .te-transition-resize,
.te-op-card.duration-resizable.resizing .te-transition-resize {
  opacity: 1;
  pointer-events: auto;
}
.te-op-card.duration-resizable.resizing {
  cursor: ew-resize;
}
.te-op-card.duration-resizable .te-transition-resize.start { left: 0; }
.te-op-card.duration-resizable .te-transition-resize.end { right: 0; }
.te-op-card.duration-resizable .te-transition-resize::after {
  content: "";
  position: absolute;
  inset: 4px 3px;
  background: repeating-linear-gradient(90deg, transparent 0 2px, color-mix(in srgb, var(--bg) 72%, transparent) 2px 3px);
}
.te-op-card.dragging {
  cursor: grabbing;
  opacity: .9;
}
.te-op-card.copy-source {
  opacity: .55;
}
.te-op-card.copy-ghost {
  z-index: 5;
  pointer-events: none;
  opacity: 0.78;
  border: 1px dashed var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, var(--plate));
}
.te-op-card.copy-ghost::after {
  content: "+";
  position: absolute;
  right: 8px;
  top: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--bg);
  font-size: 11px;
  font-weight: 900;
  line-height: 1;
}
.te-op-card.executing {
  background: color-mix(in srgb, var(--pst) 20%, var(--plate));
  animation: te-chip-test-flash 0.7s ease-out;
}
.te-op-card-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* An action said as its chip says it (ADR 0028), a little larger on the editor's taller cards. */
.te-op-card-parts .rd-chip-token { font-size: 11px; height: 22px; }
.te-op-card-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 800;
}
.te-op-card-summary {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: 11px;
}
.te-op-card-time { color: var(--muted); font-size: 11px; text-align: right; }
.te-op-card-del { color: var(--muted); font-size: 12px; font-weight: 800; text-align: center; }
.te-op-card.fader-expanded {
  min-height: calc(42px + var(--fader-expanded-extra, 62px));
  grid-template-rows: 32px minmax(54px, 1fr);
  align-items: center;
  padding-bottom: 0;
  overflow: visible;
}
.te-op-card.fader-expanded .te-op-card-main,
.te-op-card.fader-expanded .te-op-card-time,
.te-op-card.fader-expanded .te-op-card-del {
  grid-row: 1;
}
/* Combined (locked) action cards — pulled in from another template. */
.te-op-card.combined {
  grid-template-columns: minmax(0, 1fr) auto;
  z-index: 2;
  cursor: pointer;
  opacity: 0.6;
  background: color-mix(in srgb, var(--template-color, var(--muted)) 8%, var(--plate));
}
.te-op-card.combined:hover {
  opacity: 0.95;
}
.te-op-card.seam.combined {
  z-index: 9;
  grid-template-columns: minmax(0, 1fr) auto;
  pointer-events: auto;
}
.te-op-card.combined .rd-chip-kind {
  color: color-mix(in srgb, var(--template-color, var(--accent)) 80%, var(--text));
  background: color-mix(in srgb, var(--template-color, var(--accent)) 18%, var(--panel-2));
}
.te-op-card.folder-locked {
  cursor: default;
  opacity: 0.66;
}
.te-op-card.folder-locked.selected {
  opacity: 0.82;
}
.te-op-card.ui-selected { background: var(--plate-selected); color: var(--text); }
.te-op-card-source {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 96px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-height: 18px;
  padding: 1px 6px;
  background: color-mix(in srgb, var(--template-color, var(--muted)) 14%, var(--plate));
  color: var(--template-color, var(--muted));
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
}
.te-op-card-source-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--template-color, var(--muted));
  flex-shrink: 0;
}
.te-fader-curve {
  position: absolute;
  left: 56px;
  right: 82px;
  top: auto;
  bottom: 6px;
  height: 12px;
  pointer-events: none;
  opacity: 0.9;
  overflow: visible;
  z-index: 1;
}
.te-op-card.has-fader-curve:not(.fader-expanded) .te-fader-curve {
  display: none;
}
.te-op-card.fader-expanded .te-fader-curve {
  display: flex;
  flex-direction: column;
  gap: 5px;
  left: 0;
  right: 0;
  top: 44px;
  bottom: 0;
  height: auto;
  padding: 7px 10px 8px;
  border-top: 1px solid color-mix(in srgb, var(--line) 72%, transparent);
  border-radius: 0 0 var(--r-control) var(--r-control);
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--bg) 42%, transparent), color-mix(in srgb, var(--bg) 18%, transparent)),
    color-mix(in srgb, var(--bg) 48%, var(--panel));
}
.te-fader-curve.interactive {
  pointer-events: auto;
}
.te-fader-curve-row {
  position: relative;
  display: block;
  min-height: 30px;
  padding: 3px 8px;
  border-radius: var(--r-control);
  background: var(--plate);
}
.te-fader-curve-row:nth-child(even) {
  background: var(--plate-hover);
}
.te-fader-curve-row:only-child {
  padding-left: 8px;
}
.te-fader-curve-label {
  position: absolute;
  z-index: 0;
  left: 18px;
  top: 50%;
  max-width: min(42%, 190px);
  transform: translateY(-50%);
  pointer-events: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: color-mix(in srgb, var(--muted) 58%, transparent);
  font-size: 11px;
  font-weight: 900;
  line-height: 1;
}
.te-fader-plot {
  position: absolute;
  inset: 8px 0 9px;
  overflow: visible;
}
.te-fader-curve-row .te-fader-plot {
  display: block;
  position: relative;
  z-index: 1;
  inset: auto;
  height: 22px;
  width: 100%;
  min-width: 0;
}
.te-fader-curve.interactive .te-fader-plot {
  cursor: crosshair;
}
.te-fader-curve svg {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.te-fader-curve polyline {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.te-fader-dot {
  background: var(--accent);
  pointer-events: auto;
  cursor: grab;
}
.te-fader-dot:hover,
.te-fader-dot:focus-visible {
  background: color-mix(in srgb, var(--accent) 64%, var(--text));
  transform: translate(-50%, -50%) scale(1.12);
}
.te-fader-dot.at-playhead {
  background: color-mix(in srgb, var(--accent) 76%, var(--text));
  transform: translate(-50%, -50%) scale(1.06);
}
.te-fader-dot.dragging {
  cursor: grabbing;
  background: color-mix(in srgb, var(--accent) 78%, var(--text));
  transform: translate(-50%, -50%) scale(1.12);
}
.te-fader-tip {
  position: absolute;
  z-index: 3;
  transform: translate(-50%, -50%);
  padding: 3px 7px;
  border-radius: var(--r-pill);
  background: var(--float);
  backdrop-filter: var(--float-blur);
  color: var(--text);
  font-size: 10px;
  font-weight: 900;
  line-height: 1;
  white-space: nowrap;
  box-shadow: var(--float-shadow);
  pointer-events: none;
}

/* Combine picker bar in the timeline toolbar. */
.te-combine-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow-x: auto;
  flex-shrink: 1;
}
.te-combine-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.te-combine-empty { color: var(--muted); font-size: 11px; }

/* Global hint/status line above the control room bar. */
.app-hintbar {
  flex-shrink: 0;
  height: 26px;
  min-height: 26px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  color: var(--muted);
  font-size: 11px;
  line-height: 1.3;
  min-width: 0;
  overflow: hidden;
}
.app-hintbar::before {
  content: 'i';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--plate);
  color: var(--accent);
  font-size: 9px;
  font-weight: 800;
  font-style: italic;
  flex-shrink: 0;
}
.app-hintbar.hint,
.app-hintbar.info {
  color: var(--text);
}
.app-hintbar.error {
  color: var(--pgm);
  background: color-mix(in srgb, var(--pgm) 10%, var(--panel));
}
.app-hintbar.error::before {
  content: '!';
  background: color-mix(in srgb, var(--pgm) 20%, var(--panel));
  color: var(--pgm);
  font-style: normal;
}
.app-hintbar.warn {
  color: color-mix(in srgb, var(--on) 70%, var(--text));
  background: color-mix(in srgb, var(--on) 10%, var(--panel));
}
.app-hintbar.warn::before {
  content: '!';
  background: color-mix(in srgb, var(--on) 20%, var(--panel));
  color: var(--on);
  font-style: normal;
}
.app-hint-message {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-hint-token {
  display: inline-flex;
  align-items: center;
  min-height: 16px;
  margin: 0 3px;
  padding: 1px 5px;
  border: 0;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--panel-2) 72%, transparent);
  color: color-mix(in srgb, var(--text) 92%, white);
  font-size: 10px;
  font-weight: 950;
  letter-spacing: 0.04em;
  line-height: 1;
  vertical-align: 1px;
}

@keyframes te-chip-test-flash {
  0% {
    background: color-mix(in srgb, var(--pst) 36%, var(--panel));
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--pst) 65%, transparent);
  }
  55% {
    box-shadow: 0 0 0 5px color-mix(in srgb, var(--pst) 18%, transparent), 0 0 18px color-mix(in srgb, var(--pst) 36%, transparent);
  }
  100% {
    box-shadow: none;
  }
}

@keyframes te-cti-test-flash {
  0% {
    width: 4px;
    filter: brightness(1.8);
  }
  55% {
    width: 4px;
    filter: brightness(1.45);
  }
  100% {
    width: 2px;
    filter: brightness(1);
  }
}
.te-op-empty {
  position: absolute;
  left: 16px;
  right: 16px;
  top: 54px;
  border: 1px dashed var(--line);
  border-radius: var(--r-control);
  color: var(--muted);
  padding: 16px 8px;
  text-align: center;
  font-size: 12px;
}
.te-lane-footer {
  display: flex;
  justify-content: center;
  padding: 8px 10px;
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel-2) 60%, var(--bg));
  flex-shrink: 0;
}
.te-lane-test {
  min-width: 116px;
  padding: 6px 12px;
}

.te-timebar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  flex-shrink: 0;
}
.te-time-label { color: var(--muted); font-size: 11px; margin-left: auto; }
.te-time-now { color: var(--pst); font-size: 12px; font-weight: 800; min-width: 60px; }
.te-timebar .te-from-start-toggle {
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
}
.te-timebar .te-from-start-toggle:hover {
  color: var(--text);
}

.te-clip-switches {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 12px;
}

.te-clip-toggle {
  min-width: 0;
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
}

.te-clip-toggle span:last-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.te-props { overflow-y: auto; }
.te-props.readonly .ui-chip,
.te-props.readonly .te-target-search,
.te-props.readonly .ui-field,
.te-props.readonly .te-combobox-toggle,
.te-props.readonly .fader-track,
.te-props.readonly .te-fader-keyframe-time,
.te-props.readonly .ui-range,
.te-props.readonly label {
  cursor: default;
}
.te-props.readonly .te-prop-section button,
.te-props.readonly .te-prop-section input,
.te-props.readonly .te-prop-section label,
/* select was missing here, so a dropdown in a read-only panel stayed live and edited the shared
   template from a place that presents itself as a viewer. */
.te-props.readonly .te-prop-section select,
.te-props.readonly .fader-track {
  pointer-events: none;
}
/* …except what this item is allowed to change. A property exposed as an event tag is the item's
   own, and the panel marks those rows so the blanket lock lets them through — the lock is there to
   stop an edit reaching the shared TEMPLATE, which is exactly what these rows do not do. */
.te-props.readonly .te-prop-section .tc-field:not(.tc-disabled),
.te-props.readonly .te-prop-section .tc-field:not(.tc-disabled) *,
.te-props.readonly .te-prop-section .te-combo:not(.te-combo-locked),
.te-props.readonly .te-prop-section .te-combo:not(.te-combo-locked) * {
  pointer-events: auto;
}
/* Closing a picture window, playing a preview or operating live output does not edit the event
   template. The caller only offers live controls where available; their disabled states apply. */
.te-props.readonly .te-prop-section .ui-picture-close,
.te-props.readonly .te-prop-section .graphics-preview-controls .ui-btn:not(:disabled),
.te-props.readonly .te-prop-section .graphics-transport .ui-btn:not(:disabled) {
  pointer-events: auto;
}
/* Each transition control is locked by its own tag; native disabled states keep template-only
   choices out, while the exposed type, effect and parameters remain usable in the rundown. */
.te-props.readonly .te-transition-picker .ui-chip:not(:disabled),
.te-props.readonly .te-transition-picker .ui-field:not(:disabled),
.te-props.readonly .te-transition-picker .ui-range:not(:disabled),
.te-props.readonly .te-transition-picker .toggle-label:has(.toggle-input:not(:disabled)),
.te-props.readonly .te-transition-picker .toggle-input:not(:disabled) { pointer-events: auto; cursor: pointer; opacity: 1; }
.te-props.readonly .te-prop-section .tc-field:not(.tc-disabled) .tc-input,
.te-props.readonly .te-prop-section .te-combo:not(.te-combo-locked) .te-combo-trigger {
  opacity: 1;
}
/* Text reads the same way. The row carries the # only when the template exposed that exact field,
   and the input marks itself readonly when it did not, so the blanket lock lets through precisely
   the words this item is allowed to write - a ticker's headline being the whole point of the item. */
.te-props.readonly .te-prop-section .te-field-input-row:has(.te-field-expose-static) .ui-field:not([readonly]) {
  pointer-events: auto;
  opacity: 1;
}
.te-props.readonly .te-prop-row:has(.te-field-expose-static) > .ui-field:not([readonly]) {
  pointer-events: auto;
  opacity: 1;
}
/* And a switch: an action's ON/OFF given to the item, Autotake's among them. */
.te-props.readonly .te-prop-section:has(.te-field-expose-static) .toggle-label,
.te-props.readonly .te-prop-section:has(.te-field-expose-static) .toggle-input {
  pointer-events: auto;
  cursor: pointer;
}
/* Fixed Event settings read as locked when the operator asks to see them. Dim the controls, never
   their section or picker wrapper: opacity there also makes popovers transparent and traps their
   stacking. Channel choices use buttons and faders use a track, so include those as well as fields.
   In mixed sections, each field row decides for itself whether it is editable. */
.te-props-item :is(.te-prop-section, .te-payload-field, .te-transition-param, .te-field-input-row):not(:has(.te-field-expose-static)):not(.te-prop-keep)
  :is(
    .te-prop-label:not(:has(.ui-btn)),
    .te-transition-param-label:not(:has(.ui-btn)),
    .te-prop-label:has(.ui-btn) > span,
    .te-transition-param-label:has(.ui-btn) > span,
    .ui-btn:not(.tc-handle), .ui-chip, .te-combo-trigger, .toggle-label, .ui-field, .ui-range, .ui-color-input,
    .tc-handles, .tc-aside, .fader-track, .te-fader-keyframe > span, .te-slider-row > span
  ) { opacity: 0.38; }
.te-props-item .tc-field.tc-disabled .tc-handles { color: var(--text); }
/* The digit group is dimmed together, so the disabled buttons must not fade a second time. */
.te-props-item .tc-field.tc-disabled .tc-handle { opacity: 1; }
.te-field-lock { display: none; }
.te-kf-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 11px 6px;
  flex-shrink: 0;
}
/* Events uses the same compact coloured action row as the folding Properties headings. Include
   the inset in the heading's width, so its mark stays inside the panel and aligns with the fields. */
.te-kf-header.te-action-heading {
  box-sizing: border-box;
  gap: 6px;
  width: 100%;
  padding: 6px 11px;
  border-bottom: 1px solid var(--line);
  background: var(--panel-2);
  font-size: 11px;
}
/* What the action does takes the width there is, the longest part giving way first. */
.te-action-heading .rd-chip-route { flex: 1 1 auto; min-width: 0; }
/* In the rundown's properties an action is a band that folds (ActionBand), as the simulators' are. What
   it holds is the panel's own fields, and a list opened in one comes out over the band, not cut by it. */
.ui-fold.te-action-band > .ui-fold-body { overflow: visible; }
/* The original folding header surrounds a compact Actions row. Only its title gets the coloured
   surface: the chevron and count stay outside it, on the header's normal neutral ground. */
.te-action-band > .ui-fold-head .ui-fold-title { flex: 1 1 auto; }

/* Properties are compact in height, in the events editor and the rundown alike: a field is read at a
   glance and many sit one under the other. Timecodes keep their width, which is what makes a pair a
   target, and give up only the air above and below. */
/* One inset and field height in Events and on an item. Textareas keep room for several lines. */
.te-props .te-prop-section { padding: 3px 11px; }
.te-props .ui-field:not(.ui-textarea) { height: 24px; }
.te-props .te-prop-label { margin-bottom: 3px; }
.te-props .te-field-label-row { min-height: 18px; }
.te-props .te-field-expose { width: 18px; height: 18px; }
.te-props .te-combo-trigger { min-height: 24px; height: auto; padding: 2px 8px; }
.te-props .tc-field { --tc-size: 13px; --tc-pad-x: 10px; --tc-pad-y: 3px; }
.te-props .tc-handle { height: auto; }
/* Read, not shouted: the fields' words at an ordinary weight, the small labels over them a little
   firmer; only the chips, which say what an action does, stay bold. */
.te-props .te-prop-label { font-weight: 650; }
.te-props .tc-input { font-weight: 500; }
.te-props .te-combo-trigger-label,
.te-props .te-combo-option-label { font-weight: 500; }
.te-props .toggle-label,
.te-props .te-clip-toggle { font-weight: 500; }
.te-props .ui-chip { font-weight: 600; }
/* A label, the value and its tag have one place in every short property row. Let the label wrap
   before shrinking the timecode's digit targets; text payloads and pickers use the same columns. */
.te-props .te-prop-row {
  display: grid;
  grid-template-columns: 64px minmax(112px, 1fr) 18px;
  align-items: center;
  gap: 4px 7px;
  min-width: 0;
}
.te-props .te-prop-section.te-prop-row { box-sizing: border-box; min-height: 31px; }
.te-props-item .te-prop-row { grid-template-columns: 64px minmax(112px, 1fr); }
.te-props .te-prop-row > .te-prop-label {
  grid-column: 1;
  grid-row: 1;
  margin: 0;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.25;
  text-transform: none;
}
.te-props .te-prop-row > :is(.tc-field, .te-combo, .toggle-label, .ui-field) { grid-column: 2; grid-row: 1; min-width: 0; }
.te-props .te-prop-row > .te-field-expose { grid-column: 3; grid-row: 1; justify-self: end; }
.te-props .te-prop-row > .te-prop-hint { grid-column: 1 / -1; margin-top: 2px; }
.te-props .te-prop-row > .tc-field { --tc-size: 12px; --tc-pad-x: 6px; --tc-pad-y: 3px; }
.te-props .te-prop-row > .tc-field .tc-aside { right: 4px; }
.te-props .te-prop-row > .tc-field .tc-unit { left: 6px; font-weight: 600; letter-spacing: 0; }
.te-props .te-prop-row > .tc-field .tc-unit-short { font-size: 8px; font-weight: 600; letter-spacing: 0; }
.te-props .te-payload-field + .te-payload-field { margin-top: 6px; }
.te-lane-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}
.te-lane-preview { background: var(--pst); box-shadow: 0 0 5px var(--pst); }
.te-lane-program { background: var(--accent); box-shadow: 0 0 5px var(--accent); }
.te-lane-takeout { background: var(--on); box-shadow: 0 0 5px var(--on); }
.te-kf-el {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 13px;
  font-weight: 800;
}
.te-prop-section {
  padding: 10px 11px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 40%, transparent);
  flex-shrink: 0;
}
.te-prop-label {
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  margin-bottom: 7px;
}
.te-field-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.te-field-input-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 28px;
  align-items: center;
  gap: 6px;
}
.te-field-input-row + .te-field-input-row {
  margin-top: 6px;
}
.te-field-expose {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.te-field-input-row > .te-field-expose { justify-self: end; }
.te-prop-hint {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.4;
  margin-top: 7px;
}
.te-editable-fields {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.te-editable-field-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20px;
  align-items: center;
  gap: 7px;
  min-height: 36px;
  padding: 5px;
}
.te-editable-field-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.te-editable-field-name {
  min-width: 0;
  width: 100%;
  font-size: 12px;
  font-weight: 800;
}
.te-editable-field-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
}
.rd-editable-fields {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.rd-editable-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.rd-editable-field-label {
  color: var(--muted);
  font-size: 11px;
  font-weight: 800;
}
.cfg-robotics-shot-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cfg-robotics-shot {
  border-radius: var(--r-card);
  padding: 10px;
  background: var(--plate);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cfg-robotics-shot-head {
  display: flex;
  align-items: end;
  gap: 10px;
}
.cfg-robotics-shot-name { flex: 1 1 auto; min-width: 0; }
.cfg-robotics-shot-cmd { flex: 0 0 auto; }
.cfg-robotics-shot-head .cfg-inspector-remove { align-self: center; }

.cfg-robotics-shot-device {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 80px 80px;
  align-items: end;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--line);
}
.cfg-robotics-shot-device-name {
  align-self: center;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  min-width: 0;
}
.cfg-robotics-shot-device label { min-width: 0; }
.te-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.te-target-picker {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.te-target-search {
  padding: 0 8px;
  font-size: 11px;
  width: 100%;
}
.te-combo {
  position: relative;
  min-width: 0;
}
.te-combo-trigger {
  width: 100%;
  min-height: 42px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 8px;
  text-align: left;
}
.te-combo-compact .te-combo-trigger { min-height: 24px; height: 24px; padding: 0 8px; }
.te-combo-compact .te-combo-pop { min-width: 220px; }
.te-combo-trigger-main {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
}
.te-combo-trigger-copy,
.te-combo-option-copy {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.te-combo-trigger-label,
.te-combo-option-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-size: 11px;
  font-weight: 850;
}
.te-combo-trigger-detail,
.te-combo-option-detail {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: 10px;
  font-weight: 650;
}
.te-combo-caret {
  flex: 0 0 auto;
  color: var(--muted);
  font-size: 10px;
  font-weight: 900;
}
.te-combo-pop {
  position: absolute;
  z-index: 50;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  padding: 7px;
}
/* Opened upwards, the search stays next to the trigger and the list rises from it. */
.te-combo-pop.up { display: flex; flex-direction: column-reverse; }
.te-combo .te-combo-pop.up .te-combo-list { margin-top: 0; margin-bottom: 6px; }
.te-combo-search {
  width: 100%;
  min-width: 0;
  padding: 5px 8px;
  font-size: 11px;
}
.te-combo-list {
  display: flex;
  flex-direction: column;
  gap: 3px;
  max-height: 210px;
  overflow-y: auto;
  margin-top: 6px;
}
/* A row keeps its height however many there are: the list scrolls, its rows never squeeze. */
.te-combo-option {
  flex: none;
}
.te-combo-group {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 6px 2px 1px;
  color: var(--muted);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.te-combo-group .ui-icon { width: 12px; height: 12px; }
.te-combo-icon { flex: 0 0 auto; width: 14px; height: 14px; color: var(--muted); }
.te-combo-group:first-child { margin-top: 0; }
.te-combo-empty {
  padding: 9px 7px;
  color: var(--muted);
  font-size: 11px;
}
.te-combo-token-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}
.te-combo-token {
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
}
.te-combo-token-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.te-combo-token-remove { flex: 0 0 auto; color: var(--muted); }
.te-combo-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 7px;
}
.te-fader-rows {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.te-fader-rows.is-fader { gap: 2px; }
.te-fader-row {
  justify-content: flex-start;
  width: 100%;
  min-height: 28px;
  padding: 0 7px;
  text-align: left;
}
.te-fader-row-content {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  min-width: 0;
}
.te-fader-row-kind {
  flex: 0 0 auto;
  min-width: 28px;
  min-height: 16px;
  padding: 1px 5px;
  background: color-mix(in srgb, var(--row-color, var(--muted)) 16%, var(--plate));
  color: var(--row-color, var(--muted));
  font-size: 8px;
  letter-spacing: .04em;
  text-align: center;
}
.te-fader-row-text {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.te-slider-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.te-slider-row .ui-range { flex: 1 1 auto; width: auto; min-width: 88px; }
.te-slider-row input[type=number] {
  width: 68px;
}
.te-slider-row span {
  min-width: 54px;
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
  text-align: right;
}

.te-fader-automation-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.te-fader-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.te-fader-keyframe-btn {
  font-size: 10px;
  font-weight: 850;
}
.te-fader-add-row {
  justify-content: space-between;
  width: 100%;
  margin-top: 3px;
  font-size: 11px;
  font-weight: 800;
}
.te-fader-add-row-main {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.te-fader-add-row-plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  line-height: 1;
}
.te-fader-add-row-hint {
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
}
.te-fader-add-pop {
  margin-top: 8px;
  padding: 8px;
}
.te-fader-control {
  display: flex;
  align-items: flex-start;
}
.te-fader-keyframes {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 9px;
}
.te-fader-keyframes-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: var(--muted);
  font-size: 9px;
  font-weight: 850;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.te-fader-keyframe {
  display: grid;
  grid-template-columns: minmax(74px, auto) minmax(0, 1fr) auto 20px;
  align-items: center;
  gap: 7px;
  min-height: 28px;
  padding: 4px 5px;
  color: var(--text);
  font-size: 11px;
  font-weight: 700;
}
.te-fader-keyframe-target {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
}
.te-fader-keyframe-time {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--accent);
  text-align: left;
}
.te-check-row {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
  font-size: 12px;
  margin-bottom: 8px;
}
.te-props-footer {
  position: sticky;
  bottom: 0;
  display: flex;
  justify-content: center;
  padding: 9px 11px;
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel) 92%, var(--bg));
  flex-shrink: 0;
}
.te-props-test {
  min-width: 112px;
}

.te-combobox {
  position: relative;
  width: 100%;
}

.te-combobox .ui-field {
  padding-right: 34px;
}

.te-combobox-toggle {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 1;
}

.te-combobox-toggle span {
  font-size: 13px;
  line-height: 1;
}

.te-combobox-menu {
  position: absolute;
  z-index: 50;
  top: calc(100% + 5px);
  left: 0;
  right: 0;
  max-height: 236px;
  overflow: auto;
  padding: 5px;
}

.te-combobox-option {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(70px, 0.55fr) minmax(0, 1fr) auto;
  align-items: center;
  justify-content: initial;
  justify-items: start;
  gap: 8px;
  min-height: 34px;
  padding: 6px 8px;
  text-align: left;
}

.te-combobox-id {
  color: var(--accent);
  font-weight: 900;
  font-family: var(--mono, monospace);
}

.te-combobox-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
  font-weight: 750;
}

.te-combobox-kind {
  color: var(--muted);
  font-size: 10px;
  font-weight: 850;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.te-combobox-empty {
  padding: 9px 10px;
  color: var(--muted);
  font-size: 12px;
}

input[type="number"] {
  appearance: textfield;
  -moz-appearance: textfield;
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

@media (max-width: 1100px) {
  .te-workspace { grid-template-columns: 230px 152px minmax(320px, 1fr) 230px; }
  .te-workspace.props-hidden { grid-template-columns: 230px 152px minmax(320px, 1fr); }
  .te-type-label { display: none; }
}

/* ─── Log tab ───────────────────────────────────────────────────────────────── */

.log-root {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg);
}

.log-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}

.log-search-wrap {
  position: relative;
  flex: 1;
  min-width: 180px;
  max-width: 420px;
}
.log-search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  pointer-events: none;
}
.log-search {
  width: 100%;
  padding-left: 30px;
}
.log-toolbar-label {
  flex: 0 0 auto;
  margin-left: 4px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
}
/* Toolbar-height variant of the shared search combobox — the editor sizing is far too tall here. */
.log-filter-combo {
  flex: 0 0 auto;
  width: 146px;
}
.log-filter-combo .te-combo-trigger {
  min-height: 30px;
  height: 30px;
  padding: 0 8px;
}
.log-filter-combo .te-combo-trigger-label {
  font-size: 12px;
  font-weight: 700;
}
/* Right-anchored so the last filters in the row do not open off the edge of the window. */
.log-filter-combo .te-combo-pop {
  left: auto;
  right: 0;
  min-width: 208px;
}
.log-highlight-areas { width: 78px; }
.log-highlight-control { position: relative; flex: 0 0 auto; }
.log-highlight-trigger { height: 30px; min-height: 30px; padding: 0 8px; }
.log-highlight-count {
  min-width: 16px;
  padding: 2px 5px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--accent) 22%, var(--panel));
  color: var(--accent);
  font-size: 10px;
  font-weight: 800;
  text-align: center;
}
.log-highlight-popover {
  z-index: 75;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: min(440px, calc(100vh - 16px));
  padding: 10px;
  color: var(--text);
}
.log-highlight-heading,
.log-highlight-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.log-highlight-heading { font-size: 12px; font-weight: 750; }
.log-highlight-heading > span:last-child { color: var(--muted); font-size: 11px; font-weight: 600; }
.log-highlight-list { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
.log-highlight-rule {
  display: grid;
  grid-template-columns: minmax(90px, 1fr) 132px 36px 22px;
  align-items: center;
  gap: 6px;
}
.log-highlight-rule-text { width: 100%; min-width: 0; height: 30px; padding: 0 8px; font-size: 11px; }
.log-highlight-rule-preset { min-width: 0; overflow: hidden; color: var(--text); font-size: 11px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.log-highlight-rule-column { width: 132px; min-width: 0; }
.log-highlight-rule-column .te-combo-trigger { height: 30px; min-height: 30px; padding: 0 7px; }
.log-highlight-rule-column .te-combo-trigger-label { font-size: 11px; font-weight: 650; }
.log-highlight-rule-column .te-combo-pop { min-width: 180px; }
.log-highlight-rule-color.ui-color-input { width: 36px; height: 26px; }
.log-highlight-rule-remove.ui-btn-icon { --ui-btn-h: 22px; width: 22px; height: 22px; }
.log-highlight-empty { padding: 8px 2px; color: var(--muted); font-size: 11px; }
.log-highlight-actions { padding-top: 7px; border-top: 1px solid var(--line); }
.log-count {
  margin-left: auto;
  color: var(--muted);
  font-size: 12px;
  font-weight: 700;
}
.log-table {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin: 8px 10px 10px;
  border-radius: var(--r-card);
  /* More columns than the window is wide: the head and the feed move sideways together. */
  overflow: auto hidden;
  background: var(--panel);
}
.log-head,
.log-row {
  display: grid;
  /* The columns shown, as the Logs tab's column picker sets them (LogTab.tsx), and a last narrow
     track for that picker at the end of the header. */
  --log-columns-picker: 19px;
  grid-template-columns: var(--log-columns, 108px minmax(0, 1fr));
  align-items: center;
  gap: 8px;
}
.log-head-cell,
.log-row > span {
  min-width: 0;
}
.log-head {
  min-height: 32px;
  padding: 0 10px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  flex-shrink: 0;
}
.log-head-cell {
  position: relative;
  display: flex;
  align-items: center;
  gap: 3px;
  overflow: visible;
}
.log-head-cell > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.log-column-filter { display: inline-flex; flex: 0 0 auto; }
.log-column-filter-trigger.ui-btn-icon {
  --ui-btn-h: 19px;
  width: 19px;
  height: 19px;
  color: var(--muted);
  opacity: 0.65;
}
.log-head-cell:hover .log-column-filter-trigger,
.log-column-filter-trigger.selected,
.log-column-filter-trigger:focus-visible { opacity: 1; }
/* The column picker, at the end of the header: a glyph like the filters', its list in plain type. */
/* The picker of columns keeps to the table's right edge when the table is moved sideways: it is how
   a column that does not fit is taken away again. */
.log-head-columns { justify-content: flex-end; position: sticky; right: 0; z-index: 2; align-self: stretch; margin-right: -10px; padding: 0 10px 0 6px; background: var(--panel-2); }
.log-head-columns .te-combo-icon-trigger.ui-btn-icon {
  --ui-btn-h: 19px;
  width: 19px;
  height: 19px;
  color: var(--muted);
}
.log-head-columns .te-combo-pop {
  min-width: 248px;
  text-transform: none;
  letter-spacing: 0;
  font-size: 12px;
  font-weight: 500;
}
.log-column-filter-trigger.selected { color: var(--accent); }
.log-column-filter-pop {
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: 5px;
  max-height: min(340px, calc(100vh - 16px));
  padding: 8px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text);
  font-size: 12px;
  font-weight: 500;
}
.log-column-filter-search { width: 100%; min-width: 0; padding: 5px 8px; font-size: 11px; }
.log-column-filter-apply { justify-content: flex-start; width: 100%; padding-inline: 8px; }
.log-column-filter-heading {
  padding: 3px 2px 0;
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.log-column-filter-values { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.log-column-filter-option { min-height: 27px; padding: 4px 6px; }
.log-column-filter-check {
  display: inline-flex;
  flex: 0 0 14px;
  width: 14px;
  height: 14px;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-chip);
  background: var(--plate);
  color: var(--ink);
  font-size: 10px;
  font-weight: 900;
}
.log-column-filter-option[aria-checked="true"] .log-column-filter-check { background: var(--accent); }
.log-column-filter-value { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log-column-filter-count { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.log-column-filter-actions { padding-top: 5px; border-top: 1px solid var(--line); }
.log-head, .log-body { min-width: var(--log-min-width, 0); }
.log-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* The feed keeps the reader's place itself (virtualFeed.ts); the browser must not do it a second time. */
  overflow-anchor: none;
}
.log-virtual-spacer {
  position: relative;
  min-height: 100%;
}
.log-row {
  position: absolute;
  left: 0;
  right: 0;
  min-height: 38px;
  height: 38px;
  /* One track of the row's own height: a cell that would be taller is cut, never drawn over the row below. */
  grid-template-rows: minmax(0, 1fr);
  padding: 5px 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 42%, transparent);
  overflow: hidden;
}
.log-row:hover { background: var(--plate-hover); }
.log-time {
  color: var(--muted);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 11px;
}
.log-domain,
.log-source,
.log-level {
  justify-content: center;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  background: color-mix(in srgb, var(--source-color, var(--line)) 14%, var(--panel));
  color: var(--source-color, var(--text));
  font-size: 11px;
  font-weight: 800;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.log-domain {
  background: color-mix(in srgb, var(--domain-color, var(--line)) 13%, var(--panel));
  color: color-mix(in srgb, var(--domain-color, var(--text)) 75%, var(--text));
}
.log-level {
  background: color-mix(in srgb, var(--level-color, var(--line)) 14%, var(--panel));
  color: var(--level-color, var(--muted));
  text-transform: uppercase;
}
.log-message {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 2px;
}
.log-message > span:first-child,
.log-wire {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.log-message > span:first-child {
  color: var(--text);
  font-size: 12px;
  font-weight: 650;
}
.log-meta {
  display: flex;
  align-items: center;
  gap: 5px;
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.3px;
  /* One line, whatever the column's width: a second line would make the row taller than its place in
     the feed and push it over the next. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.log-wire {
  color: var(--muted);
  font-family: 'SF Mono', 'Fira Code', Consolas, monospace;
  font-size: 11px;
}
.log-command {
  display: flex;
  gap: 2px;
  min-width: 0;
}
.log-copy-button.ui-btn-icon { --ui-btn-h: 23px; width: 23px; height: 23px; color: var(--muted); }
.log-copy-button:hover:not(:disabled) { color: var(--accent); }
.log-empty {
  padding: 32px;
  color: var(--muted);
  font-size: 13px;
  text-align: center;
}

.source-gvg { --source-color: var(--source-gvg); }
.source-sony { --source-color: var(--source-sony); }
.source-obs { --source-color: var(--source-obs); }
.source-calrec { --source-color: var(--source-calrec); }
.source-studer { --source-color: var(--source-studer); }
.source-dhd { --source-color: var(--source-dhd); }
.source-fxmotion { --source-color: var(--source-fxmotion); }
.source-telemetrics { --source-color: var(--source-telemetrics); }
.source-vizengine { --source-color: var(--source-vizengine); }
.source-mse { --source-color: var(--source-mse); }
.source-bigviz { --source-color: var(--source-bigviz); }
.source-lottie { --source-color: var(--source-lottie); }
.source-airspeed { --source-color: var(--source-airspeed); }
.source-quantel { --source-color: var(--source-quantel); }
.source-mos { --source-color: var(--source-mos); }
.source-templates { --source-color: var(--source-templates); }
.source-settings { --source-color: var(--source-settings); }
.source-system { --source-color: var(--source-system); }

.domain-video-mixer { --domain-color: var(--domain-video-mixer); }
.domain-audio-mixer { --domain-color: var(--domain-audio-mixer); }
.domain-video-server { --domain-color: var(--domain-video-server); }
.domain-graphics { --domain-color: var(--domain-graphics); }
.domain-robotics { --domain-color: var(--domain-robotics); }
.domain-newsroom { --domain-color: var(--domain-newsroom); }
.domain-hotkey { --domain-color: var(--domain-hotkey); }
.domain-rundown { --domain-color: var(--domain-rundown); }
.domain-event { --domain-color: var(--domain-event); }
.domain-settings { --domain-color: var(--domain-settings); }
.domain-transport { --domain-color: var(--domain-transport); }
.domain-system { --domain-color: var(--domain-system); }

.level-info { --level-color: var(--accent); }
.level-warn { --level-color: var(--on); }
.level-error { --level-color: var(--pgm); }
.level-debug { --level-color: var(--muted); }
.source-cloud { --source-color: var(--source-cloud); }
.source-mcp { --source-color: var(--source-mcp); }
.source-flows { --source-color: var(--source-flows); }

/* A tenant, node or person on a log line, in its name's colour (NameChip.tsx), which is the one the
   launcher gives it. A person is a pill; a tenant or node a tag. */
.name-chip {
  display: inline-block;
  max-width: 220px;
  padding: 0 6px;
  border-radius: var(--r-control);
  font-size: 10px;
  font-weight: 750;
  line-height: 16px;
  letter-spacing: 0;
  text-transform: none;
  vertical-align: middle;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.name-chip-who { border-radius: var(--r-card); }

/* Highlighted rows — the area colour, or the chosen phrase colour, washes the row gently. Phrase
   matches also stack up to three narrow colour marks in the existing left padding. Text keeps its
   normal colours so warn/error rows still signal their own severity when highlighted. */
.log-row.log-highlight,
.sim-log-row.log-highlight {
  background: color-mix(in srgb, var(--log-highlight-color, var(--domain-color, var(--accent))) 13%, var(--panel));
}
.log-row.log-highlight:hover,
.sim-log-row.log-highlight:hover {
  background: color-mix(in srgb, var(--log-highlight-color, var(--domain-color, var(--accent))) 20%, var(--panel));
}
.log-row.log-highlight::before {
  content: '';
  position: absolute;
  z-index: 1;
  inset: 0 auto 0 0;
  width: var(--log-highlight-stripe-width, 0px);
  background: var(--log-highlight-stripes, transparent);
  pointer-events: none;
}
.log-row.log-highlight .log-message > span:first-child,
.sim-log-row.log-highlight .sim-log-message {
  font-weight: 800;
}
.log-word-highlight {
  padding: 0 1px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--log-word-color) 20%, transparent);
  color: var(--log-word-color) !important;
  font-weight: 850;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

@media (max-width: 980px) {
  .log-toolbar { flex-wrap: wrap; }
  .log-count { margin-left: 0; }
}

/* Log filters use the shared choices; the toolbar only sets their position and width. */
.log-views { flex-shrink: 0; }
.log-levels { display: inline-flex; gap: 3px; flex-shrink: 0; }
.log-level-toggle { min-width: 48px; }
.log-level-toggle:not(.selected) { background: transparent; color: var(--muted); }
/* A level shown takes the colour its lines have in the log (.level-*), so the button reads as them. */
.log-level-toggle.selected {
  background: color-mix(in srgb, var(--level-color) 34%, var(--panel));
  color: var(--level-color);
  font-weight: 800;
}
.log-level-toggle.selected:hover:not(:disabled) {
  background: color-mix(in srgb, var(--level-color) 42%, var(--panel));
}
.log-error { margin: 8px 14px 0; color: var(--pgm); font-size: 12px; }
.log-cell { min-width: 0; overflow: hidden; white-space: nowrap; }
/* Where a line happened, read like the path at the top: tenant, node, then the profiles it ran on. */
.log-where { display: flex; align-items: center; }
/* No step gives way to the next: each is read whole, and the cell cuts what does not fit at its end,
   where the hint says the rest. */
.log-where-step { display: inline-flex; align-items: center; flex: 0 0 auto; }
.log-where-step .path-step-arrow { margin: 0 4px; }
.log-where-step .name-chip { flex: 0 0 auto; max-width: none; }
.log-where-profile { display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto; color: var(--muted); font-size: 12px; white-space: nowrap; }
.log-where-profile .path-step-label { overflow: visible; }
.log-plain { color: var(--muted); font-size: 12px; text-overflow: ellipsis; }
.log-mono { font-family: 'SF Mono', 'Fira Code', Consolas, monospace; font-size: 11px; }

/* ─── Settings tab ────────────────────────────────────────────────────────────── */

.settings-root {
  flex: 1; display: flex; flex-direction: column; min-height: 0; background: var(--bg);
}

.settings-toolbar {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 16px; border-bottom: 1px solid var(--line);
  background: var(--panel); flex-shrink: 0;
}

.settings-search-wrap {
  position: relative; display: flex; align-items: center; flex: 1; max-width: 420px;
}
.settings-search-icon {
  position: absolute; left: 10px; color: var(--muted); font-size: 16px; pointer-events: none;
}
.settings-search {
  width: 100%; padding: 7px 32px 7px 32px; font-size: 13px;
}
.settings-search::placeholder { color: var(--muted); }
.settings-search-clear {
  position: absolute; right: 8px;
}


.settings-body {
  --settings-rail-col: 192px;
  --settings-props-col: 260px;
  /* How wide a map of two steps grows (keys onto shortcuts, channels onto virtual channels): wider,
     its cards turn into long thin bars. */
  --settings-map-width: 860px;
  flex: 1;
  display: grid;
  grid-template-columns: var(--settings-rail-col) minmax(0, 1fr);
  min-height: 0;
  overflow: hidden;
}

.settings-body.props-open {
  grid-template-columns: var(--settings-rail-col) minmax(0, 1fr) var(--settings-props-col);
}

/* Admin's rail a step wider, for a tenant's name beside its word; its edge drags it wider still. */
.admin-root .settings-body { --settings-rail-col: 224px; }
/* Left jump-nav rail: grouped, color-coded, scroll-spy highlights the current section. */
.settings-rail {
  min-width: 0;
  overflow-y: auto;
  padding: 16px 10px 32px 16px;
  border-right: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel) 55%, var(--bg));
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.settings-rail-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
  --group-color: var(--accent);
}
.settings-rail-group[data-group="Flows"] { --group-color: var(--category-flows); }
.settings-rail-group[data-group="Shortcuts"] { --group-color: var(--category-shortcuts); }
.settings-rail-group[data-group="This node"] { --group-color: var(--muted); }
.settings-rail-group[data-group="Format"] { --group-color: var(--accent); }
.settings-rail-group[data-group="Devices"] { --group-color: var(--accent); }
.settings-rail-group[data-group="Events"] { --group-color: var(--event-live); }
.settings-rail-group[data-group="Mapping"] { --group-color: var(--accent); }

/* Who holds a block of the rail: the set, the tenant or this node, a glaze of their colour behind
   everything they hold, and at its head their word in that colour and their name, as the status bar
   says them; a plate to open the set, or plain words where no set holds them. */
.settings-rail-block {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0 -4px;
  padding: 6px 4px 8px;
  border-radius: var(--r-card);
  background: color-mix(in srgb, var(--owner-color) 7%, transparent);
}
.settings-rail-owner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
  min-width: 0;
  height: 28px;
  margin-bottom: -6px;
  padding: 0 8px;
  border-radius: var(--r-control);
  /* A deeper band of the owner's colour, so the head reads apart from what it holds. */
  background: color-mix(in srgb, var(--owner-color) 9%, var(--bg));
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
}
.settings-rail-owner.ui-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--owner-color) 16%, var(--bg)); }
/* A step above the group headings it holds (10px), so the holder reads first. */
.settings-rail-owner b { flex: none; font-size: 11px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase; color: var(--owner-color); }
.settings-rail-owner > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  /* The holder's name, a chip at the band's right end. */
  padding: 2px 6px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--owner-color) 16%, var(--panel));
  font-size: 11px;
  font-weight: 700;
}
.settings-rail-group-head {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 0 5px 6px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: var(--group-color);
}
/* Within a holder's block, a hairline between one group and the next. */
.settings-rail-block .settings-rail-group + .settings-rail-group {
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.settings-rail-link {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  text-align: left;
  padding: 6px 8px;
  white-space: nowrap;
  overflow: hidden;
}
.settings-rail-link-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.settings-rail-count {
  margin-left: auto;
  min-width: 1.4em;
  color: color-mix(in srgb, var(--group-color) 68%, var(--muted));
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  font-weight: 800;
  text-align: right;
}
.settings-rail-link.active .settings-rail-count {
  color: var(--group-color);
}
/* Sections one thing holds, a design and its nodes: together on a glaze of its colour. */
.settings-rail-held {
  display: flex;
  flex-direction: column;
  margin: 6px 0 0;
  padding: 0 0 2px;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--held-color) 12%, transparent);
}
.settings-rail-held .settings-rail-owner { margin-bottom: 2px; background: none; }
/* The same on the page: what one thing holds, on its glaze. */
.settings-held {
  margin: 8px -12px 0;
  padding: 2px 12px 12px;
  border-radius: var(--r-card);
  background: color-mix(in srgb, var(--held-color) 7%, transparent);
}
.settings-held[hidden] { display: none; }
.settings-rail-held .settings-rail-count { color: var(--held-color); }
/* A rail whose edge can be dragged: the grip stands on its right edge. */
.settings-rail.sized { position: relative; }

.settings-content { min-width: 0; overflow-y: auto; padding: 16px 24px 72px; }

.settings-props-slot {
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  border-left: 1px solid var(--line);
  background: var(--panel);
}

.settings-no-results { color: var(--muted); font-size: 13px; padding: 32px 0; text-align: center; }

.settings-group {
  margin-bottom: 36px;
  --group-color: var(--accent);
}
.settings-group[data-group="Flows"] { --group-color: var(--category-flows); }
.settings-group[data-group="Shortcuts"] { --group-color: var(--category-shortcuts); }
.settings-group[data-group="This node"] { --group-color: var(--muted); }
.settings-group[data-group="Format"] { --group-color: var(--accent); }
.settings-group[data-group="Devices"] { --group-color: var(--accent); }
.settings-group[data-group="Events"] { --group-color: var(--event-live); }
.settings-group[data-group="Mapping"] { --group-color: var(--accent); }

.settings-group-head {
  /* Leave air above the held title, with the same glass tokens as the floating status panel. */
  position: sticky;
  top: 8px;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  padding: 11px 16px;
  border-radius: var(--r-card);
  background: color-mix(in srgb, var(--panel-2) 86%, transparent);
  text-align: left;
}
/* Held at the top, it turns to glass: what scrolls under it shows through, blurred, as the Status
   panel floats, but faintly, so its own words are the ones read. Only its look changes, never its
   size, so nothing moves. */
.settings-group-head.stuck {
  background: color-mix(in srgb, var(--panel-2) 92%, transparent);
  -webkit-backdrop-filter: var(--float-blur);
  backdrop-filter: var(--float-blur);
  box-shadow: var(--float-shadow);
}
.settings-group-head-text { display: flex; flex-direction: column; gap: 2px; }
.settings-group-head h1 {
  margin: 0;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--text);
}
.settings-group-head p {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
}

.cfg-section { margin-bottom: 26px; scroll-margin-top: 12px; }
.cfg-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--muted); margin-bottom: 12px; padding-bottom: 6px; text-align: left;
  border-bottom: 1px solid var(--line);
}

.cfg-mapping-stack {
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.cfg-mapping-category {
  min-width: 0;
}

.cfg-mapping-category + .cfg-mapping-category {
  padding-top: 18px;
  border-top: 1px solid color-mix(in srgb, var(--line) 72%, transparent);
}

.cfg-mapping-category-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  color: var(--text);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.6px;
}

.cfg-mapping-category-title::before {
  content: '';
  flex-shrink: 0;
  width: 5px;
  height: 18px;
  border-radius: var(--r-pill);
  background: var(--group-color, var(--accent));
}

/* Double-click-to-rename label, used in place of separate "Name" fields. */
.inline-rename {
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  padding: 0 3px;
}
.inline-rename:hover {
  background: color-mix(in srgb, var(--text) 9%, transparent);
  box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--accent) 55%, transparent);
}
.inline-rename-input {
  box-sizing: border-box;
  width: 100%;
  padding: 0 4px;
  margin: -1px 0;
  height: 1.5em;
  border: 0;
  border-radius: var(--r-control);
}
.cfg-device-name {
  align-self: flex-start;
  max-width: 100%;
  font-size: 14px;
  font-weight: 750;
  color: var(--text);
}
.cfg-device-name.inline-rename { padding-left: 0; }
.cfg-device-name.inline-rename-input { max-width: 100%; }

/* Mapped items inside a virtual card, stacked downward as chips. */
.cfg-card-chips {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  width: 100%;
  max-width: calc(100% - 12px);
  margin-top: 1px;
}
.cfg-card-chip {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  border: 0;
  background: color-mix(in srgb, var(--link-color, var(--accent)) 16%, var(--bg));
  color: var(--text);
  border-radius: var(--r-control);
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 800;
  line-height: 1.5;
}
.cfg-card-chip[draggable="true"] { cursor: grab; }
.cfg-card-chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cfg-card-chip-rm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 15px;
  height: 15px;
  padding: 0;
  border: 0;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--panel) 70%, transparent);
  color: var(--muted);
  cursor: pointer;
  font-size: 12px;
  font-weight: 900;
  line-height: 1;
  /* Same reasoning as .cfg-room-reset { padding: 2px 8px; font-size: 11px; }
.cfg-room-remove: a × on every chip at once is noise, hover is the reveal. */
  opacity: 0;
  transition: opacity 0.1s ease;
}

.cfg-card-chip:hover .cfg-card-chip-rm,
.cfg-card-chip-rm:focus-visible {
  opacity: 1;
}
.cfg-card-chip-rm:hover {
  background: var(--pgm);
  color: var(--on-fill);
}
.cfg-link-card.has-chips {
  height: auto;
  min-height: var(--cfg-link-row-height, 46px);
  /* Its own height and never less. A list long enough to scroll squeezed every card to fit instead,
     and the chips climbed over the card's name. */
  flex: 0 0 auto;
  justify-content: flex-start;
  padding-top: 8px;
  padding-bottom: 8px;
}

.cfg-inspector-note {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
}

.cfg-link-pill.inherit-count {
  color: var(--text);
  background: color-mix(in srgb, var(--event-color, var(--accent)) 20%, transparent);
}

.cfg-inherit-inline-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 18px;
  padding: 0 7px;
  border: 0;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--event-color, var(--accent)) 18%, transparent);
  color: var(--text);
  font-size: 10px;
  font-weight: 850;
  letter-spacing: 0;
  line-height: 1;
  text-transform: none;
}

.cfg-field-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.cfg-field-label {
  min-width: 110px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.cfg-note {
  margin: 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
}

.cfg-runtime {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: var(--settings-map-width);
}
.cfg-failover {
  max-width: 980px;
}
/* Rows under a section's cards (This node's timings, the Reference's): a gap between the two. */
.cfg-runtime-after { margin-top: 14px; }
.cfg-rooms {
  max-width: 980px;
}
.cfg-runtime .vcfg-row {
  background: var(--plate);
  border-radius: var(--r-control);
}
.cfg-runtime .cfg-field-row {
  margin-bottom: 0;
}

/* Shortcuts: one row per action, its keys to the right, read left to right: the action, the key,
   what the key brings in. */
.cfg-keymap {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Shortcuts, mapped as channels are (components/ui/ChannelLinker.tsx): keys onto the room's own
   named shortcuts. A key waiting to be pressed lights its add card. */
.cfg-link-card.cfg-link-add-card.capturing { background: var(--plate-selected); }

.cfg-keymap-kbd {
  flex: none;
  min-width: 26px;
  padding: 2px 7px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--text);
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 11px;
  font-weight: 800;
  text-align: center;
}

.cfg-keymap-detail { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
/* What a key brings in: the standard choice, as Frame clock's, one option under the other. */
.cfg-keymap-brings .ui-seg { flex-direction: column; align-items: stretch; }
.cfg-keymap-brings .ui-seg-btn { text-align: left; }
.cfg-keymap-slot { justify-content: space-between; }
/* One step to the next in a properties pane, top to bottom: an arrow with room on both sides, as
   the page's arrow between two columns. What is not a step (a colour) sits under a rule. */
.cfg-props-down { color: var(--muted); font-size: 15px; font-weight: 800; text-align: center; line-height: 1; padding: 6px 0; }
.cfg-props-rule { height: 1px; margin: 6px 0; background: var(--line); }
.cfg-keymap-detail .cfg-node-field { gap: 8px; }

.cfg-key-default {
  min-height: 32px;
}

.cfg-room-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 76px;
  gap: 10px;
}

/* A room, an arrow, and what the room holds: every group of settings under it is that room's own. */
.cfg-room-linker { max-width: 980px; }
.cfg-room-linker .cfg-link-card.cfg-room-card,
.cfg-room-linker .cfg-link-card.cfg-room-add-chip { height: auto; min-height: 46px; }
.cfg-link-card.cfg-room-holds { cursor: pointer; }
/* A card's count, the same pill as a column title's, at the card's right. */
.cfg-link-card.cfg-card-counted { padding-right: 44px; }
.cfg-link-card > .cfg-card-count { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); }
/* In the rail's colours for the three groups. */
.cfg-link-card.cfg-room-holds { background: color-mix(in srgb, var(--group-color, var(--accent)) 10%, var(--plate)); }
.cfg-link-card.cfg-room-holds[data-group="Devices"] { --group-color: var(--pst); }
.cfg-link-card.cfg-room-holds[data-group="Mapping"] { --group-color: var(--on); }
.cfg-link-card.cfg-room-holds[data-group="Events"] { --group-color: var(--event-group); }
.cfg-room-reset-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.settings-group-room {
  margin-left: 10px;
  padding: 1px 8px;
  background: var(--plate);
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  vertical-align: middle;
}

.cfg-link-card.cfg-room-card,
.cfg-link-card.cfg-room-add-chip {
  height: 100%;
  min-height: 0;
  flex: initial;
}

.cfg-link-card.cfg-room-card {
  background: color-mix(in srgb, var(--panel-2) 68%, var(--bg));
}

.cfg-link-card.cfg-room-card .cfg-link-pill {
  top: auto;
  bottom: 8px;
}

.cfg-room-remove {
  position: absolute;
  top: 8px;
  right: 8px;
  /* Above .cfg-link-pill's z-index: 1, or the "open" pill paints over this button wherever the two
     corners are close enough to overlap, making it unclickable rather than merely hard to see. */
  z-index: 2;
  /* Sitting on every card at once reads as clutter rather than a control; appearing on hover is
     what tells you it belongs to the card your pointer is over. */
  opacity: 0;
  transition: opacity 0.1s ease;
}

.cfg-link-card:hover .cfg-room-remove,
.cfg-room-remove:focus-visible {
  opacity: 1;
}


/* Delete button on mapping cards. */
.cfg-card-remove {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 4;
  opacity: 0;
  pointer-events: auto;
  transition: opacity 0.1s;
}
.cfg-link-card:hover .cfg-card-remove,
.cfg-link-card:focus-within .cfg-card-remove,
.cfg-card-remove:focus-visible {
  opacity: 1;
}
.cfg-endpoint { display: flex; flex-direction: column; gap: 8px; }
.cfg-endpoint-header { display: flex; align-items: baseline; gap: 10px; }
.cfg-endpoint-label { font-size: 13px; font-weight: 600; color: var(--text); }
.cfg-endpoint-desc { font-size: 11px; color: var(--muted); }

.cfg-endpoint-row { display: flex; align-items: center; gap: 10px; }

.cfg-serial {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.cfg-serial .vcfg-port-sel {
  min-width: 180px;
}

/* --- Toggle switch --- */
/* The one switch (ui/Toggle.tsx), the one size: 30 by 16 wherever it is. */
.toggle-label {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  cursor: pointer;
  user-select: none;
  font-size: 12px;
}
.toggle-input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.toggle-track {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
  box-sizing: border-box;
  width: 30px;
  height: 16px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--panel) 72%, var(--bg));
  box-shadow: none;
  transition: background 0.16s, border-color 0.16s, box-shadow 0.16s;
}
.toggle-track::after {
  content: '';
  position: absolute;
  top: 1px;
  left: 1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--text);
  transition: left 0.16s, background 0.16s;
}
.toggle-input:checked + .toggle-track {
  background: color-mix(in srgb, var(--accent) 62%, var(--panel));
  box-shadow: none;
}
.toggle-input:checked + .toggle-track::after {
  left: 15px;
  background: var(--text);
}
.toggle-warn .toggle-input:checked + .toggle-track {
  background: color-mix(in srgb, var(--warn) 70%, var(--panel));
  box-shadow: none;
}
.toggle-warn .toggle-input:checked + .toggle-track::after { background: var(--bg); }
.toggle-input:disabled + .toggle-track { opacity: 0.45; }
.toggle-input:focus-visible + .toggle-track {
  outline: 2px solid var(--focus-line);
  outline-offset: 1px;
}

.cfg-sim-toggle { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.cfg-sim-badge {
  font-size: 11px; font-weight: 700; letter-spacing: 0.4px;
  border-radius: var(--r-control); padding: 3px 8px;
}
.cfg-sim-badge.sim   { color: var(--pst); background: color-mix(in srgb, var(--pst) 14%, var(--panel)); }
.cfg-sim-badge.real  { color: var(--on); background: color-mix(in srgb, var(--on) 14%, var(--panel)); }

.cfg-host { width: 140px; }

.cfg-sim-endpoint {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: 32px;
  min-width: 162px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--panel-2);
  color: var(--text);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.cfg-sim-endpoint span {
  color: var(--muted);
}
.cfg-sim-endpoint strong {
  color: var(--text);
  font-weight: 800;
}

.cfg-number-field {
  position: relative;
  display: inline-grid;
  grid-template-columns: minmax(0, 1fr) 22px;
  align-items: stretch;
  height: 32px;
  min-width: 76px;
  overflow: hidden;
  border: 0;
  border-radius: var(--r-control);
  background: var(--field);
  color: var(--text);
  transition: background 0.16s, opacity 0.16s;
}
.cfg-number-field .cfg-number-value {
  min-width: 0;
  width: 100%;
  height: 100%;
  min-height: 0;
  border-radius: 0;
  background: transparent;
  padding: 5px 8px;
  font-size: 12px;
}
.cfg-number-field .cfg-number-value:focus { outline: none; }
.cfg-number-field:focus-within {
  outline: 2px solid var(--focus-line);
  outline-offset: 1px;
}
.cfg-number-field.disabled { opacity: 0.35; }
.cfg-number-stepper {
  display: grid;
  grid-template-rows: 1fr 1fr;
  border-left: 1px solid color-mix(in srgb, var(--line) 85%, transparent);
  background: color-mix(in srgb, var(--panel) 72%, var(--bg));
}
.cfg-number-stepper .cfg-number-step {
  --ui-btn-h: 100%;
  display: grid;
  place-items: center;
  width: 100%;
  min-width: 0;
  padding: 0;
  border-radius: 0;
}
.cfg-number-stepper .cfg-number-step + .cfg-number-step {
  border-top: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.cfg-step-arrow {
  width: 8px;
  height: 5px;
}
.cfg-step-arrow.up { clip-path: polygon(0 100%, 50% 0, 100% 100%); background: currentColor; }
.cfg-step-arrow.down { clip-path: polygon(0 0, 100% 0, 50% 100%); background: currentColor; }
.cfg-port {
  width: 82px;
  flex: 0 0 auto;
}

.cfg-primary-number {
  width: 150px;
  height: auto;
  padding: 9px 12px;
  font-size: 26px;
  font-weight: 850;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}


.cfg-select {
  background: var(--field);
  border: 0;
  color: var(--text);
  border-radius: var(--r-control);
  padding: 5px 8px;
  font-size: 12px;
  min-width: 116px;
}
.cfg-select.wide {
  min-width: 180px;
}
.cfg-select:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; }


.cfg-map {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 880px;
}
.cfg-map.compact {
  max-width: 520px;
}
.cfg-map-head,
.cfg-map-row {
  display: grid;
  align-items: center;
  gap: 8px;
}
.cfg-map-head {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  padding: 0 8px;
}
.cfg-map-row {
  background: var(--plate);
  border-radius: var(--r-control);
  padding: 7px 8px;
}
.cfg-map-rolls {
  grid-template-columns: minmax(130px, 1.2fr) 112px 92px 132px 28px;
}
.cfg-map-two {
  grid-template-columns: minmax(170px, 1fr) 96px 28px;
}
.cfg-row-btn {
  width: 28px;
  height: 28px;
}
.cfg-add-row {
  border: 1px solid transparent;
  background: var(--plate);
  color: var(--muted);
  border-radius: var(--r-control);
  cursor: pointer;
  font-weight: 800;
}
.cfg-add-row {
  align-self: flex-start;
  padding: 6px 10px;
  font-size: 12px;
}
.cfg-add-row:hover { color: var(--text); background: var(--plate-hover); }

.cfg-device-inventory {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 1120px;
}

.cfg-device-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.cfg-device-group-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.cfg-device-group-head > span {
  color: var(--text);
  font-size: 13px;
  font-weight: 800;
  min-width: 112px;
}

.cfg-device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  align-items: stretch;
  gap: 10px;
}

/* A device card is the device at a glance: on or off, its state, its name, how it is reached. The
   rest is in its properties. */
.cfg-device-card,
.cfg-device-add-chip {
  --cfg-device-card-min-height: 112px;
}

.cfg-device-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  min-height: var(--cfg-device-card-min-height);
}
.cfg-device-card.search-hit { background: color-mix(in srgb, var(--warn) 18%, var(--plate)); }
.cfg-device-card.selected.search-hit { background: color-mix(in srgb, var(--warn) 28%, var(--plate-selected)); }
.cfg-device-summary {
  color: var(--muted);
  font-size: 11px;
  font-family: 'SF Mono', 'Fira Code', monospace;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cfg-device-card-warn {
  margin-top: auto;
  color: var(--warn);
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cfg-device-failover { --cfg-device-card-min-height: 130px; }

/* A device's properties, in groups; a group with nothing in it for this device is not shown. */
.cfg-device-fields { display: flex; flex-direction: column; gap: 14px; }
.cfg-device-fields[hidden] { display: none; }
.cfg-device-props-group { display: flex; flex-direction: column; gap: 8px; }
.cfg-device-props-group:has(> .cfg-device-props-body:empty) { display: none; }
.cfg-device-props-title {
  color: var(--muted);
  font-size: 10px;
  font-weight: 850;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.cfg-device-props-body { display: flex; flex-direction: column; gap: 10px; }
.cfg-device-fields .cfg-device-protocol { flex-wrap: wrap; }

.cfg-device-card.primary {
}

.cfg-device-card.disabled {
  opacity: 0.62;
}

.cfg-device-card-top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cfg-device-card-top .cfg-row-btn {
  margin-left: auto;
}

.cfg-runtime-action {
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.6px;
  text-transform: uppercase;
}

.cfg-runtime-action.active {
  color: var(--pst);
}

.cfg-runtime-action.idle {
  color: var(--accent);
}

.cfg-runtime-action.unavailable {
  color: var(--pgm);
}

.cfg-device-enabled {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
}

.cfg-failover-self {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cfg-device-protocol {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.cfg-ai-instructions-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.cfg-ai-instructions-field .ui-textarea { width: 100%; }

/* Transfer agents nested inside an asset-management device card (MSE + Engines pattern). */
.cfg-mam-agents {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.cfg-mam-agent {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 9px 10px;
  border-radius: var(--r-control);
  background: var(--plate);
}
.cfg-mam-agent.disabled {
  opacity: 0.55;
}
.cfg-mam-agent-top {
  display: flex;
  align-items: center;
  gap: 10px;
}
.cfg-mam-agent-name {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 600;
}
/* OBS additional clip-folder list (extra scan paths, e.g. Kelda storage). */
.cfg-clip-folders {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.cfg-clip-folder-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.cfg-clip-folder-row > .cfg-host {
  flex: 1 1 auto;
  min-width: 0;
}
/* Collapsed advanced sections (rarely-changed MOS ports / NCS identity). */
.cfg-mam-advanced {
  margin-top: 2px;
}
.cfg-mam-advanced > summary {
  cursor: pointer;
  font-size: 11px;
  color: var(--muted);
  padding: 4px 0;
  user-select: none;
}
.cfg-mam-advanced > summary:hover {
  color: var(--text);
}
.cfg-mam-advanced[open] > summary {
  margin-bottom: 6px;
}

.cfg-device-instructions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 9px 10px;
  border-radius: var(--r-control);
  background: var(--plate);
}

.cfg-device-instructions-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
}

.cfg-ai-platform-tabs {
  display: flex;
  gap: 2px;
  padding: 2px;
  border-radius: var(--r-control);
  background: var(--panel);
}

.cfg-device-instructions ul {
  margin: 0;
  padding-left: 16px;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.35;
}

.cfg-device-warning {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 9px 11px;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--warn) 16%, var(--panel));
}

.cfg-device-warning-title {
  color: color-mix(in srgb, var(--warn) 88%, var(--text));
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.3px;
}

.cfg-device-warning-body {
  color: var(--text);
  font-size: 11px;
  line-height: 1.4;
}

.cfg-device-warning-body strong {
  color: color-mix(in srgb, var(--warn) 70%, var(--text));
  font-weight: 800;
}

.cfg-device-instructions li {
  overflow-wrap: anywhere;
}

.cfg-device-instructions code {
  padding: 1px 4px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
  color: var(--text);
  font: 10px ui-monospace, SFMono-Regular, Menlo, monospace;
}

.cfg-device-instructions li + li {
  margin-top: 4px;
}

.cfg-device-sim-option .toggle-label {
  color: var(--text);
  font-size: 12px;
  font-weight: 700;
}

.cfg-device-field-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
}

.cfg-device-card .cfg-endpoint,
.cfg-device-fields .cfg-endpoint {
  gap: 6px;
}

.cfg-device-card .cfg-endpoint-header,
.cfg-device-fields .cfg-endpoint-header {
  display: none;
}

.cfg-device-card .cfg-endpoint-row,
.cfg-device-fields .cfg-endpoint-row {
  flex-wrap: wrap;
}

.cfg-linker {
  --cfg-link-row-height: 46px;
  --cfg-link-row-gap: 7px;
  display: grid;
  grid-template-columns: minmax(190px, 0.9fr) 24px minmax(220px, 1fr) 24px minmax(260px, 1fr);
  align-items: start;
  gap: 10px;
  max-width: 1120px;
}

.settings-map-with-props {
  display: block;
  max-width: none;
}

.settings-map-with-props .cfg-linker {
  grid-template-columns: minmax(190px, 0.9fr) 24px minmax(220px, 1fr);
  max-width: var(--settings-map-width);
}

.settings-props-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 100%;
  overflow: hidden;
  border: 0;
  border-radius: 0;
  background: var(--panel);
}

.settings-props-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 48px;
  padding: 11px 12px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: 10px;
  font-weight: 850;
  letter-spacing: 3px;
  text-transform: uppercase;
}

.settings-props-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px;
}

.settings-props-empty {
  color: var(--muted);
  font-size: 12px;
  font-style: italic;
  padding: 6px 0;
}

.cfg-linker-empty {
  min-height: 90px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.cfg-linker-empty .setup-hint {
  flex: 1 1 280px;
  max-width: 560px;
}

.cfg-link-col,
.cfg-inspector,
.cfg-audio-available,
.cfg-fader-strip,
.cfg-me-link {
  background: var(--plate);
  border-radius: var(--r-control);
}

.cfg-link-col,
.cfg-inspector,
.cfg-audio-available {
  padding: 10px;
}

.cfg-inspector-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}

.cfg-inspector-head .cfg-link-title {
  margin-bottom: 0;
}

.cfg-inspector-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.cfg-link-title {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  margin-bottom: 8px;
}

.cfg-link-title-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 17px;
  height: 15px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--text) 15%, transparent);
  color: var(--text);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

.cfg-offline-toggle {
  margin-left: auto;
  text-transform: uppercase;
}
.cfg-offline-toggle.selected:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 24%, var(--panel));
  color: var(--accent);
}
.cfg-offline-toggle.selected:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 32%, var(--panel));
}

.cfg-link-col > .ui-seg {
  margin-bottom: 8px;
}

.cfg-link-filter {
  display: flex;
  justify-content: center;
  margin: -2px 0 8px;
}

.cfg-section-filter {
  display: flex;
  margin: -4px 0 16px;
}

.cfg-link-title-badge {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 2px 6px;
  border-radius: var(--r-chip);
  border: 0;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent);
}

.cfg-link-title-badge.device-mode {
  max-width: 170px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cfg-link-title-badge.device-mode.mirror {
  color: var(--pst);
  background: color-mix(in srgb, var(--pst) 18%, transparent);
}

.cfg-link-title-badge.device-mode.failover {
  color: var(--takeout);
  background: color-mix(in srgb, var(--takeout) 18%, transparent);
}

.cfg-proto-tabs {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border-radius: var(--r-control);
  background: var(--panel-2);
}

.cfg-proto-tab {
  min-height: 24px;
  border: 0;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
}

.cfg-proto-tab:hover {
  color: var(--text);
}

.cfg-proto-tab.active {
  background: var(--accent);
  color: var(--ink);
}

.cfg-link-list {
  display: flex;
  flex-direction: column;
  gap: var(--cfg-link-row-gap);
  min-height: 0;
}

.cfg-linker .cfg-link-list:not(.horizontal) {
  max-height: calc((var(--cfg-link-row-height) * 10) + (var(--cfg-link-row-gap) * 9));
  overflow-y: auto;
  padding-right: 2px;
}

.cfg-link-list.horizontal {
  flex-direction: row;
  flex-wrap: wrap;
}

.cfg-link-card {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: var(--cfg-link-row-height, 46px);
  min-height: var(--cfg-link-row-height, 46px);
  display: flex;
  flex: 0 0 var(--cfg-link-row-height, 46px);
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  color: var(--text);
  padding: 8px 10px;
  text-align: left;
}

.cfg-link-card:has(.cfg-card-enable) {
  padding-left: 48px;
}

.cfg-link-card.disabled {
  opacity: 0.48;
}

.cfg-card-enable {
  position: absolute;
  left: 9px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 30px;
  height: 22px;
  border: 1px solid transparent;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--muted);
  cursor: pointer;
  font-size: 8px;
  font-weight: 900;
  letter-spacing: 0.4px;
}

.cfg-card-enable.active {
  background: color-mix(in srgb, var(--card-enable-color, var(--pst)) 12%, transparent);
  color: var(--card-enable-color, var(--pst));
}

.cfg-card-enable:hover {
  color: var(--accent);
  background: var(--plate-hover);
}

.cfg-link-card.cfg-device-add-chip {
  height: auto;
  min-height: var(--cfg-device-card-min-height);
  flex: initial;
  align-self: stretch;
  justify-content: center;
  padding: 10px;
}

.cfg-link-add-card {
  border: 1px dashed color-mix(in srgb, var(--line) 85%, transparent);
  color: var(--muted);
  background: transparent;
}

.cfg-link-add-card:hover {
  color: var(--text);
}

/* In an empty column the add card is the only thing on screen. Keep it the same
   full-width, chip-height card it becomes once real chips exist, instead of
   collapsing to a 46px square (the row flex would otherwise treat the card's
   flex-basis as its width). */
.cfg-linker-empty .cfg-link-add-card {
  flex: 0 0 auto;
  width: min(100%, 360px);
}

.cfg-link-card[draggable="true"] {
  cursor: grab;
}

.cfg-link-card[draggable="true"]:active {
  cursor: grabbing;
  opacity: 0.86;
  transform: scale(0.99);
}

/* A card that says more under its name than one line grows to hold it, as one with chips does. */
.cfg-link-card.has-sub {
  height: auto;
  min-height: var(--cfg-link-row-height, 46px);
  flex: 0 0 auto;
}

.cfg-link-card.colored {
  --card-enable-color: var(--link-color, var(--pst));
  background: color-mix(in srgb, var(--link-color, var(--accent)) 24%, var(--panel));
}

.cfg-link-card.colored:hover {
  background: color-mix(in srgb, var(--link-color, var(--accent)) 29%, var(--panel));
}

.cfg-link-card.colored.selected {
  background: color-mix(in srgb, var(--link-color, var(--accent)) 34%, var(--panel));
}

.cfg-event-card {
  --card-enable-color: var(--event-color, var(--pst));
}

.cfg-event-card.selected {
  background: color-mix(in srgb, var(--event-color) 22%, var(--panel));
}

/* A physical card gets an accent plate only while it is the open properties selection. */
.cfg-link-card.cfg-link-physical.selected {
  background: color-mix(in srgb, var(--accent) 14%, var(--panel));
}

/* Tenant identity follows the same chosen or automatic colour in Control plane and launcher. */
.cfg-link-card.admin-tenant-color {
  --card-enable-color: var(--link-color);
  background: color-mix(in srgb, var(--link-color) 10%, var(--panel));
}

.cfg-link-card.admin-tenant-color:hover {
  background: color-mix(in srgb, var(--link-color) 16%, var(--panel));
}

.cfg-link-card.admin-tenant-color.selected {
  background: color-mix(in srgb, var(--link-color) 24%, var(--panel));
}

.cfg-link-card.admin-tenant-color::before {
  content: '';
  position: absolute;
  top: 7px;
  bottom: 7px;
  left: 0;
  width: 4px;
  border-radius: 0 3px 3px 0;
  background: var(--link-color);
  pointer-events: none;
}
.admin-group-color-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.admin-group-color-row .ui-color-input {
  width: 44px;
  height: 32px;
}

.cfg-link-card-main {
  max-width: calc(100% - 58px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  font-weight: 750;
  line-height: 1.2;
}

.cfg-link-card-main.inline-rename {
  padding-left: 0;
}

.cfg-link-card-sub {
  max-width: calc(100% - 58px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.2;
}

.cfg-link-card:has(.cfg-link-pill) .cfg-link-card-sub {
  max-width: calc(100% - 84px);
}

.cfg-link-card:has(.cfg-link-status-pills) .cfg-link-card-sub {
  max-width: calc(100% - 126px);
}

.cfg-link-add-card .cfg-link-card-main,
.cfg-link-add-card .cfg-link-card-sub {
  max-width: calc(100% - 42px);
}

.cfg-link-status-pills {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 58%;
}

.cfg-link-status-pills .cfg-link-pill {
  position: static;
  max-width: none;
}

.cfg-link-pill {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 1;
  background: color-mix(in srgb, var(--muted) 16%, var(--panel-2));
  color: var(--muted);
  border: 0;
  border-radius: var(--r-pill);
  padding: 1px 6px;
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
  max-width: 42%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cfg-link-pill.mapped {
  color: var(--ink);
  background: color-mix(in srgb, var(--link-color, var(--on)) 84%, white);
}

.cfg-link-pill.primary-type {
  color: var(--text);
  background: color-mix(in srgb, var(--accent) 38%, var(--bg));
}
.cfg-link-pill.insert-type {
  color: var(--text);
  background: color-mix(in srgb, var(--warn) 30%, var(--bg));
}

.cfg-link-pill.secondary-type {
  color: var(--text);
  background: color-mix(in srgb, var(--on) 36%, var(--bg));
}

.cfg-link-pill.free {
  color: var(--muted);
}

.cfg-link-drop {
  position: absolute;
  right: 8px;
  bottom: 7px;
  color: var(--muted);
  border: 1px dashed color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: var(--r-control);
  padding: 2px 6px;
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
}

.cfg-link-drop.plus {
  min-width: 22px;
  text-align: center;
  color: var(--text);
  background: var(--plate);
}

.cfg-link-card.drop-ready {
  background: color-mix(in srgb, var(--accent) 12%, color-mix(in srgb, var(--link-color, var(--accent)) 10%, var(--panel)));
  box-shadow: none;
}

.cfg-link-card.drop-ready::after {
  content: '';
  position: absolute;
  inset: 6px;
  border: 1px dashed color-mix(in srgb, var(--accent) 72%, transparent);
  border-radius: var(--r-control);
  pointer-events: none;
}

.cfg-link-card.drop-ready .cfg-card-chip {
  opacity: 0.74;
  transform: translateX(-2px);
}

.cfg-graphics-field-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.cfg-graphics-field-map {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: flex-end;
}

.cfg-graphics-field-map label {
  flex: 1 1 110px;
  min-width: 0;
}

.cfg-graphics-field-map .cfg-inspector-remove {
  flex: 0 0 26px;
}

.cfg-event-short-input {
  max-width: 120px;
}

.cfg-event-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.cfg-event-alias-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 7px;
  align-items: center;
}

.cfg-event-swatch-btn {
  --ui-swatch-size: 22px;
}

.cfg-event-detail-panel {
  min-width: 0;
}

/* Event-type inheritance picker: same event tree + "Inherits from" footer as the Events tab,
   slotted into the settings properties pane. */
.cfg-inherit-tree {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 260px;
  border-radius: var(--r-control);
  background: var(--plate);
  overflow: hidden;
}

.cfg-inherit-tree-list {
  flex: 1 1 auto;
  min-height: 0;
}

.te-list-item.inherited .te-item-name {
  color: var(--text);
  font-weight: 800;
}

.te-inherit-mark {
  justify-content: center;
  margin-left: auto;
  width: 22px;
  min-height: 22px;
  height: 22px;
  padding: 0;
  font-size: 12px;
  font-weight: 900;
}

.cfg-graphics-field-add {
  margin-top: 2px;
}

.cfg-link-arrow {
  align-self: start;
  /* col-padding(10) + title-line(15) + title-margin-bottom(8) + half-card(23) = 56px */
  padding-top: calc(10px + 15px + 8px + var(--cfg-link-row-height, 46px) / 2);
  color: var(--muted);
  font-weight: 800;
  text-align: center;
}

.cfg-link-arrow.small {
  padding-top: 0;
}

.cfg-field-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.cfg-field-stack label {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.cfg-field-stack label > span {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
}

.cfg-assigned-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.cfg-assigned-group > span {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
}

.cfg-assigned-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 28px;
}

.cfg-assigned-pill,
.cfg-empty-pill {
  min-height: 26px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--text);
  padding: 3px 7px;
  font-size: 11px;
  font-weight: 750;
}

.cfg-empty-pill {
  color: var(--muted);
  background: color-mix(in srgb, var(--muted) 9%, transparent);
}

.cfg-assigned-pill button {
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--muted);
  cursor: pointer;
  font-size: 10px;
  font-weight: 900;
  line-height: 1;
}

.cfg-assigned-pill button:hover {
  color: var(--on-fill);
  background: var(--pgm);
}

.cfg-inline {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cfg-me-linker {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 8px;
  max-width: 880px;
}

.cfg-me-link {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) 24px minmax(110px, 0.8fr);
  align-items: center;
  gap: 8px;
  padding: 8px;
}

.cfg-audio-linker {
  max-width: 1120px;
}

.cfg-physical-fader {
  min-width: 112px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-radius: var(--r-control);
  background: var(--plate);
  padding: 7px 9px;
  color: var(--text);
}

.cfg-physical-fader.linked { background: color-mix(in srgb, var(--pst) 14%, var(--plate)); }

.cfg-physical-fader span {
  font-weight: 750;
  font-size: 12px;
}

.cfg-physical-fader small {
  color: var(--muted);
  font-size: 10px;
}

.cfg-fader-board {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  overflow-x: auto;
  padding-bottom: 2px;
}

.cfg-fader-strip {
  position: relative;
  width: 94px;
  flex: 0 0 94px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  background: var(--panel);
  padding: 7px 5px;
}

.cfg-fader-strip.manual { background: color-mix(in srgb, var(--pst) 12%, var(--plate)); }

.cfg-fader-strip.mute {
  background: color-mix(in srgb, var(--pgm) 12%, var(--plate));
  opacity: 0.78;
}

.cfg-fader-strip .cfg-select {
  min-width: 0;
  width: 100%;
}

.strip-remove {
  position: absolute;
  right: 4px;
  top: 4px;
  width: 18px;
  height: 18px;
  font-size: 10px;
  opacity: 0.8;
}

.cfg-fader-name {
  width: 100%;
  height: 25px;
  padding: 4px 22px 4px 6px;
  text-align: center;
  font-size: 11px;
  font-weight: 750;
}

.cfg-fader-source {
  height: 24px;
  padding: 3px 5px;
  font-size: 10px;
}

.cfg-fader-source-label {
  width: 100%;
  color: var(--muted);
  font-size: 9px;
  font-weight: 750;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-transform: uppercase;
}

.cfg-fader-level-wrap {
  position: relative;
  width: 26px;
  height: 92px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  background: var(--field);
  border-radius: var(--r-chip);
}

.cfg-fader-level-bar {
  width: 100%;
  background: linear-gradient(to top, var(--pst), var(--accent));
  border-radius: var(--r-chip);
  transition: height 0.1s ease;
}

.cfg-fader-level {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: ns-resize;
  writing-mode: vertical-lr;
  direction: rtl;
  margin: 0;
  padding: 0;
}

.cfg-standard-fader {
  width: 88px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  border-radius: var(--r-control);
  background: var(--plate);
  padding: 8px 7px;
}

.cfg-standard-fader.manual { background: color-mix(in srgb, var(--pst) 12%, var(--plate)); }

.cfg-standard-fader.mute {
  background: color-mix(in srgb, var(--pgm) 12%, var(--plate));
  opacity: 0.82;
}

.cfg-fader-db {
  color: var(--muted);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  min-height: 12px;
}

.cfg-fader-keyframe-chip {
  width: 100%;
  min-height: 24px;
  border: 0;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--muted);
  cursor: pointer;
  font: inherit;
  font-size: 10px;
  font-weight: 850;
  line-height: 1;
}

.cfg-fader-keyframe-chip:hover {
  background: var(--plate-hover);
  color: var(--text);
}

.cfg-fader-keyframe-chip.active {
  background: var(--accent);
  color: var(--ink);
}

.cfg-mode-buttons {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
  width: 100%;
}

.cfg-mode-buttons.horizontal {
  grid-template-columns: repeat(3, 1fr);
  max-width: 260px;
}

.cfg-mode-buttons button {
  border: 0;
  background: var(--plate);
  color: var(--muted);
  border-radius: var(--r-chip);
  cursor: pointer;
  padding: 3px 2px;
  font-size: 9px;
  font-weight: 800;
  text-transform: uppercase;
}

.cfg-mode-buttons button.active {
  color: var(--ink);
  background: var(--accent);
}

.cfg-fader-add {
  min-width: 74px;
  min-height: 236px;
  border: 1px dashed var(--line);
  background: transparent;
  color: var(--muted);
  border-radius: var(--r-control);
  cursor: pointer;
  padding: 10px;
  font-weight: 800;
}

.cfg-fader-add:hover {
  color: var(--text);
  background: var(--plate-hover);
}

/* --- Scrollbars --- */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--plate-selected); border-radius: var(--r-chip); }
::-webkit-scrollbar-thumb:hover { background: var(--muted); }
::-webkit-scrollbar-corner { background: transparent; }

/* --- Drag/drop fader pills --- */
.cfg-physical-fader[draggable] { cursor: grab; }
.cfg-physical-fader[draggable]:active { cursor: grabbing; }

@media (max-width: 980px) {
  .settings-toolbar {
    flex-wrap: wrap;
  }

  .settings-rail {
    padding-left: 12px;
  }

  .settings-body {
    --settings-rail-col: 150px;
  }

  .settings-search-wrap {
    max-width: none;
    min-width: 260px;
  }

  .cfg-device-grid {
    grid-template-columns: 1fr;
  }

  .cfg-room-list {
    grid-template-columns: 1fr;
  }

  .cfg-linker {
    grid-template-columns: 1fr;
  }

  .settings-map-with-props .cfg-linker {
    grid-template-columns: 1fr;
  }

  .settings-body.props-open {
    grid-template-columns: var(--settings-rail-col) minmax(0, 1fr);
  }

.settings-props-slot {
    position: fixed;
    inset: 48px 0 26px auto;
    z-index: 30;
  width: min(var(--settings-props-col), 86vw);
  border-left: 1px solid var(--line);
  background: var(--float);
  box-shadow: var(--float-shadow);
  backdrop-filter: var(--float-blur);
  }

  .cfg-link-arrow {
    display: none;
  }
}

/* ─── Rundown tab ──────────────────────────────────────────────────────────── */
/* Three zones: rundown context and timing in a collapsible rail on the left, monitors and timeline
   in the middle, events on the right. Both rails run top to bottom. */
.rd-root {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* Where you are across the top, the panels and the timeline, then the story strip across all three. */
  grid-template-rows: auto minmax(0, 1fr) auto;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
}
/* Each in its own row, whether the path bar is there or hidden: auto-placed, the story strip would
   take the timeline's row the moment the bar is hidden. */
.rd-root > .path-bar { grid-column: 1 / -1; grid-row: 1; }
.rd-column-row { grid-row: 2; display: grid; grid-template-rows: minmax(0, 1fr); min-width: 0; min-height: 0; overflow-x: auto; overflow-y: hidden; }
.rd-column-row > .rd-rail, .rd-column-row > .rd-main, .rd-column-row > .rd-aside { grid-row: 1; }
.rd-root > .rd-overview-wrap { grid-row: 3; }
.rd-column-row > .rd-main { grid-column: var(--rd-main-column, 2); }
/* Extra columns share the available width while reserving space for the timeline. */
.rd-root.rd-multi-columns { --rd-column-width: clamp(150px, calc((100vw - 360px - var(--rd-closed-columns) * 30px) / var(--rd-open-columns)), var(--editor-rail-left)); }
.rd-column-tools { display: flex; flex: none; align-items: center; gap: 2px; min-height: 28px; padding: 3px 4px; border-bottom: 1px solid var(--line); }
/* Open, a column's head has a pane head's × and grip where a pane's are; lower and darker than the
   panes' heads under it, as the frame they stand in. */
.rd-column-tools.ui-pane-head { min-height: 24px; padding: 1px 0 1px 4px; background: color-mix(in srgb, var(--bg) 55%, var(--panel)); }
/* Its + opens with the × and grip, on hover; at rest the count stands where every count does, 10 px
   in from the right edge. */
.rd-column-tools.ui-pane-head { padding-right: 8px; }
.rd-column-tools.ui-pane-head:is(:hover, :focus-within) { padding-right: 0; }
.rd-column-tools.ui-pane-head > .rd-column-add { display: none; }
.rd-column-tools.ui-pane-head:is(:hover, :focus-within) > .rd-column-add { display: inline-flex; }
@media (hover: none) { .rd-column-tools.ui-pane-head { padding-right: 0; } .rd-column-tools.ui-pane-head > .rd-column-add { display: inline-flex; } }
.rd-column-title { flex: 1; min-width: 0; padding-left: 3px; color: var(--muted); font-size: 9px; font-weight: 700; }
.rd-column-add { flex: none; }
.rd-column-tools.movable { cursor: grab; }
.rd-column-collapsed .rd-column-tools { flex-direction: column; }
.rd-column-collapsed-body { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; min-height: 0; overflow-x: hidden; overflow-y: auto; padding: 8px 3px; }
.rd-column-pane-chip { flex: 0 0 auto; width: 22px; height: auto; min-height: 22px; padding: 5px 3px; border-radius: var(--r-chip); font-size: 9px; line-height: 1.1; writing-mode: vertical-rl; text-orientation: mixed; }
.rd-column-mini-label { align-self: center; margin-top: auto; writing-mode: vertical-rl; color: var(--muted); font-size: 10px; }
.rd-column-empty { padding: 10px; margin: 0; color: var(--muted); font-size: 11px; }
.rd-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}

/* ── Left rail: rundown context + timing ─────────────────────────────────── */
.rd-rail {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  border-right: 1px solid var(--line);
  background: var(--panel);
}
.rd-rail-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 0;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
/* A part of the rail that folds to one line, as a sidebar section does: chevron, name, and while
   folded a one-line summary of what it holds.
   The rail itself never scrolls. Its open sections share its height and each scrolls on its own, so
   there is one scrollbar under the pointer and every section's head stays in view. An open section
   asks for an equal share and takes no more than it holds; what one does not need goes to the
   others, and Events and Clips, which fill whatever they are given, take what is left. */
.rd-rail-section { flex: 0 0 auto; display: flex; flex-direction: column; gap: 0; min-width: 0; min-height: 0; }
.rd-rail-section-head { flex: none; }
.rd-rail-section.open { flex: 1 1 0; min-height: 64px; max-height: max-content; }
.rd-rail-section.open > .rd-rail-section-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 10px; }
/* Nested bands reach the pane's edges; their fields supply the normal inset. The pane still scrolls. */
.rd-rail-section.rd-rail-flush.open > .rd-rail-section-body { padding: 0; }
.rd-rail-section.rd-rail-fill.open { flex-grow: 2; min-height: 200px; max-height: none; }
/* Clips with no asset system to browse is one line saying where to add one: no more than that. */
.rd-rail-section.rd-rail-fill.open:has(> .rd-rail-section-body > .rd-aside-coming) { flex-grow: 1; min-height: 64px; max-height: max-content; }
/* What scrolls by itself, the event tree, the clip browser, an item's properties, runs edge to edge,
   and the section round it does not scroll as well. */
.rd-rail-section.rd-rail-own-scroll.open > .rd-rail-section-body { overflow: hidden; padding: 0; }
.rd-rail-section.rd-rail-own-scroll.open > .rd-rail-section-body > * { flex: 1; min-height: 0; }
/* The rundown's own controls are few and their pickers open downwards over what follows: the
   section keeps its height and does not clip them. */
.rd-rail-section.rd-rail-fixed.open { flex: none; max-height: none; }
.rd-rail-section.rd-rail-fixed.open > .rd-rail-section-body { overflow: visible; }
/* The grip says a section can be dragged, to either side or along its own. */
.rd-rail-section-grip {
  flex: none;
  margin-left: auto;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: -2px;
  opacity: 0;
  cursor: grab;
}
:is(.rd-rail-section-head, .rd-column-tools).movable:hover .rd-rail-section-grip { opacity: .8; }
.rd-rail-section-head.movable:active { cursor: grabbing; }
/* Where a section being dragged would land: a line before or after the one under it. */
.rd-rail-section.drop-before { box-shadow: 0 -3px 0 var(--accent); }
.rd-rail-section.drop-after { box-shadow: 0 3px 0 var(--accent); }
.rd-rail-section-head {
  align-items: center;
  /* No gap: the toggle's own inset puts the count at the right edge every count shares. */
  /* A section's head is a band the width of its panel, a rung above it, stacked on the next with a
     hairline between, as a code editor's side panels are: it stands apart from what it holds
     without a box round anything. */
  background: var(--panel-2);
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  color: color-mix(in srgb, var(--text) 78%, var(--muted));
  cursor: pointer;
  display: flex;
  gap: 0;
  min-width: 0;
  padding: 0;
  text-align: left;
  width: 100%;
}
.rd-rail-section-head:hover { color: var(--text); background: color-mix(in srgb, var(--text) 6%, var(--panel-2)); }
.rd-rail-section-toggle:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; border-radius: var(--r-chip); }
.rd-rail-section-chevron { flex: 0 0 10px; font-size: 10px; }
.rd-rail-section-title {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.rd-rail-section-summary {
  color: var(--text);
  flex: 1 1 auto;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  min-width: 0;
  opacity: .8;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rd-rail-section-body { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
/* Something in the section that must never go unseen, folded or not: rehearsal mode, for one. */
.rd-rail-section-badge {
  background: var(--warn);
  border-radius: var(--r-chip);
  color: var(--bg);
  flex: 0 0 auto;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .08em;
  margin-left: auto;
  padding: 1px 5px;
  text-transform: uppercase;
}
/* In the rail's top corner, over the first section's head band rather than on a row of its own:
   the heads start at the very top. */
.rd-rail-toggle {
  position: absolute;
  z-index: 2;
  top: 4px;
  right: 4px;
  margin: 0;
}
/* Collapsed: the wall clock only, turned on its side so it fits the sliver. */
.rd-rail-mini {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  padding: 32px 0 10px;
}
.rd-rail-mini-clock {
  color: var(--accent);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  writing-mode: vertical-rl;
  letter-spacing: 0.08em;
}
.rd-empty-state {
  display: flex;
  flex-direction: column;
  grid-template-columns: none;
  align-items: stretch;
  justify-content: flex-start;
  text-align: center;
}
.rd-empty-content { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; }
.rd-empty-content .te-combo { width: min(320px, 100%); }
.rd-empty {
  color: var(--muted);
  padding: 12px;
  font-size: 13px;
}
.rd-setup-hint {
  margin: 8px 12px;
  width: auto;
}
.rd-empty-state .rd-setup-hint {
  margin: 0 0 14px;
}


.rd-rundown-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.rd-rundown-row .te-combo {
  flex: 1 1 auto;
}
.rd-rundown-row .te-combo-trigger {
  min-height: 36px;
}
/* Newsroom filter above the rundown picker — it scopes the list, so it reads in the order it acts:
   narrow to a newsroom, then pick within it. Kept visually subordinate (shorter, smaller, muted)
   so the picker below it stays the primary control. */
.rd-rundown-sources { margin-bottom: 4px; }
.rd-rundown-sources .te-combo-trigger { min-height: 26px; padding-block: 2px; }
/* The label carries its own weight and colour, so subordinate styling has to land on it rather
   than on the trigger, or the filter reads as a second equal-weight picker. */
.rd-rundown-sources .te-combo-trigger-label { font-size: 11px; font-weight: 600; color: var(--muted); }
.rd-rundown-sources .te-combo-trigger.has-selection .te-combo-trigger-label { color: var(--text); }
.rd-runs-row { display: flex; align-items: center; gap: 7px; min-width: 0; }
.rd-runs-label { color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.rd-runs-row select,
.rd-runs-toolbar select {
  min-width: 0;
  flex: 1 1 auto;
  height: 28px;
  padding: 0 8px;
  font-size: 11px;
}
.rd-rec-indicator {
  padding: 2px 6px;
  border-radius: var(--r-pill);
  background: var(--pgm);
  color: var(--on-fill);
  font-size: 9px;
  font-weight: 900;
  letter-spacing: .08em;
  box-shadow: 0 0 10px color-mix(in srgb, var(--pgm) 55%, transparent);
  animation: rd-rec-pulse 1.4s ease-in-out infinite;
}
@keyframes rd-rec-pulse { 50% { opacity: .55; } }

.rd-pp { grid-area: pp; }

.rd-title {
  background: transparent;
  border: none;
  border-bottom: 1px solid transparent;
  color: var(--text);
  font-size: 18px;
  font-weight: 600;
  padding: 4px 2px;
  min-width: 0;
  width: 100%;
  flex: 1 1 auto;
}
.rd-title:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; border-bottom-color: transparent; }
.rd-title-group {
  width: 100%;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
}
.rd-delete-rundown { flex: 0 0 auto; }
.rd-timing-row {
  display: flex;
  align-items: center;
  /* Flush left with the rest of the header strip; it was right-aligned for the old right-hand rail. */
  justify-content: flex-start;
  gap: 16px;
  min-width: 0;
}

.rd-timing-block { display: flex; flex-direction: column; line-height: 1.1; }
.rd-timing-label { font-size: 10px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.rd-timing-value { font-size: 18px; font-variant-numeric: tabular-nums; }
.rd-timing-value.rd-over { color: var(--warn); }

.rd-save { width: 9px; height: 9px; border-radius: 50%; background: var(--pst); transition: background .2s; }
.rd-save-saving { background: var(--warn); }
.rd-save-error { background: var(--pgm); }

/* The aside moved out to .rd-root, so the body is just the timeline column. */
.rd-body { flex: 1; min-height: 0; display: flex; min-width: 0; }
.rd-stories { min-height: 0; overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.rd-stories-toolbar { display: flex; gap: 8px; }
.rd-aside { border-left: 1px solid var(--line); background: var(--panel); min-height: 0; display: flex; flex-direction: column; position: relative; }
/* Placement only — the button itself is the shared .te-panel-close, the same one the events editor's
   Properties panel uses. Beside the Inserts heading rather than above it: the heading row has room to
   its right, and a row of its own cost vertical space in the panel that has least to spare. */



/* ─── Rundown timeline (Premiere/Resolve-style) — overrides the earlier rd- block ── */
/* Stacked in the rail, one timer per row. */
.rd-header-timing { display: flex; flex-direction: column; align-items: stretch; gap: 6px; min-width: 0; width: 100%; }

.rd-hc {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 360px;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--panel-2) 80%, transparent), color-mix(in srgb, var(--bg) 86%, transparent)),
    var(--panel-2);
}
.rd-hc-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center center;
  background: var(--bg);
}
.rd-hc-relay-hint {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px 14px;
  text-align: center;
  background: var(--panel);
  color: color-mix(in srgb, var(--text) 82%, transparent);
  font-size: 11px;
  line-height: 1.4;
}
.rd-hc-relay-hint strong {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text);
}
.rd-hc-relay-hint em {
  font-style: normal;
  color: var(--text);
}
.rd-hc-top {
  flex: none;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 30px;
  padding: 0 10px 0 4px;
  background: var(--panel-2);
}
/* One flat band: the item said in it as in the story's head, its state at the right as the story's is,
   a dot and the word in the tally's colour. No plate inside the frame, no pill. */
.rd-hc-event.ui-event-identity { flex: 1 1 auto; gap: 6px; }
/* On a picture: nothing at rest. With the pointer on it, the item's chip and its state along its top in
   the monitor's glass (MonitorVideo's top), in a lifted or pinned window too; a problem shows without. */
.rd-hc-row { display: flex; flex: 1 1 auto; align-items: center; gap: 8px; min-width: 0; }
.rd-hc-row > :first-child { flex: 1 1 auto; min-width: 0; }
.rd-hc-row .rd-hc-event.ui-event-identity { background: transparent; }
.rd-hc-row .rd-hc-event.ui-event-identity.action-parts-surface:hover { background: var(--plate-hover); }
.rd-hc-row .rd-hc-nothing { padding-left: 4px; color: var(--muted); font-size: 12px; }
.rd-hc-row > .rd-hc-label { padding-right: 4px; }
.ui-hover-enlarged .monitor-top:has(> .rd-hc-row) { display: flex; }
.rd-hc-overlay { position: absolute; z-index: 5; top: 8px; left: 8px; right: 8px; display: flex; padding: 4px 6px; border-radius: var(--r-control);
  background: color-mix(in srgb, var(--bg) 64%, transparent); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); }
.rd-hc-has-monitor:hover .rd-hc-overlay { display: none; }
.rd-hc-label.ui-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  min-height: 0;
  padding: 0;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-weight: 800;
  color: var(--monitor-tone);
  background: none;
  white-space: nowrap;
  flex: none;
}
.rd-hc-label.ui-badge::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--monitor-tone); }
/* ON AIR saying the programme's sound is dropping out (monitorNotes.ts): ink on the band, as its label
   is. What a monitor says of itself otherwise is under the i beside its buttons. */
/* The programme's sound dropping out, said on ON AIR's picture, top left, quietly: a small glass pill
   with a warning dot, the share of the sound filled in after it. */
.rd-hc-sound { position: absolute; top: 8px; left: 8px; z-index: 3; display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px 3px 7px;
  border-radius: var(--r-pill); background: color-mix(in srgb, var(--bg) 66%, transparent); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  color: var(--text); font-size: 10px; font-weight: 500; white-space: nowrap; pointer-events: auto; }
.rd-hc-sound::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--warn); }
.rd-hc-sound-figure { color: var(--muted); font-variant-numeric: tabular-nums; }
.rd-hc-manual-release {
  margin-right: 0;
  color: var(--muted);
  font-size: 9px;
  font-weight: 900;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.rd-hc-body {
  position: relative;
  flex: 0 0 auto;
  box-sizing: border-box;
  aspect-ratio: 16 / 9;
  width: 100%;
  display: flex;
  align-items: flex-end;
  min-height: 0;
  padding: 34px 10px 10px;
}
.rd-hc-has-monitor .rd-hc-body {
  padding: 0;
}
.rd-hc-body.rd-hc-empty {
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 18px;
}
@media (max-width: 1500px) {
  .rd-hc {
    width: 320px;
  }
}

.rd-body { display: flex; min-width: 0; }

.rd-clip-chip {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .03em;
  background: var(--template-color, var(--accent));
  color: var(--ink);
  border-radius: var(--r-control);
  padding: 3px 8px;
}

.rd-tree { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.rd-tree-search { align-items: center; padding: 6px 8px; }
.rd-tree-hidden-toggle { flex: none; align-self: stretch; min-height: 28px; font-size: 11px; color: var(--muted); }
.rd-tree-hidden-toggle .toggle-track { order: 2; }
.rd-tree-list { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; }
/* In a rail the tree runs almost to the edges and steps in half as far per folder: 268px is too
   narrow to spend a third of it on air before an event's name. */
.rd-rail-section .rd-tree-list { padding: 4px 4px 4px 6px; }
.rd-rail-section .te-list-tree .te-list-item,
.rd-rail-section .te-list-tree .te-folder-row { margin-left: calc(var(--tree-depth, 0) * 7px); }
.rd-tree-dur { margin-left: auto; color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.rd-story-library-root.drop-target {
  background: var(--plate-hover);
}
.rd-story-library-count {
  min-width: 18px;
  padding: 1px 5px;
  border-radius: var(--r-pill);
  background: var(--plate);
  color: var(--muted);
  font-size: 10px;
  text-align: center;
}
.rd-saved-story { cursor: grab; }
.rd-saved-story:active { cursor: grabbing; }
.rd-saved-story-delete { margin-left: 3px; opacity: 0; }
.rd-saved-story:hover .rd-saved-story-delete,
.rd-saved-story-delete:focus-visible { opacity: 1; }
.rd-saved-story-empty { margin-left: 44px; }
.rd-tree-editable {
  flex: 0 1 auto;
  min-height: 0;
  max-height: 38%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel-2) 52%, var(--panel));
}
.rd-tree-editable > .ui-fold-head { flex: none; }
.rd-tree-editable > .ui-fold-body { min-height: 0; overflow-y: auto; padding: 0; }
/* The bands share the panel's edges; only their headings step in. Fields keep the usual panel padding. */
.rd-tree-editable .te-action-band > .ui-fold-head .ui-fold-toggle { padding-left: 38px; }
.rd-tree-editable + .rd-tree-search { border-top: 0; }
/* Compact the Event Tags fields here (not the Properties panel) so the template tree above stays visible. */
.rd-tree-editable .te-prop-label { margin-bottom: 6px; }
.rd-tree-editable .rd-editable-fields { gap: 6px; }
.rd-tree-editable .rd-editable-field { gap: 2px; }
.rd-tree-editable .rd-editable-field-label { font-size: 10px; }
/* The compact tag boxes in this panel — but not the timecode, whose box and drag targets are sized
   together through --tc-* so they cannot come apart. */
.rd-tree-editable .ui-field:not(.tc-input) { font-size: 11px; }
/* The timecode sized through --tc-*, which is the only way its box and its drag targets stay
   together. Scoped here on purpose: this panel sits under the tree and has to leave room for it,
   while the Props column has the width to show a pair you can grab without aiming. */
.rd-tree-editable .tc-field { --tc-size: 13px; --tc-pad-x: 8px; --tc-pad-y: 5px; }
/* Tags grouped by the action they belong to. The heading is the one Props uses, quieter here. */
.rd-tree-editable .rd-editable-group { display: flex; flex-direction: column; gap: 6px; }
.rd-tree-editable .rd-editable-group + .rd-editable-group { margin-top: 4px; }
.rd-tree-editable .te-kf-header { padding: 2px 0 0; gap: 6px; }
.rd-tree-editable .te-kf-header.te-action-heading { padding: 4px 8px; margin-top: 2px; border-radius: var(--r-control); }
/* One of several panels stacked into a single list: it has no header of its own and does not
   scroll — the column around it does, so the whole item reads as one thing. */
/* Specific enough to beat `.rd-template-props .te-col.te-props`, which sets flex:1 and left every
   stacked copy stretching and scrolling on its own. */
.te-props.te-props-stacked,
.rd-template-props .te-col.te-props.te-props-stacked {
  flex: 0 0 auto;
  min-height: 0;
  overflow: visible;
  border-right: 0;
}

/* "Show event tags (editable)": every row this item may change carries the static #, so a section without one is
   a section with nothing in it for the operator. Asking the DOM which sections those are keeps the
   filter exact without a registry of rows to maintain alongside the rows themselves. */
.rd-props-only-editable .te-prop-section:not(:has(.te-field-expose-static)):not(.te-prop-keep) { display: none; }
.rd-props-only-editable :is(.te-payload-field, .te-transition-param):not(:has(.te-field-expose-static)) { display: none; }
.rd-props-only-editable .te-prop-section:has(> .te-field-label-row .te-field-lock) > .te-transition-picker > .te-chips { display: none; }
.rd-props-only-editable .te-field-lock { display: none; }
/* The action's own heading stays over what is left of it, to say which action the rows belong to;
   an action with nothing left for the operator goes altogether, heading and all. */
.rd-props-only-editable .te-kf-header { display: flex; }
.rd-props-only-editable .te-props-stacked:not(:has(.te-field-expose-static, .te-prop-keep)) { display: none; }
/* A dropdown opened in the panel has to come out OVER this bar. The bar is sticky and comes last
   in the DOM, so without saying otherwise it paints on top of the list it is supposed to sit
   under — the options end up half-hidden behind the filter. */
.rd-template-props .te-combo:has(.te-combo-pop) {
  position: relative;
  z-index: 60;
}
.rd-props-filter {
  position: sticky;
  z-index: 1;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding: 7px 11px 7px 18px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  color: var(--muted);
  font-size: 11px;
  cursor: pointer;
}

/* The AI asks panel reads as a short exchange, with a reviewable proposal before execution. */
.ai-panel { display: flex; flex-direction: column; gap: 9px; min-width: 0; font-size: 12px; }
.ai-chat-shell { display: flex; flex-direction: column; height: clamp(300px, 52vh, 640px); min-height: 0; overflow: hidden; border-radius: var(--r-card); background: var(--bg); }
.ai-chat-thread { display: flex; flex: 1 1 auto; flex-direction: column; gap: 14px; min-height: 0; overflow-y: auto; padding: 18px 16px; user-select: text; }
.ai-chat-empty { align-self: center; margin: auto; color: var(--muted); text-align: center; }
.ai-chat-message { display: flex; flex-direction: column; gap: 6px; max-width: min(100%, 800px); overflow-wrap: anywhere; }
.ai-chat-user { align-self: flex-end; padding: 9px 13px; border-radius: var(--r-card); background: color-mix(in srgb, var(--accent) 18%, var(--panel-2)); }
.ai-chat-assistant { align-self: flex-start; width: 100%; padding: 0 2px; }
.ai-chat-label { color: var(--muted); font-size: 10px; font-weight: 750; letter-spacing: 0.35px; }
.ai-chat-reply { white-space: pre-wrap; }
.ai-chat-markdown { white-space: normal; line-height: 1.5; }
.ai-chat-markdown > :first-child { margin-top: 0; }
.ai-chat-markdown > :last-child { margin-bottom: 0; }
.ai-chat-markdown p { margin: 0 0 8px; }
.ai-chat-markdown h1,
.ai-chat-markdown h2,
.ai-chat-markdown h3,
.ai-chat-markdown h4,
.ai-chat-markdown h5,
.ai-chat-markdown h6 { margin: 10px 0 5px; color: var(--text); line-height: 1.25; }
.ai-chat-markdown h1 { font-size: 1.45em; }
.ai-chat-markdown h2 { font-size: 1.3em; }
.ai-chat-markdown h3 { font-size: 1.15em; }
.ai-chat-markdown h4,
.ai-chat-markdown h5,
.ai-chat-markdown h6 { font-size: 1em; }
.ai-chat-markdown ul,
.ai-chat-markdown ol { display: grid; gap: 3px; margin: 0 0 8px; padding-left: 1.4em; }
.ai-chat-markdown blockquote { margin: 0 0 8px; padding: 4px 9px; border-radius: var(--r-chip); background: var(--plate); color: var(--muted); }
.ai-chat-markdown blockquote p { margin: 0 0 4px; }
.ai-chat-markdown pre { max-width: 100%; margin: 0 0 8px; overflow-x: auto; padding: 8px; border-radius: var(--r-control); background: var(--bg); white-space: pre; }
.ai-chat-markdown code { padding: 1px 4px; border-radius: var(--r-chip); background: var(--plate); font-family: var(--font-mono, ui-monospace, monospace); font-size: 0.92em; }
.ai-chat-markdown pre code { padding: 0; background: transparent; }
.ai-chat-markdown a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.ai-chat-markdown hr { width: 100%; margin: 2px 0 8px; border: 0; border-top: 1px solid var(--line); }
.ai-chat-table-scroll { max-width: 100%; margin: 0 0 8px; overflow-x: auto; }
.ai-chat-markdown table { width: max-content; min-width: 100%; border-collapse: collapse; text-align: left; }
.ai-chat-markdown th,
.ai-chat-markdown td { padding: 4px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
.ai-chat-markdown th { color: var(--text); font-weight: 750; }
.ai-chat-proposal-title { margin-top: 2px; color: var(--muted); font-size: 10px; font-weight: 750; text-transform: uppercase; }
.ai-proposal { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ai-proposal-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 26px; color: var(--muted); font-size: 10px; font-weight: 750; letter-spacing: 0.35px; text-transform: uppercase; }
.ai-proposal-head .ui-btn { margin-left: auto; letter-spacing: normal; text-transform: none; }
.ai-proposal .cfg-props-down { padding: 2px 0; }
.ai-step { display: flex; flex-direction: column; gap: 6px; padding: 8px; border-radius: var(--r-control); background: var(--plate); min-width: 0; }
.ai-step-detail { color: var(--muted); font-size: 10px; }
.ai-step-detail summary { width: fit-content; cursor: pointer; }
.ai-step-detail pre { max-height: 220px; overflow: auto; margin: 6px 0 0; padding: 8px; border-radius: var(--r-control); background: var(--bg); color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.ai-line { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ai-line-note { padding-left: 2px; color: var(--muted); font-size: 10px; overflow-wrap: anywhere; }
.ai-proposal-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 24px; margin-top: 2px; }
.ai-proposal-foot > .ui-btn:only-child { margin-right: auto; }
.ai-state { display: inline-flex; align-items: center; gap: 5px; color: var(--muted); font-size: 11px; font-weight: 700; }
.ai-state-executed { color: var(--text); }
.ai-state.failed { color: var(--pgm); }
.ai-proposal-discarded .ai-step, .ai-proposal-replaced .ai-step, .ai-proposal-undone .ai-step { opacity: 0.55; }
.ai-chat-note { color: var(--muted); font-size: 10px; overflow-wrap: anywhere; }
.ai-chat-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 3px; }
.ai-chat-error { color: var(--pgm); }
.ai-chat-error .ai-chat-label { color: var(--pgm); }
.ai-chat-thinking { color: var(--muted); }
.ai-chat-composer { display: flex; flex: 0 0 auto; flex-direction: column; gap: 4px; margin: 8px; padding: 7px 8px 5px; border-radius: var(--r-card); background: var(--panel-2); }
.ai-chat-composer .ui-field { width: 100%; min-height: 38px; max-height: 144px; padding: 8px 9px; border-radius: var(--r-control); background: transparent; resize: none; overflow-y: auto; }
.ai-chat-composer .ui-field:hover:not(:disabled):not(:focus) { background: transparent; }
.ai-chat-composer .ui-field:focus { outline: 0; }
.ai-chat-composer:focus-within { outline: 2px solid var(--focus-line); outline-offset: -2px; }
.ai-chat-composer-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.ai-chat-composer-actions { display: flex; flex: 0 0 auto; align-items: center; gap: 6px; }
.ai-chat-model { max-width: 150px; overflow: hidden; color: var(--muted); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; }
.ai-chat-send { border-radius: 50%; }

/* Metadata for the item filter and path-specific input permissions, with no visible tag mark. */
.te-field-expose-static { display: none; }

.rd-aside { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
/* The side panel in folding sections, sharing its height as the left rail's do. */
.rd-aside-sections {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0;
}
.rd-aside-sections .rd-inserts-section { padding: 0; border-bottom: 0; }
.rd-aside-empty {
  color: var(--muted);
  font-size: 12px;
  padding: 14px 12px;
}
.rd-aside-coming {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
/* ── Timecode field ────────────────────────────────────────────────────────
   A field like any other: the box is the shared Input, unchanged, so it sits in a column of fields without
   announcing itself. All this adds is three invisible drag targets laid OVER the pairs it shows —
   the thing you grab is the thing you are changing — and it stays a text box you can type into,
   because typing 1:30 beats dragging to it. touch-action:none or iPadOS scrolls instead of counts. */
/* A derived reading beside a label — the length an out-point works out to, and the like. Quiet on
   purpose: it is there to be glanced at, not edited. */
.te-prop-label-aside {
  color: color-mix(in srgb, var(--muted) 70%, transparent);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
}

/* Size lives HERE, on the field, and both the box and the handles read it. They have to agree
   exactly — the handles are laid out in ch, so a font size that applies to only one of them puts
   every target a fraction of a character off, further with each pair. A context that wants a
   smaller timecode changes these three and nothing else. */
.tc-field {
  position: relative;
  display: block;
  min-width: 0;
  --tc-size: 17px;
  --tc-pad-x: 12px;
  --tc-pad-y: 7px;
}
/* Big on purpose: there is room in this column, and a timecode is the one tag you both READ at a
   glance and grab a specific pair of. Large tabular digits make each pair a target you can hit
   without aiming, which is most of what was wrong with it small. */
.tc-input {
  font-variant-numeric: tabular-nums;
  /* Big enough that a pair is a target you can hit without aiming, small enough that three of
     these stacked do not take the column. Each pair is still ~19px wide at this size. */
  font-size: var(--tc-size);
  font-weight: 700;
  /* No letter-spacing, deliberately: it adds a pixel after EVERY character, so a two-digit pair is
     2ch + 2px wide and the handles below — measured in ch — drift a little further right with each
     one. Eight characters in, the last pair's target sat half a digit off. Tabular digits are
     already evenly spaced; the tracking bought nothing and cost the alignment. */
  letter-spacing: 0;
  line-height: 1;
  padding: var(--tc-pad-y) var(--tc-pad-x);
  text-align: center;
}
.tc-field.tc-indefinite-on .tc-handles { color: color-mix(in srgb, var(--muted) 62%, var(--text)); }
.tc-field.tc-indefinite-on .tc-input:focus { color: color-mix(in srgb, var(--muted) 62%, var(--text)); }
/* Same padding and type as the input, so 1ch here is 1ch there and the slots land on the pairs. */
/* Same padding, type and centring as the input, so 1ch here is 1ch there and the slots land on the
   pairs rather than on equal thirds of the box. */
.tc-handles {
  position: absolute;
  inset: 1px;
  display: flex;
  align-items: stretch;
  justify-content: center;
  padding: 0 var(--tc-pad-x);
  font-size: var(--tc-size);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
/* The overlay IS the digits you see, and the input's own text is hidden behind it until you type.
   Two separate text layouts — one in an <input>, one in spans — can be given the same font and
   still not land on the same pixel, and every attempt to make them agree by arithmetic drifted a
   fraction of a character further with each pair. So there is one layout: what is drawn is what is
   grabbed. The input takes over the moment it has focus, because then a caret has to be visible in
   it. */
.tc-handles { color: var(--text); user-select: none; }
.tc-input { color: transparent; caret-color: var(--text); }
.tc-input:focus { color: var(--text); }
.tc-input:focus ~ .tc-handles { color: transparent; }
.tc-field.tc-disabled .tc-handles { color: color-mix(in srgb, var(--text) 45%, transparent); }
.tc-handle-pair { display: flex; flex: 0 0 auto; align-items: stretch; }
/* The colon belongs to neither pair: dead width between two targets. */
.tc-sep { flex: 0 0 auto; display: inline-flex; align-items: center; color: inherit; }
.tc-handle {
  flex: 0 0 auto;
  border: 0;
  padding: 0;
  background: transparent;
  font: inherit;
  /* A button does NOT inherit colour — it falls back to the UA's buttontext, which is black. The
     digits live in these buttons now, so without this the whole timecode goes black on a dark
     field. */
  color: inherit;
  cursor: ns-resize;
  touch-action: none;
  border-radius: var(--r-chip);
}
/* Which pair you are about to take. Without it the targets are invisible and the only way to find
   out is to drag and see what moves. */
/* The drag affordance: the pair the pointer would take if it pressed now. Suppressed while the
   field is being typed into — the pointer is not what is moving the value then. */
.tc-field:not(.tc-typing):hover .tc-handle:hover { background: var(--plate-hover); }
.tc-handle.on { background: color-mix(in srgb, var(--accent) 26%, transparent); }
/* A picked pair is a SELECTION, so it looks like one — the same muted wash text selection has
   everywhere else. Earlier attempts drew a block, a caret and a colour while merely TYPING, where
   nothing was selected and the mark could only read as "grab me". Here something really is
   selected, and saying so is the whole point of having double-clicked it. */
.tc-handle.picked {
  background: color-mix(in srgb, var(--accent) 34%, transparent);
  border-radius: var(--r-chip);
}
/* While typing, the handles must not eat the caret: focus hands the box back to the keyboard. */
.tc-input:focus ~ .tc-handles { pointer-events: none; }
/* Disabled takes the drag away, not the digits. They live in the handles now — hiding those blanked
   a locked field completely, because the input's own text is transparent behind them. */
.tc-field.tc-disabled .tc-handles { pointer-events: none; }
.tc-field.tc-disabled .tc-handle { cursor: default; }
.tc-dragging .tc-input { background: var(--plate-selected); }
/* A note on the zero rather than a replacement for it: the digits stay, and stay draggable. */
.tc-unit,
.tc-unit-short {
  color: color-mix(in srgb, var(--accent) 75%, var(--text));
  font-size: 9px;
  font-weight: 900;
  letter-spacing: 0.8px;
  opacity: 0;
  transition: opacity .1s ease;
}
.tc-unit {
  position: absolute;
  top: 50%;
  left: 9px;
  transform: translateY(-50%);
  pointer-events: none;
}
/* The two ends of one answer: the name on the left, the notation on the right. */
.tc-aside {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 7px;
  pointer-events: none;
}
/* Only while the pointer is actually over a pair: a permanent caption beside four of them is
   clutter, and the question "which one is this" only exists in the moment you are reaching. */
.tc-field:hover .tc-unit,
.tc-field:hover .tc-unit-short,
.tc-dragging .tc-unit,
.tc-dragging .tc-unit-short,
/* While typing it is not a hint but a readout: it names the pair the next digit lands in. */
.tc-typing .tc-unit,
.tc-typing .tc-unit-short { opacity: 1; }

.tc-indefinite {
  color: color-mix(in srgb, var(--accent) 70%, var(--text));
  font-size: 15px;
  line-height: 1;
}

.rd-runs-panel { flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 0; padding: 0; overflow-y: auto; }
/* The picker owns its row. It is the first decision in the panel and the only control here whose
   whole job is a label — sharing the row is what reduced it to a chevron. */
.rd-runs-toolbar { display: flex; align-items: center; gap: 7px; padding: 8px 10px 4px; }
.rd-runs-toolbar > .te-combo { flex: 1 1 auto; min-width: 0; }
.rd-runs-empty { justify-content: flex-start; align-items: flex-start; gap: 12px; padding: 10px; }

/* ── Event tag controls: a tag renders as whatever it actually is ─────────── */
/* Tag comboboxes reuse the app's searchable picker, compacted: a tag option is a single line, with
   none of the badge-plus-two-lines the target pickers show, so the 42px trigger is wasted height.
   Scoped rather than global — the target pickers still need the room. */
/* Keep the menu's ancestors fully opaque: opacity groups the floating list with the trigger,
   so its backdrop cannot blur the rest of the screen and nearby controls paint over it.
   Disabled controls already dim themselves through the shared button styles. */
.te-tag-combo { min-width: 0; }
.te-tag-combo .te-combo { width: 100%; }
.te-tag-combo.disabled { pointer-events: none; }
.te-tag-combo .te-combo-trigger {
  min-height: 0;
  padding: 4px 7px;
}
.te-tag-combo .te-combo-trigger-label { font-size: 11px; }
.te-tag-combo .ui-menu-item { padding: 6px 8px; }
.te-tag-combo .te-combo-option-label { font-size: 11px; }
.te-tag-combo .te-combo-list {
  gap: 2px;
  margin-top: 4px;
}
.te-tag-color {
  width: 46px;
}
.te-slider-row.te-tag-slider span {
  min-width: 40px;
  text-align: right;
}

/* Transition hovering an item: it lands on that item's leading edge — the boundary with the item
   before — so the cue is a bar on that edge, not the generic accessory badge. */
.rd-part-transition-drop {
  background: color-mix(in srgb, var(--accent) 16%, var(--panel-2));
}
/* Kept inside the box: .rd-part clips its overflow, so a negative offset would vanish. */
.rd-part.rd-part-transition-drop::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--accent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 75%, transparent);
  z-index: 3;
}
.rd-part.rd-part-transition-drop::after { content: none; }

/* ── Capability-driven transition picker ─────────────────────────────────── */
.te-transition-picker {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.te-transition-native-label {
  align-items: center;
  color: var(--muted);
  display: flex;
  font-size: 9px;
  font-weight: 800;
  gap: 5px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.te-transition-live-dot {
  background: var(--pst);
  border-radius: 50%;
  height: 5px;
  width: 5px;
}
.te-transition-params {
  border-left: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-left: 8px;
}
.te-transition-param {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.te-transition-param-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
}
.te-transition-warn {
  color: var(--warn);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.45;
}
.te-transition-hint {
  color: var(--muted);
  font-size: 10px;
  line-height: 1.45;
}

.rd-inserts-section {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
}
/* The shelf headers carry their count in the same pill the event tree uses, so "how many are
   parked here" reads the same way in both panels. Flex, because that pill positions itself with
   margin-left:auto. */
.rd-inserts-story {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0;
}
.rd-inserts-list { max-height: 190px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 0; }
.rd-inserts-list .te-list-item { cursor: default; }
.rd-inserts-list .te-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rd-insert-run { padding: 3px 9px; font-size: 11px; flex: none; }
.rd-insert-x { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 14px; line-height: 1; padding: 2px 4px; flex: none; }
.rd-insert-x:hover { color: var(--pgm); }
.rd-inserts-drop {
  border: 1px dashed var(--line);
  border-radius: var(--r-card);
  color: var(--muted);
  font-size: 11px;
  padding: 9px 12px;
  text-align: center;
}
.rd-inserts-section.dragover .rd-inserts-drop { border: 1px dashed var(--accent); color: var(--text); background: var(--plate-selected); }
.rd-inserts-section.dragover {
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}
/* Skipped list: the same shelf as Inserts, but these items know where they came from. Dashed and
   struck through so the two groups never read as the same thing at a glance — an insert was never
   scheduled, a skipped item was and got dropped. */
.rd-skipped-list .te-list-item {
  border-style: dashed;
  opacity: .72;
}
.rd-skipped-list .te-list-item:hover { opacity: 1; }
.rd-skipped-list .te-item-name { text-decoration: line-through; }
.rd-skipped-story {
  flex: none;
  font-size: 10px;
  color: var(--muted);
  max-width: 88px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rd-insert-revert {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 2px 4px;
  flex: none;
}
.rd-insert-revert:hover { color: var(--accent); }

/* A line across the app under its tabs, for a state the whole node is in: a forensic session, a copy
   of another tenant's node (ForensicBanner.tsx, ReplicaBanner.tsx). */
.app-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 14px;
  font-size: 12px;
  background: color-mix(in srgb, var(--warn) 14%, var(--panel));
}
.app-banner-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--warn);
  box-shadow: 0 0 6px var(--warn);
  animation: forensic-pulse 2s ease-in-out infinite;
}
@keyframes forensic-pulse {
  50% { opacity: .45; }
}
.app-banner-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rd-run-summary { display: flex; align-items: center; flex-wrap: wrap; gap: 5px 10px; padding: 4px 10px 8px; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.rd-run-replay-progress { height: 4px; overflow: hidden; border-radius: var(--r-pill); background: var(--panel-2); }
.rd-run-replay-progress > span { display: block; height: 100%; border-radius: inherit; background: var(--accent); transition: width .1s linear; }
.rd-run-actions { flex: none; min-height: 0; max-height: 240px; display: flex; flex-direction: column; gap: 4px; overflow-y: auto; }
.rd-run-action {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr);
  align-items: center;
  justify-content: initial;
  gap: 7px;
  width: 100%;
  min-height: 32px;
  padding: 6px 7px;
  text-align: left;
}
.rd-run-action.issue { opacity: 1; }
.rd-run-action-time { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.rd-run-action-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; }
/* Replay position. Three states, no glyphs: what has gone recedes, what is happening is lit, what
   is coming stays as it was. Colour does the whole job, so the list reads as one moving thing
   rather than a column of badges. */
.rd-run-action-done { opacity: 0.45; }
.rd-run-action-active {
  font-weight: 700;
}
/* The issue flag is a property of the run and outranks where the playhead happens to be. */

.rd-run-issue { display: flex; flex-direction: column; gap: 8px; }
.rd-run-issue .ui-field { min-width: 0; width: 100%; }
/* One transport and one shared cursor, for replay and marking a problem. */
.rd-run-player { margin: 2px 10px 10px; padding: 9px; display: flex; flex-direction: column; gap: 9px; background: var(--panel-2); border-radius: var(--r-control); }
.rd-run-transport { display: flex; align-items: center; gap: 8px; }
.rd-run-transport-main { flex: none; min-width: 82px; }
.rd-run-player-state { flex: 1; min-width: 0; color: var(--muted); font-size: 10px; }
.rd-run-player > .ui-range { flex: none; width: 100%; min-width: 0; }
.rd-run-player-meta { display: flex; align-items: center; justify-content: space-between; gap: 10px; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.rd-run-position { color: var(--accent); font-weight: 800; }
.rd-run-position > span { color: var(--muted); font-weight: 500; }
.rd-run-report-time { padding: 2px 5px; border-radius: var(--r-chip); background: var(--plate); font-variant-numeric: tabular-nums; }
.rd-run-report-actions { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 6px; }
.rd-run-report-hint { flex: 1; min-width: 100px; color: var(--muted); font-size: 10px; }
/* What to do WITH the run, as opposed to what to do inside it. Last, and deliberately quiet. */
.rd-run-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 10px; border-top: 1px solid var(--line); }
.rd-run-footer > * { flex: 0 1 auto; min-width: 0; }
/* The scroller for the whole item. Each action's panel used to own its own, so a clip with four
   actions had four scrollbars and four headings — one list, scrolled once, is what it is. */
.rd-template-props {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.rd-template-props .te-col.te-props {
  flex: 1;
  border-right: none;
}

.ncs-root {
  display: flex;
  width: 100vw;
  height: 100vh;
  min-height: 0;
  overflow: hidden;
  background: var(--panel);
  color: var(--text);
}

.ncs-root .rd-tree {
  width: 100%;
}

/* Wide enough, the newsroom's page puts the picked event's tags, its graphic's preview among them,
   beside the events rather than under them: the journalist sees the strap while writing it. */
@media (min-width: 720px) {
  .ncs-root .rd-tree {
    display: grid;
    grid-template-columns: minmax(240px, 1fr) minmax(300px, 440px);
    grid-template-rows: minmax(0, 1fr) auto;
  }
  .ncs-root .rd-tree-list { grid-column: 1; grid-row: 1; }
  .ncs-root .rd-tree-search { grid-column: 1; grid-row: 2; }
  .ncs-root .rd-tree-editable { grid-column: 2; grid-row: 1 / span 2; max-height: none; border-top: 0; }
}

/* ─── Rundown: a vertical stack of story segments + 3 operation lanes ─────────── */
.rd-header-timing .rd-timing-value.rd-under { color: var(--pst); }
.rd-header-timing .rd-timing-value.rd-over { color: var(--pgm); }
.rd-header-timing .rd-timing-row {
  /* Two timers per row in the rail: one per row wasted most of the height. */
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
  gap: 6px;
  width: 100%;
}
.rd-header-timing .rd-timing-block {
  flex: 0 0 auto;
  min-width: 0;
  /* Left-aligned now that this is the main column, not a right-hand rail. */
  align-items: flex-start;
  gap: 2px;
  padding: 6px 8px;
  border-radius: var(--r-control);
  line-height: 1.2;
}
.rd-header-timing .rd-timing-label {
  color: var(--timing-color, var(--muted));
  font-size: 9px;
  font-weight: 800;
}
.rd-header-timing .rd-timing-value {
  font-size: 14px;
  font-weight: 800;
  font-family: 'SF Mono', 'Fira Code', monospace;
  line-height: 18px;
  color: color-mix(in srgb, var(--text) 92%, var(--muted));
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rd-header-timing .rd-timing-clock .rd-timing-value {
  font-size: 14px;
}
.rd-header-timing .rd-timing-status .rd-timing-value {
  font-family: inherit;
  font-size: 12px;
}
.rd-timing-time-input {
  width: 100%;
  min-width: 0;
  height: 18px;
  padding: 0;
  border: 0;
  border-radius: var(--r-control);
  background: transparent;
  color: color-mix(in srgb, var(--text) 92%, var(--muted));
  font: inherit;
  font-size: 14px;
  font-weight: 800;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-variant-numeric: tabular-nums;
  line-height: 18px;
  text-align: left;
  color-scheme: dark;
}
.rd-timing-time-input::placeholder {
  color: color-mix(in srgb, var(--muted) 72%, transparent);
}
.rd-timing-time-input:disabled {
  color: var(--muted);
  cursor: not-allowed;
}
.rd-timing-subvalue {
  margin-top: 0;
  color: color-mix(in srgb, var(--text) 66%, var(--muted));
  font-size: 8.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rd-timing-subvalue.rd-under,
.rd-header-timing .rd-timing-value.rd-ahead {
  color: var(--pst);
}
.rd-timing-subvalue.rd-over,
.rd-timing-subvalue.rd-late,
.rd-header-timing .rd-timing-value.rd-late {
  color: var(--warn);
}

/* Pinned below the timeline it navigates: flex: 0 0 auto keeps it in place while the stack above
   scrolls, and the divider is on top now that nothing follows it. */
/* The story strip across the screen, and its fold. */
.rd-overview-wrap {
  grid-column: 1 / -1;
  display: flex;
  align-items: stretch;
  min-width: 0;
  background: var(--panel);
  border-top: 1px solid var(--line);
}
.rd-overview-wrap > .rd-overview { flex: 1; min-width: 0; border-top: 0; }
/* At the strip's right end: every story folded but the one on air (ADR 0170). */
.rd-overview-fold-others.ui-btn { order: 2; flex: none; align-self: center; margin: 0 8px; }
.rd-overview-toggle {
  flex: none;
  width: 26px;
  font-size: 10px;
}
.rd-overview-summary {
  display: flex;
  align-items: center;
  padding: 5px 12px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.rd-overview {
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  gap: 6px;
  padding: 6px 12px 7px;
  background: var(--panel);
  border-top: 1px solid var(--line);
  min-height: 52px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-gutter: stable;
}
.rd-ov-seg {
  --rd-ov-gradient: transparent 0% 100%;
  position: relative;
  flex: 0 0 var(--rd-ov-width, 136px);
  min-width: 136px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  background:
    linear-gradient(90deg, var(--rd-ov-gradient)),
    var(--plate);
  color: var(--muted);
  padding: 5px 10px;
  overflow: hidden;
  text-align: left;
}
.rd-ov-seg.has-events {
  color: color-mix(in srgb, var(--text) 86%, var(--rd-ov-color));
}
.rd-ov-seg.ui-selected {
  background: var(--plate-selected);
  color: var(--text);
}
.rd-ov-name {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  font-weight: 750;
}
.rd-ov-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  color: color-mix(in srgb, var(--text) 58%, var(--muted));
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.rd-ov-seg.has-events .rd-ov-meta {
  color: color-mix(in srgb, var(--text) 68%, var(--muted));
}
.rd-ov-seg.ui-selected .rd-ov-meta {
  color: color-mix(in srgb, var(--text) 78%, var(--muted));
}
.rd-ov-dot {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 50%;
  background: var(--rd-ov-color, var(--line));
}
.rd-ov-playhead {
  position: absolute;
  top: 4px;
  bottom: 4px;
  z-index: 3;
  width: 2px;
  transform: translateX(-1px);
  background: var(--accent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 76%, transparent);
  pointer-events: none;
}
.rd-ov-playhead::before {
  content: "";
  position: absolute;
  top: -1px;
  left: -4px;
  width: 10px;
  height: 5px;
  border-radius: var(--r-chip);
  background: var(--accent);
  box-shadow: 0 0 7px color-mix(in srgb, var(--accent) 70%, transparent);
}

.rd-body {
  flex: 1 1 0;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  display: flex;
}
.rd-stack {
  flex: 1 1 auto;
  height: 100%;
  min-height: 0;
  min-width: 0;
  overflow-x: hidden;
  overflow-y: auto;
  /* Room either side for the on-air story's lane names (LaneGutters). */
  padding: 10px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rd-stack-toolbar { flex: 0 0 auto; display: flex; align-items: center; gap: 12px; }
.rd-stack-hint { color: var(--muted); font-size: 12px; }
.rd-stack-hint kbd { background: var(--plate); border-radius: var(--r-chip); padding: 0 5px; font-size: 11px; }
.rd-add-story {
  height: auto;
  min-height: 78px;
  flex: 0 0 auto;
  align-self: stretch;
  padding: 14px 18px;
}
.rd-add-story .cfg-link-card-main {
  font-size: 14px;
}
.rd-add-story.dragover {
  border: 1px dashed var(--accent);
  background: var(--plate-selected);
}

.rd-seg { flex: 0 0 auto; overflow: hidden; }
/* Which story is which, at a glance: a lamp in its head, green while on air in it (NEXT there too or
   not), orange while only NEXT is, with its word where the head has room; whatever is selected, so
   what is on air never hides. The story keeps the plain edge every story has: a coloured frame round
   the chips crowded them. Selection has a place of its own, the story's head, lit as a selected
   button is. Its ruler's ON AIR and NEXT say the rest. */
.rd-seg-state { display: inline-flex; flex: 0 0 auto; align-items: center; gap: 5px; color: var(--state-color); font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.rd-seg-state.on-air { --state-color: var(--pst); }
.rd-seg-state.next { --state-color: var(--on); }
.rd-seg-state-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--state-color); box-shadow: 0 0 6px color-mix(in srgb, var(--state-color) 60%, transparent); }
@container (max-width: 560px) { .rd-seg-state-word { display: none; } }
.rd-seg.ui-selected.ui-interactive:hover { background: var(--plate-story-selected); }
.rd-seg.ui-selected > .rd-seg-head,
.rd-seg.ui-selected > .rd-seg-head:hover { background: var(--plate-story-selected); }
.rd-seg-head { display: flex; align-items: center; gap: 8px; padding: 6px 8px; background: var(--panel-2); cursor: grab; container-type: inline-size; }
.rd-seg-head:active { cursor: grabbing; }
.rd-seg-arrow { transition: transform .12s; }
.rd-seg-arrow.open { transform: rotate(90deg); }
.rd-seg-index { color: var(--muted); font-variant-numeric: tabular-nums; width: 18px; text-align: right; }
.rd-seg-slug { flex: 1; background: transparent; border: none; color: var(--text); font-weight: 600; padding: 4px 2px; min-width: 80px; }
.rd-seg-slug:focus { outline: none; }
.rd-seg-take-block {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 24px;
  max-width: 240px;
  padding: 3px 8px;
  border: 0;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--warn) 18%, var(--panel));
  color: color-mix(in srgb, var(--warn) 82%, var(--text));
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.03em;
  line-height: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}
.rd-seg-dur { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 12px; }

.rd-seg-body { position: relative; overflow-x: auto; background: var(--timeline-ground); cursor: crosshair; }
.rd-seg-dragover { background: color-mix(in srgb, var(--accent) 8%, var(--timeline-ground)); }
.rd-seg-panning, .rd-seg-panning * { cursor: ew-resize !important; user-select: none; }
/* Roaming (a middle click on empty timeline): the move cursor, as a browser's autoscroll shows. */
.timeline-roam-mark { position: fixed; z-index: 10000; width: 26px; height: 26px; margin: -13px 0 0 -13px; display: grid; place-items: center; border-radius: var(--r-pill); background: color-mix(in srgb, var(--bg) 70%, transparent); color: var(--text); font-size: 16px; pointer-events: none; }
.timeline-roaming, .timeline-roaming * { cursor: all-scroll !important; user-select: none; }
.rd-seg-zooming,
.rd-seg-zooming * {
  cursor: ns-resize !important;
  user-select: none;
}
.rd-seg-empty { color: var(--muted); font-size: 12px; padding: 14px; }
/* What times the item, along the story's bottom edge: a part per speaker in that presenter's colour, in the
   timeline's own time, drawn as the folder's rule in the events tree is: one flat line on the very
   edge, the parts flush, rounded only at its two ends. In rehearsal mode it shows the voice too: faint until its part
   is made, filling from left to right over the time the node expects the part to take, solid once it
   is made, red when it could not be. */
.rd-seg-speakers { bottom: 0; height: 19px; left: 0; pointer-events: none; position: absolute; right: 0; z-index: 3; }
.rd-seg-speaker { background: color-mix(in srgb, var(--speaker-color) 7%, transparent); box-shadow: inset 1px 0 0 var(--timeline-ground); bottom: 0; height: 19px; overflow: hidden; position: absolute; pointer-events: auto; }
.rd-seg-speaker::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--speaker-color); }
/* Past the item's end, on air until the next was taken: striped, in the warning colour. */
.rd-seg-speaker.over { background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--warn) 14%, transparent) 0 6px, transparent 6px 12px); }
.rd-seg-speaker.over .rd-seg-speaker-label { color: var(--warn); }
/* The same quiet timing readout as the hover card, within the item's unchanged temporal edges. */
.rd-seg-speaker-label { position: relative; z-index: 1; max-width: calc(100% - 6px); height: 16px; padding-top: 1px; padding-bottom: 1px; margin: 0 3px; }
.rd-seg-speaker:first-child { border-radius: var(--r-pill) 0 0 var(--r-pill); }
.rd-seg-speaker:last-child { border-radius: 0 var(--r-pill) var(--r-pill) 0; }
.rd-seg-speaker:only-child { border-radius: var(--r-pill); }
.rd-seg-speaker.waiting,
.rd-seg-speaker.making { background: color-mix(in srgb, var(--speaker-color) 6%, transparent); }
.rd-seg-speaker.waiting::after,
.rd-seg-speaker.making::after { opacity: .28; }
.rd-seg-speaker-fill {
  animation: rd-speaker-fill var(--fill-ms) linear both;
  background: var(--speaker-color);
  bottom: 0;
  left: 0;
  position: absolute;
  height: 3px;
  z-index: 1;
  width: var(--fill-to);
}
@keyframes rd-speaker-fill { from { width: var(--fill-from); } to { width: var(--fill-to); } }
.rd-seg-speaker.failed::after { background: var(--pgm); }
.rd-seg-canvas {
  position: relative;
  isolation: isolate;
  min-width: 100%;
  padding: 24px 0 23px;
  background:
    linear-gradient(to bottom, color-mix(in srgb, var(--line) 52%, transparent) 23px, transparent 24px),
    repeating-linear-gradient(to right, transparent 0, transparent calc(var(--rd-major-step) - 1px), color-mix(in srgb, var(--line) 42%, transparent) calc(var(--rd-major-step) - 1px), color-mix(in srgb, var(--line) 42%, transparent) var(--rd-major-step)),
    repeating-linear-gradient(to right, transparent 0, transparent calc(var(--rd-minor-step) - 1px), color-mix(in srgb, var(--line) 26%, transparent) calc(var(--rd-minor-step) - 1px), color-mix(in srgb, var(--line) 26%, transparent) var(--rd-minor-step)),
    var(--timeline-ground);
  background-position:
    0 0,
    var(--rd-grid-origin, 0px) 0,
    var(--rd-grid-origin, 0px) 0,
    0 0;
}
.rd-timeline-state-band {
  --rd-band-color: var(--on);
  position: absolute;
  inset-block: 0;
  z-index: 0;
  min-width: 2px;
  pointer-events: none;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--rd-band-color) 12%, transparent),
    color-mix(in srgb, var(--rd-band-color) 7%, transparent) 72%,
    color-mix(in srgb, var(--rd-band-color) 11%, transparent));
  border-inline: 1px solid color-mix(in srgb, var(--rd-band-color) 28%, transparent);
  box-shadow: inset 0 0 24px color-mix(in srgb, var(--rd-band-color) 5%, transparent);
}
.rd-timeline-state-band-onair { --rd-band-color: var(--pst); }
.rd-timeline-state-band-next { --rd-band-color: var(--on); }

.rd-seg-ruler {
  position: absolute;
  inset: 0 0 auto 0;
  height: 24px;
  pointer-events: none;
  z-index: 1;
}
.rd-seg-ruler-tick {
  position: absolute;
  top: 6px;
  transform: translateX(-50%);
  color: color-mix(in srgb, var(--muted) 82%, transparent);
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  text-shadow: 0 1px 0 var(--bg);
  white-space: nowrap;
}
.rd-ruler-state-range {
  --rd-range-color: var(--on);
  position: absolute;
  top: 20px;
  height: 2px;
  min-width: 2px;
  border-radius: var(--r-pill);
  background: var(--rd-range-color);
  box-shadow: 0 0 7px color-mix(in srgb, var(--rd-range-color) 64%, transparent);
  z-index: 2;
}
.rd-ruler-state-range::before,
.rd-ruler-state-range::after {
  content: "";
  position: absolute;
  top: -3px;
  width: 1px;
  height: 7px;
  border-radius: var(--r-chip);
  background: var(--rd-range-color);
}
.rd-ruler-state-range::before { left: 0; }
.rd-ruler-state-range::after { right: 0; }
.rd-ruler-state-range-onair { --rd-range-color: var(--pst); }
.rd-ruler-state-range-next { --rd-range-color: var(--on); }

.rd-seg-parts { position: relative; z-index: 3; height: 34px; margin-bottom: 5px; }
/* The item stands out from its actions by size and weight, not colour: its chip fills the item's
   height, its name a step larger; the actions' words a step quieter, their kinds as they are. */
.rd-part > .ui-event-identity.action-parts-surface { align-self: stretch; }
.rd-part > .ui-event-identity .ui-event-name { font-size: 13px; font-weight: 800; }
.rd-lane .te-op-card.rd-chip .rd-chip-token { color: color-mix(in srgb, var(--text) 78%, var(--muted)); }
.rd-part { position: absolute; top: 0; height: 34px; box-sizing: border-box; display: flex; align-items: center; gap: 7px; padding: 0 8px; overflow: hidden; cursor: pointer;
  /* No outline and no edge, as the live stack's rows have none: a mild wash of the type's colour.
     Squarer than a panel's corner, as the action chips under it. */
  border-radius: var(--r-chip); border: 1px solid transparent;
  background: color-mix(in srgb, var(--template-color, var(--accent)) 14%, var(--panel-2)); }
/* Geometry and gestures stay on the timeline item; the shared main chip draws its contents. */
.rd-part:has(> .rd-main-event) { padding: 0; background: transparent; border-radius: var(--r-control); }
.rd-part:is(:hover, .rd-part-picked):has(> .rd-main-event), .rd-part:has(> .rd-main-event):has(.rd-chip-status-error) { background: transparent; }
.rd-part > .rd-main-event { flex: 1; width: 100%; height: 100%; min-height: 0; }
.rd-part.rd-part-picked > .rd-main-event { background: color-mix(in srgb, var(--kind-color, var(--panel-2)) 38%, var(--panel-2)); }
/* The full-height white edge matches the coloured operation borders at the same time position. */
.rd-part:not(.rd-part-compact-marker) { border-left-color: var(--on-fill); }
.rd-part.rd-part-compact-marker {
  gap: 0;
  padding: 0;
  border-width: 0;
}
.rd-part[draggable="true"] { cursor: grab; }
.rd-part[draggable="true"]:active { cursor: grabbing; }
.rd-part:hover { background: color-mix(in srgb, var(--template-color, var(--accent)) 22%, var(--panel-2)); }
/* Picked with the box (useMarquee.tsx): brighter than hover, as a selected plate is. */
.rd-chip.rd-chip-picked { filter: brightness(1.35); }
.rd-part.rd-part-picked { background: color-mix(in srgb, var(--template-color, var(--accent)) 38%, var(--panel-2)); }
.rd-chip-skipped { opacity: .38; filter: saturate(.3); }
/* A chip switched off in the Events editor: there, to be switched on, and doing nothing. */
.te-op-card.off { opacity: .38; filter: saturate(.3); }
.rd-skipped-body { display: flex; flex-direction: column; gap: 8px; font-size: 12px; color: var(--muted); }
.rd-part-selected {
  outline: none;
}
.rd-part-selected::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background: var(--plate-selected);
  pointer-events: none;
}
.rd-part-selected > * {
  position: relative;
  z-index: 1;
}
.rd-part-accessory-drop {
  outline: 2px dashed color-mix(in srgb, var(--accent) 82%, transparent);
  outline-offset: -4px;
  background: color-mix(in srgb, var(--accent) 22%, var(--panel-2));
}
.rd-part-accessory-drop::after {
  content: "+";
  flex: 0 0 auto;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--bg) 64%, var(--accent));
  color: var(--accent);
  font-weight: 900;
  line-height: 1;
}
/* Archive item dragged from the media browser hovering an event: drop binds the media. */
.rd-part-media-drop {
  outline: 2px dashed color-mix(in srgb, var(--template-color, var(--accent)) 85%, transparent);
  outline-offset: -4px;
  background: color-mix(in srgb, var(--template-color, var(--accent)) 30%, var(--panel-2));
}
/* Event references media the video server doesn't have (yet) — e.g. transfer pending. */
.rd-media-missing-badge {
  flex: 0 0 auto;
  font-size: 11px;
  line-height: 1;
  color: var(--on);
}
/* Media archive embed under the Clips aside tab. */
.rd-media-browser {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}
.rd-media-browser-frame {
  flex: 1 1 auto;
  width: 100%;
  border: 0;
  border-radius: var(--r-control);
  background: var(--panel-2);
}
.rd-part-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rd-duration-chip {
  flex: 0 0 auto;
  margin-left: auto;
  border: 0;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--bg) 58%, color-mix(in srgb, var(--template-color, var(--accent)) 18%, var(--panel-2)));
  color: color-mix(in srgb, var(--text) 84%, var(--template-color, var(--accent)));
  padding: 1px 5px;
  font-size: 10px;
  font-weight: 800;
  line-height: 1.2;
  white-space: nowrap;
}
.rd-duration-chip.from-video {
  background: color-mix(in srgb, var(--template-color, var(--accent)) 24%, var(--panel-2));
}
.rd-part-trimmable {
  padding-left: 11px;
  padding-right: 11px;
}
.rd-trim-summary {
  flex: 0 1 auto;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 5px;
  border: 0;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--panel-2) 74%, var(--template-color, var(--accent)));
  color: color-mix(in srgb, var(--text) 78%, var(--muted));
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
}
.rd-trim-summary b {
  color: color-mix(in srgb, var(--template-color, var(--accent)) 62%, white);
  font-size: 8px;
  letter-spacing: .04em;
}
.rd-trim-summary > span { color: var(--muted); }
.rd-trim-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 9;
  width: 8px;
  cursor: ew-resize;
  touch-action: none;
}
.rd-trim-handle::after {
  content: "";
  position: absolute;
  top: 5px;
  bottom: 5px;
  width: 2px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--warn) 78%, var(--text));
  opacity: 0;
  transition: opacity .12s ease;
}
.rd-trim-in { left: 0; }
.rd-trim-out { right: 0; }
.rd-trim-in::after { left: 3px; }
.rd-trim-out::after { right: 3px; }
.rd-part-trimmed .rd-trim-handle::after {
  opacity: 0;
}
.rd-part-trimmable:hover .rd-trim-handle::after,
.rd-part-trimming .rd-trim-handle::after {
  opacity: 1;
  box-shadow: 0 0 7px color-mix(in srgb, var(--warn) 70%, transparent);
}
.rd-trim-label {
  position: absolute;
  top: -40px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  border: 0;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--warn) 18%, var(--plate));
  color: var(--warn);
  padding: 3px 7px;
  font-size: 10px;
  font-weight: 900;
  line-height: 1.1;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--bg) 60%, transparent);
}
.rd-trim-label-edge {
  letter-spacing: .02em;
}
.rd-trim-label-dur {
  font-size: 11px;
  color: color-mix(in srgb, var(--text) 92%, var(--warn));
}
.rd-trim-label-dur::before {
  content: "⟼ ";
  color: var(--warn);
}
/* What a drop from the Events panel would make of the story, before the button is let go: the new
   item where it would run and as long as it would be, faint and outlined; an item it would replace
   fades under it. */
.rd-part.rd-part-ghost {
  background: color-mix(in srgb, var(--template-color, var(--accent)) 14%, transparent);
  border: 1px dashed var(--template-color, var(--accent));
  opacity: .8;
  pointer-events: none;
  z-index: 11;
}
.rd-part-ghost .rd-part-name { font-style: italic; }
.rd-part-ghost-dur { color: var(--muted); font-size: 11px; margin-left: auto; white-space: nowrap; }
.rd-part.rd-part-replace-drop { opacity: .3; }
/* An accessory's chips where they would run once it is dropped on the item under it. */
.rd-chip.rd-chip-drop-preview { border-style: dashed; opacity: .5; pointer-events: none; }
.rd-drop-cursor {
  position: absolute;
  top: -5px;
  bottom: -5px;
  z-index: 12;
  width: 2px;
  transform: translateX(-1px);
  background: var(--warn);
  box-shadow: 0 0 10px color-mix(in srgb, var(--warn) 80%, transparent);
  pointer-events: none;
}
.rd-drop-cursor::before,
.rd-drop-cursor::after {
  content: "";
  position: absolute;
  left: -4px;
  width: 10px;
  height: 4px;
  border-radius: var(--r-chip);
  background: var(--warn);
}
.rd-drop-cursor::before { top: -1px; }
.rd-drop-cursor::after { bottom: -1px; }
.rd-event-cue {
  position: absolute;
  top: -22px;
  z-index: 7;
  display: flex;
  align-items: center;
  transform: translateX(-50%);
  pointer-events: none;
  --rd-cue-color: var(--on);
  color: var(--ink);
}
.rd-event-cue span {
  border: 0;
  border-radius: var(--r-pill);
  background: var(--rd-cue-color);
  padding: 1px 5px;
  font-size: 9px;
  font-weight: 900;
  letter-spacing: .06em;
  line-height: 1.2;
  white-space: nowrap;
}
.rd-event-cue-onair { --rd-cue-color: var(--pst); }
.rd-event-cue-next { --rd-cue-color: var(--on); z-index: 8; }
.rd-inherit-badge {
  flex: 0 0 auto;
  border: 0;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--template-color, var(--accent)) 20%, transparent);
  color: color-mix(in srgb, var(--template-color, var(--accent)) 80%, var(--text));
  padding: 0 5px;
  font-size: 9px;
  font-weight: 800;
  line-height: 1.25;
}

.rd-seg-lanes { position: relative; }
.rd-seg-transition-lanes {
  margin-bottom: 6px;
}
.rd-seg-transition-lanes .rd-lane { border-bottom: 1px solid var(--line); }
.rd-lane {
  position: relative;
  height: var(--rd-row-height, 34px);
  border-top: 1px solid var(--line);
}
/* The loupe. Pinned to the top of the strip and moving only along time, because that is the axis
   with anything between two values — and because holding the button still is what asks for it.
   Pointer-transparent: the gesture that opened it owns the pointer. */
.rd-loupe {
  position: absolute;
  top: 0;
  z-index: 60;
  overflow: hidden;
  pointer-events: none;
}
/* What is inside is a real StorySegment, so everything it draws for its own sake has to be taken
   back off: its header, its frame, and its scrollbar. The strip itself is left exactly as it is —
   that is the point of rendering the real one. */
/* Shifted up by the same offset the panel is placed at, so the rows inside line up with the rows
   underneath. Row heights do not depend on zoom, so the two instances agree on this exactly. */
.rd-loupe-view { height: 100%; }
.rd-loupe-view > .rd-seg-wrap > .rd-seg {
  margin: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.rd-loupe-view .rd-seg-head { display: none; }
.rd-loupe-view .rd-seg-body {
  height: 100%;
  overflow: hidden;
}
.rd-loupe-view .rd-seg-body::-webkit-scrollbar { display: none; }
/* Pinned labels follow the container's scroll, and this container is scrolled somewhere the
   operator never asked to be. They would sit on top of the very seam being inspected. */
/* Floated over the strip rather than stacked above it: the panel's height is the band of lanes it
   magnifies, and a header in the flow would push that band out of alignment with the rows the
   panel is sitting on. */
.rd-loupe-head {
  position: absolute;
  top: 3px;
  right: 5px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 1px 6px;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--panel) 88%, var(--bg));
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.6px;
}
.rd-loupe-scale { color: color-mix(in srgb, var(--accent) 80%, var(--text)); }
.rd-loupe-lanes { position: relative; }
.rd-loupe-lane {
  position: relative;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 50%, transparent);
}
.rd-loupe-lane:last-child { border-bottom: 0; }
/* The exact instant under the pointer — the reference the magnified widths are read against. */
.rd-loupe-center {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: color-mix(in srgb, var(--accent) 70%, transparent);
}

/* Where an operation's lane starts in its row: nothing to see, only for the gutter to find. */
.rd-lane-op-mark { position: absolute; top: var(--rd-chip-top, 3px); left: 0; width: 0; height: 0; pointer-events: none; }
/* The lanes' names, outside the story's frame while it is on air or selected (LaneGutters): each
   lane's operation on the left, each row's kind on the right, as letters stacked down them. */
.rd-seg-wrap { flex: 0 0 auto; position: relative; }
.rd-seg-gutter { bottom: 0; pointer-events: none; position: absolute; top: 0; width: 11px; }
.rd-seg-gutter-ops { left: -14px; }
.rd-seg-gutter-kinds { right: -14px; }
.rd-gutter-kind,
.rd-gutter-op {
  align-items: center;
  display: flex;
  flex-direction: column;
  font-size: 8px;
  font-weight: 900;
  justify-content: center;
  left: 0;
  line-height: 7.5px;
  pointer-events: auto;
  position: absolute;
  text-transform: uppercase;
  width: 11px;
}
/* Filled in the colour of the machine it drives (shared/actionColors.ts), dark letters on it. */
.rd-gutter-kind { background: var(--kind-color, var(--accent)); border-radius: var(--r-chip); color: var(--ink); }
.rd-gutter-op { border-radius: var(--r-chip); }
.rd-gutter-op.rd-op-preview { background: var(--on); color: var(--ink); }
.rd-gutter-op.rd-op-program { background: var(--pst); color: var(--ink); }
.rd-gutter-op.rd-op-takeout { background: var(--pgm); color: var(--ink); }
.rd-gutter-op.rd-op-transition { background: color-mix(in srgb, var(--on) 50%, var(--pst)); color: var(--ink); }
.rd-loupe-view .rd-seg-gutter { display: none; }
.rd-lane-preview  { background: color-mix(in srgb, var(--on)  6%, transparent); }
.rd-lane-program  { background: color-mix(in srgb, var(--pst) 7%, transparent); }
.rd-lane-takeout  { background: color-mix(in srgb, var(--pgm) 6%, transparent); }
.rd-chip.te-op-card { position: absolute; top: var(--rd-chip-top, 3px); box-sizing: border-box; height: 24px; width: auto; min-width: 24px; max-width: none;
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 5px; padding: 1px 5px; border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--rd-op-color, var(--accent)) 26%, var(--panel-2));
  /* No outline and no edge: its lane is said by its row and its name in the margin. */
  border: 1px solid transparent;
  cursor: default; overflow: hidden; }
.rd-chip-action.te-op-card {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  padding-left: 6px;
}
/* The pointer target of a chip too narrow to hit, widened symmetrically and drawn as nothing. The
   chip itself stays the width of the time it takes, at every zoom; this is what keeps a two-pixel
   action clickable without it claiming seconds it does not have. */
.rd-chip.te-op-card::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-1 * var(--rd-chip-hit-pad, 0px));
  right: calc(-1 * var(--rd-chip-hit-pad, 0px));
  z-index: 0;
}
.rd-chip.te-op-card.rd-chip-compact-marker {
  padding: 0;
  border-width: 0;
}
.rd-chip-transition.te-op-card {
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  padding-left: 6px;
  min-width: 2px;
}
.rd-chip .te-op-card-main { min-width: 0; flex: 1 1 auto; }
.rd-chip .te-op-card-label { font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Fader chips with keyframe automation: the curve renders read-only under the chip header.
   Chip height comes inline from RundownTab (RUNDOWN_FADER_CURVE_* must match this geometry). */
.rd-chip.rd-chip-keyframes.te-op-card {
  align-content: start;
  grid-template-rows: 20px;
}
.rd-chip.rd-chip-keyframes .te-fader-curve {
  /* Explicit: .rd-chip-selected > * flips children to position:relative for its highlight
     overlay, which would drop the curve into grid flow and collapse it. */
  position: absolute;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  left: 0;
  right: 0;
  top: 26px;
  bottom: 0;
  height: auto;
  /* No horizontal padding: x maps to time, so 0 ms must sit exactly on the chip's left edge. */
  padding: 1px 0 2px;
  border-top: 1px solid color-mix(in srgb, var(--line) 72%, transparent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 62%, transparent), color-mix(in srgb, var(--bg) 44%, transparent));
  pointer-events: none;
}
.rd-chip.rd-chip-keyframes .te-fader-curve-row {
  flex: 1 1 0;
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}
.rd-chip.rd-chip-keyframes .te-fader-curve-row .te-fader-plot {
  position: absolute;
  inset: 2px 0;
  height: auto;
  width: auto;
}
.rd-chip.rd-chip-keyframes .te-fader-curve polyline { stroke-width: 2; }
/* Read-only: the dots must not advertise grabbing (the shared component's base rules show a
   grab cursor + hover scale for the template editor). Pointer events stay ON so hovering a dot
   surfaces its data-hint (level + time) in the bottom hint bar. */
.rd-chip.rd-chip-keyframes .te-fader-dot,
.rd-chip.rd-chip-keyframes .te-fader-dot:hover {
  width: 7px;
  height: 7px;
  border-width: 0;
  pointer-events: auto;
  cursor: default;
  background: var(--accent);
  box-shadow: none;
  transform: translate(-50%, -50%);
}
.rd-chip.rd-chip-keyframes .te-fader-curve-label {
  left: 8px;
  max-width: 60%;
  font-size: 9px;
}
/* ─── Narrow-chip disclosure ─────────────────────────────────────────────────
   Chips shrink with zoom; instead of ellipsizing words mid-letter, drop content
   in priority order and keep the glanceable token. Full details live in the shared chip hover card. */
/* Width buckets come from RundownTab (chipWidthClass/partWidthClass — chip widths are known at
   render time). The shared hover card shows what these widths hide. */
.rd-chip.rd-w-md .te-fader-curve-label { display: none; }
.rd-chip.rd-w-md .rd-chip-route .rd-chip-arrow,
.rd-chip.rd-w-md .rd-chip-route .rd-chip-token-destination { display: none; }
.rd-chip.rd-w-md .rd-chip-route .rd-chip-token-source { max-width: 100%; }
/* A fader, keyer or output keeps what it becomes, the point of it, and drops what it acts on. */
.rd-chip.rd-w-md .rd-chip-route.keep-result .rd-chip-token-source { display: none; }
.rd-chip.rd-w-md .rd-chip-route.keep-result .rd-chip-token-destination { display: inline-flex; max-width: 100%; }
.rd-chip.rd-w-sm .rd-chip-video .rd-chip-clip-id,
.rd-chip.rd-w-sm .rd-chip-video .rd-chip-loop { display: none; }
.rd-chip.rd-w-sm .rd-chip-video .rd-chip-token { max-width: 100%; }
.rd-chip.rd-w-xs .rd-chip-token { padding: 0 3px; letter-spacing: 0; }
/* Group the fixed-width chip content; its hover card lives outside the timeline. */
.rd-peek-content {
  display: flex;
  align-items: center;
  min-width: 0;
  flex: 1 1 auto;
}
.rd-part > .rd-peek-content { width: 100%; gap: 7px; }
.rd-chip > .rd-peek-content { gap: 5px; }
.rd-chip-action > .rd-peek-content,
.rd-chip-transition > .rd-peek-content { gap: 0; }
.rd-part.rd-pw-md .rd-trim-summary { display: none; }
.rd-part.rd-pw-sm .rd-part-name { display: none; }
.rd-part.rd-pw-sm .ui-event-name { display: none; }
.rd-part.rd-pw-xs .rd-duration-chip { display: none; }
.rd-chip-route,
.rd-chip-video {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
}
/* Shared kind wash for Actions and the small action row inside a Properties heading. */
.rd-rail-stack-row,
.action-parts-surface {
  --action-surface-idle: color-mix(in srgb, var(--kind-color, var(--panel-2)) 8%, transparent);
  --action-surface-active: color-mix(in srgb, var(--kind-color, var(--panel-2)) 30%, transparent);
}
.rd-chip-token {
  display: inline-flex;
  align-items: center;
  /* Start-aligned so a too-narrow token clips the END of the text — the start of a name is
     the readable part when zoomed out. Identical to centered when the text fits (the box
     hugs its content). */
  justify-content: flex-start;
  min-width: 0;
  max-width: 55%;
  height: 20px;
  padding: 0 6px;
  /* A plate, no stroke: inside a chip, a heading or the path bar it is a part of something already
     outlined, and a second outline only made the whole busier. No colour of its own, a light glaze:
     what shows through is what holds it, the chip's action type, or plain grey on the panel; every
     part alike, before the arrow and after it (ADR 0051). */
  border: 0;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--text) 13%, transparent);
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 10px;
  font-weight: 900;
  letter-spacing: 0.02em;
  line-height: 1;
}
.rd-chip-token-source {
  flex: 0 1 auto;
}
.rd-chip-token-destination {
  flex: 0 1 auto;
  color: var(--text);
}
/* The kind of machine an action drives, one mark everywhere (components/ActionParts.tsx, KindMark):
   its short name on a plate of the machine's colour, dark on light so it reads the same on a
   tinted chip, a progress fill or the panel. */
.kind-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-width: 27px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--kind-color, var(--text)) 72%, var(--text));
  color: var(--bg);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .04em;
  line-height: 1;
}
/* Last in a chip: at its right edge, what it does before it; in a rundown chip, clear of the corner
   where whether it ran is marked. */
.rd-chip-route.has-kind { width: 100%; }
.rd-chip-kind { margin-left: auto; }
.rd-chip .rd-chip-kind { margin-right: 20px; }
.te-op-card.combined .rd-chip-kind { --kind-color: var(--template-color, var(--accent)); }
/* A rundown action chip in its machine's colour, as mild as the live stack's rows, with no outline:
   its lane is the row it is in, named in the margin, and a hairline on its left edge. Narrow, it keeps
   what it does and lets the machine go, which the margin says too. */
.rd-chip.rd-chip-action.te-op-card {
  background: color-mix(in srgb, var(--kind-color, var(--rd-op-color, var(--accent))) 13%, var(--panel-2));
}
.rd-chip.rd-w-lg .rd-chip-kind { display: none; }
.rd-chip-arrow {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  /* White: an arrow joins two parts and means nothing of its own. */
  color: color-mix(in srgb, var(--text) 85%, transparent);
}
.rd-chip-arrow .ui-icon {
  width: 14px;
  height: 14px;
}
.rd-chip-token-command {
  flex: 0 0 auto;
  /* As wide as its word: an arrow and what it acts on follow it (ADR 0031). */
  max-width: none;
  gap: 4px;
  color: var(--text);
}
.rd-chip-token-command .ui-icon {
  width: 12px;
  height: 12px;
}
/* One compact rendering of ActionParts for the Actions list and folding Properties headings. */
.action-parts-compact { gap: 4px; }
.action-parts-compact .rd-chip-token { height: 16px; padding: 0 5px; font-size: 10px; font-weight: 800; max-width: none; flex: 0 1 auto; }
.action-parts-compact .rd-chip-arrow { width: 13px; height: 13px; }
.action-parts-compact .rd-chip-arrow .ui-icon { width: 12px; height: 12px; }
.action-parts-surface {
  box-sizing: border-box;
  padding: 2px 4px;
  border-radius: var(--r-control);
  background: var(--action-surface-idle);
}
.action-parts-surface:hover, .te-action-band > .ui-fold-head:hover .action-parts-surface { background: var(--action-surface-active); }
.rd-chip-clip-id {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 11px;
  font-weight: 850;
}
/* A chip that grows to its label must not then clip it: the width buckets that hide detail on narrow
   chips, and the ellipsis on the name, both assume a fixed time-true width. */
.rd-chip[style*="max-content"] .rd-chip-clip-id {
  overflow: visible;
  text-overflow: clip;
}
.rd-chip[style*="max-content"] .rd-peek-content { max-width: none; }
.rd-chip-loop {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  color: color-mix(in srgb, var(--accent) 86%, var(--text));
}
.rd-chip-loop .ui-icon {
  width: 15px;
  height: 15px;
}
.rd-chip-op {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 20px;
  border-radius: var(--r-control);
  background: var(--rd-op-color, var(--accent));
  color: var(--ink);
  font-size: 9px;
  font-weight: 900;
  letter-spacing: 0.03em;
  line-height: 1;
}
.rd-chip.rd-op-preview .rd-chip-op { color: var(--ink); }
.rd-chip.rd-op-program .rd-chip-op { color: var(--ink); }
.rd-chip.rd-op-takeout .rd-chip-op { color: var(--ink); }
.rd-chip.rd-transition.rd-op-program .rd-chip-op {
  background: linear-gradient(90deg, var(--on), var(--pst));
  color: var(--ink);
}
.rd-chip.rd-transition.rd-op-takeout .rd-chip-op {
  background: linear-gradient(90deg, var(--pst), var(--pgm));
  color: var(--ink);
}
.rd-chip-flash-success {
  animation: rd-chip-flash-success .72s ease-out;
}
.rd-chip-flash-error {
  animation: rd-chip-flash-error .9s ease-out;
}
@keyframes rd-chip-flash-success {
  0% {
    box-shadow:
      0 0 0 2px color-mix(in srgb, var(--pst) 96%, transparent),
      0 0 18px color-mix(in srgb, var(--pst) 72%, transparent);
    filter: brightness(1.18);
  }
  100% {
    box-shadow: none;
    filter: none;
  }
}
@keyframes rd-chip-flash-error {
  0%,
  45% {
    box-shadow:
      0 0 0 2px color-mix(in srgb, var(--pgm) 96%, transparent),
      0 0 18px color-mix(in srgb, var(--pgm) 74%, transparent);
    filter: brightness(1.16);
  }
  100% {
    box-shadow: none;
    filter: none;
  }
}

.rd-seg-playhead {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: var(--accent);
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 84%, transparent);
  pointer-events: none;
  z-index: 45;
  will-change: transform;
}
.rd-seg-playhead::before {
  content: "";
  position: absolute;
  top: 0;
  left: -7px;
  width: 16px;
  height: 13px;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  background: var(--accent);
  filter: drop-shadow(0 0 7px color-mix(in srgb, var(--accent) 80%, transparent));
}
.rd-seg-playhead-label {
  position: absolute;
  top: 13px;
  left: 8px;
  padding: 3px 8px;
  border-radius: var(--r-control);
  background: color-mix(in srgb, var(--accent) 18%, var(--float));
  -webkit-backdrop-filter: var(--float-blur);
  backdrop-filter: var(--float-blur);
  box-shadow: 0 4px 12px color-mix(in srgb, var(--bg) 34%, transparent);
  color: var(--accent);
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 12px;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  white-space: nowrap;
  z-index: 2;
}
/* One compact glass notice for Take blocks and Preview, Program or Take Out outcomes. */
.rd-playhead-notice {
  --rd-notice-color: var(--accent);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  box-sizing: border-box;
  max-width: min(440px, calc(100vw - 32px));
  min-height: 24px;
  padding: 3px 5px;
  background: color-mix(in srgb, var(--rd-notice-color) 10%, var(--float));
  color: var(--text);
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .01em;
  line-height: 1;
  white-space: nowrap;
  pointer-events: none;
}
.rd-playhead-notice-label,
.rd-playhead-notice-target {
  display: inline-block;
  min-width: 0;
  padding: 3px 5px;
  border-radius: var(--r-chip);
  overflow: hidden;
  text-overflow: ellipsis;
}
.rd-playhead-notice-label { flex: 0 0 auto; background: color-mix(in srgb, var(--rd-notice-color) 18%, transparent); color: var(--rd-notice-color); }
.rd-playhead-notice-target { background: color-mix(in srgb, var(--text) 9%, transparent); }
.rd-playhead-notice-arrow { flex: 0 0 auto; color: var(--muted); }
.rd-playhead-notice-detail { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--muted); font-weight: 650; }
.ui-playhead-continue { pointer-events: auto; }
.gfx-playhead-notice { position: absolute; top: 76px; z-index: 70; }
.scene-tl-lane { position: relative; }
.scene-tl-span { position: absolute; top: 8px; height: 12px; background: color-mix(in srgb, var(--accent) 24%, transparent); border-radius: var(--r-chip); }
.rd-seg-playhead-note { position: absolute; top: 31px; left: 8px; z-index: 50; }
/* Only the notice rises above the playhead; the action lanes do not form a stacking context. */
.rd-lane-playhead-note { position: absolute; top: 2px; z-index: 70; }
.rd-seg-playhead-note-cueing,
.rd-seg-playhead-note-block { --rd-notice-color: var(--warn); }
.rd-seg-playhead-note-ready { --rd-notice-color: var(--pst); }
.rd-seg-playhead-note-error { --rd-notice-color: var(--pgm); }

.rd-seg-mini-ruler { height: 6px; }

/* ─── Rundown: layers are rows, operation state is carried by chip color ──────── */
.rd-lane { background: transparent; }
.rd-lane:nth-of-type(even) { background: color-mix(in srgb, var(--panel-2) 35%, transparent); }
.rd-lane.rd-transition-lane {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--on) 7%, transparent),
    color-mix(in srgb, var(--pst) 9%, transparent)
  );
}
.rd-lane-empty { color: var(--muted); font-size: 12px; padding: 10px; }

.rd-chip.rd-op-preview { --rd-op-color: var(--on); }
.rd-chip.rd-op-program { --rd-op-color: var(--pst); }
.rd-chip.rd-op-takeout { --rd-op-color: var(--pgm); }
/* Keep the operation readable at a glance without tinting the whole rundown chip more heavily. */
.rd-chip.te-op-card.rd-op-preview,
.rd-chip.te-op-card.rd-op-program,
.rd-chip.te-op-card.rd-op-takeout { border-left-color: var(--rd-op-color); }
.rd-chip-selected {
  outline: none;
}
.rd-chip-selected::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background: var(--plate-selected);
  pointer-events: none;
}
.rd-chip-selected > * {
  position: relative;
  z-index: 1;
}
.rd-chip:focus-visible {
  outline: 2px solid var(--focus-line);
  outline-offset: 1px;
}
.rd-chip-timing-editable {
  cursor: grab;
}
.rd-chip-timing-editable:active,
.rd-chip-timing-dragging {
  cursor: grabbing;
}
.rd-action-resize {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 10px;
  opacity: 0;
  cursor: ew-resize;
  touch-action: none;
  z-index: 2;
}
.rd-action-resize::after {
  content: '';
  position: absolute;
  top: 6px;
  bottom: 6px;
  width: 2px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--rd-op-color, var(--accent)) 76%, var(--text));
}
.rd-action-resize-start { left: 0; }
.rd-action-resize-end { right: 0; }
.rd-action-resize-start::after { left: 3px; }
.rd-action-resize-end::after { right: 3px; }
.rd-chip-timing-editable:hover .rd-action-resize,
.rd-chip-timing-editable:focus-visible .rd-action-resize,
.rd-chip-timing-dragging .rd-action-resize {
  opacity: 1;
}
.rd-chip.rd-transition {
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--rd-op-color, var(--pst)) 16%, var(--panel-2)),
    color-mix(in srgb, var(--rd-op-color, var(--pst)) 28%, var(--panel-2))
  );
}

.mx-bank-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ── Story script in the rail ────────────────────────────────────────────── */
.rd-rail-script {
  border-top: 1px solid var(--line);
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  gap: 5px;
  margin-top: 4px;
  padding-top: 8px;
}
.rd-rail-empty { color: var(--muted); font-size: 11px; padding: 10px 0; }
.rd-rail-script-head {
  align-items: baseline;
  display: flex;
  gap: 6px;
  justify-content: space-between;
}
.rd-rail-script-slug {
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.06em;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}
.rd-rail-script-progress {
  color: var(--pst);
  flex: 0 0 auto;
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}
.rd-rail-script-progress.overrun {
  background: var(--on);
  border-radius: var(--r-chip);
  color: var(--ink);
  padding: 1px 5px;
}
/* Which block is being read, of how many, beside how far into it. */
.rd-rail-script-where { align-items: center; display: inline-flex; flex: 0 0 auto; gap: 6px; }
.rd-rail-script-block { color: var(--muted); font-size: 9px; font-variant-numeric: tabular-nums; font-weight: 800; }
/* Read view and edit field share metrics so clicking in doesn't reflow the text. */
.rd-rail-script-read,
.rd-rail-script-text {
  background: color-mix(in srgb, var(--panel-2) 70%, transparent);
  border: 1px solid transparent;
  border-radius: var(--r-control);
  color: var(--text);
  font-family: inherit;
  font-size: 11.5px;
  /* A little air between lines, so one reader's said words don't touch the next line's. */
  line-height: 1.7;
  padding: 6px 7px;
}
.rd-rail-script-read {
  cursor: text;
  /* No scrollbar of its own — the rail body is already a scroll region, and a nested one just hides
     script behind a bar you have to find. */
  flex: 0 0 auto;
  overflow: visible;
}
.rd-rail-script-read:hover { background: var(--plate-hover); }
.rd-rail-script-text {
  overflow: hidden;
  resize: none;
  width: 100%;
}
.rd-rail-script-text:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 1px; background: var(--field-hover); }
/* Editing: the text field over a drawing of its text in the readers' colours (ScriptEditMirror). The
   field's own letters are invisible; its caret and selection show. Both boxes are the same to the
   pixel, and one line taller at the top, where the first block's item is named. */
.rd-rail-script-editor { position: relative; }
.rd-rail-script-editor .rd-rail-script-text.over,
.rd-rail-script-mirror { padding-top: calc(6px + 11.5px * 1.7); }
.rd-rail-script-text.over { background: transparent; caret-color: var(--text); color: transparent; position: relative; }
.rd-rail-script-text.over:focus { background: transparent; }
.rd-rail-script-text.over::placeholder { color: var(--muted); }
.rd-rail-script-text.over::selection { background: color-mix(in srgb, var(--accent) 38%, transparent); color: transparent; }
.rd-rail-script-mirror {
  background: var(--panel-2);
  border: 1px solid transparent;
  border-radius: var(--r-control);
  color: var(--text);
  font-size: 11.5px;
  inset: 0;
  line-height: 1.7;
  overflow: hidden;
  overflow-wrap: break-word;
  padding-bottom: 6px;
  padding-left: 7px;
  padding-right: 7px;
  pointer-events: none;
  position: absolute;
  white-space: pre-wrap;
}
/* A name as a tag, in the reader's colour: colour and ground only, so it takes the same room as the
   letters typed over it. */
.rd-rail-script-mirror-speaker {
  background: color-mix(in srgb, var(--speaker-color, var(--muted)) 22%, transparent);
  border-radius: var(--r-chip);
  color: var(--speaker-color, var(--muted));
}
.rd-rail-script-mirror-instruction { color: var(--muted); }
/* The item a block goes to, on the blank line above it: smaller, and never wrapping, so it keeps to
   that one line. */
.rd-rail-script-mirror-shot {
  color: var(--muted);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.rd-rail-script-mirror-shot.folded { color: var(--warn); }
.rd-rail-script-mirror-first { left: 7px; position: absolute; top: 6px; }
.rd-rail-script-para { margin: 0 0 12px; }
.rd-rail-script-para:last-child { margin-bottom: 0; }
/* The paragraph bound to the on-air shot: its edge a bar of how far it has been read (ReadBar), red
   below that, as on air. */
.rd-rail-script-para.on-air {
  margin-left: -7px;
  padding-left: 7px;
  position: relative;
}
.rd-rail-script-readbar {
  background: var(--pgm);
  border-radius: var(--r-chip);
  left: 0;
  overflow: hidden;
  position: absolute;
  width: 3px;
}
.rd-rail-script-readbar-fill {
  background-repeat: no-repeat;
  left: 0;
  position: absolute;
  top: 0;
  transition: height .25s linear;
  width: 100%;
}
/* Words judged said: inverted in the colour of whoever said them, so the reading's progress and its
   speaker read at once. Still an estimate, drawn as a run rather than a cursor. */
.rd-script-word-said { background: var(--speaker-color, var(--muted)); color: var(--bg); }
/* One shot's block of script, each reader's line as written, under the name of the item it goes to. */
.rd-rail-script-para { white-space: pre-line; }
.rd-rail-script-shot {
  color: var(--muted);
  display: block;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .08em;
  margin-bottom: 2px;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rd-rail-script-shot.folded { color: var(--warn); }
/* Who reads next, named in brackets in the script: a small tag in that presenter's colour. */
.rd-script-speaker {
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--speaker-color, var(--muted)) 22%, transparent);
  color: var(--speaker-color, var(--muted));
  font-size: 0.82em;
  font-weight: 800;
  letter-spacing: .04em;
  margin-right: 2px;
  padding: 0 3px;
}
/* An instruction nobody reads: dimmed, so the read text stands out. */
.rd-script-instruction { color: var(--muted); font-style: italic; opacity: .75; }
.rd-rail-script-empty { color: var(--muted); font-style: italic; }
.rd-rail-script-meta {
  color: var(--muted);
  font-size: 9px;
  font-variant-numeric: tabular-nums;
}

/* ── Presenter tag on the story header ───────────────────────────────────── */
.rd-seg-presenter-picker { flex: 0 0 auto; min-width: 170px; }
.rd-seg-presenter-picker .te-combo-trigger { min-height: 0; padding: 3px 6px; }
.rd-seg-presenter {
  align-items: center;
  cursor: pointer;
  /* The owning profile colours the plate; each reader keeps their own dot and speaking colour. */
  background: color-mix(in srgb, var(--presenters-profile-color) 22%, var(--panel-2));
  border: 0;
  border-radius: var(--r-control);
  display: inline-flex;
  flex: 0 0 auto;
  gap: 5px;
  padding: 2px 6px;
}
.rd-seg-presenter.readonly { cursor: default; }
/* One reader in the tag: its own colour, beside the others the script names. */
.rd-seg-presenter-reader { align-items: center; display: inline-flex; gap: 4px; }
.rd-seg-presenter-reader + .rd-seg-presenter-reader { border-left: 1px solid var(--line); padding-left: 5px; }
/* Who is reading now: inverted in their colour, as their said words are in the script panel. */
.rd-seg-presenter-reader.speaking { background: var(--presenter-color); border-radius: var(--r-chip); padding: 0 4px; }
.rd-seg-presenter-reader.speaking .rd-seg-presenter-name,
.rd-seg-presenter-reader.speaking .rd-seg-presenter-wpm { color: var(--bg); }
.rd-seg-presenter-reader.speaking .rd-seg-presenter-dot { background: var(--bg); }
.rd-seg-presenter-dot {
  background: var(--presenter-color);
  border-radius: 50%;
  flex: 0 0 auto;
  height: 6px;
  width: 6px;
}
.rd-seg-presenter-name {
  color: var(--text);
  font-size: 10px;
  font-weight: 700;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rd-seg-presenter-wpm {
  color: var(--muted);
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}
/* Rehearsal mode on this machine: a switch under the script, lit yellow while it is on, so nobody
   forgets it before a real show. */
/* Options (OptionsSection.tsx): the show's switches, one row each. */
.options-rows { display: flex; flex-direction: column; gap: 8px; padding: 8px 10px 10px; }
.options-rehearsal { color: var(--muted); padding: 2px 0; }
.options-rehearsal-label { color: var(--text); font-size: 12px; font-weight: 700; }
.options-rehearsal.on .options-rehearsal-label { color: var(--warn); }
.options-rehearsal-detail { font-size: 11px; }
/* A voice reads this story (narration): green once its files are made, amber while they are being
   made, red when one could not be. */
.rd-seg-presenter-voice {
  border-radius: var(--r-chip);
  font-size: 8px;
  font-weight: 800;
  letter-spacing: .06em;
  padding: 1px 4px;
}
.rd-seg-presenter-voice.ready { background: color-mix(in srgb, var(--pst) 22%, transparent); color: var(--pst); }
.rd-seg-presenter-voice.making { background: color-mix(in srgb, var(--warn) 22%, transparent); color: var(--warn); }
.rd-seg-presenter-voice.failed { background: color-mix(in srgb, var(--pgm) 22%, transparent); color: var(--pgm); }

/* ── Presenters settings ─────────────────────────────────────────────────── */
.cfg-presenters { display: flex; flex-direction: column; gap: 12px; }
/* The presenter's voice: chips and voice picker at their own width, under the heading, like Color. */
.cfg-presenter-voice { margin-top: 6px; }
.cfg-presenter-voice .ui-seg,
.cfg-presenter-voice .vcfg-port-sel { align-self: flex-start; }
.cfg-presenter-station {
  border-radius: var(--r-control);
  background: var(--plate);
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
}
.cfg-presenter-station .cfg-hint { margin: 0; max-width: 62ch; }
.cfg-field-suffix { color: var(--muted); font-size: 11px; font-weight: 700; }

/* Did this action run? Sits in the chip's bottom-right corner. Program results survive until reset;
   the current NEXT cue overlays them while it is pending/ready — the flash animation above is gone
   in under a second, which is no use when the question is asked afterwards ("did that happen?").
   Its own backdrop, because on a keyframed fader chip the corner sits over the curve. */
.rd-chip .rd-chip-status {
  position: absolute;
  right: 2px;
  bottom: 1px;
  z-index: 3;
  pointer-events: none;
}
/* Not run yet: present enough to learn what the corner means, quiet enough to ignore across a
   rundown where most chips are always in this state. */
.rd-chip .rd-chip-status-idle { color: color-mix(in srgb, var(--muted) 52%, transparent); background: none; }
.rd-chip .rd-chip-status-pending { color: color-mix(in srgb, var(--muted) 76%, transparent); background: none; }
.rd-chip .rd-chip-status-cued { color: var(--warn); }
/* Sent but not yet confirmed: the same green, held back, so a glance across the timeline reads
   confirmed work as brighter than work still in flight. */
.rd-chip .rd-chip-status-success { color: color-mix(in srgb, var(--pst) 70%, transparent); }
.rd-chip .rd-chip-status-confirmed,
.rd-chip .rd-chip-status-done { color: var(--pst); }
.rd-chip .rd-chip-status-error {
  color: var(--pgm);
  background: color-mix(in srgb, var(--pgm) 22%, var(--panel-2));
}
/* A failure is the one state worth interrupting for: the chip's plate turns red and the mark says
   why. Nothing is outlined. */
.rd-chip:has(.rd-chip-status-error) { background: var(--fail-plate); }

/* ─── Rundown rail: live stack — the rundown as a top-to-bottom list of now / next / on-take ── */
.rd-rail-stack {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* The rail's section gives it its edge and its line; its rows start where the script's text does. */
  padding: 0;
}
.rd-rail-stack-section { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rd-rail-stack-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 1px;
  min-width: 0;
  padding: 2px 4px;
  border-radius: var(--r-control);
}
/* The item on air, how far through it is on the rundown clock: a line under its head, in on air's
   green as its title, on a faint track; the head itself unfilled, as NEXT's and ON TAKE's are. A
   camera item with a planned duration reads exactly like a clip item. */
.rd-rail-stack-head-live {
  padding-bottom: 5px;
  background:
    linear-gradient(var(--pst), var(--pst)) left bottom / var(--rd-stack-progress, 0%) 2px no-repeat,
    linear-gradient(color-mix(in srgb, var(--text) 12%, transparent), color-mix(in srgb, var(--text) 12%, transparent)) left bottom / 100% 2px no-repeat;
}
.rd-rail-stack-title {
  flex: none;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.rd-rail-stack-onair .rd-rail-stack-title { color: var(--pst); }
.rd-rail-stack-next .rd-rail-stack-title { color: var(--on); }
.rd-rail-stack-take .rd-rail-stack-title { color: color-mix(in srgb, var(--pgm) 85%, var(--text)); }
.rd-rail-stack-sub {
  font-size: 10px;
  font-family: 'SF Mono', 'Fira Code', monospace;
  color: color-mix(in srgb, var(--muted) 90%, transparent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.rd-rail-stack-transition {
  flex: none;
  margin-left: auto;
  padding: 2px 6px;
  border-radius: var(--r-chip);
  background: color-mix(in srgb, var(--on) 18%, var(--panel-2));
  color: var(--on);
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.rd-rail-stack-row {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 2px 4px;
  border-radius: var(--r-control);
  /* The machine's colour, faintly, until it is sent, ready or playing, when it deepens. */
  background: var(--action-surface-idle);
}
/* A row said as its chip says it: the same plates, a size down to fit the list. */
.rd-rail-stack-label:has(.rd-rail-stack-parts) { display: flex; align-items: center; gap: 6px; }
.rd-rail-stack-suffix { flex: none; color: var(--muted); font-size: 10px; }
.rd-rail-stack-label {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 11px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The frame an on-air row landed on, seconds and frames, in a frame-accurate room. */
.rd-rail-stack-frame {
  flex: none;
  margin-left: auto;
  font-size: 10px;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-variant-numeric: tabular-nums;
  color: color-mix(in srgb, var(--muted) 90%, transparent);
}
/* Same status glyphs as the chips, laid out in-row instead of pinned to a chip corner. */
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status {
  flex: none;
  gap: 3px;
  margin-left: auto;
  margin-right: -2px;
}
.ui-chip-hover-action .rd-chip-status { margin-left: 0; }
.rd-chip-status-retries { margin-left: 3px; font-variant-numeric: tabular-nums; letter-spacing: 0; }
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-retries { margin-left: 0; }
.rd-rail-stack-row .rd-rail-stack-frame + .rd-chip-status { margin-left: 0; }
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-idle { color: color-mix(in srgb, var(--muted) 52%, transparent); }
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-pending { color: color-mix(in srgb, var(--muted) 76%, transparent); }
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-success { color: color-mix(in srgb, var(--pst) 70%, transparent); }
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-confirmed,
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-completed,
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-done { color: var(--pst); }
:is(.rd-rail-stack-row, .ui-event-identity, .ui-chip-hover-action) .rd-chip-status-error { color: var(--pgm); }
/* Live rows fill left-to-right on the rundown clock; a fully green stack reads as "played out —
   probably time to take". The gradient stops are hard so the fill edge is a crisp playhead.
   Instant actions (crosspoint cut, fader set) snap to full the moment they fire. */
.rd-rail-stack-row-live {
  background: linear-gradient(
    90deg,
    var(--action-surface-active) 0 var(--rd-stack-progress, 0%),
    var(--action-surface-idle) var(--rd-stack-progress, 0%) 100%
  );
}
.rd-rail-stack-row-played {
  background: var(--action-surface-active);
}
/* A cued NEXT row the device has CONFIRMED: acknowledged, holding — same green family as played,
   slightly quieter. */
.rd-rail-stack-row-ready {
  background: color-mix(in srgb, var(--kind-color, var(--pst)) 22%, transparent);
}
/* Sent, but nothing has confirmed it yet — or the device cannot confirm at all. Same green, held
   well back, so the row reads as done-ish without claiming the confirmation the fill used to imply
   the moment a command left the building. */
.rd-rail-stack-row-sent {
  background: color-mix(in srgb, var(--kind-color, var(--pst)) 12%, transparent);
}
.rd-rail-stack-emptyrow {
  padding: 2px 4px;
  font-size: 10px;
  color: color-mix(in srgb, var(--muted) 70%, transparent);
}
.rd-rail-stack-row:has(.rd-chip-status-error) {
  background: color-mix(in srgb, var(--pgm) 14%, transparent);
}

/* Event blocks carry the same mark as their chips, rolled up: one tick means something in the item
   ran, two mean all of it did. Deliberately the identical badge — same box, size, colours and corner
   — so it reads as the same signal at a different scale, with only the number of ticks differing. */
.rd-part > .rd-chip-status {
  position: absolute;
  /* Exactly the chips' offsets, so the marks form one column down the item and its lanes. It sits
     over the trim handle's lower few pixels; `pointer-events: none` keeps the handle draggable. */
  right: 2px;
  bottom: 1px;
  z-index: 10;
  pointer-events: none;
}
.rd-part > .rd-chip-status-idle { color: color-mix(in srgb, var(--muted) 52%, transparent); background: none; }
.rd-part > .rd-chip-status-pending { color: color-mix(in srgb, var(--muted) 76%, transparent); background: none; }
.rd-part > .rd-chip-status-success,
.rd-part > .rd-chip-status-done { color: var(--pst); }
/* The pair has to read as two ticks, not one wide glyph. */
.rd-part > .rd-chip-status-done { letter-spacing: -1.5px; padding-right: 3.5px; }
.rd-part > .rd-chip-status-error {
  color: var(--pgm);
  background: color-mix(in srgb, var(--pgm) 22%, var(--panel-2));
}
/* Zoomed out far enough and the badge is wider than the block it describes, so it reads as belonging
   to the neighbour. Drop it — but not the information: a failure keeps the block's own edge, which
   survives any zoom and is the one state worth spotting from across the rundown. */
.rd-part.rd-pw-xs .rd-chip-status { display: none; }
.rd-part:has(.rd-chip-status-error) { background: var(--fail-plate); }
.rd-part:has(.rd-chip-status-error):hover { background: color-mix(in srgb, var(--pgm) 36%, var(--panel-2)); }

/* Newsroom-template binding under the event tree: the key a newsroom's own automation template uses,
   so an item a journalist inserted resolves to this event. Deliberately plain — it is typed once per
   event and then forgotten, unlike the inherit list above it. */

/* Status strip above the /ncs event tree when a newsroom is hosting the page in an iframe. It has to
   explain itself: the operator sees this panel inside someone else's UI, with no other feedback. */
/* Connection status as a column on the right of the panel, collapsing to a sliver so the event list
   keeps the width. .ncs-root is a flex row, so this sits right simply by coming last. */
.ncs-status {
  flex: 0 0 220px;
  width: 220px;
  align-self: stretch;
  overflow: auto;
  padding: 6px 8px;
  border-left: 1px solid var(--line);
  background: var(--panel-2);
  display: grid;
  align-content: start;
  gap: 4px;
  font-size: 11px;
  position: relative;
}
/* Collapse toggle in the top right corner, so the strip can get out of the way of the event list. */
.ncs-status-toggle {
  position: sticky;
  top: 0;
  justify-self: end;
}
.ncs-status-state { justify-self: start; min-height: 18px; }
.ncs-status.collapsed { flex: 0 0 26px; width: 26px; padding: 4px 2px; overflow: hidden; }
.ncs-status-line, .ncs-status-meta { word-break: break-word; }
.ncs-status-line { color: var(--text); font-weight: 600; }
.ncs-status-meta { color: var(--muted); }
.ncs-status-log summary { color: var(--muted); cursor: pointer; }
.ncs-status-log pre {
  margin: 6px 0 0;
  max-height: 160px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
  font-size: 10px;
  color: var(--muted);
}

/* Read-only, copyable panel URL. Wide, because the useful part is at the end of it. */
.cfg-plugin-url .cfg-host { flex: 1 1 auto; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; }

/* Send button in the newsroom panel. Separate from selecting an event on purpose: the tags below it
   only exist once an event is selected, so one gesture cannot both choose and deliver. */

/* Drag handle in the newsroom panel. A dedicated grip rather than the whole row: pressing it starts
   the gesture immediately, with no movement threshold to guess at and no ambiguity with the click
   that selects the row. */

/* ─── GFX tab ───────────────────────────────────────────────────────────────── */

.gfx-tab {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.gfx-main {
  position: relative;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: var(--editor-rail-left) minmax(0, 1fr) var(--editor-rail-right);
}

.gfx-main.props-closed {
  grid-template-columns: var(--editor-rail-left) minmax(0, 1fr);
}
.gfx-main { grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "library center props" "timeline timeline props"; }
.gfx-main > .gfx-library { grid-area: library; }
.gfx-main > .gfx-center { grid-area: center; }
.gfx-main > .gfx-timeline { grid-area: timeline; }
.gfx-main > .gfx-props { grid-area: props; }
.gfx-main.props-closed { grid-template-areas: "library center" "timeline timeline"; }
/* The library and the timeline's list of layers are one sidebar: folded, both narrow to the rail, and
   a layer keeps only the mark of its kind (its name is in the hint and the properties). */
.gfx-main.library-collapsed { grid-template-columns: 44px minmax(0, 1fr) var(--editor-rail-right); }
.gfx-main.library-collapsed.props-closed { grid-template-columns: 44px minmax(0, 1fr); }
/* The list of layers continues the library's column: flush with it, as wide as it, open or folded. */
.gfx-main > .gfx-timeline { margin-left: 0; border-top-left-radius: 0; border-bottom-left-radius: 0; }
.gfx-main.library-collapsed .gfx-timeline { --editor-rail-left: 44px; }
.gfx-main.library-collapsed .gfx-tl-name { justify-content: center; padding-left: 0; padding-right: 0; font-size: 0; }
.gfx-main.library-collapsed .gfx-tl-layer-name,
.gfx-main.library-collapsed .gfx-tl-row-actions,
.gfx-main.library-collapsed .gfx-tl-remove,
.gfx-main.library-collapsed .gfx-tl-name .te-folder-arrow { display: none; }
.gfx-main.library-collapsed .gfx-tl-name .te-list-item { justify-content: center; padding: 0; }

.gfx-props-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: -4px;
}

.gfx-panel-title {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---- Library rail ---- */

.gfx-library {
  border-right: 1px solid var(--line);
  background: var(--panel);
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}

.gfx-library-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
}

.gfx-library-actions {
  display: flex;
  gap: 4px;
}

.gfx-new-wrap {
  position: relative;
}

.gfx-new-menu {
  position: absolute;
  top: 26px;
  left: 0;
  z-index: 20;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 160px;
}

.gfx-new-menu .ui-btn {
  width: 100%;
  justify-content: flex-start;
}

.gfx-library-error {
  padding: 6px 10px;
  font-size: 11px;
  color: var(--warn);
  border-bottom: 1px solid var(--line);
}

.gfx-library-list {
  flex: 1;
  overflow-y: auto;
  padding: 4px;
}

.gfx-library-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  padding: 6px 8px;
  /* As tall as the buttons that show on hover, so a row does not grow, and its neighbours move, under the pointer. */
  min-height: 32px;
  min-width: 0;
}

.gfx-library-item-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.gfx-badge {
  flex-shrink: 0;
  min-height: 16px;
  padding: 1px 4px;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.6px;
  color: var(--muted);
}

.gfx-library-item-actions {
  display: none;
  gap: 2px;
}

.gfx-library-item:hover .gfx-library-item-actions {
  display: flex;
}

.gfx-library-item-actions .ui-icon {
  width: 12px;
  height: 12px;
}

.gfx-delete-armed:not(:disabled) {
  color: var(--pgm);
  background: color-mix(in srgb, var(--pgm) 15%, var(--panel));
}

.gfx-library-empty {
  padding: 14px 10px;
  color: var(--muted);
  font-size: 12px;
}

/* ---- Canvas ---- */

.gfx-center {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.gfx-playout-test {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding-right: 10px;
  margin-right: 4px;
  border-right: 1px solid var(--line);
}

.gfx-playout-error {
  color: var(--pgm);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
}

/* Playout + view controls, under the canvas. Two bars beat one: the header used to hold the
   document actions AND these, and at narrow widths the row overflowed into the properties panel.
   This strip wraps instead of overflowing, so it survives a half-width window. */
.gfx-stage-controls {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 10px;
  padding: 5px 10px;
  border-top: 1px solid var(--line);
  background: var(--panel);
}

.gfx-stage-controls-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.gfx-stage-controls .gfx-playout-test {
  flex-wrap: wrap;
  gap: 5px;
  border-right: 0;
  padding-right: 0;
  margin-right: 0;
}

.gfx-stage-outer {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
}

.gfx-stage-wrap {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: auto;
  display: flex;
  background: var(--panel);
}

.gfx-stage-wrap.zooming {
  cursor: ns-resize;
}


.gfx-stage-empty {
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 13px;
}

.gfx-stage {
  position: relative;
  margin: auto;
  flex-shrink: 0;
  /* Transparency checkerboard: graphics render keyed over program. Kept just
     above the visibility threshold — it must never read as part of the design. */
  background: repeating-conic-gradient(var(--canvas-checker-a) 0% 25%, var(--canvas-checker-b) 0% 50%) 0 0 / 24px 24px;
  box-shadow: var(--float-shadow);
}

.gfx-stage-lottie,
.gfx-stage-grid,
.gfx-stage-overlay {
  position: absolute;
  inset: 0;
}

.gfx-stage-lottie svg {
  display: block;
}

.gfx-stage-grid {
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--canvas-grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--canvas-grid) 1px, transparent 1px);
  opacity: 0.35;
}

.gfx-stage-overlay {
  touch-action: none;
  cursor: default;
}

.gfx-selection {
  position: absolute;
  pointer-events: none;
  border: 1.5px solid var(--accent);
  border-radius: var(--r-chip);
}

.gfx-guide {
  position: absolute;
  pointer-events: none;
  background: var(--canvas-guide);
  z-index: 5;
}

.gfx-guide-v {
  top: 0;
  bottom: 0;
  width: 1px;
}

.gfx-guide-h {
  left: 0;
  right: 0;
  height: 1px;
}

/* ---- Properties panel ---- */

.gfx-props {
  border-left: 1px solid var(--line);
  background: var(--panel);
  overflow-y: auto;
  min-height: 0;
  min-width: 0;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.gfx-props-section {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.gfx-props-heading {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: var(--muted);
}

.gfx-props-row {
  display: flex;
  align-items: flex-end;
  gap: 6px;
}

/* A property that is either on or off, sitting in the row with the fields it governs — reading as
   part of the control rather than as a command to run. */
.gfx-props-toggle {
  flex: 1;
  min-width: 0;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}
.gfx-props-modes { gap: 4px; }

.gfx-props-note {
  margin: 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--muted);
}

.gfx-props-note code {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-radius: var(--r-chip);
  padding: 0 4px;
  font-size: 10px;
}

.gfx-numfield {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.gfx-numfield span {
  font-size: 9px;
  letter-spacing: 0.5px;
  color: var(--muted);
  text-transform: uppercase;
}

.gfx-textfield {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.gfx-textfield span {
  font-size: 9px;
  letter-spacing: 0.5px;
  color: var(--muted);
  text-transform: uppercase;
}

.gfx-colorfield {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
}

.gfx-colorfield span {
  font-size: 9px;
  letter-spacing: 0.5px;
  color: var(--muted);
  text-transform: uppercase;
}

.gfx-colorfield .ui-color-input {
  width: 100%;
}

/* The graphic's shapes in a row, the one on the canvas lit; the add and remove at the row's end. */
.gfx-shape-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.gfx-shape-field {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.gfx-field-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
}

.gfx-field-row code {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-radius: var(--r-chip);
  padding: 1px 5px;
  font-size: 10px;
}

.gfx-field-row span {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gfx-keytoggle {
  flex-shrink: 0;
  width: 20px;
  min-width: 20px;
  height: 20px;
  padding: 0;
  font-size: 9px;
}

/* Blue is a keyframe at the playhead. A property that is animated with none here is light, one that is not
   animated at all is grey: the diamond lights up where a keyframe is, not where there is none. */
.gfx-keytoggle.animated:not(.selected) {
  color: var(--text);
}
.ui-chip.gfx-keytoggle.selected {
  color: var(--accent);
}

/* ---- Timeline ---- */

.gfx-timeline {
  height: 272px;
  flex-shrink: 0;
  background: var(--panel);
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin: 8px;
  overflow: hidden;
}

.gfx-timeline-empty {
  height: 40px;
}

.gfx-timeline-toolbar {
  min-height: 36px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--line);
}

/* The speed picker beside Play: as wide as its longest, its list as wide as the trigger and no wider. */
.gfx-speed-wrap { flex: none; }
.gfx-speed { width: 84px; }
.gfx-speed .te-combo-trigger { min-height: 26px; padding: 2px 8px; font-variant-numeric: tabular-nums; }
.gfx-speed .te-combo-pop { min-width: 132px; }
.gfx-timecode {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--text);
  min-width: 92px;
}

.gfx-seg-readout {
  font-size: 10px;
  color: var(--muted);
}

.gfx-timeline-toolbar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.gfx-ease-strip {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: var(--muted);
}

.gfx-addlayer {
  display: flex;
  gap: 4px;
}

.gfx-timeline-zoom {
  flex: 0 0 110px;
  width: 110px;
}

.gfx-timeline-body {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

.gfx-timeline-content {
  position: relative;
  min-width: 100%;
}

.gfx-tl-row {
  display: flex;
  height: 32px;
  margin-bottom: 1px;
}

.gfx-tl-name {
  position: sticky;
  left: 0;
  z-index: 3;
  flex-shrink: 0;
  width: var(--editor-rail-left);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px;
  background: var(--panel);
  border-right: 1px solid var(--line);
  font-size: 12px;
  min-width: 0;
}

.gfx-tl-lane {
  position: relative;
  flex-shrink: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}

/* The sticky cell stays opaque; selection and hover belong to the shared row inside it. */
.gfx-tl-layer-cell { padding: 0; }
.gfx-tl-layer-cell > .te-list-item { width: 100%; height: 100%; }

.gfx-tl-ruler-row {
  height: 24px;
  position: sticky;
  top: 0;
  z-index: 4;
}

.gfx-tl-ruler-row .gfx-tl-name,
.gfx-tl-ruler {
  background: var(--panel-2);
}

.gfx-tl-ruler {
  cursor: ew-resize;
  touch-action: none;
  overflow: hidden;
}

.gfx-tl-tick {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  padding-left: 4px;
  border-left: 1px solid color-mix(in srgb, var(--line) 80%, transparent);
  font-size: 9px;
  color: var(--muted);
  pointer-events: none;
}

.gfx-tl-markers-row {
  height: 22px;
}

.gfx-tl-markers-name {
  color: var(--muted);
}

.gfx-tl-markers {
  touch-action: none;
}

.gfx-seg {
  position: absolute;
  top: 3px;
  bottom: 3px;
  border-radius: var(--r-chip);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  padding-left: 6px;
  overflow: hidden;
  white-space: nowrap;
  pointer-events: none;
}

.gfx-seg-in {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: var(--accent);
}

.gfx-seg-loop {
  background: color-mix(in srgb, var(--pst) 18%, transparent);
  color: var(--pst);
}

.gfx-seg-out {
  background: color-mix(in srgb, var(--on) 20%, transparent);
  color: var(--on);
}

.gfx-seg-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 9px;
  transform: translateX(-50%);
  cursor: ew-resize;
  z-index: 2;
}

.gfx-seg-handle::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 2px;
  bottom: 2px;
  width: 2px;
  border-radius: var(--r-chip);
  background: var(--muted);
}

.gfx-seg-handle:hover::after {
  background: var(--accent);
}

/* Continue stop: a park point inside the Loop segment (advanced past with the
   Continue command). Drawn as a pin so it reads differently from keyframes. */
.gfx-stop-pin {
  position: absolute;
  top: 1px;
  bottom: 1px;
  width: 10px;
  transform: translateX(-50%);
  cursor: ew-resize;
  z-index: 3;
  touch-action: none;
}

.gfx-stop-pin::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--warn);
  border-radius: var(--r-chip);
}

.gfx-stop-pin::after {
  content: '';
  position: absolute;
  left: 1px;
  top: -1px;
  width: 8px;
  height: 6px;
  background: var(--warn);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

.gfx-stop-pin:hover::before,
.gfx-stop-pin:hover::after {
  background: color-mix(in srgb, var(--warn) 60%, white);
}

.gfx-tl-markers-name .gfx-tl-row-actions {
  margin-left: auto;
}

.gfx-tl-kind {
  flex-shrink: 0;
  color: var(--muted);
  display: inline-flex;
}

.gfx-tl-kind .ui-icon {
  width: 12px;
  height: 12px;
}

.gfx-tl-layer-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gfx-tl-layer-name.hidden-layer {
  opacity: 0.45;
  text-decoration: line-through;
}

.gfx-tl-row-actions {
  display: none;
  gap: 2px;
}

.gfx-tl-name:hover .gfx-tl-row-actions,
.gfx-tl-name:focus-within .gfx-tl-row-actions {
  display: flex;
}

.gfx-tl-row-actions .ui-icon {
  width: 11px;
  height: 11px;
}

.gfx-tl-prop-row {
  height: 22px;
}

.gfx-tl-prop-name {
  padding-left: 26px;
  color: var(--muted);
  gap: 6px;
}

.gfx-tl-prop-name .gfx-keytoggle {
  width: 16px;
  height: 16px;
}

.gfx-tl-span {
  position: absolute;
  top: 7px;
  bottom: 7px;
  background: color-mix(in srgb, var(--panel-2) 80%, var(--accent) 6%);
  border-radius: var(--r-chip);
}

/* Tenant is the outermost scope every other object lives inside, so the status bar states it
   permanently rather than leaving it to be inferred from whatever is on screen. In the desktop app it
   reads as a label — a gallery belongs to one tenant — and only staff in a browser get a picker.
   Metrics match .app-room so the two line up. */
.app-tenant {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* The remote rundown renders the real tab. Read-only, it sits in an inert subtree, dimmed slightly and
   with the cursor left as default, so it reads as something being watched rather than something that
   is about to respond — inert already guarantees it will not. Editable, it looks like what it is. */
.rd-remote { display: flex; flex-direction: column; min-height: 0; height: 100%; }
/* A take or cue refused because the gallery runs another rundown: the notice that says so flashes,
   instead of a second message saying it again. */
.rd-remote-notice-flash { animation: rd-remote-notice-flash 0.9s ease-out; }
@keyframes rd-remote-notice-flash {
  0% { filter: brightness(1.35); }
  100% { filter: none; }
}
.rd-remote-body { flex: 1; min-height: 0; position: relative; }
.rd-remote-body:not(.editable) { opacity: 0.92; }
.rd-remote-body:not(.editable) * { cursor: default !important; }
.rd-remote-notice {
  display: flex; align-items: center; gap: 12px; justify-content: space-between;
  margin: 8px 12px; padding: 8px 12px; border-radius: var(--r-control);
  background: color-mix(in srgb, var(--warn) 14%, var(--panel));
}
.rd-remote-notice.admin-error { background: var(--fail-plate); }
/* Which gallery is on screen, and whether it is live: the two things a remote screen must never let
   anyone be unsure of. */
.rd-remote-bar { gap: 10px; }
.rd-remote-gallery { font-weight: 600; color: var(--text); }
.rd-remote-state {
  padding: 2px 8px; border-radius: var(--r-control); font-size: 11px; font-weight: 700; letter-spacing: 0.5px;
  text-transform: uppercase; color: var(--muted); background: var(--plate);
}
.rd-remote-state.live { color: var(--pst); background: color-mix(in srgb, var(--pst) 14%, var(--panel)); }

/* Says what the picker beside it cannot: what is on screen is another tenant's, not this node's. */
/* The tenant this app's LiveDeck belongs to, beside its name. */
/* The gallery's frame clock: source and timecode, amber when a reference it follows is lost. */
.app-clock-wrap { position: relative; display: inline-flex; }
.app-clock {
  gap: 6px;
  padding: 0 8px;
  font-size: 11px;
}
.app-clock.accurate { color: var(--accent); }
.app-clock.lost { background: color-mix(in srgb, var(--on) 16%, var(--plate)); color: var(--on); }
.app-clock-source { font-weight: 800; letter-spacing: 1px; font-size: 10px; }
.app-clock-tc { font-variant-numeric: tabular-nums; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
/* Its frames change thirty times a second. A box of fixed size, contained, so each change lays out and
   paints only the timecode, not the whole page around it; inside the button, since a box laid out by
   the button's own row is laid out again with it. */
.app-clock-tc-text { display: block; width: 11ch; height: 1lh; contain: strict; }
/* Opened over every pane, where its clock stands (FrameClock.tsx places it). */
.app-clock-panel {
  position: fixed;
  z-index: 1000;
  width: 340px;
  padding: 12px 14px;
  color: var(--text);
  font-size: 12px;
  line-height: 1.45;
}
/* The top bar's panels (ADR 0164) and, while its reference is lost, the clock: on the right, left of
   the tabs, which they take the place of at the right. */
.app-upper-panels { display: flex; align-items: center; gap: 4px; margin-left: auto; min-width: 0; }
.app-upper-panels > .ui-add-choice, .app-upper-panels > .app-lower-panel-chip { flex: none; }
.app-header .app-upper-panels ~ .app-tabs { margin-left: 0; }
/* The Timing pane's clock card opens the frame clock's facts. */
.rd-timing-clock-wrap { display: flex; min-width: 0; }
.rd-timing-clock-wrap > .rd-timing-clock { flex: 1 1 auto; min-width: 0; text-align: left; }
.rd-timing-clock.lost .rd-timing-label { color: var(--warn); }
.app-clock-title { font-weight: 700; font-size: 13px; margin-bottom: 6px; }
.app-clock-facts { display: grid; grid-template-columns: max-content 1fr; gap: 3px 12px; margin: 0; }
.app-clock-facts dt { color: var(--muted); }
.app-clock-facts dd { margin: 0; }
.app-clock-downloads { display: flex; gap: 8px; margin-top: 10px; }
.app-tenant-label {
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  white-space: nowrap;
}

.app-tenant-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* An unbound install is a supported state, not a fault: say so quietly rather than in alarm colours. */
.app-tenant.unbound .app-tenant-name {
  color: var(--muted);
  font-weight: 500;
}

/* Credentials are shown exactly once, so the panel has to read as something to act on now rather
   than a status line that can be scrolled past. */
.admin-issued {
  margin: 10px 0 12px;
  padding: 12px;
}
.admin-issued-head {
  display: flex;
  align-items: center;
  gap: 12px;
  font-weight: 600;
  font-size: 12px;
  margin-bottom: 9px;
}
.admin-issued-row { display: flex; align-items: center; gap: 10px; margin-bottom: 5px; }
.admin-issued-label {
  min-width: 68px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.6;
}
.admin-issued-row .copy-field { flex: 1; }
.admin-issued-row > code {
  user-select: all;
  padding: 3px 8px;
  border-radius: var(--r-chip);
  background: var(--field);
  font-size: 12px;
}
.admin-issued-note { font-size: 11px; opacity: 0.6; margin-top: 7px; }
/* A person's properties: a new password made for them, said once, then the button that makes one. */
.admin-user-password { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.admin-user-password > * { margin: 0; }
.admin-user-password .copy-field { align-self: stretch; }

/* Connecting is a deliberate, blocking act: it decides which customer this machine belongs to. */
.connect-note { margin: 0; font-size: 12px; opacity: 0.65; line-height: 1.45; }
.connect-modes { display: flex; gap: 8px; margin-top: 2px; }
.connect-error {
  font-size: 12px;
  padding: 8px 10px;
  border-radius: var(--r-control);
  background: var(--fail-plate);
}
.connect-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }

/* Administration is a settings page: it uses .settings-root, .settings-toolbar, the rail and
   .cfg-section, so what follows is only the parts Settings has no equivalent for. */
.admin-toolbar-spacer { flex: 1; }
/* Stage is its own settings group, alongside tenant-scoped administration. */
.settings-rail-group[data-group="Stage"] { --group-color: var(--group-stage); }
.admin-root .settings-rail-group[data-group="Tenant"] { --group-color: var(--accent); }
.settings-group[data-group="Stage"] .settings-group-head { --group-color: var(--group-stage); }

.admin-signin-hint { padding: 24px; }

/* Signed out is a page with something to do on it, not a sentence about a control elsewhere. */
.admin-signin { padding: 40px 24px; max-width: 560px; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.admin-signin h3 { margin: 0; font-size: 15px; font-weight: 600; }
.admin-signin-note { font-size: 12px; opacity: 0.6; line-height: 1.5; margin: 0; }

/* Its own class, not .cfg-add-row: that one styles a dashed BUTTON, so using it on the container
   drew a box around the row and trapped the button inside it. */
/* Dashed like .cfg-link-add-card (the tenant/group "+" cards), so a row that needs an actual typed
   value first — an email can't be guessed and renamed after, the way a tenant or group name can —
   still reads as the same "somewhere new goes here" affordance ending the list. */
.admin-add-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: var(--cfg-link-row-height, 46px);
  border: 1px dashed var(--line);
  border-radius: var(--r-control);
  padding: 6px 10px;
  margin-bottom: 4px;
}
.admin-add-row .ui-field {
  flex: 1;
  max-width: 340px;
}
.cfg-section-note { margin: -4px 0 12px; font-size: 12px; opacity: 0.6; }
/* A node's syncs (Settings → This machine, Admin → Nodes): one block per sync, what it took and sent. */
.admin-sync { font-size: 12px; color: var(--muted); }
.admin-sync.warn { color: var(--warn); }
.admin-node-sync p { margin: 2px 0; }
.admin-sync-part { margin-top: 10px; }
.cfg-sync { display: flex; flex-direction: column; gap: 6px; max-width: 900px; }
/* The calibration run's results (Settings → Timing): one line per device, its lead and how evenly. */
/* The leads read back, the pane's whole width: a figure and its five samples on one line. */
.cfg-calibration-results { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 12px; font-size: 12px; }
.cfg-calibration-results li { display: flex; align-items: baseline; gap: 2px 10px; flex-wrap: wrap; color: var(--text); }
.cfg-calibration-results li.warn { color: var(--warn); }
.cfg-calibration-device { flex: 0 0 100%; font-weight: 600; }
.cfg-calibration-error { margin: 0 0 12px; font-size: 12px; color: var(--warn); }
.admin-error {
  margin: 8px 12px; padding: 10px 12px;
  background: var(--fail-plate); color: var(--text);
}
.admin-empty { opacity: 0.5; font-size: 12px; margin: 4px 0; }

.admin-row {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; margin-bottom: 4px;
}
.admin-name { font-weight: 600; }
.admin-desc, .admin-seen { opacity: 0.6; font-size: 12px; }
.admin-node-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.admin-spacer { flex: 1; }

.admin-status {
  min-width: 62px;
  justify-content: center;
}
.admin-perm-areas { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; }
.admin-perm-area { display: flex; flex-direction: column; gap: 4px; }
.admin-perm-area-head {
  font-size: 10px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase;
  color: var(--muted); padding-bottom: 4px; border-bottom: 1px dashed var(--line);
}
.admin-perm { font-size: 12px; }

.admin-issued {
  margin: 10px 0 12px; padding: 12px;
}
.admin-issued-head { display: flex; align-items: center; gap: 12px; font-weight: 600; font-size: 12px; margin-bottom: 9px; }
.admin-issued-head .ui-btn { margin-left: auto; }
.admin-issued-row { display: flex; align-items: center; gap: 10px; margin-bottom: 5px; }
.admin-issued-label { min-width: 68px; font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.6; }
.admin-issued-row code { user-select: all; padding: 3px 8px; border-radius: var(--r-chip); background: var(--field); font-size: 12px; }
.admin-issued-note { font-size: 11px; opacity: 0.6; margin-top: 7px; }
/* Confirms the click did something, since the field is select-all text a click could otherwise
   just as easily have selected instead of copied. */

/* Tenant and group cards reuse the control-room card, so a customer looks like the other things you
   open rather than like a table row. Only the open-state colour differs, to match the rail. */
.admin .cfg-room-card .cfg-link-pill { margin-left: auto; }

/* Which customer you are working on, stated twice on purpose: in the toolbar where it survives
   scrolling, and above the sections it actually scopes. Getting this wrong means editing the wrong
   broadcaster's users, so it is worth the repetition. */
/* Staff → tenant, drawn as one unit rather than two loose facts: which employee you are, and which
   customer you currently have open. The tenant slot is always present, filled or "none open", so
   its emptiness is a visible state instead of the box simply not being there yet. */
.admin-open-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: none;
}
.admin-open-tenant {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 14px; padding: 9px 14px; border-radius: var(--r-card);
  background: var(--plate);
}
.admin-open-label {
  font-size: 10px; font-weight: 800; letter-spacing: 1px; text-transform: uppercase; opacity: 0.8;
}
.admin-open-name { font-size: 13px; font-weight: 700; color: var(--text); }
.admin-open-tenant .ui-btn { margin-left: auto; }
/* The add-user field sits at the end of the left column, where the AddChip sits on the right. */
/* Two columns and one arrow, not the three-column mapping grid: left as-is, the pair landed in
   the narrowest cells of a five-column template and left half the row empty. */
.cfg-linker-pair { grid-template-columns: minmax(280px, 1fr) 24px minmax(280px, 1fr); }

/* The add field ends the left column where the AddChip ends the right one. It wraps rather than
   squeezing the input to a width an email address cannot be read in. */
.cfg-link-list .admin-add-row { margin: 6px 0 0; flex-wrap: wrap; }
.cfg-link-list .admin-add-row .ui-field { flex: 1 1 180px; min-width: 0; max-width: none; }
.settings-props-body .admin-perm-area { margin-bottom: 14px; }

/* ── Flows (components/FlowWorkspace.tsx, components/FlowRecorder.tsx, ADR 0053, ADR 0054) ───────────────────
   Plates, as One look has everything: the chosen flow outlined in the selection line, and recording
   in the tally's red, as a recorder's lamp is. Record is a pill of the status bar, as Shortcuts and
   Status are; recording, its steps open upward from it, in a panel of its own. */
.flow-rec-wrap { position: relative; flex: 0 0 auto; }
.flow-rec {
  gap: 7px;
  padding: 0 10px;
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
}
.flow-rec-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.flow-rec.on .flow-rec-dot { background: var(--pgm); box-shadow: 0 0 8px color-mix(in srgb, var(--pgm) 70%, transparent); }
.flow-rec.on:not(.paused) .flow-rec-dot { animation: flow-rec-lamp 1.2s ease-in-out infinite; }
.flow-rec.paused .flow-rec-dot { background: color-mix(in srgb, var(--pgm) 45%, var(--muted)); box-shadow: none; }
.flow-rec-count { color: var(--muted); font-weight: 700; font-variant-numeric: tabular-nums; }
@keyframes flow-rec-lamp { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .flow-rec.on:not(.paused) .flow-rec-dot { animation: none; } }

/* The steps so far, under the button in Options. */
.flow-rec-panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 320px;
  margin-top: 6px;
}
.flow-rec-head { display: flex; flex-direction: column; gap: 3px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.flow-rec-kicker { color: var(--muted); font-size: 10px; font-weight: 900; letter-spacing: 1.6px; text-transform: uppercase; }
.flow-rec-note { color: color-mix(in srgb, var(--text) 78%, var(--muted)); font-size: 12px; line-height: 1.35; }
.flow-rec-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 0;
  overflow-y: auto;
  counter-reset: flow-rec-step;
}
.flow-rec-steps li {
  counter-increment: flow-rec-step;
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  gap: 6px;
  padding: 5px 8px;
  border-radius: var(--r-control);
  background: var(--plate);
  color: var(--text);
  font-size: 12px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.flow-rec-steps li::before { content: counter(flow-rec-step); color: var(--muted); font-weight: 800; font-variant-numeric: tabular-nums; }
.flow-rec-empty { margin: 0; color: var(--muted); font-size: 12px; }
.flow-rec-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.flow-rec-actions .flow-rec-discard { margin-left: auto; }

/* Problems, a section of Status (ProblemsSection.tsx, ADR 0115): each problem marked here, with what went wrong. */
.problem-list { list-style: none; margin: 0; padding: 4px 0; display: flex; flex-direction: column; gap: 6px; min-height: 0; overflow-y: auto; }
.problem-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 8px; padding: 6px 8px; border-radius: var(--r-control); background: var(--plate); }
.problem-list li .ui-field { grid-column: 1 / -1; }
.problem-when { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.problem-list li { grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; }
/* The code a customer gives LiveDeck: tinted so it is found at a glance, copied with a click. */
.problem-code.ui-btn { grid-row: 1; grid-column: 3; gap: 6px; padding: 0 8px; background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--text); }
.problem-code.ui-btn:hover { background: color-mix(in srgb, var(--accent) 34%, transparent); }
.problem-code code { font-family: 'SF Mono', 'Fira Code', Consolas, monospace; font-size: 12px; font-weight: 700; letter-spacing: .5px; }
.problem-code .ui-icon { width: 12px; height: 12px; }
.problem-unsent { grid-row: 1; grid-column: 2; color: var(--muted); font-size: 11px; white-space: nowrap; }

/* Live, a section of Status (LiveSection.tsx): each live slot's link, as a QR code a phone reads, with
   its code and the link beside it. The code's ground is light, as a phone's camera needs. */
.live-slot-body { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-start; }
.live-qr { flex: 0 0 auto; width: 148px; height: 148px; border-radius: var(--r-control); }
.live-qr-ground { fill: var(--on-fill); }
.live-qr-cells { fill: var(--ink); }
/* A slot someone is sending into: a green light and the word, as the status bar says devices are live. */
.live-connected { display: inline-flex; align-items: center; gap: 6px; }
.live-connected::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--pst); }
.live-slot-actions { flex: 1 1 140px; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }

/* Feeds, a section of Status (FeedsSection.tsx): the pictures chosen to watch, each a tile with its
   name, and the dashed card that adds one. */
.feeds-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 8px; align-items: start; }
/* A colour's theme role in the graphics editor (GfxTab.tsx RoleSwatches): its name, then the five. */
.gfx-role-swatches { display: grid; gap: 6px; }
.gfx-role-label { color: var(--muted); font-size: 11px; }
/* The data picker (DataPicker.tsx): named data as a tree, each value as it is now. */
.data-picker-anchor { display: inline-flex; }
.data-picker { position: fixed; z-index: 1000; box-sizing: border-box; display: grid; grid-template-rows: auto auto minmax(0, 1fr) auto; gap: 8px; width: min(420px, calc(100vw - 16px)); max-width: calc(100vw - 16px); max-height: min(480px, calc(100dvh - 16px)); padding: 10px; overflow: hidden; }
.data-picker-heading { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 10px; }
.data-picker-heading strong { color: var(--text); font-size: 12px; font-weight: 700; }
.data-picker-heading span { color: var(--muted); font-size: 11px; }
.data-picker > .ui-field { width: 100%; }
.data-picker-tree { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.data-picker-row { display: flex; align-items: center; min-height: 30px; gap: 7px; padding-right: 8px; padding-left: calc(8px + var(--data-depth, 0) * 14px); }
.data-picker-disclosure { flex: 0 0 12px; color: var(--muted); font-size: 10px; text-align: center; }
.data-picker-disclosure.empty { visibility: hidden; }
.data-picker-key { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.data-picker-key.is-branch { font-weight: 650; }
.data-picker-value { flex: none; max-width: 45%; overflow: hidden; color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; text-overflow: ellipsis; white-space: nowrap; }
.data-picker-value.is-branch { font-size: 10px; }
.data-picker-empty { color: var(--muted); padding: 8px; font-size: 12px; }
.data-picker-formats { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 8px; border-top: 1px solid var(--line); }
.gfx-props-linked { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--muted); font-size: 11px; }
/* Themes (ThemesSection.tsx): each a name and its five colours; open, a colour a row. */
.themes-section > .ui-fold-body { padding-inline: 0; }
.themes-list { display: grid; gap: 0; min-width: 0; }
.themes-own-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 40px; margin-left: 24px; padding: 6px 8px 6px 0; border-bottom: 1px solid var(--line); }
.themes-own-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.themes-own-copy strong { color: var(--text); font-size: 12px; }
.themes-own-copy span { color: var(--muted); font-size: 11px; }
.themes-fold > .ui-fold-body { padding: 0 10px 10px 24px; }
.themes-fold .ui-fold-title { color: var(--text); }
/* The palette on a lighter plate, so a ground as dark as the screen's own still shows. */
.themes-fold-colours { display: inline-flex; align-items: center; gap: 3px; flex: none; padding: 3px; border-radius: var(--r-chip); background: color-mix(in srgb, var(--text) 14%, transparent); }
.themes-fold-colours > span { width: 12px; height: 12px; border-radius: var(--r-chip); }
.themes-edit { display: grid; gap: 10px; min-width: 0; padding: 10px 0 4px; border-top: 1px solid var(--line); }
.themes-edit-heading { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
.themes-edit-heading span { color: var(--muted); font-size: 11px; }
.themes-name-row { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.themes-edit-heading .themes-name-label { flex: none; color: var(--muted); font-size: 11px; font-weight: 650; }
.themes-edit-heading .themes-name-value { display: inline-block; min-width: 0; max-width: 260px; overflow: hidden; color: var(--text); font-size: 12px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; }
.themes-name-value.inline-rename-input { width: min(260px, 100%); max-width: 260px; height: 28px; margin: 0; }
.themes-roles { display: grid; gap: 2px; min-width: 0; }
.themes-role { display: grid; grid-template-columns: minmax(88px, 1fr) minmax(120px, 1.5fr) minmax(90px, auto); align-items: center; gap: 10px; min-height: 34px; padding: 4px 8px; border-bottom: 1px solid var(--line); color: var(--text); }
.themes-role:last-child { border-bottom: 0; }
.themes-role-name { color: var(--muted); font-size: 12px; }
.themes-colour-value { display: flex; align-items: center; gap: 8px; min-width: 0; cursor: pointer; }
.themes-colour-value .ui-color-input { flex: none; width: 40px; height: 24px; }
.themes-colour-value code { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; font-variant-numeric: tabular-nums; }
.themes-role .toggle-label { justify-self: start; color: var(--muted); font-size: 11px; }
.themes-actions, .themes-add { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.themes-actions { padding-top: 2px; }
.themes-grow { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); font-size: 11px; }
.themes-grow .ui-color-input { width: 38px; height: 24px; }
.themes-remove { margin-left: auto; }
.themes-paste { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 10px; min-width: 0; color: var(--muted); font-size: 11px; }
.themes-paste > span { font-weight: 650; }
.themes-paste .ui-field { min-width: 0; }
.themes-error { color: var(--warn); font-size: 12px; }
@media (max-width: 560px) {
  .themes-own-row { align-items: flex-start; }
  .themes-fold > .ui-fold-body { padding-left: 16px; }
  .themes-role { grid-template-columns: minmax(76px, .8fr) minmax(0, 1.2fr) auto; gap: 6px; padding-inline: 4px; }
  .themes-paste { grid-template-columns: 1fr; gap: 4px; }
}
/* Feeds and Live scroll within themselves when they hold more than a panel has room for; the bar only
   under the pointer, so still they stand without a line beside them. */
.feeds-grid, .live-list { max-height: min(70vh, 760px); overflow-y: auto; overscroll-behavior: contain; }
/* Only scrolling content keeps room for its bar: a picture lifted on hover (HoverEnlarge) can take
   it away for a moment. The non-scrolling column wrappers keep no gutter, so pane heads reach the
   column edge without a blank strip below its close button. */
:is(.app-dock-scroll, .feeds-grid, .live-list) { scrollbar-gutter: stable; }
:is(.feeds-grid, .live-list)::-webkit-scrollbar-thumb { background: transparent; }
:is(.feeds-grid, .live-list):hover::-webkit-scrollbar-thumb { background: var(--plate-selected); }
.feeds-tile { margin: 0; min-width: 0; border-radius: var(--r-control); overflow: hidden; background: var(--plate); }
.feeds-caption { display: flex; align-items: center; gap: 4px; padding: 3px 4px 3px 2px; font-size: 11px; color: var(--text); min-width: 0; }
.feeds-caption > .feeds-picker { flex: 1 1 auto; min-width: 0; }
.feeds-fold { flex: none; color: var(--muted); }
/* A line high, the name keeps the letters that hang below it. */
.feeds-picker .te-combo-trigger-label { line-height: 1.35; }

/* Its × and its grip, as a pane's: there under the pointer, out of the way otherwise. */
.feeds-caption .ui-pane-controls { padding-right: 0; }
.feeds-tile[draggable="true"] { cursor: grab; }
.feeds-tile:is(:hover, :focus-within) .ui-pane-controls { grid-template-columns: 20px 12px; column-gap: 4px; }
.feeds-tile:is(:hover, :focus-within) .ui-pane-close { opacity: 1; pointer-events: auto; }
.feeds-tile:hover .ui-fold-grip { opacity: .8; }
/* A gateway picture in the monitors' own player (MonitorVideo), its bar holding what it shows on the left. */
.feeds-player { display: block; }
.feeds-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.feeds-choose { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.feeds-choose > :first-child { flex: 1; min-width: 0; }

/* The Flows page is Settings' (ADR 0034, ADR 0058): its rail, its mapping across, the room's triggers
   dragged onto its flows as a physical fader onto a virtual one, and the properties down. Its own:
   the flows a trigger starts, each run or run back; a flow's steps as their chips say them, in the
   pane rather than cut. */
.flows-empty { max-width: 60ch; }
/* Only takes the copy and paste keys of the cards in it (clipboard.ts): no box of its own. */
.flows-clip-keys { display: contents; }
.design-editor { display: flex; flex-direction: column; gap: 10px; }
.design-field-child { margin-left: 12px; width: calc(100% - 12px); }
.configuration-map-error { display: flex; align-items: center; gap: 8px; color: var(--pgm); }
.flows-text { width: 100%; box-sizing: border-box; }
.flows-lines { resize: vertical; min-height: 64px; font-family: 'SF Mono', 'Fira Code', monospace; font-size: 11.5px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; overflow-x: hidden; }
.flows-text[readonly] { color: var(--muted); }
.flows-now { color: var(--muted); font-size: 11px; line-height: 1.35; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.flows-now .app-chip-dot { display: inline-block; margin-right: 6px; vertical-align: 1px; }
.flows-seconds { gap: 8px; }
.flows-seconds .cfg-field-label { flex: 1; }
.flows-unit { color: var(--muted); font-size: 12px; }
.flows-run { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.flows-run-btn { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; }
.flows-run-btn .ui-icon { width: 13px; height: 13px; }
/* In effect as Status says a device wants looking at: the room is not as it was set up. */
.flows-in-effect { margin: 0; color: var(--on); font-size: 12px; line-height: 1.4; }
.flows-outcome { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.4; overflow-wrap: anywhere; }
.flows-outcome.failed { color: var(--pgm); }
.flows-step-block { display: flex; flex-direction: column; }
.flows-step { display: flex; flex-direction: column; gap: 6px; padding: 8px; border-radius: var(--r-control); background: var(--plate); }
.flows-step-head { position: relative; display: flex; align-items: center; min-height: 20px; }
.flows-step-head .flows-step-remove { top: 0; right: 0; }
.flows-step:hover .flows-step-remove, .flows-step-remove:focus-visible { opacity: 1; }
.flows-step-chips { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
/* A step's chip wraps in the pane: its parts on the next line, never cut. */
.flows-step-parts.rd-chip-route, .ai-line-parts.rd-chip-route { flex-wrap: wrap; white-space: normal; row-gap: 4px; overflow: visible; }
.flows-step-parts .rd-chip-token, .ai-line-parts .rd-chip-token { height: auto; min-height: 20px; padding-block: 3px; max-width: 100%; font-size: 11px; line-height: 1.2; white-space: normal; overflow-wrap: anywhere; }
.flows-step-rest { color: var(--muted); font-family: 'SF Mono', 'Fira Code', monospace; font-size: 10.5px; }
.flows-step-changes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; color: color-mix(in srgb, var(--muted) 80%, transparent); font-family: 'SF Mono', 'Fira Code', monospace; font-size: 10px; line-height: 1.35; overflow-wrap: anywhere; }
.flows-unapproved { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.flows-text.invalid { background: var(--fail-plate); }
.flows-now.failed { color: var(--pgm); }
/* A trigger that fired, and the flow it played or reversed, flash as a chip that fires in the rundown
   does: two names for one flash, so the next restarts it. Red where a step failed. */
.cfg-link-card.flows-flash-a { animation: flows-flash-a .72s ease-out; }
.cfg-link-card.flows-flash-b { animation: flows-flash-b .72s ease-out; }
.cfg-link-card.flows-flash-a.failed { animation: flows-flash-failed-a .9s ease-out; }
.cfg-link-card.flows-flash-b.failed { animation: flows-flash-failed-b .9s ease-out; }
@keyframes flows-flash-a { 0% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--pst) 96%, transparent), 0 0 18px color-mix(in srgb, var(--pst) 72%, transparent); filter: brightness(1.18); } 100% { box-shadow: none; filter: none; } }
@keyframes flows-flash-b { 0% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--pst) 96%, transparent), 0 0 18px color-mix(in srgb, var(--pst) 72%, transparent); filter: brightness(1.18); } 100% { box-shadow: none; filter: none; } }
@keyframes flows-flash-failed-a { 0%, 45% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--pgm) 96%, transparent), 0 0 18px color-mix(in srgb, var(--pgm) 74%, transparent); filter: brightness(1.16); } 100% { box-shadow: none; filter: none; } }
@keyframes flows-flash-failed-b { 0%, 45% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--pgm) 96%, transparent), 0 0 18px color-mix(in srgb, var(--pgm) 74%, transparent); filter: brightness(1.16); } 100% { box-shadow: none; filter: none; } }
@media (prefers-reduced-motion: reduce) { .cfg-link-card[class*="flows-flash-"] { animation-duration: .01s; } }

.configuration-profile-inspector { display: flex; flex-direction: column; gap: 10px; }
.configuration-profile-history { display: flex; flex-direction: column; gap: 4px; }
.configuration-profile-history > button { flex-direction: column; align-items: flex-start; text-align: left; }

.log-message-main {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.log-message-main > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}
/* A line's words as a path, like the one at the top of a tab (components/LogMessage.tsx). */
.log-msg { display: flex; align-items: center; min-width: 0; overflow: hidden; white-space: nowrap; }
.log-msg-lead { flex: 0 0 auto; }
.log-msg-step { display: inline-flex; align-items: center; min-width: 0; font-weight: 500; color: color-mix(in srgb, var(--text) 86%, transparent); }
.log-msg-step:last-child { overflow: hidden; text-overflow: ellipsis; }
.log-msg .path-step-arrow { margin: 0 6px; }
/* A device's own words: a command, a file, an id. */
.log-code { font-family: 'SF Mono', 'Fira Code', Consolas, monospace; font-size: 11px; font-weight: 500; padding: 0 4px; border-radius: var(--r-chip); background: color-mix(in srgb, var(--text) 8%, transparent); }
.log-meta-part { display: inline-flex; align-items: center; gap: 5px; }
.log-meta-dot { opacity: .6; }
.log-meta-dir { display: inline-flex; align-items: center; gap: 2px; }
.log-meta-dir .ui-icon { width: 10px; height: 10px; }
.log-action-controls {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
/* Add group takes a field or a chip dropped on it, as a group card does. */
.design-add-group { display: flex; min-width: 0; }
.design-add-group > .cfg-link-card { flex: 1 1 auto; }
.design-add-group.drop-ready > .cfg-link-card { background: var(--plate-selected); }

/* Panes (PanesMenu.tsx): a pane listing the screen's sections, each switched on or off. */
.app-panes-tree { min-height: 0; overflow-y: auto; padding-block: 4px; }
.app-panes-content .ui-fold-body { padding: 0; }
.app-panes-content .ui-fold-head { border-bottom: 0; min-height: 28px; }
.app-panes-content .ui-fold > .ui-fold-head > .ui-fold-toggle { padding: 4px 8px 4px calc(8px + var(--pane-depth, 0) * 14px); }
.app-panes-content .ui-fold-actions { padding: 2px 8px 2px 0; }
.app-panes-node > .ui-fold > .ui-fold-head .ui-fold-title { font-size: 11px; font-weight: 600; letter-spacing: 0; text-transform: none; }
.app-panes-place-group + .app-panes-place-group { border-top: 1px solid var(--line); margin-top: 3px; padding-top: 3px; }
.app-panes-row { display: flex; min-height: 28px; padding: 4px 8px 4px calc(24px + var(--pane-depth, 0) * 14px); gap: 8px; }
.app-panes-row:hover, .app-panes-row:focus-within { background: var(--plate); }
.app-panes-row .toggle-track { order: 2; }
.app-panes-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; }
.app-panes-row:has(.toggle-input:not(:checked)) .app-panes-name { color: var(--muted); }
.app-panes-switch { gap: 0; }
.app-panes-toggle-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.app-panes-filter { flex: none; padding: 8px; border-top: 1px solid var(--line); }
.app-panes-filter .ui-field { width: 100%; }
.app-panes-empty { padding: 8px 16px; color: var(--muted); font-size: 11px; }

.rd-rail-section-body[hidden] { display: none; }

/* Replay and problem reports use the same full-width folds as the other panes. */
.rd-run-stat { display: inline-flex; align-items: center; gap: 5px; }
.rd-run-fold { flex: none; }
.rd-run-issue .ui-btn { padding-inline: 10px; }
.problem-list { gap: 0; padding: 0; }
.problem-list > li { display: block; padding: 0; border-radius: 0; background: transparent; }
.problem-report-meta { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.problem-report .ui-field { width: 100%; }
.problem-report > .ui-fold-head .ui-fold-title { flex: none; font-variant-numeric: tabular-nums; }

.rd-rail-section:has(.rd-runs-panel).open > .rd-rail-section-body { padding: 0; gap: 0; }

.rd-rail-section-toggle { display: flex; flex: 1; align-items: center; gap: 6px; min-width: 0; padding: 6px 10px; cursor: pointer; }
.problem-toolbar { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 6px 10px; border-bottom: 1px solid var(--line); }
.problem-key { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.rd-run-actions .rd-run-action { grid-template-columns: 42px minmax(0, 1fr); min-height: 29px; }
.rd-run-action-time { display: inline-flex; justify-content: center; padding: 2px 4px; border-radius: var(--r-chip); background: var(--plate); }

/* One schematic of a transition (TransitionPreview.tsx), shown on hover as a graphic's preview is:
   the picture on air, dark, and the next one, light, changing places as the effect would. */
.transition-sample { position: relative; display: block; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; border-radius: var(--r-control); background: var(--bg); }
.transition-sample-onair, .transition-sample-next, .transition-sample-cover { position: absolute; inset: 0; }
.transition-sample-onair { background: linear-gradient(160deg, color-mix(in srgb, var(--text) 16%, var(--bg)), var(--bg)); }
.transition-sample-next { background: linear-gradient(160deg, var(--text), color-mix(in srgb, var(--text) 62%, var(--bg))); opacity: 0; }
.transition-sample-wipe .transition-sample-next { opacity: 1; clip-path: inset(0 0 0 100%); }
.transition-sample-slide .transition-sample-next, .transition-sample-swipe .transition-sample-next { opacity: 1; }
.transition-sample-swipe:not(.swipe-in) .transition-sample-onair { z-index: 1; }
.transition-sample-onair > span, .transition-sample-next > span { position: absolute; left: 10px; bottom: 8px; font-size: 10px; font-weight: 600; letter-spacing: .12em; }
.transition-sample-onair > span { top: 8px; bottom: auto; color: var(--muted); }
.transition-sample-next > span { right: 10px; left: auto; color: var(--bg); }
.transition-sample-cover { background: var(--bg); opacity: 0; }
.transition-sample-stinger .transition-sample-cover { opacity: 1; transform: translateX(-100%); background: linear-gradient(120deg, var(--bg), var(--muted)); }
.transition-sample-scene { position: absolute; inset: 0; width: 100%; height: 100%; fill: currentColor; opacity: .1; }
.transition-sample-onair { color: var(--text); }
.transition-sample-next { color: var(--bg); }
.transition-preview { display: block; width: 100%; }
.transition-preview-progress { display: block; height: 2px; background: var(--plate); }
.transition-preview-progress > span { display: block; width: 100%; height: 100%; background: var(--muted); transform: scaleX(0); transform-origin: left; }
.transition-preview-caption { display: flex; justify-content: space-between; gap: 8px; padding: 6px 4px 2px; color: var(--muted); font-size: 10px; }
.transition-preview-caption > span:first-child { color: var(--text); }
.transition-sample-cover { z-index: 2; }

/* Output (ADR 0165): ON AIR and NEXT, each its own monitor, one above the other, with the take between
   them running from left to right. */
.rd-output { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
/* The monitors as wide as the column: the section's own margin only a hair. */
.rd-rail-section.open > .rd-rail-section-body:has(> .rd-output) { padding: 4px; }
.rd-output > .rd-hc { width: 100%; }
/* Each title at its outer edge: the top monitor's over its picture, the bottom one's under it, so the
   take stands alone between the two pictures, whichever is on top. */
.rd-output > .rd-hc:last-child { flex-direction: column-reverse; }
/* The take in the middle between the monitors; ⇅ at the right edge, out of its way. */
.rd-output-take { position: relative; display: flex; align-items: center; min-width: 0; padding: 0 26px; }
.rd-output-take > .rd-header-transitions { flex: 1 1 auto; align-items: center; }
.rd-output-swap.ui-btn-icon { position: absolute; right: 0; top: 50%; transform: translateY(-50%); color: var(--muted); }
.rd-hc-result { display: inline-flex; flex: none; }
.rd-hc-result .rd-chip-status { position: static; }
.rd-header-transitions { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* The take's transition shares Actions' plates; it is as long as the transition, and fills from left
   to right on the timeline's clock, NEXT's tone giving way to ON AIR's as the mix runs. */
.rd-take-transition { position: relative; flex-direction: row; align-items: center; flex: none; height: 26px; min-width: 0; gap: 4px; padding: 1px 2px 1px 6px; transition: width .12s ease; }
.rd-take-transition:hover { background: var(--action-surface-active); }
.rd-take-transition.is-cut { background: var(--action-surface-idle); }
.rd-take-transition.is-cut:hover { background: var(--plate-hover); }
.rd-take-transition-label.ui-btn { flex: 1 1 auto; min-width: 0; height: 100%; min-height: 0; padding: 0; align-items: center; justify-content: flex-start; background: none; text-transform: none; font-weight: 500; }
.rd-take-transition-label.ui-btn:disabled { opacity: 1; cursor: default; }
.rd-take-transition .rd-chip-route { flex-direction: row; align-items: center; width: 100%; gap: 4px; }
.rd-take-transition .rd-chip-token-command { flex: none; padding: 2px 5px; font-size: 9px; }
.rd-take-transition .rd-chip-arrow, .rd-take-transition .rd-chip-token-destination { display: none; }
.rd-take-transition .rd-take-transition-duration { flex: none; margin-left: auto; padding: 0 4px; font-size: 10px; font-variant-numeric: tabular-nums; }
.rd-take-transition-flow { order: -1; display: flex; flex: none; color: var(--text); }
.rd-take-transition-flow .ui-icon { width: 12px; height: 12px; }
.rd-take-transition .rd-chip-kind { order: -2; min-width: 0; padding: 2px 5px; margin: 0; }
.rd-take-transition .rd-chip-status { margin: 0; }
/* In Actions, an action not run yet keeps the room its two checks will take, so its kind stands where
   a run one's does. */
.rd-rail-stack-row .rd-chip-status, .ui-chip-hover-action .rd-chip-status { min-width: 21px; box-sizing: border-box; align-self: flex-end; margin-bottom: 0; }
/* The main item's checks too: at its foot, 2 px up, in line with its lanes' chips, not in its middle. */
.rd-part > .ui-event-identity .ui-event-status { align-self: flex-end; margin-bottom: 1px; }
/* As on the rundown's chips: the checks at the foot of the row, 2 px up, not in its middle. */
.rd-take-transition.rd-rail-stack-row-live { background: linear-gradient(90deg, color-mix(in srgb, var(--pst) 34%, var(--action-surface-active)) 0 var(--rd-stack-progress, 0%), color-mix(in srgb, var(--on) 20%, var(--action-surface-idle)) var(--rd-stack-progress, 0%) 100%); }
.rd-take-transition.rd-rail-stack-row-live::before { content: ''; position: absolute; left: 0; bottom: 0; height: 2px; width: var(--rd-stack-progress, 0%); border-radius: var(--r-control); background: var(--kind-color); pointer-events: none; }
.rd-take-transition-handle.ui-btn-icon { flex: none; width: 18px; height: 18px; min-height: 0; padding: 0; color: var(--muted); cursor: ew-resize; touch-action: none; }
.rd-take-transition-top.ui-btn-icon { position: absolute; top: 0; left: 0; width: 8px; height: 100%; min-height: 0; padding: 0; overflow: hidden; background: none; z-index: 1; }
.rd-monitor-pending .rd-hc-result { animation: rd-rec-pulse 1s ease-in-out infinite; }
.rd-hc-next { --monitor-tone: var(--on); }
.rd-hc-program { --monitor-tone: var(--pst); }
.rd-hc-take-effect, .rd-monitor-arrived::after { position: absolute; inset: 0; z-index: 7; pointer-events: none; border-radius: inherit; box-sizing: border-box; padding: 3px; background: var(--monitor-tone); mask: linear-gradient(var(--ink) 0 0) content-box, linear-gradient(var(--ink) 0 0); mask-composite: exclude; opacity: 0; }
.rd-monitor-arrived::after { content: ''; animation: rd-monitor-arrival .45s ease-out both; }
.rd-monitor-arrived .rd-hc-top { animation: rd-monitor-band-arrival .45s ease-out both; }
@keyframes rd-monitor-arrival { from { opacity: .18; } to { opacity: 0; } }
@keyframes rd-monitor-band-arrival { 30% { filter: brightness(1.2); } }
.app-panes-content { display: flex; flex-direction: column; min-height: 0; }
.app-panes-content .app-panes-tree { max-height: 60vh; overflow: auto; }
@media (prefers-reduced-motion: reduce) { .rd-monitor-arrived::after, .rd-monitor-arrived .rd-hc-top { animation: none; } }

.ui-hover-enlarged .monitor-top { display: none; }

/* Feed pictures kept after their tile went (FeedsSection.tsx): the windows stand in the top layer, so
   the place that holds them takes no room. */
.feeds-kept { position: fixed; left: 0; top: 0; width: 0; height: 0; overflow: hidden; }

/* A scene on the Graphics canvas (ScenePanels.tsx, ADR 0152): its ground and boxes under the graphic,
   each box its source's live picture, cut as its framing says. */
.scene-stage { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.scene-preview-picture { display: block; position: relative; width: 100%; overflow: hidden; }
.scene-preview-box { position: absolute; overflow: hidden; }
.scene-steps, .scene-air-step { display: flex; flex-direction: column; gap: 6px; }
.scene-box { position: absolute; overflow: hidden; background: color-mix(in srgb, var(--bg) 70%, transparent); }
.scene-box-video { position: absolute; max-width: none; object-fit: fill; }
.scene-box-empty { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); font-size: 12px; outline: 1px dashed var(--line); outline-offset: -1px; }
.scene-box-name { position: absolute; left: 6px; top: 6px; padding: 2px 7px; border-radius: var(--r-pill); background: color-mix(in srgb, var(--bg) 66%, transparent); color: var(--text); font-size: 10px; opacity: 0; }
.scene-box.selected .scene-box-name { opacity: 1; }
.onair-boxes { position: absolute; inset: 0; z-index: 3; }
.onair-boxes:focus { outline: none; }
.onair-boxes:focus-visible .onair-box.selected { outline: 2px solid var(--focus-line); outline-offset: 1px; }
.onair-box { position: absolute; background: var(--plate); border-radius: var(--r-chip); cursor: move; touch-action: none; }
.onair-box:hover { background: var(--plate-hover); }
.onair-box.selected { background: var(--plate-selected); }
.onair-box-selection { inset: 0; }
.onair-box-corner { position: absolute; width: 12px; height: 12px; border-radius: var(--r-chip); background: var(--accent); pointer-events: auto; }
.onair-box-corner.tl { left: -6px; top: -6px; cursor: nwse-resize; }
.onair-box-corner.br { right: -6px; bottom: -6px; cursor: nwse-resize; }
.onair-box-corner.tr { right: -6px; top: -6px; cursor: nesw-resize; }
.onair-box-corner.bl { left: -6px; bottom: -6px; cursor: nesw-resize; }
.scene-box-corner { position: absolute; right: -6px; bottom: -6px; width: 12px; height: 12px; border-radius: var(--r-chip); background: var(--accent); pointer-events: auto; cursor: nwse-resize; }
.scene-range { display: grid; grid-template-columns: 52px minmax(0, 1fr) 44px; align-items: center; gap: 8px; color: var(--muted); font-size: 11px; }
.scene-range > span:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.scene-box-list { display: flex; flex-direction: column; gap: 2px; }
.scene-box-row { display: flex; align-items: center; gap: 8px; min-height: 26px; padding: 2px 8px; }
.scene-box-row-name { flex: 1 1 auto; min-width: 0; }
.scene-box-row-source { color: var(--muted); font-size: 11px; }
.scene-boxes-heading { display: flex; align-items: center; justify-content: space-between; }
.scene-layouts { display: flex; flex-wrap: wrap; gap: 4px; }

/* ── Getting started (GettingStarted.tsx): three steps on floating glass, moving nothing ───────── */
.gs-panel {
  position: fixed;
  z-index: 50;
  top: 96px;
  left: 50%;
  transform: translateX(-50%);
  box-sizing: border-box;
  width: min(900px, calc(100vw - 32px));
  max-height: calc(100vh - 140px);
  overflow: auto;
  padding: 20px 22px 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.gs-head { display: flex; align-items: center; gap: 10px; }
.gs-head h2 { margin: 0; font-size: 18px; font-weight: 650; }
.gs-head-space { flex: 1; }
.gs-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.gs-step {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 14px;
  border-radius: var(--r-card);
  background: var(--plate);
}
.gs-step.done { background: var(--plate-hover); }
.gs-step p { margin: 0; flex: 1; color: var(--muted); font-size: 12px; line-height: 1.45; }
.gs-step-title { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; }
.gs-step-mark {
  display: inline-grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: var(--r-pill);
  background: var(--plate-selected);
  font-size: 11px;
}
.gs-step.done .gs-step-mark { background: var(--accent); color: var(--ink); }
.gs-picture { width: 100%; height: auto; max-height: 96px; }
.gs-shape { fill: var(--plate-hover); }
.gs-dim { fill: var(--plate-selected); }
.gs-lit { fill: var(--accent); }
.gs-onair { fill: color-mix(in srgb, var(--pgm) 55%, transparent); }
.gs-line { fill: none; stroke: var(--plate-selected); stroke-width: 3; stroke-linecap: round; }
.gs-line-lit { stroke: var(--accent); }
.gs-note { display: flex; flex-direction: column; gap: 8px; font-size: 12px; color: var(--muted); }
.gs-note p { margin: 0; }
.gs-note strong { color: var(--text); font-weight: 600; }
.gs-off { margin: 0; display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; align-items: baseline; }
.gs-off dt { color: var(--text); }
.gs-off dd { margin: 0; }
.gs-off code { font-size: 11px; color: var(--text); background: var(--plate); padding: 1px 5px; border-radius: var(--r-chip); user-select: all; }
.gs-chip { position: fixed; z-index: 50; left: 50%; transform: translateX(-50%); bottom: 52px; padding: 4px; border-radius: var(--r-card); }
.gs-chip-count { color: var(--muted); font-weight: 500; }
@media (max-width: 720px) { .gs-steps { grid-template-columns: 1fr; } }

/* A node on another build than the stage's screens (NodeBuildNotice.tsx): said, not drawn against. */
.node-build-notice { min-height: 100vh; display: grid; place-items: center; padding: 16px; background: var(--bg); }
.node-build-card { width: min(520px, 100%); box-sizing: border-box; padding: 22px; display: flex; flex-direction: column; gap: 12px; }
.node-build-card h3 { margin: 0; font-size: 16px; }
.node-build-card p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.5; }
.node-build-card code { color: var(--text); background: var(--plate); padding: 1px 5px; border-radius: var(--r-chip); }
.node-build-asked { color: var(--text); }
.node-build-actions { display: flex; gap: 8px; }
