/* Display Max control — a vision-mixer surface: graphite panels, tally red for live,
   green for armed and selected. */

/* The hidden attribute must always win. Several rules below set an explicit display,
   which would otherwise override the browser default of display:none and leave panels,
   overlays and toggled fields permanently visible. */
[hidden] { display: none !important; }

:root {
  --ink:        #eef0f2;
  --ink-dim:    #8b929b;
  --graphite:   #16181c;
  --panel:      #1d2026;
  --panel-2:    #23272e;
  --hairline:   #333941;
  --tally:      #e8412f;   /* live */
  --armed:      #69a84b;   /* selected / ready — rgb(105, 168, 75) */
  /* One green, doing one job: affirmative. Two greens a shade apart — a mint for confirm and
     an olive for selected — read as the same colour and give the eye nothing to sort by. The
     meaningful pair on this surface is red for live against green for ready. */
  --go:         #69a84b;   /* confirm — the same green as armed */
  --label: 600 11px/1 ui-sans-serif, "Roboto Condensed", "Arial Narrow", system-ui, sans-serif;
  --num: 500 12px/1 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0; background: var(--graphite); color: var(--ink);
  font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}
h1 { font-size: 22px; margin: 0 0 16px; letter-spacing: -.01em; }
h2 {
  font: var(--label); letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-dim); margin: 0 0 8px; padding-bottom: 6px; border-bottom: 1px solid var(--hairline);
}
h2.mt { margin-top: 18px; }
.eyebrow { font: var(--label); letter-spacing: .16em; text-transform: uppercase; color: var(--ink-dim); }
.meta { font: var(--num); color: var(--ink-dim); }

/* ---------- tally bar ---------- */
.tally {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 20px;
  padding: 10px 18px; background: #101216; border-bottom: 1px solid var(--hairline);
}
.tally-id { display: flex; align-items: center; gap: 10px; min-width: 260px; }
.tally-id strong { font-size: 13px; font-weight: 600; }
.tally-id .eyebrow { display: block; }
.lamp {
  width: 12px; height: 12px; border-radius: 50%; background: #3a3f47;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.12);
}
.lamp.live { background: var(--tally); box-shadow: 0 0 14px rgba(232,65,47,.75); }
.tally-right { margin-left: auto; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }

.tabs { display: flex; gap: 2px; }
.tab {
  font: var(--label); letter-spacing: .12em; text-transform: uppercase;
  background: transparent; color: var(--ink-dim); border: 1px solid transparent;
  padding: 9px 16px; border-radius: 3px; cursor: pointer;
}
.tab:hover { color: var(--ink); }
.tab.is-on { color: #101216; background: var(--armed); }


/* ---------- layout ---------- */
/* Columns rather than a grid: a short panel no longer reserves the height of the tallest
   one beside it, which is what left the large empty gaps. */
.panel-grid { padding: 10px; }
.panel-grid > .panel:not(.wide) { break-inside: avoid; page-break-inside: avoid; }
.panel-grid { columns: 3 340px; column-gap: 10px; }
.panel-grid > .wide { column-span: all; }

.panel {
  background: var(--panel); border: 1px solid var(--hairline); border-radius: 6px;
  padding: 12px 14px; margin: 0 0 10px; display: inline-block; width: 100%;
}
.panel.wide { display: block; margin-bottom: 10px; }
.panel-push { outline: 1px solid rgba(242,177,52,.25); }

.row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.row.tight { margin-top: 6px; }
.controls { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 8px 10px; margin-top: 10px; }
.controls.dense { grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 6px 8px; }

label { display: block; font: var(--label); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-dim); }
label.inline { display: inline-flex; align-items: center; gap: 8px; }
label.check { display: inline-flex; align-items: center; gap: 8px; text-transform: none; letter-spacing: .02em; font-size: 12px; color: var(--ink); }

/* ---------- switches ----------
   Every tick box in the control app is a switch. A tick reads as "this is selected"; a switch
   reads as "this is on", which is what every one of these actually means — audio is on, the
   shadow is on, the limiter is on. It is also readable across a gallery at a glance, which a
   14px tick is not, and the accent colour matches the sliders and the armed state so "green
   means on" is one rule rather than three.
   It is still a checkbox underneath: the tab order, the space bar, the label click and every
   .checked in the scripts all work exactly as before. */
input[type=checkbox] {
  appearance: none; -webkit-appearance: none; flex: 0 0 auto; position: relative;
  width: 34px; height: 19px; margin: 0; border-radius: 19px; cursor: pointer;
  background: var(--graphite); border: 1px solid var(--hairline);
  transition: background 140ms ease, border-color 140ms ease;
}
input[type=checkbox]::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px;
  border-radius: 50%; background: var(--ink-dim);
  transition: transform 140ms ease, background 140ms ease;
}
input[type=checkbox]:checked {
  background: color-mix(in srgb, var(--armed) 32%, transparent); border-color: var(--armed);
}
input[type=checkbox]:checked::after { transform: translateX(15px); background: var(--armed); }
input[type=checkbox]:disabled { opacity: .45; cursor: not-allowed; }
/* Keyboard focus has to stay visible: the switch is now the only thing showing state. */
input[type=checkbox]:focus-visible { outline: 2px solid var(--armed); outline-offset: 2px; }
output { float: right; font: var(--num); color: var(--armed); text-transform: none; letter-spacing: 0; }

select, textarea,
input[type=text], input[type=number], input[type=password], input[type=time] {
  width: 100%; margin-top: 4px; background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 3px; padding: 6px 8px; font: inherit; font-size: 13px;
}
/* Border only. The global :focus-visible ring below is what a keyboard user relies on, and
   clearing the outline here would take it away from them. */
select:focus, textarea:focus,
input[type=text]:focus, input[type=number]:focus, input[type=password]:focus, input[type=time]:focus {
  border-color: var(--armed);
}
textarea {
  display: block; resize: vertical; line-height: 1.5;
  font-family: inherit;          /* browsers default a textarea to monospace */
}
textarea::placeholder, input::placeholder { color: var(--ink-dim); opacity: 1; }
input.narrow { width: auto; flex: 1 1 140px; }
input.tiny { width: 60px; flex: 0 0 60px; text-align: center; }
label.inline select, label.inline input { margin-top: 0; width: auto; }
/* Colour inputs sit inside flex rows, where they were shrinking to a sliver — flex items
   collapse below their content unless told not to. Fixed size, and the browser's inner
   padding removed so the whole control is the colour rather than a stripe of it. */
input[type=color] {
  flex: 0 0 auto; width: 52px; min-width: 52px; height: 32px;
  padding: 3px; background: var(--panel-2);
  border: 1px solid var(--hairline); border-radius: 4px; cursor: pointer;
}
input[type=color]:hover { border-color: var(--armed); }
input[type=color]::-webkit-color-swatch-wrapper { padding: 0; }
input[type=color]::-webkit-color-swatch { border: 1px solid rgba(0, 0, 0, .4); border-radius: 2px; }
input[type=color]::-moz-color-swatch { border: 1px solid rgba(0, 0, 0, .4); border-radius: 2px; }

/* The swatch alone doesn't say much on a dark panel, so each one carries its hex value. */
.colour-field { display: inline-flex; align-items: center; gap: 7px; }
.colour-field .hex {
  font: var(--num); font-size: 11px; color: var(--ink-dim);
  letter-spacing: .04em; text-transform: uppercase; min-width: 58px;
}
input[type=range] { width: 100%; margin-top: 4px; accent-color: var(--armed); height: 16px; }
:focus-visible { outline: 2px solid var(--armed); outline-offset: 2px; }

/* ---------- buttons ---------- */
.btn {
  font: var(--label); letter-spacing: .1em; text-transform: uppercase;
  padding: 7px 12px; border-radius: 3px; border: 1px solid var(--hairline);
  background: var(--panel-2); color: var(--ink); cursor: pointer; text-decoration: none; display: inline-block;
}
.btn:hover { border-color: #4a525c; }
.btn-go { background: var(--go); border-color: var(--go); color: #0b1a06; }
.btn-ghost { background: transparent; }
.btn[disabled] { opacity: .4; cursor: not-allowed; }

.transport { display: grid; grid-template-columns: 2fr 1fr; gap: 8px; margin-top: 12px; }
.btn-push, .btn-pull { font-size: 14px; letter-spacing: .18em; padding: 14px 10px; border: none; }
.btn-push { background: var(--tally); color: #fff; }
.btn-pull { background: var(--panel-2); color: var(--ink); border: 1px solid var(--hairline); }
.btn-push:active { filter: brightness(1.15); }

/* ---------- pickers & media ---------- */
.picker, .media-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 6px; max-height: 190px; overflow-y: auto; padding: 2px;
}
.media-grid { max-height: none; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
.thumb {
  position: relative; aspect-ratio: 16 / 9; border-radius: 4px; overflow: hidden; cursor: pointer;
  background: #0c0e11; border: 2px solid transparent;
}
.thumb img, .thumb video { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb.sel { border-color: var(--armed); }
.thumb.live { border-color: var(--tally); }
.thumb .cap {
  position: absolute; inset: auto 0 0 0; padding: 4px 6px; font: var(--num); font-size: 10px;
  background: linear-gradient(transparent, rgba(0,0,0,.85)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.thumb .del {
  position: absolute; top: 4px; right: 4px; background: rgba(0,0,0,.6); color: #fff; border: none;
  border-radius: 3px; padding: 3px 6px; font-size: 11px; cursor: pointer; opacity: 0;
}
.thumb:hover .del { opacity: 1; }

.drop {
  border: 1px dashed var(--hairline); border-radius: 6px; padding: 26px; text-align: center; color: var(--ink-dim);
}
.drop.over { border-color: var(--armed); background: rgba(242,177,52,.06); }
.drop p { margin: 4px 0; }
.link { color: var(--armed); cursor: pointer; text-decoration: underline; text-transform: none; letter-spacing: 0; font: inherit; display: inline; }
.queue { margin: 12px 0; display: grid; gap: 6px; }
.queue div { font: var(--num); color: var(--ink-dim); }

/* ---------- playlists ---------- */
.list { list-style: none; margin: 12px 0 0; padding: 0; }
.list li {
  display: flex; align-items: center; gap: 10px; padding: 10px;
  border: 1px solid var(--hairline); border-radius: 4px; margin-bottom: 6px; cursor: pointer;
}
.list li.sel { border-color: var(--armed); }
.list li span.meta { margin-left: auto; }

.items { display: grid; gap: 8px; margin-top: 12px; }
.item {
  display: grid; grid-template-columns: 110px 1fr auto; gap: 12px; align-items: start;
  padding: 10px; border: 1px solid var(--hairline); border-radius: 4px; background: var(--panel-2);
}
.item img { width: 110px; aspect-ratio: 16/9; object-fit: cover; border-radius: 3px; background: #000; }
.item .fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; }
.item .ord { display: grid; gap: 4px; }

/* ---------- toast & login ---------- */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  background: var(--panel-2); border: 1px solid var(--hairline); border-left: 3px solid var(--go);
  padding: 10px 16px; border-radius: 4px; font: var(--num); z-index: 50;
}
.toast.bad { border-left-color: var(--tally); }

.login-page { display: grid; place-items: center; min-height: 100vh; }
.login-card { background: var(--panel); border: 1px solid var(--hairline); border-radius: 6px; padding: 28px; width: min(360px, 92vw); }
.login-card .btn { width: 100%; margin-top: 16px; }
.error { color: var(--tally); font-size: 13px; }

/* ---------- screen picker & screen cards ---------- */
.screen-pick { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.screen-pick select { min-width: 180px; }
.screen-pick.all select { border-color: var(--tally); color: var(--tally); }

.screen-card {
  display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: start;
  padding: 12px; border: 1px solid var(--hairline); border-radius: 4px; background: var(--panel-2);
}
.screen-card.live { border-color: var(--tally); }
.screen-card h3 { margin: 0 0 4px; font-size: 15px; font-weight: 600; }
.screen-card code {
  display: inline-block; font: var(--num); color: var(--armed);
  background: #101216; padding: 4px 8px; border-radius: 3px; margin: 4px 6px 0 0; word-break: break-all;
}
.screen-card .acts { display: grid; gap: 6px; }

/* ---------- program / preview monitors ---------- */
.monitors { padding-bottom: 12px; }
.mon-wrap { display: grid; grid-template-columns: 1fr 170px 1fr; gap: 14px; align-items: start; }
.mon-wrap.collapsed .mon { display: none; }
.mon-label {
  font: var(--label); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-dim);
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  margin-bottom: 6px; margin-inline: auto; max-width: calc(34vh * 16 / 9); width: 100%;
}
.mon-label.live { color: var(--tally); }
.mon-box {
  position: relative; aspect-ratio: 16 / 9; background: #000; border: 1px solid var(--hairline);
  border-radius: 4px; overflow: hidden;
}
.mon-pgm .mon-box { border-color: var(--tally); }
.mon-pvw .mon-box { border-color: var(--armed); }
/* the monitors are real players, scaled down */
.mon-box iframe {
  position: absolute; top: 0; left: 0; width: 1920px; height: 1080px; border: 0;
  transform: scale(var(--monscale, .28)); transform-origin: 0 0;
}

.take-col { display: grid; gap: 8px; align-content: start; padding-top: 22px; }
.btn-take {
  background: var(--tally); color: #fff; border: none;
  font-size: 14px; letter-spacing: .16em; padding: 20px 10px;
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
}
/* The chevrons point the way the scene travels: preview on the left, program on the right. */
.btn-take .chev { opacity: .75; font-size: 16px; line-height: 1; }
.btn-take:not(.idle) .chev { animation: chevNudge 1.6s ease-in-out infinite; }
.btn-take.idle .chev { opacity: .35; }
@keyframes chevNudge {
  0%, 100% { transform: translateX(0); opacity: .55; }
  50%      { transform: translateX(3px); opacity: 1; }
}
.btn-take:active { filter: brightness(1.15); }
.btn-take.idle { background: var(--panel-2); color: var(--ink-dim); border: 1px solid var(--hairline); }

/* ---------- preset strip ---------- */
.presets { display: flex; align-items: center; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.preset-bar { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; }
.preset {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 12px; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--hairline); border-radius: 3px; color: var(--ink); font-size: 13px;
}
.preset:hover { border-color: var(--armed); }
.preset kbd {
  font: var(--num); background: #101216; border: 1px solid var(--hairline); border-radius: 2px; padding: 1px 5px; color: var(--armed);
}
.preset .x { color: var(--ink-dim); padding-left: 2px; }

/* ---------- schedule rows ---------- */
.rule { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center;
        padding: 10px 12px; border: 1px solid var(--hairline); border-radius: 4px; background: var(--panel-2); }
.rule.on { border-color: var(--go); }
.rule h4 { margin: 0 0 2px; font-size: 14px; font-weight: 600; }
.rule .when { font: var(--num); color: var(--ink-dim); }
.rule .badge { font: var(--label); letter-spacing: .1em; text-transform: uppercase; color: var(--go); }

/* ---------- media warnings ---------- */
.thumb.warn { border-color: var(--armed); }
.thumb .flag {
  position: absolute; top: 4px; left: 4px; background: var(--armed); color: #101216;
  font: var(--label); padding: 2px 5px; border-radius: 2px;
}

/* ---------- shortcuts overlay ---------- */
.keys-help { position: fixed; inset: 0; background: rgba(8, 9, 11, .8); display: grid; place-items: center; z-index: 60; }
.keys-card { background: var(--panel); border: 1px solid var(--hairline); border-radius: 6px; padding: 24px; width: min(460px, 92vw); }
.keys-card ul { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 8px; font-size: 13px; }
.keys-card kbd {
  font: var(--num); background: var(--panel-2); border: 1px solid var(--hairline);
  border-bottom-width: 2px; border-radius: 3px; padding: 2px 7px; margin-right: 6px;
}

@media (max-width: 900px) {
  .mon-wrap { grid-template-columns: 1fr; }
  .take-col { padding-top: 0; }
}

.ver { opacity: .5; letter-spacing: .04em; }

.keys-card { position: relative; }
.keys-close {
  position: absolute; top: 10px; right: 12px; background: none; border: 0; cursor: pointer;
  color: var(--ink-dim); font-size: 22px; line-height: 1; padding: 4px 8px; border-radius: 3px;
}
.keys-close:hover { color: var(--ink); background: var(--panel-2); }

/* ---------- updater ---------- */
.drop.disabled { opacity: .45; pointer-events: none; }
.confirm-box {
  margin-top: 14px; padding: 14px; border-radius: 4px;
  border: 1px solid var(--armed); background: rgba(105, 168, 75, .07);
}
.confirm-box p { margin: 0 0 6px; }
#updLog { margin-top: 12px; }
#updLog div, #healthBox div { font: var(--num); color: var(--ink-dim); }
#healthBox { display: grid; gap: 4px; margin-bottom: 12px; }

/* ---------- shortcut chips ---------- */
.chip-bar { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  padding: 5px 9px; font-size: 12px; border-radius: 3px;
  background: var(--panel-2); border: 1px solid var(--hairline); color: var(--ink);
}
.chip:hover { border-color: var(--armed); }
.chip kbd {
  font: var(--num); font-size: 10px; color: var(--armed);
  background: #101216; border: 1px solid var(--hairline); border-radius: 2px; padding: 1px 4px;
}
.chip .x { color: var(--ink-dim); font-size: 11px; }
.chip .x:hover { color: var(--tally); }

/* ---------- ticker preview ---------- */
/* Overflow stays visible so a brand mark can overhang, the same as on screen. The message is
   clipped by its own wrapper instead — leaving it to the outer box meant a long line ran
   straight across the panel the moment the mark was allowed to overhang. */
.tick-preview {
  position: relative; overflow: visible;
  margin-top: 8px; padding: 8px 10px; border-radius: 3px;
  color: var(--tcolor, #fff); border: 1px solid var(--hairline);
}
.tp-clip { overflow: hidden; border-radius: inherit; }
.tp-run {
  display: inline-block; white-space: nowrap;
  animation: tp-scroll 18s linear infinite;
}
@keyframes tp-scroll { from { transform: none } to { transform: translateX(-50%) } }

/* Standing still is easier to read while a look is being built. */
.tick-preview:hover .tp-run { animation-play-state: paused; }
.tick-preview.theme-dark     { background: color-mix(in srgb, var(--tbg, #0a0c0f) 82%, transparent); }
.tick-preview.theme-solid    { background: var(--tbg, #0a0c0f); }
.tick-preview.theme-gradient { background: linear-gradient(90deg, var(--tbg, #000) 60%, transparent); }
.tick-preview.theme-clear    { background: repeating-linear-gradient(45deg, #1a1d22, #1a1d22 6px, #16181c 6px, #16181c 12px); }
.tick-preview.font-system    { font-family: system-ui, sans-serif; }
.tick-preview.font-condensed { font-family: "Roboto Condensed", "Arial Narrow", sans-serif; }
.tick-preview.font-mono      { font-family: ui-monospace, Menlo, monospace; }
.tick-preview.font-serif     { font-family: Georgia, serif; }
.tick-preview.font-rounded   { font-family: "SF Pro Rounded", Nunito, system-ui, sans-serif; }
.tick-preview.bold  { font-weight: 700; }
.tick-preview.upper { text-transform: uppercase; letter-spacing: .06em; }
.tick-preview .t-sep { color: var(--taccent, #e8412f); font-style: normal; padding: 0 .8em; }
.tick-preview .t-label {
  display: inline-block; margin-right: .7em; padding: 2px 7px;
  background: var(--taccent, #e8412f); color: var(--tbg, #0a0c0f);
  font-weight: 700; text-transform: uppercase; letter-spacing: .07em; font-size: .8em; border-radius: 2px;
}

.swatches { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.swatches label.inline { gap: 5px; }

/* ---------- collapsible panels ---------- */
.panel.foldable > h2:first-of-type { cursor: pointer; user-select: none; position: relative; padding-right: 18px; }
.panel.foldable > h2:first-of-type::after {
  content: '−'; position: absolute; right: 0; top: -1px; color: var(--ink-dim); font-size: 13px;
}
.panel.folded > h2:first-of-type::after { content: '+'; color: var(--armed); }
.panel.folded > h2:first-of-type { margin-bottom: 0; border-bottom: 0; padding-bottom: 0; }
.panel.folded > *:not(h2:first-of-type) { display: none; }
.panel.foldable > h2:first-of-type:hover { color: var(--ink); }

/* A pull button lights up while there is actually something on screen to pull. */
.btn.armed { border-color: var(--tally); color: #fff; background: rgba(232, 65, 47, .18); }
.btn-pull.armed { background: var(--tally); color: #fff; }

/* A player reporting a playback problem shouldn't blend into the status line. */
.meta.bad { color: var(--tally); }

/* ---------- live sub-tabs ---------- */
.subtabs {
  display: flex; gap: 2px; align-items: center; flex: 0 0 auto;
  padding: 2px; background: var(--graphite);
  border: 1px solid var(--hairline); border-radius: 4px;
}
.subtab {
  font: var(--label); letter-spacing: .1em; text-transform: uppercase;
  background: transparent; color: var(--ink-dim); border: 0;
  padding: 6px 14px; border-radius: 3px; cursor: pointer; white-space: nowrap;
}
.subtab:hover { color: var(--ink); background: var(--panel-2); }
.subtab.is-on { color: #101216; background: var(--armed); }

/* A pane divided into sub-panels. The panes are laid out in CSS columns, which
   ignore [hidden] unless display is said out loud, and which strand two short
   panels in the first column with two empty ones beside them. A wrapping row
   lets each panel take the width it can get. */
[data-subpanel][hidden] { display: none; }
[data-subpanel] {
  columns: auto;
  display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px;
}
[data-subpanel] > .panel { flex: 1 1 340px; }
[data-subpanel] > .panel.wide { flex-basis: 100%; }

/* The nav is a pill group, so it must not stretch to the width of the pane. */
.subtabs.pane-tabs { margin: 10px 10px 0; align-self: flex-start; width: max-content; }

/* ---------- program / preview clarity ---------- */
.mon-label .tag {
  font-size: 9px; letter-spacing: .12em; padding: 2px 5px; margin-left: 6px;
  border-radius: 2px; background: var(--panel-2); color: var(--ink-dim);
}
.mon-label.live .tag { background: var(--tally); color: #fff; }

.mon.inactive .mon-box { opacity: .45; }
.mon.inactive .mon-label { opacity: .6; }

.mon-hint {
  position: absolute; inset: 0; z-index: 2; display: grid; place-content: center;
  text-align: center; padding: 12px; gap: 6px;
  background: rgba(16, 18, 22, .82); color: var(--ink-dim); font-size: 12px; line-height: 1.6;
}
.mon-hint strong { color: var(--tally); }
.mon-hint em { color: var(--armed); font-style: normal; }

.take-note { margin: 0 0 2px; line-height: 1.4; }


/* Each group holds three panels; on a wide screen they sit side by side, and the column
   packing only kicks in when there isn't room for three. */
@media (min-width: 1200px) {
  .panel-grid[data-panel="live"] { columns: auto; display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; align-items: start; }
  .panel-grid[data-panel="live"] > .wide { grid-column: 1 / -1; }
  .panel-grid[data-panel="live"] > .panel { display: block; margin: 0; }
}


/* One line beneath the monitors carrying the section tabs and the saved looks, instead of
   two full-width bars stacked above and below. */
.strip {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--hairline);
}
.strip .eyebrow { flex: 0 0 auto; }
.strip .preset-bar { flex: 1 1 200px; margin: 0; }
.btn-sm { padding: 5px 10px; font-size: 10px; }

/* Monitors were taking half the window before a single control was visible. */
.monitors { padding: 10px 12px; }
.mon-wrap {
  gap: 32px;
  /* Columns sized to the monitors rather than to the window: three wide columns with
     centred content read as one row, not two slabs with a stranded transport. */
  grid-template-columns: minmax(0, calc(34vh * 16 / 9)) 150px minmax(0, calc(34vh * 16 / 9));
  justify-content: center;
}
/* Cap by width, not height: the box keeps its 16:9 ratio, so limiting the width is what
   actually limits how much of the window the monitors eat. Both boxes centre in their
   column — pinning them to the outer edges left a wide gap either side of the transport
   and made the pair look flung apart. */
.mon-box { max-width: calc(34vh * 16 / 9); margin-inline: auto; }
.mon-label { margin-bottom: 4px; font-size: 10px; }
.take-col { gap: 6px; padding-top: 18px; }
.take-col .btn { padding: 7px 10px; }
.btn-take { padding: 14px 10px !important; font-size: 13px; }
.take-note { font-size: 10px; opacity: .8; }

/* Image favourites carry a thumbnail, so the chip is a little taller than the others. */
.chip-img { padding: 3px 8px 3px 3px; gap: 7px; }
.chip-img img {
  width: 34px; height: 22px; object-fit: cover; border-radius: 2px; background: #000; display: block;
}


/* ---------- portrait screens ----------
   A 9:16 monitor is tall, so the pair sit narrower and the transport column keeps its width
   rather than being squeezed between two slabs. */
.mon-wrap.portrait .mon-box,
.mon-wrap.portrait .mon-label { max-width: calc(34vh * 9 / 16); }
.mon-wrap.portrait .mon-box { aspect-ratio: 9 / 16; }
.mon-wrap.portrait { grid-template-columns: 1fr 170px 1fr; }


/* Colour rows in the ticker panel: label above, swatch and hex below, so three of them
   fit the panel width without the labels being clipped. */
.swatches { gap: 12px 14px; }
.swatches label.inline {
  display: grid; gap: 4px; justify-items: start;
  font: var(--label); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-dim);
}

/* A favourite whose file has been deleted is kept, but greyed and struck through rather
   than silently doing nothing when clicked. */
.chip-missing { opacity: .5; text-decoration: line-through; cursor: not-allowed; }
.chip-missing:hover { border-color: var(--hairline); }

/* Player status sits beside the looks, where the rest of the screen-specific controls are,
   rather than wrapping into a tall block in the tally bar. */
.strip .players {
  margin-left: auto; text-align: right; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; max-width: 42ch; flex: 0 1 auto;
}
.strip .preset-bar { flex: 0 1 auto; }

/* ---------- camera panel ---------- */
/* ---------- self view and angle checking ----------
   The monitors already show the composited picture, so this is deliberately small: enough to
   frame a shot and to look down another camera before switching to it. */
.cam-angles { display: flex; align-items: stretch; gap: 12px; flex-wrap: wrap; }
.angle-col { display: flex; flex-direction: column; gap: 5px; flex: 1 1 200px; min-width: 0; }
.angle-col .eyebrow { margin-bottom: 1px; }

.selfview {
  position: relative; flex: 0 0 auto; width: 200px; aspect-ratio: 16 / 9;
  background: #05070a; border: 1px solid var(--hairline); border-radius: 4px; overflow: hidden;
}
.selfview video { width: 100%; height: 100%; object-fit: cover; display: block; transform: scaleX(-1); }
.sv-tag {
  position: absolute; left: 0; bottom: 0; padding: 2px 6px;
  font: var(--label); font-size: 9px; letter-spacing: .1em; text-transform: uppercase;
  background: rgba(10, 12, 15, .8); color: var(--ink-dim); border-radius: 0 3px 0 0;
}

.angle-list { display: flex; flex-wrap: wrap; gap: 4px; }
.angle {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px; cursor: pointer; text-align: left; white-space: nowrap;
  background: var(--panel-2); border: 1px solid var(--hairline); border-radius: 3px;
  color: var(--ink-dim); font-size: 12px;
}
.angle:hover { color: var(--ink); border-color: var(--armed); }
.angle.shown { border-color: var(--armed); color: var(--ink); }
.angle.live { border-color: var(--tally); color: var(--ink); }
.angle i {
  font-style: normal; font: var(--label); font-size: 9px; letter-spacing: .1em;
  color: var(--tally);
}

.angle-actions { display: flex; align-items: center; gap: 10px; margin-top: auto; }

.warn-note {
  border-left: 3px solid var(--armed); padding: 8px 10px; margin-top: 8px;
  background: rgba(105, 168, 75, .07); color: var(--ink); line-height: 1.5;
}

/* ---------- camera audio controls ---------- */
.audio-bar { display: flex; align-items: center; gap: 10px; margin: 8px 0 4px; }

.btn-mute { flex: 0 0 auto; min-width: 92px; }
.btn-mute.is-muted { background: var(--tally); border-color: var(--tally); color: #fff; }

.meter {
  flex: 1 1 120px; height: 12px; border-radius: 6px; overflow: hidden;
  background: var(--graphite); border: 1px solid var(--hairline);
}
.meter span {
  display: block; height: 100%; width: 0;
  /* Quiet through to loud. With one green the old green-to-green gradient was a flat bar;
     this reads as a meter should — green until it approaches clipping, then red. */
  background: linear-gradient(90deg, var(--go) 0%, var(--go) 72%, var(--tally) 100%);
  transition: width 60ms linear;
}
.meter span.hot { background: var(--tally); }


/* The camera section holds a single wide panel, so its preview and controls sit side by
   side rather than stacking down a narrow column. */
/* Two camera panels share the row equally instead of stacking, so the local camera and the
   remote rig are visible at the same time. */
@media (min-width: 1000px) {
  .panel-grid[data-panel="live"] > .panel[data-sec="camera"].wide { grid-column: span 1; }
  /* The local camera is the tall one — controls, audio, transport. Letting it hold both rows
     keeps the two feed lists stacked in the right-hand column: remote cameras above, network
     cameras beneath. Without the span the second list wraps back under the local camera and
     the pair are read as belonging to different columns. */
  .panel-grid[data-panel="live"] > .panel[data-cam="local"] { grid-row: span 2; }
}
@media (min-width: 1000px) and (max-width: 1399px) {
  .panel-grid[data-panel="live"] { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1400px) {
  .panel-grid[data-panel="live"] > .panel[data-sec="camera"].wide { grid-column: span 3; }
  .panel-grid[data-panel="live"] { grid-template-columns: repeat(6, 1fr); }
  .panel-grid[data-panel="live"] > .panel:not([data-sec="camera"]) { grid-column: span 2; }
  .panel-grid[data-panel="live"] > .wide:not([data-sec="camera"]) { grid-column: 1 / -1; }
}

/* The local camera panel reads top to bottom in one column: what the camera sees and which
   camera it is, then how it looks, then its sound, then one row of actions. The old two-column
   split left a tall empty gap beside the settings and scattered six controls down the side. */
.panel[data-sec="camera"] > .cam-angles { margin: 8px 0 12px; }


/* ---------- pairing a rig ----------
   The code is the whole point of the window, so it gets the room. White behind it always,
   whatever the rest of the app is doing: a scanner wants dark on light, and a code inverted to
   suit a dark interface is a code that does not read. */
.pair-card { max-width: 420px; text-align: center; }
.pair-code {
  width: min(300px, 70vw); margin: 14px auto 10px; padding: 10px;
  background: #fff; border-radius: 6px;
}
.pair-code svg { width: 100%; height: auto; display: block; }
.pair-url code { word-break: break-all; font-size: 11px; }
.pair-card .row { justify-content: center; }

/* ---------- framing a shot ----------
   The pane is the camera's own picture with the window drawn over it. What falls outside the
   window is dimmed and not hidden, deliberately: an operator tightening a shot needs to see
   what is about to be lost from it — a hand at the edge of frame, somebody about to walk in.
   The dimming is one huge spread shadow on the window itself rather than four panels, so
   there is nothing to keep in step with it. */
.framer-wrap { margin: 10px 0 4px; display: grid; gap: 6px; }

/* The pane is a fixed patch of the panel; the stage inside it is the shape the picture will
   actually land in. They are two elements because the stage has to change proportions with
   the chosen edge — a 9:16 format framed in a 16:9 box is not the framing that reaches the
   screen, it only looks like it. Same container-unit fit as the player's shape box, for the
   same reason: aspect-ratio cannot express "largest box of this ratio that fits". */
.framer {
  position: relative; width: 100%; max-width: 420px; height: 236px;
  container-type: size; cursor: move; user-select: none;
  /* Without this a drag on a touchscreen scrolls the panel instead of moving the window. */
  touch-action: none;
}
.frame-stage {
  position: absolute; inset: 0; margin: auto; overflow: hidden;
  width:  min(100cqw, calc(100cqh * var(--pane-ar, 1.7778)));
  height: min(100cqh, calc(100cqw / var(--pane-ar, 1.7778)));
  background: #05070a; border: 1px solid var(--hairline); border-radius: 4px;
}
/* Matched to the panel's own scaling, set alongside it: framing against a picture cropped
   differently from the one going out puts the window in the wrong place. */
.framer video { width: 100%; height: 100%; object-fit: cover; display: block; }

.framer .frame-none {
  position: absolute; inset: 0; margin: 0; display: grid; place-items: center;
  padding: 12px; text-align: center; color: var(--ink-dim); font-size: 11px; line-height: 1.5;
}
.frame-stage.has-picture .frame-none { display: none; }

/* Stood down: this panel is not the place to frame somebody else's camera. Greyed rather than
   removed, so the control does not vanish and reappear as feeds are switched between. */
.framer.is-off { opacity: .4; pointer-events: none; }

.frame-box {
  position: absolute; box-sizing: border-box; border: 1px solid var(--armed);
  box-shadow: 0 0 0 100vmax rgba(5, 7, 10, .55);
}
/* Nothing is being excluded when the whole frame is in use, so nothing is dimmed and the
   window steps back to a hairline rather than reading as a second edge to the pane. */
.frame-stage.is-whole .frame-box { box-shadow: none; border-color: rgba(105, 168, 75, .35); }

.frame-box i {
  position: absolute; width: 14px; height: 14px; box-sizing: border-box;
  background: var(--armed); border-radius: 2px; cursor: nwse-resize;
}
.frame-box i[data-grip="nw"] { left: -7px; top: -7px; }
.frame-box i[data-grip="se"] { right: -7px; bottom: -7px; }
.frame-box i[data-grip="ne"] { right: -7px; top: -7px; cursor: nesw-resize; }
.frame-box i[data-grip="sw"] { left: -7px; bottom: -7px; cursor: nesw-resize; }

/* A punch-in far enough to soften the picture is coloured, not only worded. */
.meta.warn { color: var(--tally); }


/* ---------- wordmark ---------- */
.brand {
  display: flex; align-items: baseline; gap: 4px; flex: 0 0 auto;
  font: 700 15px/1 ui-sans-serif, system-ui, sans-serif; letter-spacing: -.01em;
  padding-right: 14px; margin-right: 2px; border-right: 1px solid var(--hairline);
}
.brand b { color: var(--ink); font-weight: 700; }
.brand span { color: var(--armed); font-weight: 500; }
.login-card .brand, .front .brand { border: 0; padding: 0; margin-bottom: 6px; font-size: 20px; }

@media (max-width: 1100px) { .brand { display: none; } }

/* ---------- remote guests ---------- */
.rule.guest.waiting { border-color: var(--armed); }
.rule.guest.on-air  { border-color: var(--tally); }
.badge.live { color: var(--tally); }
.tiny-sel { width: auto; flex: 0 0 auto; }

/* What the pasted address was understood to be. */
.resolved {
  border-left: 3px solid var(--hairline); padding: 6px 9px; margin: 6px 0 0;
  background: var(--panel-2); line-height: 1.5;
}
.resolved.clean { border-left-color: var(--go); }
.resolved.bad { border-left-color: var(--tally); color: var(--tally); }

/* ---------- guest preview ---------- */
.guest-preview {
  position: relative; width: 260px; aspect-ratio: 16 / 9; margin: 8px 0;
  background: #05070a; border: 1px solid var(--tally); border-radius: 4px; overflow: hidden;
}
.guest-preview video { width: 100%; height: 100%; object-fit: cover; display: block; }
.guest-preview .btn { position: absolute; top: 6px; right: 6px; }

/* ---------- remote camera cards ---------- */
.guest-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 8px; margin-top: 10px;
}
.gcard {
  padding: 0 0 10px; border: 1px solid var(--hairline); border-radius: 4px;
  background: var(--panel-2); display: grid; gap: 7px; align-content: start;
  overflow: hidden;
}
.gcard > .gc-head, .gcard > .gc-meta, .gcard > .gc-actions { padding: 0 10px; }

/* The picture comes first: with six cameras, a face identifies one faster than a name. */
.gc-thumb {
  position: relative; aspect-ratio: 16 / 9; background: #05070a;
  border-bottom: 1px solid var(--hairline);
}
.gc-thumb video { width: 100%; height: 100%; object-fit: cover; display: block; }
.gc-thumb:not(.has-feed)::after {
  content: ''; position: absolute; inset: 0;
  background: repeating-linear-gradient(45deg, #101216, #101216 7px, #0b0d11 7px, #0b0d11 14px);
}
.gc-state {
  position: absolute; left: 5px; bottom: 5px; z-index: 2; padding: 2px 6px; border-radius: 2px;
  font: var(--label); font-size: 8px; letter-spacing: .12em;
  background: rgba(10, 12, 15, .85); color: var(--ink-dim);
}
.gcard.waiting .gc-state { color: var(--armed); }
.gcard.on-air .gc-state { background: var(--tally); color: #fff; }
.gcard.waiting { border-color: var(--armed); }
.gcard.on-air  { border-color: var(--tally); box-shadow: inset 0 0 0 1px rgba(232, 65, 47, .3); }
.gcard.editing { outline: 2px solid var(--armed); outline-offset: -1px; }

.gc-head b { font-size: 13px; font-weight: 600; }
.gc-meta { font: var(--num); font-size: 10px; color: var(--ink-dim); line-height: 1.4; }
.gc-actions { display: flex; flex-wrap: wrap; gap: 4px; }
.gc-actions .btn { padding: 5px 8px; font-size: 9px; letter-spacing: .08em; }
.badge.dim { color: var(--ink-dim); }

/* What the settings controls are currently pointed at. */
.editing-note {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  border-left: 3px solid var(--hairline); padding: 7px 10px; margin: 8px 0;
  background: var(--panel-2);
}
.editing-note.is-guest { border-left-color: var(--armed); background: rgba(105, 168, 75, .1); }
.editing-note strong { color: var(--armed); }

/* ---------- modal ---------- */
.modal {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: rgba(8, 9, 11, .82); padding: 20px;
}
.modal-card {
  position: relative; width: min(680px, 94vw); max-height: 88vh; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--hairline); border-radius: 6px; padding: 22px;
}
.modal-card h2 { border-bottom: 1px solid var(--hairline); }
.modal-card h2 span { color: var(--armed); text-transform: none; letter-spacing: 0; }

/* The preview box names whose feed it is, and says when nothing has arrived yet. */
.guest-preview { position: relative; }
.guest-preview::before {
  content: attr(data-who); position: absolute; top: 6px; left: 6px; z-index: 2;
  padding: 3px 7px; border-radius: 3px; background: rgba(10, 12, 15, .8);
  font: var(--label); font-size: 9px; letter-spacing: .1em; color: var(--ink);
}
.guest-preview:not(.live)::after {
  content: ''; position: absolute; inset: 0;
  background: repeating-linear-gradient(45deg, #101216, #101216 8px, #0b0d11 8px, #0b0d11 16px);
}
.guest-preview .sv-tag { z-index: 3; }

.diag {
  margin: 8px 0 0; padding: 10px; max-height: 220px; overflow: auto;
  background: #0e1014; border: 1px solid var(--hairline); border-radius: 4px;
  font: var(--num); font-size: 11px; color: var(--ink-dim); white-space: pre;
}

/* ---------- link quality ---------- */
.gc-link {
  font: var(--num); font-size: 10px; line-height: 1.4; color: var(--ink-dim);
  padding: 0 10px; min-height: 14px;
}
/* Three states need three readings. With green and red spoken for, "fair" is plain text:
   it is the one that means "worth a glance", not "act now". */
.gc-link.good    { color: var(--go); }
.gc-link.fair    { color: var(--ink); }
.gc-link.bad     { color: var(--tally); font-weight: 600; }
.gc-link.unknown { color: var(--ink-dim); }

.guest-preview::after {
  content: attr(data-link); position: absolute; right: 6px; bottom: 6px; z-index: 3;
  padding: 3px 7px; border-radius: 3px; background: rgba(10, 12, 15, .8);
  font: var(--num); font-size: 10px; color: var(--ink-dim);
}
.guest-preview:not(.live)::after { content: ''; }

/* ---------- per-camera audio meters ---------- */
.gc-audio { display: flex; align-items: center; gap: 7px; padding: 0 10px; }
.meter.mini { height: 6px; border-radius: 3px; flex: 1 1 auto; }
.meter.mini span { transition: width 40ms linear; }

/* A camera whose audio never moves is usually a muted interface, not a quiet guest. */
.meter.silent { opacity: .45; }
.gc-audio-note {
  font: var(--label); font-size: 8px; letter-spacing: .1em; color: var(--ink-dim);
  white-space: nowrap;
}


/* ---------- one action row for the local camera ---------- */
.cam-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hairline);
}
.cam-bar .btn-push, .cam-bar .btn-pull {
  flex: 0 0 auto; padding: 12px 20px; font-size: 12px; letter-spacing: .14em;
}
.cam-bar-state { display: grid; gap: 1px; flex: 1 1 200px; min-width: 0; line-height: 1.4; }
.cam-bar-state .meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cam-bar-end { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.cam-bar-end .narrow { flex: 0 0 150px; }

/* ---------- watching one remote camera ---------- */
.guest-watch { display: grid; gap: 6px; width: 260px; margin: 8px 0; }
.guest-watch .guest-preview { width: 100%; margin: 0; }
.watch-audio { display: flex; align-items: center; gap: 8px; }
.watch-audio .meter { flex: 1 1 auto; height: 8px; }
.watch-audio .meta { font-size: 10px; white-space: nowrap; }

/* Which feed carries the sound, when it is not the one being edited. */
#camPowerNote[data-audio]::after {
  content: attr(data-audio); display: block; color: var(--armed); margin-top: 2px;
}

/* Destructive actions read as destructive, without shouting. */
.btn.danger { color: var(--tally); }
.btn.danger:hover { border-color: var(--tally); background: rgba(232, 65, 47, .12); }

/* The ticker preview follows the same shapes and edges as the screen. */
.tick-preview.theme-glass     { background: color-mix(in srgb, var(--tbg, #0a0c0f) 45%, transparent); }
.tick-preview.theme-outline   { background: transparent; box-shadow: inset 0 0 0 2px var(--taccent, #e8412f); }
.tick-preview.theme-underline { background: linear-gradient(0deg, var(--tbg, #000) 60%, transparent); }
.tick-preview.shape-inset, .tick-preview.shape-pill { margin-inline: 10px; }
.tick-preview.shadow { box-shadow: 0 4px 14px rgba(0, 0, 0, .5); }
.tick-preview.edge-top, .tick-preview.edge-bottom, .tick-preview.edge-lead { position: relative; }
.tick-preview.edge-top::before, .tick-preview.edge-bottom::before {
  content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--taccent, #e8412f);
}
.tick-preview.edge-top::before { top: 0; } .tick-preview.edge-bottom::before { bottom: 0; }
.tick-preview.edge-lead::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 3px; background: var(--taccent, #e8412f);
}
.tick-preview .t-logo { height: 16px; width: auto; vertical-align: middle; margin-right: 8px; }
.tick-preview .t-logo.right { margin: 0 0 0 8px; }

/* The preview mirrors the overhang, so a mark standing proud of the bar can be judged here. */
.tick-preview { position: relative; }
.tick-preview:not(.logo-above) { overflow: hidden; }
.tick-preview .t-logo {
  position: absolute; z-index: 5; height: var(--plh, 20px); width: auto; top: 50%; left: 8px;
  transform: translate(var(--plx, 0), calc(-50% + var(--ply, 0)));
}
.tick-preview .t-logo.right  { left: auto; right: 8px;
  transform: translate(calc(var(--plx, 0) * -1), calc(-50% + var(--ply, 0))); }
.tick-preview .t-logo.centre { left: 50%;
  transform: translate(calc(-50% + var(--plx, 0)), calc(-50% + var(--ply, 0))); }


/* A long ticker message is one long line by nature, so the field wraps it rather than
   scrolling sideways — the whole message can be read while it is being written. */
#tickerText { min-height: 58px; word-break: break-word; }


/* The message passes under the mark here too, fading as it goes. */
.tick-preview.has-logo::before {
  content: ''; position: absolute; top: 0; bottom: 0; z-index: 4;
  width: calc(var(--plh, 20px) * 1.9); pointer-events: none;
}
.tick-preview.has-logo.logo-left::before {
  left: 0; background: linear-gradient(90deg, var(--tbg, #0a0c0f) 55%, transparent);
}
.tick-preview.has-logo.logo-right::before {
  right: 0; background: linear-gradient(270deg, var(--tbg, #0a0c0f) 55%, transparent);
}

/* ---------- recording ----------
   Beside the on-air lamp, because it answers the same question: what is this screen doing
   right now. Red only when it is actually rolling — not when it has been asked to. */
/* ---------- recording ----------
   Under the programme picture, because that is what it records. Red rather than the green
   every other switch uses: this one starts a file on a machine in another room, and it is the
   only control here whose cost is measured in disk. */
/* In the narrow column between the monitors, so it stacks rather than spreads. */
.rec-bar {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  margin: 2px 0 4px; padding-top: 8px; border-top: 1px solid var(--hairline);
}
.rec-bar .meta { font-size: 10px; line-height: 1.4; }
.rec-switch { gap: 8px; font-size: 11px; }
/* Unavailable, not absent: greyed and explained rather than gone. */
.rec-bar.is-off { opacity: .55; }
.rec-bar select { width: 100%; margin: 0; font-size: 11px; padding: 3px 6px; }

/* Publishing is green: it costs bandwidth, not a disk, and it is the ordinary state during a
   session with anybody remote in it. Red is kept for the one control that writes a file. */
.pub-switch input[type=checkbox]:checked {
  background: color-mix(in srgb, var(--armed) 32%, transparent); border-color: var(--armed);
}
.rec-bar.pub-on .rec-dot { background: var(--armed); }
.rec-switch input[type=checkbox]:checked {
  background: color-mix(in srgb, var(--tally) 34%, transparent); border-color: var(--tally);
}
.rec-switch input[type=checkbox]:checked::after { background: var(--tally); }
.rec-switch input[type=checkbox]:focus-visible { outline-color: var(--tally); }

/* Asked for but not yet happening — the state that needs watching, and the one a plain
   on-or-off switch would hide. The switch is where it was put; the lamp is the truth. */
.rec-bar.is-on  .rec-dot { background: var(--tally); animation: recPulse 2s ease-in-out infinite; }
.rec-bar.is-pending .rec-dot { background: var(--armed); animation: recPulse 1s ease-in-out infinite; }
.rec-bar.is-on  #recLabel { color: var(--ink); }

/* Going out to the public is red like recording, not green like a studio control: it is the
   one switch here whose consequence is outside the building and cannot be taken back. */
#strBar.is-on .rec-dot { background: var(--tally); animation: recPulse 2s ease-in-out infinite; }
#strBar.is-on #strLabel { color: var(--ink); }
.rec-bar.is-pending #recLabel { color: var(--armed); }

/* The lamp, which says what the machine is doing rather than what was asked of it. */
.rec-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--ink-dim); flex: 0 0 auto; }

@keyframes recPulse { 0%, 100% { opacity: 1 } 50% { opacity: .35 } }

/* ---------- who is signed in ---------- */
.who { display: flex; flex-direction: column; line-height: 1.25; text-align: right; margin-right: 4px; }
.who b { font-size: 12px; font-weight: 600; color: var(--ink); }
.who span { font: var(--label); font-size: 9px; letter-spacing: .1em; color: var(--ink-dim); }

.rule.user.off { opacity: .55; }
.rule.quiet { border-left-color: var(--hairline); }
.rule.quiet h4 { font-weight: 500; color: var(--ink-dim); }

/* A network camera card has no thumbnail: its picture goes to the screen, not through here. */
.gcard .gc-thumb:empty, .gcard .gc-thumb:not(:has(video)) { aspect-ratio: auto; min-height: 26px; }
.meta.good { color: var(--go); }
.meta.bad  { color: var(--tally); }

/* Marking an image as one a remote guest may put behind themselves. */
.bg-flag {
  position: absolute; left: 6px; top: 6px; z-index: 2;
  padding: 4px 8px; border-radius: 3px; cursor: pointer;
  background: rgba(10, 12, 15, .78); border: 1px solid var(--hairline);
  color: var(--ink-dim); font: var(--label); font-size: 9px; letter-spacing: .08em;
}
.bg-flag:hover { color: var(--ink); }
.bg-flag.on { background: var(--go); border-color: var(--go); color: #0b1a06; }
