/**
 * BLAST Esports Ops Workshop — shared design system.
 *
 * Loaded by both RLCS Ops Tracker and BLAST Online Staffing so the two
 * projects never drift into two different-looking tools. Originated as
 * RLCS Ops Tracker's dark theme (its blue/orange team-side colors are a
 * functionally meaningful convention worth keeping as the base), extended
 * here with a light variant and ported into a shared file both projects
 * reference instead of copy-pasting.
 *
 * Theme switching: a `data-theme="light"|"dark"` attribute on <html>,
 * applied by a small inline pre-paint <script> in each page's <head>
 * (before this stylesheet loads, so there's no flash of the wrong theme)
 * and toggled at runtime by theme.js. See theme.js for the toggle mechanism
 * — ported from BLAST Online Staffing's original implementation.
 */

:root {
  color-scheme: light;
  --bg-0: #f5f6f9;
  --bg-1: #ffffff;
  --bg-2: #eef0f5;
  --bg-3: #e2e6ef;
  --border: #d7dbe6;
  --text-0: #161922;
  --text-1: #4b5468;
  --text-2: #6b7484;

  --blue: #1d6fd1;
  --blue-dim: #dbeaff;
  --orange: #b85c00;
  --orange-dim: #ffe6cc;

  --amber: #8a5a00;
  --green: #1e7d46;
  --red: #c62828;

  --live: #d61f36;

  --shadow: rgba(20, 24, 34, 0.12);

  --radius: 10px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
}

/* Dark mode — toggled by adding data-theme="dark" to <html> (see theme.js).
   Originally RLCS Ops Tracker's only palette; every color is a variable
   specifically so this is the one place either theme needs to be defined. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg-0: #0b0d12;
  --bg-1: #12151c;
  --bg-2: #1a1e28;
  --bg-3: #232838;
  --border: #2c3142;
  --text-0: #f2f4f8;
  --text-1: #b8bfcf;
  --text-2: #7c869c;

  --blue: #3b9dff;
  --blue-dim: #1f4b73;
  --orange: #ff8a2b;
  --orange-dim: #7a4318;

  --amber: #ffb545;
  --green: #3ecf7e;
  --red: #ff5a5f;

  --live: #ff3b4e;

  --shadow: rgba(0, 0, 0, 0.4);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg-0);
  color: var(--text-0);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.4;
}

a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------- */
/* Layout shell                                                            */
/* ---------------------------------------------------------------------- */

.app-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Grid, not flex space-between: the brand (left) and status/theme-toggle
   (right) columns get a fixed width each, so when their TEXT changes after
   load ("loading event…" -> the real event name, "connecting…" -> "relay
   connected") the nav tabs in the middle column don't shift sideways — a
   flex space-between layout re-distributes gaps on every text-width change,
   which is what caused that. Content longer than its column truncates
   (see .event-name/.conn-status below) rather than pushing anything. */
.topbar {
  display: grid;
  grid-template-columns: 260px 1fr 260px;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 50;
}

.topbar .brand {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  min-width: 0; /* let the fixed grid column win over content's natural width */
}

.topbar .brand .brand-logo {
  height: 28px;
  width: auto;
  flex: 0 0 auto;
  display: block;
}

.topbar .brand .event-name {
  color: var(--text-2);
  font-weight: 400;
  font-size: 0.85em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.nav-tabs {
  display: flex;
  justify-content: center;
  gap: 4px;
  flex-wrap: wrap;
}

.nav-tabs a {
  padding: 8px 14px;
  border-radius: var(--radius);
  color: var(--text-1);
  font-size: 0.92em;
  font-weight: 600;
}

.nav-tabs a:hover {
  background: var(--bg-2);
  text-decoration: none;
}

.nav-tabs a.active {
  background: var(--bg-3);
  color: var(--text-0);
}

.main {
  flex: 1;
  padding: 24px 28px;
  max-width: 1400px;
  width: 100%;
  margin: 0 auto;
}
@media (max-width: 600px) {
  .main { padding: 16px; }
}

.topbar-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 16px;
  min-width: 0;
}

.conn-status {
  font-size: 0.8em;
  color: var(--text-2);
  display: flex;
  align-items: center;
  gap: 6px;
}
.conn-status .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--text-2);
  flex: 0 0 auto;
}
.conn-status.ok .dot { background: var(--green); }
.conn-status.error .dot { background: var(--red); }
/* Fixed width sized to the longest state ("relay unreachable") so the
   theme toggle next to it doesn't shift as the text cycles through
   connecting… / relay connected / relay unreachable. */
#conn-status-text {
  display: inline-block;
  min-width: 108px;
}

/* ---------------------------------------------------------------------- */
/* Dark/light mode toggle switch — a checkbox-driven slider with a         */
/* sliding sun/moon knob. Position-agnostic: drop it inline as a flex      */
/* child (e.g. inside .topbar), or wrap it in .theme-toggle-wrap for a     */
/* fixed top-right placement on pages with no chrome. Wired up by          */
/* theme.js. */
/* ---------------------------------------------------------------------- */

.theme-toggle-wrap {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 2000;
}
.theme-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 52px;
  height: 28px;
  cursor: pointer;
  flex-shrink: 0;
}
.theme-toggle input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}
.theme-toggle-slider {
  position: absolute;
  inset: 0;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: 999px;
  transition: background 0.15s ease;
}
.theme-toggle-slider::before {
  content: "☀️";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--bg-1);
  box-shadow: 0 1px 3px var(--shadow);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  line-height: 1;
  transition: transform 0.15s ease, background 0.15s ease;
}
.theme-toggle input:checked + .theme-toggle-slider {
  background: var(--blue);
  border-color: var(--blue);
}
.theme-toggle input:checked + .theme-toggle-slider::before {
  content: "🌙";
  transform: translateX(24px);
}
.theme-toggle input:focus-visible + .theme-toggle-slider {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------- */
/* Cards / boxes / collapsibles                                            */
/* ---------------------------------------------------------------------- */

.box {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 28px;
  overflow: hidden;
}

.box-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--border);
  font-weight: 700;
  font-size: 0.95em;
  cursor: pointer;
  user-select: none;
}

.box-header .box-header-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.box-header .box-header-sub {
  font-weight: 400;
  font-size: 0.82em;
  color: var(--text-2);
  text-transform: none;
  letter-spacing: normal;
  cursor: default;
}

.box-header .chev {
  transition: transform 0.15s ease;
  color: var(--text-2);
  flex-shrink: 0;
}

.box.collapsed .box-header .chev { transform: rotate(-90deg); }
.box.collapsed .box-body { display: none; }

.box-body { padding: 22px; }
.box-body > *:not(:last-child) { margin-bottom: 4px; }

.subtabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  padding: 0 12px;
  background: var(--bg-1);
}

.subtabs button {
  background: none;
  border: none;
  color: var(--text-2);
  padding: 10px 14px;
  font-size: 0.88em;
  font-weight: 600;
  cursor: pointer;
  border-bottom: 2px solid transparent;
}

.subtabs button:hover { color: var(--text-0); }
.subtabs button.active {
  color: var(--text-0);
  border-bottom-color: var(--blue);
}

/* ---------------------------------------------------------------------- */
/* Team-side badges (Blue = Team 1, Orange = Team 2)                       */
/* ---------------------------------------------------------------------- */

.team-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 6px;
  font-weight: 700;
  font-size: 0.9em;
  max-width: 100%;
}
.team-chip.side-1 { background: var(--blue-dim); color: var(--blue); }
.team-chip.side-2 { background: var(--orange-dim); color: var(--orange); }
.team-chip-logo { height: 16px; width: 16px; object-fit: contain; flex-shrink: 0; }
/* The name is the part that should give way when space is tight — the seed
   tag is short and meaningful, so it must never get silently clipped (that
   showed up as e.g. "(1" instead of "(15)" when the whole chip's overflow
   was hidden and the seed tag just happened to be the last flex child). */
.team-chip .team-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.team-chip .seed-tag { font-weight: 400; opacity: 0.75; flex-shrink: 0; }

/* Swap to the team's ABBR instead of ellipsis-cutting its name when space is
   tight. Queries .matchup-side's width (set below) rather than the viewport,
   since the same row can have plenty of room on a wide page but still be
   squeezed in a narrow sidebar column. Only kicks in for teams that have an
   ABBR set (see teamChipHtml) — otherwise .team-name still degrades to plain
   ellipsis as a fallback. */
.team-chip .abbr-name { display: none; }
@container (max-width: 140px) {
  .team-chip .full-name { display: none; }
  .team-chip .abbr-name { display: inline; }
}

/* ---------------------------------------------------------------------- */
/* Matchup layout — "Team A [vs] Team B" with the middle column always in */
/* the same place regardless of team-name length. Use via                */
/* RlcsCommon.matchupHtml() rather than hand-rolling inline "vs" text.    */
/* ---------------------------------------------------------------------- */

.matchup {
  display: grid;
  grid-template-columns: minmax(0,1fr) auto minmax(0,1fr);
  align-items: center;
  gap: 8px;
  width: 100%;
}
.matchup-side { display: flex; min-width: 0; container-type: inline-size; }
.matchup-a { justify-content: flex-end; }
.matchup-b { justify-content: flex-start; }
/* Fills its .matchup-side slot instead of shrink-wrapping its own text, so
   every chip in a list is the same width and lines up — a chip's box no
   longer changes size row to row just because "KC" is shorter than
   "FLCN". Text is centered within that now-fixed box. */
.matchup-side .team-chip { min-width: 0; width: 100%; box-sizing: border-box; justify-content: center; }
.matchup-mid { color: var(--text-2); font-weight: 400; text-align: center; white-space: nowrap; font-size: 0.9em; }

.status-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.75em;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.status-pill.upcoming { background: var(--bg-3); color: var(--text-1); }
.status-pill.live { background: rgba(255,59,78,0.18); color: var(--live); animation: pulse 1.6s infinite; }
.status-pill.complete { background: rgba(62,207,126,0.16); color: var(--green); }
.status-pill.qualified { background: rgba(62,207,126,0.16); color: var(--green); }
.status-pill.eliminated { background: rgba(255,90,95,0.16); color: var(--red); }
.status-pill.active { background: var(--bg-3); color: var(--text-1); }

/* A small solid dot version of the same pulse, for marking a live match
   directly on a bracket/group card rather than as a full status pill. */
.live-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--live);
  animation: pulse 1.2s infinite;
  flex-shrink: 0;
}

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

/* ---------------------------------------------------------------------- */
/* Forms / buttons / tables                                                */
/* ---------------------------------------------------------------------- */

button, .btn {
  font-family: inherit;
  font-size: 0.9em;
  font-weight: 600;
  padding: 8px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg-2);
  color: var(--text-0);
  cursor: pointer;
}
button:hover, .btn:hover { background: var(--bg-3); }
button:disabled { opacity: 0.5; cursor: not-allowed; }
button.primary { background: var(--blue); border-color: var(--blue); color: #04101c; }
button.primary:hover { background: #5aacff; }
button.danger { background: var(--red); border-color: var(--red); color: #1a0506; }
button.subtle { background: transparent; }
button.danger-text { color: var(--red); border-color: transparent; background: transparent; }
button.danger-text:hover { background: rgba(255,90,95,0.14); border-color: rgba(255,90,95,0.35); }

input, select, textarea {
  font-family: inherit;
  font-size: 0.9em;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text-0);
  border-radius: 8px;
  padding: 8px 11px;
}
input:focus, select:focus, textarea:focus { outline: 1px solid var(--blue); }
label { font-size: 0.82em; color: var(--text-1); display: block; margin-bottom: 6px; }

.field {
  margin-bottom: 14px;
}

/* ---------------------------------------------------------------------- */
/* Stream A/B button-toggle component (replaces plain <select> for Stream) */
/* ---------------------------------------------------------------------- */

.stream-toggle {
  display: inline-flex;
  gap: 6px;
}
.stream-toggle button {
  min-width: 44px;
  padding: 7px 14px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text-1);
  font-weight: 700;
}
.stream-toggle button:hover { background: var(--bg-3); color: var(--text-0); }
.stream-toggle button.selected {
  background: var(--blue);
  border-color: var(--blue);
  color: #04101c;
}
.stream-toggle button.selected:hover { background: #5aacff; }
.stream-toggle.align-right { margin-left: auto; }

/* ---------------------------------------------------------------------- */
/* Sliding two-option pill toggle — for switching between two views of the */
/* same data (e.g. a bracket visualization vs. a standings table) rather  */
/* than the .subtabs page-level tab bar. Use via RlcsCommon.viewToggleHtml */
/* / wireViewToggle(). Assumes exactly 2 equal-width options.              */
/* ---------------------------------------------------------------------- */

.view-toggle {
  position: relative;
  display: inline-flex;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px;
  flex-shrink: 0;
}
.view-toggle button {
  position: relative;
  z-index: 1;
  background: transparent;
  border: none;
  padding: 6px 18px;
  min-width: 100px;
  text-align: center;
  font-size: 0.85em;
  font-weight: 600;
  color: var(--text-2);
  cursor: pointer;
  border-radius: 999px;
  transition: color 0.2s ease;
}
.view-toggle button:hover { background: transparent; }
.view-toggle button.active { color: #04101c; }
.view-toggle-slider {
  position: absolute;
  top: 3px;
  left: 3px;
  height: calc(100% - 6px);
  width: calc(50% - 3px);
  background: var(--blue);
  border-radius: 999px;
  transition: transform 0.2s ease;
  z-index: 0;
}

table { width: 100%; border-collapse: collapse; font-size: 0.9em; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border); }
th { color: var(--text-2); font-weight: 600; font-size: 0.8em; text-transform: uppercase; letter-spacing: 0.04em; }
tr:hover td { background: rgba(127,127,127,0.05); }

.action-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 16px; align-items: center; }
.filter-bar { display: flex; gap: 10px; margin-bottom: 16px; flex-wrap: wrap; }

.grid { display: grid; gap: 20px; }
.grid.cols-2 { grid-template-columns: 1fr 1fr; }
.grid.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1280px) {
  .grid.cols-3, .grid.cols-4 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 900px) {
  .grid.cols-2, .grid.cols-3, .grid.cols-4 { grid-template-columns: 1fr; }
}

.muted { color: var(--text-2); }
.mono { font-family: var(--mono); }

/* Dirty/unsaved-edit indicator — shared by any page using the local
   edit-buffer + Save All pattern (see js/common.js's dirty-tracking
   helpers). Applied to whatever row/card element is currently holding
   unsaved local changes. */
.is-dirty {
  background: rgba(255,181,69,0.07);
  box-shadow: inset 3px 0 0 var(--amber);
}
.unsaved-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.7em;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: rgba(255,181,69,0.18);
  color: var(--amber);
}

.warn-banner {
  background: rgba(255,181,69,0.12);
  border: 1px solid rgba(255,181,69,0.35);
  color: var(--amber);
  border-radius: var(--radius);
  padding: 10px 14px;
  font-size: 0.88em;
  margin-bottom: 12px;
}
.error-banner {
  background: rgba(255,90,95,0.12);
  border: 1px solid rgba(255,90,95,0.35);
  color: var(--red);
  border-radius: var(--radius);
  padding: 10px 14px;
  font-size: 0.88em;
  margin-bottom: 12px;
}

.empty-state {
  color: var(--text-2);
  text-align: center;
  padding: 30px 10px;
  font-size: 0.9em;
}

/* Password gate overlay */
.gate-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg-0);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.gate-box {
  background: var(--bg-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px;
  width: 320px;
  text-align: center;
}
.gate-box h2 { margin: 0 0 6px; }
.gate-box p { color: var(--text-2); font-size: 0.85em; margin: 0 0 16px; }
.gate-box input { width: 100%; margin-bottom: 10px; text-align: center; }
.gate-box button { width: 100%; }
.gate-error { color: var(--red); font-size: 0.82em; min-height: 1.2em; margin-top: 8px; }
