/* relay dashboard — dark theme (default) + light theme via [data-theme="light"] */

:root {
  --bg:        #0d1117;
  --bg-2:      #161b22;
  --bg-3:      #1f242c;
  --border:    #2a3038;
  --text:      #e6edf3;
  --text-dim:  #8b949e;
  --accent:    #2dd4bf;
  --accent-2:  #0ea5a5;
  --danger:    #f85149;
  --warn:      #d29922;
  --ok:        #3fb950;
  --purple:    #c084fc;
  --blue:      #58a6ff;

  --icon-bg:        rgba(255,255,255,0.03);
  --icon-bg-hover:  rgba(255,255,255,0.06);
  --icon-border:    #2a3038;
  --icon-border-hv: #3a4048;
  --row-hover:      var(--bg-3);
  --card-bg:        #161b22;
  --modal-bg:       #161b22;
  --search-bg:      #0d1117;
  --code-bg:        #0d1117;
}

[data-theme="light"] {
  /* Material-ish light palette: a low-chroma surface container, white
     elevated surfaces, a deep teal primary, and tonal containers for
     status. The dark theme above is intentionally separate. */
  --bg:        #f2f5f7;
  --bg-2:      #ffffff;
  --bg-3:      #e9eef2;
  --border:    #d9e1e8;
  --text:      #1a1f24;
  --text-dim:  #5b6670;
  --accent:    #0f766e;
  --accent-2:  #0b5f59;
  --accent-strong:    #0b5f59;
  --accent-container: #d9f2ee;
  --accent-container-strong: #c8ece7;
  --danger:    #b3261e;
  --danger-container: #fdecea;
  --warn:      #8a5300;
  --warn-container: #fff3df;
  --ok:        #1b6e3a;
  --ok-container: #e3f5e9;
  --neutral-container: #eef1f4;
  --purple:    #6f42c1;
  --purple-container: #f3e8ff;
  --purple-container-strong: #eaddff;
  --blue:      #0b57d0;

  --icon-bg:        rgba(15,23,42,0.03);
  --icon-bg-hover:  rgba(15,23,42,0.06);
  --icon-border:    #d9e1e8;
  --icon-border-hv: #9aa6b2;
  --row-hover:      #f3f6f8;
  --card-bg:        #ffffff;
  --modal-bg:       #ffffff;
  --search-bg:      #ffffff;
  --code-bg:        #f4f6f8;

  --elev-1: 0 1px 2px rgba(16,24,40,0.06), 0 1px 3px rgba(16,24,40,0.10);
  --elev-2: 0 4px 10px rgba(16,24,40,0.08), 0 1px 3px rgba(16,24,40,0.06);
  --elev-3: 0 16px 40px rgba(16,24,40,0.16), 0 4px 10px rgba(16,24,40,0.08);
  --radius-lg: 12px;
  --radius-md: 8px;
  --radius-pill: 999px;
  --inverse-bg: #1f2937;
  --inverse-text: #f8fafc;
}

.logo-img {
  width: auto;
  display: block;
}

.sidebar .logo-img {
  max-height: 36px;
}
.app.sidebar-collapsed .sidebar .logo-img {
  max-height: 28px;
}

.login-box .logo-img {
  max-height: 120px;
  margin: 0 auto 16px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui,
               "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

/* ---------- App shell ---------- */

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

.sidebar {
  width: 220px;
  background: var(--bg-2);
  border-right: 1px solid var(--border);
  padding: 24px 0;
  display: flex;
  flex-direction: column;
}

.sidebar .logo {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  padding: 0 24px 24px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.logo-mark {
  color: var(--accent);
  font-size: 20px;
}

.sidebar nav {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.sidebar nav a {
  color: var(--text-dim);
  padding: 10px 24px;
  border-left: 2px solid transparent;
  font-weight: 500;
}

.sidebar nav a:hover {
  background: var(--bg-3);
  color: var(--text);
  text-decoration: none;
  border-left-color: var(--accent);
}

.sidebar-foot {
  padding: 0 24px;
}

.sidebar-foot a {
  color: var(--text-dim);
  font-size: 13px;
}

.content {
  flex: 1;
  padding: 32px 40px;
}

/* ---------- Headings ---------- */

h1 {
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0 0 24px;
}

h2 {
  font-size: 16px;
  font-weight: 600;
  margin: 32px 0 12px;
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--accent);
  color: #062626;
  border: none;
  border-radius: 6px;
  padding: 8px 14px;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.1s;
}

.btn:hover { background: var(--accent-2); color: #001a1a; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }

.btn.secondary {
  background: var(--bg-3);
  color: var(--text);
  border: 1px solid var(--border);
}
.btn.secondary:hover { background: var(--border); }

.btn.danger { background: var(--danger); color: #fff; }
.btn.danger:hover { background: #d13a35; }

.btn.small { padding: 4px 10px; font-size: 13px; }

/* ---------- Forms ---------- */

label {
  display: block;
  margin-bottom: 14px;
}

label > span {
  display: block;
  font-size: 13px;
  color: var(--text-dim);
  margin-bottom: 6px;
}

input[type="text"],
input[type="password"],
input[type="number"],
input[type="url"],
select,
textarea {
  width: 100%;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
  font-size: 13px;
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
}

[data-theme="light"] input:focus,
[data-theme="light"] select:focus,
[data-theme="light"] textarea:focus {
  border-color: #0d9488;
  box-shadow: 0 0 0 3px rgba(13,148,136,0.15);
}

textarea { resize: vertical; min-height: 80px; }

/* ---------- Tables ---------- */

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

th, td {
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

th {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  font-weight: 600;
  background: var(--bg-3);
}

tr:last-child td { border-bottom: none; }
tr:hover td { background: var(--row-hover); }

td.mono {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
  font-size: 13px;
  color: var(--text-dim);
}

td a.stream-name {
  display: inline-block;
  max-width: 480px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}

/* ---------- Status pills ---------- */

.pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  text-transform: lowercase;
  letter-spacing: 0.01em;
}

.status-running      { background: #103a1e; color: var(--ok); }
.status-error        { background: #3a1010; color: var(--danger); }
.status-stopped      { background: #262c34; color: var(--text-dim); }
.status-transitional { background: #3a2d10; color: var(--warn); }

/* ---------- Login page ---------- */

.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

.login-box {
  width: 340px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 32px;
}

.login-box .logo {
  font-size: 20px;
  font-weight: 600;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.login-box h1 {
  font-size: 20px;
  margin: 0 0 24px;
  color: var(--text-dim);
  font-weight: 400;
}

.login-box button {
  width: 100%;
  margin-top: 8px;
}

.error {
  color: var(--danger);
  font-size: 13px;
  margin-top: 12px;
  margin-bottom: 0;
}

/* ---------- Utility ---------- */

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.row .spacer { flex: 1; }

/* Two fields side by side. The same markup is rendered both inside the modal
   and on the full-width edit page, so the pair collapses to one column rather
   than overflowing when there is not enough room. Rows need no extra gap —
   labels carry their own margin-bottom. */
.form-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 24px;
}
/* The two checkbox rows have margin: 0 (see .check-inline), so they need
   their own spacing below rather than sitting on top of the next pair. */
.form-pair-checks {
  align-items: center;
  row-gap: 8px;
  margin-bottom: 14px;
}
.form-hint {
  display: block;
  font-size: 0.8rem;
  margin: 6px 0 0;
}
.check-inline {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
}
.check-inline > span { margin: 0; }
@media (max-width: 700px) {
  .form-pair { grid-template-columns: 1fr; }
}

.muted { color: var(--text-dim); font-size: 13px; }
.mono  { font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace; }

/* ---------- Modal ---------- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}

[data-theme="light"] .modal-backdrop {
  background: rgba(31, 35, 40, 0.45);
}

.modal {
  background: var(--modal-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 24px;
  width: 520px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}

/* A wider modal for forms whose fields pair up side by side. Opt-in, so the
   base 520px still suits the confirm dialogs. */
.modal.wide { width: 780px; }

.modal h2 {
  margin-top: 0;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
}

/* ---------- Log view ---------- */

.log-line {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
  font-size: 12px;
  padding: 3px 0;
  border-bottom: 1px solid var(--border);
  white-space: pre-wrap;
  word-break: break-all;
}

.log-line .ts   { color: var(--text-dim); }
.log-line .lvl  { font-weight: 600; margin: 0 6px; }
.log-line .lvl.INFO  { color: var(--accent); }
.log-line .lvl.WARN  { color: var(--warn); }
.log-line .lvl.ERROR { color: var(--danger); }
.log-line .lvl.DEBUG { color: var(--text-dim); }

/* Install log — shared by the Nodes list and the node detail page, which
   used to carry two drifting copies (one with hardcoded dark-only colours
   that broke in light mode). */
.install-log {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 12px;
  font-family: ui-monospace, monospace;
  font-size: 0.8rem;
  max-height: 400px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
  color: var(--text-dim);
}
.install-log .log-info  { color: var(--text-dim); }
.install-log .log-warn  { color: var(--warn); }
.install-log .log-error { color: var(--danger); }

/* --- streams.html additions --- */

[x-cloak] { display: none !important; }

.cat-tag {
  font-size: 1.1rem;
  line-height: 1;
}

.toast-container {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}

.toast {
  padding: 10px 16px;
  border-radius: 6px;
  font-size: 0.85rem;
  color: var(--text);
  background: var(--modal-bg);
  border: 1px solid var(--border);
  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
  max-width: 340px;
  pointer-events: auto;
}

[data-theme="light"] .toast {
  background: #ffffff;
  border-color: #d0d7de;
  color: var(--text);
  box-shadow: 0 4px 12px rgba(31,35,40,0.12);
}

.toast-success { border-color: var(--ok); color: var(--ok); }
.toast-error   { border-color: var(--danger); color: var(--danger); }
.toast-info    { border-color: var(--accent); color: var(--accent); }

/* --- icon buttons --- */
.icon-btn {
  background: var(--icon-bg);
  border: 1px solid var(--icon-border);
  color: var(--text-dim);
  padding: 5px 9px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
  margin-right: 4px;
  transition: all 0.15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}
.icon-btn:hover { transform: translateY(-1px); border-color: var(--icon-border-hv); color: var(--text); }

.icon-btn.icon-success { color: var(--ok); border-color: rgba(63,185,80,0.4); background: rgba(63,185,80,0.08); }
.icon-btn.icon-success:hover { background: rgba(63,185,80,0.18); border-color: var(--ok); box-shadow: 0 0 0 3px rgba(63,185,80,0.12); }

.icon-btn.icon-danger { color: var(--danger); border-color: rgba(248,81,73,0.4); background: rgba(248,81,73,0.08); }
.icon-btn.icon-danger:hover { background: rgba(248,81,73,0.18); border-color: var(--danger); box-shadow: 0 0 0 3px rgba(248,81,73,0.12); }

.icon-btn.icon-warning { color: var(--warn); border-color: rgba(210,153,34,0.4); background: rgba(210,153,34,0.08); }
.icon-btn.icon-warning:hover { background: rgba(210,153,34,0.18); border-color: var(--warn); box-shadow: 0 0 0 3px rgba(210,153,34,0.12); }

.icon-btn.icon-info { color: var(--accent); border-color: rgba(45,212,191,0.4); background: rgba(45,212,191,0.08); }
.icon-btn.icon-info:hover { background: rgba(45,212,191,0.18); border-color: var(--accent); box-shadow: 0 0 0 3px rgba(45,212,191,0.12); }

.icon-btn.icon-neutral { color: var(--text-dim); }
.icon-btn.icon-neutral:hover { color: var(--text); border-color: var(--icon-border-hv); background: var(--icon-bg-hover); }

.icon-btn.icon-purple { color: var(--purple); border-color: rgba(168,85,247,0.4); background: rgba(168,85,247,0.08); }
.icon-btn.icon-purple:hover { background: rgba(168,85,247,0.18); border-color: var(--purple); box-shadow: 0 0 0 3px rgba(168,85,247,0.12); }

[data-theme="light"] .icon-btn {
  background: #ffffff;
  border-color: #d0d7de;
  color: #57606a;
}
[data-theme="light"] .icon-btn:hover {
  background: #f6f8fa;
  border-color: #8c959f;
  color: var(--text);
  transform: translateY(-1px);
}
[data-theme="light"] .icon-btn.icon-success { color: #1a7f37; background: #dafbe1; border-color: #aceebb; }
[data-theme="light"] .icon-btn.icon-success:hover { background: #b8f0c4; border-color: #1a7f37; box-shadow: none; }
[data-theme="light"] .icon-btn.icon-danger { color: #cf222e; background: #ffebe9; border-color: #ffcecb; }
[data-theme="light"] .icon-btn.icon-danger:hover { background: #ffd8d3; border-color: #cf222e; box-shadow: none; }
[data-theme="light"] .icon-btn.icon-warning { color: #9a6700; background: #fff8c5; border-color: #f5e29a; }
[data-theme="light"] .icon-btn.icon-warning:hover { background: #fde68a; border-color: #9a6700; box-shadow: none; }
[data-theme="light"] .icon-btn.icon-info { color: #0d9488; background: #d4f2ee; border-color: #9adfd5; }
[data-theme="light"] .icon-btn.icon-info:hover { background: #b4e5df; border-color: #0d9488; box-shadow: none; }
[data-theme="light"] .icon-btn.icon-purple { color: #8250df; background: #fbefff; border-color: #dcc8ff; }
[data-theme="light"] .icon-btn.icon-purple:hover { background: #ecd8ff; border-color: #8250df; box-shadow: none; }
[data-theme="light"] .icon-btn.icon-neutral { color: #57606a; }
[data-theme="light"] .icon-btn.icon-neutral:hover { color: var(--text); border-color: #8c959f; background: #f6f8fa; }

/* Sidebar icons */
.sidebar nav a { display: flex; align-items: center; gap: 8px; }
.sidebar nav a iconify-icon { font-size: 1.15rem; opacity: 0.75; }
.sidebar-foot a { display: flex; align-items: center; gap: 8px; }
.sidebar-foot a iconify-icon { font-size: 1.15rem; opacity: 0.75; }

/* Icons inside .btn */
.btn iconify-icon { vertical-align: middle; margin-right: 4px; font-size: 1.1em; }

/* --- badges --- */
.badge {
  display: inline-block;
  padding: 3px 9px;
  font-size: 0.72rem;
  font-weight: 600;
  border-radius: 20px;
  letter-spacing: 0.3px;
  line-height: 1.3;
  border: 1px solid transparent;
  text-transform: uppercase;
}
.badge-on { color: var(--ok); background: rgba(63,185,80,0.15); border-color: rgba(63,185,80,0.35); }
.badge-off { color: var(--text-dim); background: rgba(110,118,129,0.12); border-color: rgba(110,118,129,0.25); }

[data-theme="light"] .badge-on { color: #1a7f37; background: #dafbe1; border-color: #aceebb; }
[data-theme="light"] .badge-off { color: #57606a; background: #eaeef2; border-color: #d0d7de; }

/* --- status pills (bump the existing look) --- */
.pill {
  display: inline-block;
  padding: 3px 10px;
  font-size: 0.72rem;
  font-weight: 600;
  border-radius: 20px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  border: 1px solid transparent;
}
.pill.status-running { color: var(--ok); background: rgba(63,185,80,0.15); border-color: rgba(63,185,80,0.35); }
.pill.status-error { color: var(--danger); background: rgba(248,81,73,0.15); border-color: rgba(248,81,73,0.35); }
.pill.status-transitional { color: var(--warn); background: rgba(210,153,34,0.15); border-color: rgba(210,153,34,0.35); }
.pill.status-stopped { color: var(--text-dim); background: rgba(110,118,129,0.12); border-color: rgba(110,118,129,0.25); }
.pill.status-starting { color: var(--warn); background: rgba(210,153,34,0.15); border-color: rgba(210,153,34,0.35); }
.pill.status-stopping { color: var(--warn); background: rgba(210,153,34,0.15); border-color: rgba(210,153,34,0.35); }

[data-theme="light"] .pill.status-running { color: #1a7f37; background: #dafbe1; border-color: #aceebb; }
[data-theme="light"] .pill.status-error { color: #cf222e; background: #ffebe9; border-color: #ffcecb; }
[data-theme="light"] .pill.status-stopped { color: #57606a; background: #eaeef2; border-color: #d0d7de; }
[data-theme="light"] .pill.status-transitional { color: #9a6700; background: #fff8c5; border-color: #f5e29a; }
[data-theme="light"] .pill.status-starting { color: #9a6700; background: #fff8c5; border-color: #f5e29a; }
[data-theme="light"] .pill.status-stopping { color: #9a6700; background: #fff8c5; border-color: #f5e29a; }

/* --- solid btn color variants for Create / Refresh --- */
.btn {
  background: var(--accent);
  color: #0d1117;
  border: none;
  padding: 7px 14px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.9rem;
  font-weight: 600;
  transition: all 0.15s;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn:hover { background: var(--accent-2); box-shadow: 0 0 0 3px rgba(45,212,191,0.15); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn.secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}
.btn.secondary:hover { background: var(--bg-3); border-color: var(--icon-border-hv); box-shadow: none; }

[data-theme="light"] .btn.secondary {
  background: #ffffff;
  border-color: #d0d7de;
  color: var(--text);
}
[data-theme="light"] .btn.secondary:hover {
  background: #f6f8fa;
  border-color: #0969da;
}

.btn.small { padding: 5px 10px; font-size: 0.8rem; }
.btn.danger { background: var(--danger); color: #fff; }
.btn.danger:hover { background: #d63a32; box-shadow: 0 0 0 3px rgba(248,81,73,0.15); }

/* --- stream.html detail page --- */
.cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}
.stat-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
}
.stat-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.stat-value {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--text);
  font-family: 'SFMono-Regular', Consolas, monospace;
}

.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 20px;
}

/* Two cards side by side, for short key/value panels that would otherwise
   stack into a tall column. The pair stretches to a common height so the row
   reads as one block; the shorter card simply has some room left in it. */
.cards-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  align-items: stretch;
  margin-bottom: 20px;
}
/* The cards carry their own bottom margin for the stacked case; inside the
   grid the gap does that job, so drop it rather than doubling the space. */
.cards-2 > .card { margin-bottom: 0; }
/* A collapsed card is just a header, so let it keep its own height instead of
   being padded out to match an open neighbour. */
.cards-2 > .card.card-collapsed { align-self: start; }
/* Below this the half-width card is too narrow for .kv-row's fixed 160px
   label column, so stack them back up. */
@media (max-width: 1040px) {
  .cards-2 { grid-template-columns: 1fr; }
}
.card-header {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
/* Groups the buttons at the right-hand end of a card header. */
.card-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.card-title {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
}
.card-body { padding: 16px; }

.kv-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 8px 16px;
  padding: 6px 0;
  font-size: 0.875rem;
  align-items: center;
}
.kv-row .k { color: var(--text-dim); }
.kv-row .v { color: var(--text); font-family: 'SFMono-Regular', Consolas, monospace; word-break: break-all; }

.copy-row {
  display: flex;
  gap: 8px;
  align-items: center;
}
.copy-row input {
  flex: 1;
  background: var(--code-bg);
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 6px 10px;
  border-radius: 6px;
  font-family: 'SFMono-Regular', Consolas, monospace;
  font-size: 0.8rem;
}

.logs-container {
  max-height: 400px;
  overflow-y: auto;
  font-family: 'SFMono-Regular', Consolas, monospace;
  font-size: 0.8rem;
  padding: 8px 0;
}
.log-entry {
  padding: 3px 0;
  border-bottom: 1px solid var(--border);
  line-height: 1.5;
}
.log-time { color: var(--text-dim); margin-right: 8px; }
.log-level { font-weight: 600; margin-right: 6px; }
.log-INFO  { color: var(--ok); }
.log-WARN  { color: var(--warn); }
.log-ERROR { color: var(--danger); }
.log-DEBUG { color: var(--text-dim); }
.log-msg { color: var(--text); }

.metrics-table { width: 100%; font-size: 0.82rem; font-family: 'SFMono-Regular', Consolas, monospace; }
.metrics-table th {
  text-align: left;
  padding: 8px 10px;
  font-weight: 600;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
}
.metrics-table td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text);
}

.select-sm {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 0.8rem;
}

.switch {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--text-dim);
}
.switch input { cursor: pointer; }

.page-header-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}
.page-header-row h1 { margin: 0; }
.back-link {
  color: var(--text-dim);
  font-size: 0.85rem;
  text-decoration: none;
}
.back-link:hover { color: var(--accent); }

/* --- summary stat cards (streams page header) --- */
.summary-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px;
  margin-bottom: 22px;
}
.summary-card {
  background: linear-gradient(135deg, var(--bg-2) 0%, var(--bg-3) 100%);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  transition: all 0.15s;
}
.summary-card:hover { border-color: var(--icon-border-hv); transform: translateY(-1px); }

/* Cards that do something (filter or navigate) get a pointer and the accent
   hover. A navigation card is a real <a>, so it must not inherit the global
   link colour or underline. */
.summary-card.clickable { cursor: pointer; user-select: none; }
.summary-card.clickable:hover { border-color: rgba(45,212,191,0.55); }
a.summary-card { color: inherit; }
a.summary-card:hover { text-decoration: none; }

[data-theme="light"] .summary-card {
  background: linear-gradient(135deg, #ffffff 0%, #f6f8fa 100%);
}

.summary-icon {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  flex-shrink: 0;
}
.summary-icon.teal   { background: rgba(45,212,191,0.12); color: var(--accent); }
.summary-icon.green  { background: rgba(63,185,80,0.12);  color: var(--ok); }
.summary-icon.blue   { background: rgba(88,166,255,0.12); color: var(--blue); }
.summary-icon.purple { background: rgba(168,85,247,0.12); color: var(--purple); }
.summary-icon.amber  { background: rgba(210,153,34,0.12); color: var(--warn); }
.summary-text { display: flex; flex-direction: column; min-width: 0; }
.summary-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-dim);
  margin-bottom: 4px;
}
.summary-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text);
  line-height: 1.1;
}

/* --- collapsible sidebar ---
The sidebar is one viewport tall and sticks while the page scrolls, so the
theme toggle and log out stay on screen no matter how long the page is.
align-self opts out of the flex stretch, which would otherwise size the
sidebar to the content and defeat the pinning. */
.sidebar {
  width: 220px;
  flex-shrink: 0;
  transition: width 0.2s ease;
  overflow: hidden;
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
}
/* Only the nav scrolls when every group is open. The logo and the foot stay
put, which is the point of pinning the sidebar in the first place. */
.sidebar nav { min-height: 0; overflow-y: auto; }
.sidebar-foot { flex-shrink: 0; }
.sidebar nav a {
  white-space: nowrap;
  overflow: hidden;
  transition: all 0.15s;
}
.sidebar .logo { white-space: nowrap; }
.sidebar .sidebar-foot a { white-space: nowrap; }

.app.sidebar-collapsed .sidebar {
  width: 60px;
}
.app.sidebar-collapsed .sidebar nav a {
  padding-left: 0;
  padding-right: 0;
  justify-content: center;
  gap: 0;
}
.app.sidebar-collapsed .sidebar nav a > span:not(.menu-icon) {
  display: none;
}
.app.sidebar-collapsed .sidebar nav a iconify-icon {
  margin: 0;
}
.app.sidebar-collapsed .sidebar .logo {
  justify-content: center;
}
.app.sidebar-collapsed .sidebar .logo .logo-text { display: none; }
.app.sidebar-collapsed .sidebar .sidebar-foot a {
  justify-content: center;
  gap: 0;
}
.app.sidebar-collapsed .sidebar .sidebar-foot a .foot-text { display: none; }

.sidebar nav a .menu-label { transition: opacity 0.1s; }
.app.sidebar-collapsed .sidebar nav a .menu-label { opacity: 0; pointer-events: none; }

/* --- collapsible nav groups ---
   Streams and Usage are top-level and never hidden. Everything else lives in a
   .nav-group whose children stay hidden until it opens. The markup seeds the
   Alpine `open` value with the group containing the current page, so the
   sidebar shows where you are without needing a click first. */
.nav-group-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px 24px;
  background: none;
  border: 0;
  border-left: 2px solid transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.15s;
}

.nav-group-toggle:hover { color: var(--text); }

.nav-group-toggle .menu-label { flex: 1; min-width: 0; }

.nav-caret {
  font-size: 0.85rem;
  opacity: 0.55;
  transition: transform 0.15s ease;
}

.nav-group.open .nav-caret { transform: rotate(90deg); }

.nav-group-items { display: none; }
.nav-group.open .nav-group-items { display: block; }

.sidebar nav a.active {
  color: var(--accent);
  background: var(--bg-3);
  border-left-color: var(--accent);
}

.sidebar nav a.active iconify-icon { opacity: 1; }

/* Collapsed to the icon rail there is no room for a heading and the item
   labels are faded out anyway, so drop the headings and show every destination
   at once — which is the point of an icon rail. */
.app.sidebar-collapsed .nav-group-toggle { display: none; }
.app.sidebar-collapsed .nav-group-items { display: block; }

/* Main content: column flex so the footer can be pushed to the bottom. */
.app main.content {
  flex: 1;
  min-width: 0;
  padding: 24px 32px;
  display: flex;
  flex-direction: column;
}
.app main.content > * {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}
.app main.content > .site-footer {
  margin-top: auto;
}
.app main.content > table {
  width: 100%;
}

/* Hamburger toggle button */
.sidebar-toggle {
  background: transparent;
  border: 1px solid var(--icon-border);
  color: var(--text-dim);
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 1.15rem;
  line-height: 1;
  margin-right: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  transition: all 0.15s;
}
.sidebar-toggle:hover {
  color: var(--text);
  border-color: var(--icon-border-hv);
  background: var(--icon-bg-hover);
}

[data-theme="light"] .sidebar-toggle {
  background: #ffffff;
  border-color: #d0d7de;
  color: #57606a;
}
[data-theme="light"] .sidebar-toggle:hover {
  color: var(--text);
  border-color: #8c959f;
  background: #f6f8fa;
}

/* --- button border refinements --- */
.btn {
  border: 1px solid rgba(45,212,191,0.55);
  box-shadow: 0 1px 0 rgba(0,0,0,0.15);
  /* .btn is also used on <a>, where the global a:hover would underline it. */
  text-decoration: none;
}
.btn:hover {
  border-color: var(--accent);
  box-shadow: 0 1px 0 rgba(0,0,0,0.15), 0 0 0 3px rgba(45,212,191,0.15);
  text-decoration: none;
}
.btn.secondary {
  border: 1px solid var(--border);
}
.btn.secondary:hover {
  border-color: var(--blue);
  background: rgba(88,166,255,0.06);
}

/* --- boxed layout --- */
html, body {
  background: var(--bg);
}
.app {
  max-width: none;
  margin: 0;
}
.app main.content > * {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

/* --- pagination --- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 18px 0;
  margin-top: 8px;
}
.pagination-btn {
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text-dim);
  padding: 6px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  transition: all 0.15s;
}
.pagination-btn:hover:not(:disabled) {
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(45,212,191,0.08);
}
.pagination-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.pagination-info {
  font-size: 0.85rem;
  color: var(--text-dim);
}
.pagination-info strong {
  color: var(--text);
  font-weight: 600;
}

[data-theme="light"] .pagination-btn {
  background: #ffffff;
  border-color: #d0d7de;
  color: #57606a;
}
[data-theme="light"] .pagination-btn:hover:not(:disabled) {
  color: #0d9488;
  border-color: #0d9488;
  background: #d4f2ee;
}

/* --- collapsible section toggles --- */
.collapse-toggle {
  background: transparent;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  padding: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  transition: transform 0.2s ease, color 0.15s;
}
.collapse-toggle:hover { color: var(--text); }
.collapse-toggle.collapsed { transform: rotate(-90deg); }

/* --- site footer --- */
.site-footer {
  margin-top: auto;
  padding: 18px 0 12px;
  display: flex;
  justify-content: center;
}

.footer-inner {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 16px;
  border-radius: 999px;
  background: var(--bg-2);
  border: 1px solid var(--border);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--text-dim);
  line-height: 1;
}

.footer-inner .footer-brand {
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
}

.footer-inner .footer-beta {
  font-weight: 600;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--warn);
  padding: 2px 7px;
  border-radius: 4px;
  background: rgba(210,153,34,0.12);
  border: 1px solid rgba(210,153,34,0.35);
}

.footer-inner .footer-credit {
  color: var(--text-dim);
  font-size: 0.78rem;
}

.footer-inner .footer-handle {
  color: var(--text);
  font-weight: 600;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
  font-size: 0.76rem;
}

.footer-inner .footer-version {
  color: var(--text-dim);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, monospace;
  font-size: 0.74rem;
  opacity: 0.85;
}

.footer-inner .footer-dot {
  opacity: 0.35;
  font-weight: 400;
}

[data-theme="light"] .footer-inner {
  background: #ffffff;
  border-color: #d0d7de;
}
[data-theme="light"] .footer-inner .footer-beta {
  color: #9a6700;
  background: #fff8c5;
  border-color: #f5e29a;
}

/* --- license banner (rendered by layout.html on every page) --- */

.license-global {
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: 6px;
  padding: 10px 14px;
  margin-bottom: 16px;
  background: var(--card-bg);
  font-size: 0.9rem;
}
.license-global.warn { border-left-color: var(--warn); }
.license-global.danger { border-left-color: var(--danger); }
.license-global a { color: var(--accent); margin-left: 4px; }

/* ==========================================================================
   Light theme polish — Material-inspired surfaces, elevation and states.
   Scoped to [data-theme="light"]; the dark theme above is untouched.
   ========================================================================== */

[data-theme="light"] body { background: var(--bg); }

/* Sidebar: surface, pill-shaped active indicator. */
[data-theme="light"] .sidebar {
  background: var(--bg-2);
  border-right: 1px solid var(--border);
  box-shadow: 1px 0 0 rgba(16,24,40,0.02);
}
[data-theme="light"] .sidebar nav a {
  border-left: 0;
  border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
  margin-right: 8px;
  padding: 9px 18px 9px 24px;
}
[data-theme="light"] .sidebar nav a:hover {
  background: var(--bg-3);
  color: var(--text);
}
[data-theme="light"] .sidebar nav a.active {
  background: var(--accent-container);
  color: var(--accent-strong);
  border-left: 0;
}
[data-theme="light"] .sidebar-foot a { color: var(--text-dim); }
[data-theme="light"] .sidebar-foot a:hover { color: var(--accent-strong); }

/* Elevated surfaces. */
[data-theme="light"] .card,
[data-theme="light"] .stat-card {
  border-radius: var(--radius-lg);
  border-color: var(--border);
  box-shadow: var(--elev-1);
}
[data-theme="light"] .card-header { background: var(--card-bg); }

[data-theme="light"] .summary-card {
  background: var(--card-bg);
  border-radius: var(--radius-lg);
  border-color: var(--border);
  box-shadow: var(--elev-1);
}
[data-theme="light"] .summary-card:hover {
  border-color: var(--accent-container);
  box-shadow: var(--elev-2);
}
[data-theme="light"] .summary-card.clickable:hover { border-color: var(--accent); }
[data-theme="light"] .summary-icon { border-radius: var(--radius-lg); }

/* Buttons: filled primary, tonal secondary, pill shape. */
[data-theme="light"] .btn {
  border: 0;
  border-radius: var(--radius-pill);
  color: #ffffff;
  box-shadow: var(--elev-1);
  padding: 8px 18px;
}
[data-theme="light"] .btn:hover {
  background: var(--accent-2);
  box-shadow: var(--elev-2);
}
[data-theme="light"] .btn.secondary {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  box-shadow: none;
}
[data-theme="light"] .btn.secondary:hover {
  background: var(--accent-container);
  border-color: transparent;
  color: var(--accent-strong);
  box-shadow: none;
}
[data-theme="light"] .btn.danger { background: var(--danger); color: #ffffff; }
[data-theme="light"] .btn.danger:hover { background: #8c1d18; }
[data-theme="light"] .btn.small { padding: 5px 12px; }

/* Inputs: filled surface, rounded, tonal focus ring. */
[data-theme="light"] input[type="text"],
[data-theme="light"] input[type="password"],
[data-theme="light"] input[type="number"],
[data-theme="light"] input[type="url"],
[data-theme="light"] input[type="search"],
[data-theme="light"] select,
[data-theme="light"] textarea {
  background: var(--search-bg);
  border-color: var(--border);
  border-radius: var(--radius-md);
}
[data-theme="light"] input:focus,
[data-theme="light"] select:focus,
[data-theme="light"] textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-container);
}

/* Tables: elevated surface, tinted header, quiet hover. */
[data-theme="light"] table {
  border-color: var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-1);
}
[data-theme="light"] th { background: var(--bg-3); color: var(--text-dim); }
[data-theme="light"] tbody tr:hover { background: var(--row-hover); }
[data-theme="light"] td,
[data-theme="light"] th { border-color: var(--border); }

/* Status: tonal containers instead of saturated fills. */
[data-theme="light"] .badge,
[data-theme="light"] .pill { border-color: transparent; }
[data-theme="light"] .badge-on,
[data-theme="light"] .pill.status-running {
  color: var(--ok); background: var(--ok-container); border-color: transparent;
}
[data-theme="light"] .badge-off,
[data-theme="light"] .pill.status-stopped {
  color: var(--text-dim); background: var(--neutral-container); border-color: transparent;
}
[data-theme="light"] .pill.status-error {
  color: var(--danger); background: var(--danger-container); border-color: transparent;
}
[data-theme="light"] .pill.status-transitional,
[data-theme="light"] .pill.status-starting,
[data-theme="light"] .pill.status-stopping {
  color: var(--warn); background: var(--warn-container); border-color: transparent;
}

/* Icon buttons: flat until hovered, then tonal. */
[data-theme="light"] .icon-btn {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
[data-theme="light"] .icon-btn:hover {
  background: var(--bg-3);
  border-color: transparent;
  box-shadow: none;
}
[data-theme="light"] .icon-btn.icon-success { color: var(--ok); background: var(--ok-container); }
[data-theme="light"] .icon-btn.icon-danger { color: var(--danger); background: var(--danger-container); }
[data-theme="light"] .icon-btn.icon-warning { color: var(--warn); background: var(--warn-container); }
[data-theme="light"] .icon-btn.icon-info { color: var(--accent-strong); background: var(--accent-container); }
[data-theme="light"] .icon-btn.icon-purple { color: var(--purple); background: #f3e8ff; }
[data-theme="light"] .icon-btn.icon-neutral { color: var(--text-dim); background: transparent; }
[data-theme="light"] .icon-btn.icon-success:hover { background: #d3efdc; }
[data-theme="light"] .icon-btn.icon-danger:hover { background: #fbdcd9; }
[data-theme="light"] .icon-btn.icon-warning:hover { background: #ffe8c4; }
[data-theme="light"] .icon-btn.icon-info:hover { background: #c8ece7; }
[data-theme="light"] .icon-btn.icon-purple:hover { background: #eaddff; }
[data-theme="light"] .icon-btn.icon-neutral:hover { background: var(--bg-3); }

/* Modals and toast. */
[data-theme="light"] .modal-backdrop { background: rgba(16,24,40,0.38); }
[data-theme="light"] .modal {
  border-radius: 16px;
  border-color: var(--border);
  box-shadow: var(--elev-3);
}
[data-theme="light"] .toast {
  background: var(--inverse-bg);
  color: var(--inverse-text);
  border-radius: 10px;
  box-shadow: var(--elev-2);
}
[data-theme="light"] .toast-success { border-color: var(--ok); color: #d9f5e2; }
[data-theme="light"] .toast-error { border-color: var(--danger); color: #ffd9d6; }
[data-theme="light"] .toast-info { border-color: var(--accent); color: #c8f2ed; }

/* Chrome: sidebar toggle, pagination, footer. */
[data-theme="light"] .sidebar-toggle {
  background: var(--bg-2);
  border-color: var(--border);
  border-radius: var(--radius-md);
  color: var(--text-dim);
  box-shadow: none;
}
[data-theme="light"] .sidebar-toggle:hover {
  background: var(--bg-3);
  border-color: var(--icon-border-hv);
  color: var(--text);
}
[data-theme="light"] .pagination-btn {
  background: var(--bg-2);
  border-color: var(--border);
  border-radius: var(--radius-pill);
  color: var(--text-dim);
}
[data-theme="light"] .pagination-btn:hover:not(:disabled) {
  background: var(--accent-container);
  border-color: transparent;
  color: var(--accent-strong);
}
[data-theme="light"] .footer-inner {
  background: var(--bg-2);
  border-color: var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-1);
}

/* Panels added by the license and users pages. */
[data-theme="light"] .license-global,
[data-theme="light"] .users-note,
[data-theme="light"] .lic-banner {
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-1);
}
[data-theme="light"] .lic-request,
[data-theme="light"] .lic-install,
[data-theme="light"] .install-log {
  border-radius: var(--radius-md);
}

/* First-run hint on the login page. */
.login-hint {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md, 8px);
  background: var(--card-bg);
  color: var(--text-dim);
  padding: 10px 12px;
  margin: 0 0 16px;
  font-size: 0.82rem;
  line-height: 1.45;
}
.login-hint strong { color: var(--text); }
.login-hint code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  color: var(--text);
}

/* --- release notification banner (rendered by layout.html) --- */

.release-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--blue);
  border-radius: 6px;
  padding: 10px 14px;
  margin-bottom: 16px;
  background: var(--card-bg);
  font-size: 0.9rem;
}
.release-banner iconify-icon {
  color: var(--blue);
  font-size: 1.1rem;
  flex-shrink: 0;
}
.release-banner strong { color: var(--text); }
.release-banner a { margin-left: auto; color: var(--accent); white-space: nowrap; }

[data-theme="light"] .release-banner {
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-1);
}
