/* ═══════════════════════════════════════════════════════════════════════════
   TRACKFAST control room — dark theme.

   Loads LAST, after trackfast-phase4 / -network / -phase6.

   Those three files were converted to the dark palette mechanically: every
   colour literal was mapped by property, so light backgrounds became dark
   surfaces, dark ink became light ink, and the app's purple / blue / cyan /
   accent-yellow families were folded onto the brand pink while green and red
   kept their hues because they carry state.

   This file does the three things that sweep could not:
     1. restates the tokens, so a stale phase file cannot undo the theme
     2. fixes colours whose MEANING matters (on air, valid, ready, alerts)
     3. sets the typography

   Everything above the generated block at the bottom is a deliberate decision.
   Keep it that way.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── TOKENS ──
   Restated here, identical to the :root blocks in phase4 and phase6.

   The duplication is deliberate. This file loads last, so these win, which
   means the app themes correctly even if one of the three phase stylesheets on
   the server is stale, cached behind a CDN, or simply did not get uploaded.
   Without this block a stale phase file keeps its light --tf-paper / --soft and
   every token-driven surface turns white again.

   If you change a token, change it here AND in the phase files. */
:root {
  --ink: #ffffff;
  --muted: #b3a4ab;
  --line: rgba(255, 255, 255, .10);
  --surface: #150e12;
  --soft: #0a0609;
  --navy: #070406;
  --blue: #fc0271;
  --cyan: #fc0271;
  --green: #2ecc71;
  --amber: #e8a33d;
  --red: #ff5a5a;
  --shadow: 0 16px 45px rgba(0, 0, 0, .55);

  --tf-ink: #ffffff;
  --tf-muted: #b3a4ab;
  --tf-line: rgba(255, 255, 255, .10);
  --tf-purple: #fc0271;
  --tf-purple-dark: #a80149;
  --tf-coral: #ff5a5a;
  --tf-yellow: #fc0271;
  --tf-mint: #2ecc71;
  --tf-paper: #150e12;
  --tf-wash: #0a0609;
  --tf-shadow: 0 16px 46px rgba(0, 0, 0, .55);

  color: var(--tf-ink);
  background: var(--tf-wash);
}
html, body { background: var(--tf-wash); color: var(--tf-ink); }

/* ── TYPOGRAPHY ──
   ALL CAPS, everywhere a heading, label or control appears. Aldrich carries the
   headings and labels; Roboto carries body copy and controls. Tracking is
   scaled to size — the bigger the type, the tighter the letter-spacing, because
   caps at a large size need less air, not more.

   Applied consistently: page titles, panel and section headings, the sidebar
   nav, buttons, eyebrows, table headers, status pills, definition labels. */
body,
input, select, textarea {
  font-family: Roboto, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* Page title + brand. */
h1,
.page-header h1,
.network-page-header h1,
.brand strong {
  font-family: Aldrich, sans-serif;
  font-weight: 400;
  letter-spacing: .02em;
  text-transform: uppercase;
}

/* Panel and section headings. */
h2, h3, h4,
.section-title h2,
.card-title h2 {
  font-family: Aldrich, sans-serif;
  font-weight: 400;
  letter-spacing: .06em;
  text-transform: uppercase;
}

/* Small labels: more tracking, because caps need it at small sizes. */
.eyebrow,
thead th,
th,
.status-list dt,
.pill,
.sidebar-account small,
.station-sign small,
.sidebar-more summary,
label,
.field-label,
legend {
  font-family: Aldrich, sans-serif;
  font-weight: 400;
  letter-spacing: .14em;
  text-transform: uppercase;
}
/* The label wraps its input, so only the label's own text is capitalised —
   never the value the operator typed into it. */
label input,
label select,
label textarea {
  font-family: Roboto, ui-sans-serif, system-ui, sans-serif;
  letter-spacing: 0;
  text-transform: none;
}

/* Sidebar nav. */
.sidebar nav a b,
.primary-nav a b,
.sidebar-more nav a {
  font-family: Aldrich, sans-serif;
  font-weight: 400;
  letter-spacing: .12em;
  text-transform: uppercase;
}

/* Controls. */
.button,
.btn,
button,
.link-button {
  font-family: Roboto, ui-sans-serif, system-ui, sans-serif;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* The tally light. */
.station-sign strong {
  font-family: Aldrich, sans-serif;
  font-weight: 400;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* Anywhere digits line up in a column. */
td, .metric, .stat, .count, time { font-variant-numeric: tabular-nums; }

/* ── ACCENT INK ──
   White on #FC0271 is 3.8:1 and fails; near-black on it is 5.4:1 and passes.
   Every filled-pink control therefore takes dark text, the same rule the public
   site follows. */
.button.primary,
.btn-primary,
button[type="submit"].primary,
.signal-button.is-primary {
  color: #12000a;
  border-color: transparent;
  background: linear-gradient(115deg, #fc0271, #ff3d90);
  box-shadow: 0 10px 24px rgba(252, 2, 113, .28);
  font-weight: 700;
}
.button.primary:hover,
.btn-primary:hover { filter: brightness(1.08); color: #12000a; }

/* Secondary button: a faint lift, not a white chip. */
.button {
  background: rgba(255, 255, 255, .05);
  color: var(--tf-ink);
  border: 1px solid var(--tf-line);
}
.button:hover {
  background: rgba(252, 2, 113, .10);
  border-color: rgba(252, 2, 113, .45);
  color: #fc0271;
}

.channel-card,
article.channel-card {
  background: rgba(21, 14, 18, .94);
  border: 1px solid var(--tf-line);
}

/* ── ON AIR ──
   The one piece of state in the app that has to read across a room, so it keeps
   a real signal colour rather than the brand pink. Off-air stays muted: there is
   no such thing as a decorative on-air light. */
.station-sign { border: 1px solid var(--tf-line); }
.station-sign.is-off strong { color: var(--tf-muted); text-shadow: none; }
.station-sign.is-off i { background: #4a3c42; box-shadow: none; }
.station-sign.is-live { border-color: rgba(46, 204, 113, .45); background: rgba(46, 204, 113, .10); }
.station-sign.is-live strong { color: #2ecc71; text-shadow: 0 0 6px rgba(46, 204, 113, .55); }
.station-sign.is-live i { background: #2ecc71; box-shadow: 0 0 10px rgba(46, 204, 113, .8); }

/* ── STATE THE SWEEP COULD NOT READ ──
   A colour sweep maps hues; it cannot know that "valid", "ready" and "live" are
   good news. All three came through pink, which reads as a problem. Green means
   fine, and nothing else in the app is allowed to use green. */
.validation-summary,
.validation-summary.invalid {
  background: rgba(232, 163, 61, .10);
  border: 1px solid rgba(232, 163, 61, .35);
  color: #f0c078;
}
.validation-summary.valid {
  background: rgba(46, 204, 113, .10);
  border: 1px solid rgba(46, 204, 113, .35);
  color: #7ce0a6;
}
.friendly-status,
.page-schedule .friendly-status {
  background: rgba(232, 163, 61, .12);
  border-color: rgba(232, 163, 61, .35);
  color: #f0c078;
}
.friendly-status.ready,
.page-schedule .friendly-status.ready,
.feed-hub article.ready-feed > span {
  background: rgba(46, 204, 113, .12);
  border-color: rgba(46, 204, 113, .35);
  color: #7ce0a6;
}
.signal-state.live { color: #7ce0a6; }
.signal-state.live i { background: #2ecc71; }

/* ── ALERTS ──
   Dark tints with a coloured edge, so success / warning / danger stay instantly
   distinguishable from each other and from the pink chrome. */
.alert { border-radius: .5rem; border: 1px solid; }
.alert.success { background: rgba(46, 204, 113, .10); border-color: rgba(46, 204, 113, .40); color: #7ce0a6; }
.alert.warning { background: rgba(232, 163, 61, .10); border-color: rgba(232, 163, 61, .40); color: #f0c078; }
.alert.danger,
.alert.error   { background: rgba(255, 90, 90, .10);  border-color: rgba(255, 90, 90, .40);  color: #ff9a9a; }

/* ── FORMS ──
   Focus must stay visible on a dark ground; the original pale cyan ring is not. */
input, select, textarea {
  background: #100a0d;
  border: 1px solid var(--tf-line);
  color: var(--tf-ink);
}
input::placeholder, textarea::placeholder { color: #6f5d65; }
input:focus, select:focus, textarea:focus {
  outline: 3px solid rgba(252, 2, 113, .28);
  border-color: #fc0271;
}
a:focus-visible, button:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid #fc0271;
  outline-offset: 2px;
}

/* ── TABLES ── */
thead th { color: var(--tf-muted); border-bottom: 1px solid var(--tf-line); }
tbody tr + tr td { border-top: 1px solid rgba(255, 255, 255, .06); }
tbody tr:nth-child(even) td { background: rgba(255, 255, 255, .02); }
tbody tr:hover td { background: rgba(252, 2, 113, .06); }

/* ── SCROLLBARS ── */
* { scrollbar-color: #3a2c32 transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #3a2c32; border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: #fc0271; }

/* ── LOGIN ──
   The only screen an unauthenticated person reaches; it should match the public
   landing page it is one click from. */
.login-shell, .install-shell {
  background: #0a0609;
  background-image: radial-gradient(ellipse 90% 60% at 50% 0%, rgba(252, 2, 113, .14), transparent 70%);
}
.login-card, .install-card {
  background: #150e12;
  border: 1px solid var(--tf-line);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .6);
}
.login-card .eyebrow, .install-card .eyebrow { color: #fc0271; }

/* ── SCHEDULE GAPS ──
   These keep a light parent in the un-updated stylesheets, so surface and ink
   are both pinned rather than relying on the phase files having been replaced. */
.canvas-gap,
.page-schedule .canvas-gap { background: rgba(20, 14, 17, .92); color: #e8b7cb; }
.canvas-gap > span,
.page-schedule .canvas-gap > span { background: #1d1619; color: #ff7ab0; }

/* ── MOTION ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ═══ GENERATED: SURFACES ═══
   Every selector that painted a light surface in the original light theme,
   restated dark here as well as fixed at source. Redundant on purpose — this
   file loads last, so the app themes correctly even when a phase stylesheet on
   the server is stale. Hand-tuned selectors above are excluded from this list.
   Regenerate rather than hand-edit. */
.asset-poster-card { background: rgba(29, 22, 25, 1); }
.calendar-help { background: rgba(24, 18, 21, 1); }
.calendar-time-ruler { background: rgba(27, 21, 24, 1); }
.calendar-time-ruler > header { background: rgba(29, 22, 25, 0.96); }
.calendar-toolbar { background: rgba(29, 22, 25, 0.78); }
.canvas-board { background: rgba(28, 21, 24, 1); }
.canvas-board::-webkit-scrollbar-track { background: rgba(24, 18, 21, 1); }
.canvas-day { background: rgba(27, 20, 23, 1); }
.canvas-day > header { background: rgba(29, 22, 25, 0.96); }
.canvas-day.is-today > header::after { background: rgba(20, 15, 18, 1); }
.canvas-day.is-weekend .canvas-lane { background: rgba(28, 21, 24, 0.72); }
.canvas-day.is-weekend > header { background: rgba(27, 20, 23, 0.97); }
.canvas-event { background: rgba(29, 22, 25, 1); }
.canvas-lane { background: rgba(27, 20, 23, 0.78); }
.canvas-panel { background: rgba(29, 22, 25, 1); }
.composer-dropzone.drop-active { background: rgba(26, 20, 22, 1); }
.content-tray { background: rgba(28, 21, 24, 0.94); }
.copy-feed { background: rgba(25, 19, 22, 1); }
.destination-card { background: rgba(29, 22, 25, 1); }
.destination-card.mapped { background: rgba(29, 22, 25, 1); }
.destination-filters button { background: rgba(29, 22, 25, 1); }
.destination-network { background: rgba(29, 22, 25, 0.86); }
.distribution-platform-grid article { background: rgba(29, 22, 25, 1); }
.drop-hint { background: rgba(25, 19, 22, 1); }
.empty { background: rgba(29, 22, 25, 0.94); }
.feed-card-grid article { background: rgba(28, 21, 24, 1); }
.feed-dock { background: rgba(29, 22, 25, 1); }
.feed-hub article > span { background: rgba(25, 19, 21, 1); }
.feed-hub article.ready-feed > span { background: rgba(26, 20, 22, 1); }
.issue-strip span { background: rgba(25, 19, 21, 1); }
.network-channel-switcher { background: rgba(29, 22, 25, 0.78); }
.organizer-bar { background: rgba(29, 22, 25, 0.94); }
.package-studio { background: rgba(29, 22, 25, 0.82); }
.page-channel .panel { background: rgba(29, 22, 25, 0.94); }
.page-library .asset-poster-card { background: rgba(29, 22, 25, 1); }
.page-library .organizer-bar { background: rgba(29, 22, 25, 0.94); }
.page-library .panel { background: rgba(29, 22, 25, 0.94); }
.page-library .studio-nav a.active { background: rgba(24, 18, 21, 1); }
.page-library .studio-nav a:hover { background: rgba(24, 18, 21, 1); }
.page-library .studio-sidebar { background: rgba(29, 22, 25, 0.86); }
.page-library .studio-toolbar { background: rgba(29, 22, 25, 0.84); }
.page-library input { background: rgba(29, 22, 25, 1); }
.page-library select { background: rgba(29, 22, 25, 1); }
.page-library textarea { background: rgba(29, 22, 25, 1); }
.page-playlist .panel { background: rgba(29, 22, 25, 0.94); }
.page-schedule .canvas-gap > span { background: rgba(29, 22, 25, 0.88); }
.page-schedule .canvas-lane { background: rgba(27, 20, 23, 0.78); }
.page-schedule .canvas-panel { background: rgba(29, 22, 25, 1); }
.page-schedule .content-tray { background: rgba(28, 21, 24, 0.94); }
.page-schedule .panel { background: rgba(29, 22, 25, 0.94); }
.page-schedule input { background: rgba(29, 22, 25, 1); }
.page-schedule select { background: rgba(29, 22, 25, 1); }
.page-schedule textarea { background: rgba(29, 22, 25, 1); }
.panel { background: rgba(29, 22, 25, 0.94); }
.pill { background: rgba(26, 19, 22, 1); }
.pill.accepted { background: rgba(26, 19, 22, 1); }
.pill.blocked { background: rgba(25, 19, 22, 1); }
.pill.building { background: rgba(26, 19, 22, 1); }
.pill.completed { background: rgba(26, 19, 22, 1); }
.pill.confirmed { background: rgba(26, 19, 22, 1); }
.pill.connecting { background: rgba(26, 20, 23, 1); }
.pill.critical { background: rgba(25, 19, 22, 1); }
.pill.degraded { background: rgba(26, 20, 23, 1); }
.pill.dispatch_failed { background: rgba(25, 19, 22, 1); }
.pill.failed { background: rgba(25, 19, 22, 1); }
.pill.failover { background: rgba(26, 20, 23, 1); }
.pill.healthy { background: rgba(26, 19, 22, 1); }
.pill.incomplete { background: rgba(26, 19, 22, 1); }
.pill.not_configured { background: rgba(26, 20, 23, 1); }
.pill.pass { background: rgba(26, 19, 22, 1); }
.pill.ready { background: rgba(26, 19, 22, 1); }
.pill.requested { background: rgba(26, 20, 23, 1); }
.pill.sent { background: rgba(26, 19, 22, 1); }
.pill.unknown { background: rgba(26, 19, 22, 1); }
.pill.warning { background: rgba(26, 20, 23, 1); }
.platform-tile-grid article { background: rgba(29, 22, 25, 0.82); }
.playlist-drop-form { background: rgba(28, 21, 24, 1); }
.playlist-hero .pill { background: rgba(29, 22, 25, 1); }
.playlist-item { background: rgba(28, 21, 24, 1); }
.primary-nav a.active span { background: rgba(21, 16, 18, 1); }
.publish-button:disabled { background: rgba(25, 19, 22, 1); }
.rail-row > span { background: rgba(25, 18, 21, 1); }
.readiness-checks article > span { background: rgba(26, 19, 22, 1); }
.readiness-checks article.complete { background: rgba(27, 20, 23, 1); }
.rundown-event { background: rgba(29, 22, 25, 1); }
.sequence-number { background: rgba(24, 18, 21, 1); }
.signal-flow .signal-destination { background: rgba(29, 22, 25, 1); }
.signal-flow article { background: rgba(29, 22, 25, 1); }
.studio-nav a.active { background: rgba(25, 19, 22, 1); }
.studio-nav a:hover { background: rgba(25, 19, 22, 1); }
.studio-scoreboard article { background: rgba(29, 22, 25, 0.72); }
.studio-scoreboard article:nth-child(n) { background: rgba(29, 22, 25, 0.72); }
.tag-cloud a { background: rgba(27, 20, 23, 1); }
.timeline article > span { background: rgba(29, 22, 25, 1); }
.trackfast-origin { background: rgba(26, 19, 22, 1); }
.tray-card { background: rgba(29, 22, 25, 1); }
.tray-card.active { background: rgba(28, 21, 24, 1); }
.tray-card:hover { background: rgba(28, 21, 24, 1); }
.warning-copy { background: rgba(26, 19, 22, 1); }
progress::-webkit-progress-bar { background: rgba(24, 18, 21, 1); }
