/* The theme's colours (themes.js sets them for the account's theme; these are Midnight, the default).
   Everything else is derived from them, so a theme is just these. */
:root {
  --bg: #0e0f13;
  --bg-elev: #15171d;
  --bg-elev-2: #1b1e26;
  --border: #262a35;
  --text: #e7e9ee;
  --text-dim: #9aa0ac;
  --accent: #7c5cff;
  --accent-2: #22d3ee;
  --on-accent: #ffffff;
  --danger: #ff5c7c;
  --success: #34d399;
  --warning: #f59e0b;
  --info: #4da3ff;
  --accent-grad: linear-gradient(135deg, var(--accent), var(--accent-2));
  --danger-grad: linear-gradient(135deg, color-mix(in srgb, var(--danger) 82%, #000), var(--danger));
  --radius: 10px;
  font-size: 15px;
}

* { box-sizing: border-box; }

/* Author display rules (.tab-btn { display:flex } etc.) would otherwise beat the UA's
   [hidden] { display:none } - the hidden attribute is used to hide tabs an account can't use. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, "Segoe UI", Inter, Roboto, sans-serif;
}

button {
  font-family: inherit;
  cursor: pointer;
}

/* Secondary buttons, in the theme's colours (a few had none of their own and were the browser's
   default white buttons). Early in the file, so any button's own rules still win. */
.ghost {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
}
.ghost:where(:hover:not(:disabled)) { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); }

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

.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background: radial-gradient(circle at 20% 20%, color-mix(in srgb, var(--accent) 14%, var(--bg)) 0%, var(--bg) 60%);
}

.login-card {
  width: 360px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 32px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}

.login-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
}

.login-logo h1 { font-size: 20px; margin: 0; }

.login-sub { color: var(--text-dim); margin: 4px 0 24px; font-size: 13px; }

.login-card label { display: block; font-size: 12px; color: var(--text-dim); margin: 14px 0 6px; }

.login-card input {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 14px;
}

.login-card input:focus { outline: none; border-color: var(--accent); }

.login-card .login-remember { display: flex; align-items: center; gap: 8px; width: fit-content; margin: 14px 0 0; font-size: 13px; cursor: pointer; }
.login-card .login-remember input { width: 16px; height: 16px; margin: 0; padding: 0; accent-color: var(--accent); cursor: pointer; }

.login-card button[type="submit"] {
  width: 100%;
  margin-top: 22px;
  padding: 11px;
  border: none;
  border-radius: 8px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-weight: 600;
  font-size: 14px;
}

.login-card button[disabled] { opacity: 0.6; }

.login-error { color: var(--danger); font-size: 13px; margin-top: 12px; min-height: 16px; }
.login-hint { font-size: 11px; color: var(--text-dim); margin-top: 5px; }
.login-switch { margin-top: 18px; font-size: 12.5px; color: var(--text-dim); text-align: center; }
.login-switch a { color: var(--accent-2); text-decoration: none; }
.login-switch a:hover { text-decoration: underline; }
.login-success {
  margin-top: 16px;
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--success) 40%, transparent);
  background: color-mix(in srgb, var(--success) 10%, transparent);
  color: var(--success);
  font-size: 13px;
  line-height: 1.45;
}
@media (max-width: 420px) {
  .login-card { width: calc(100% - 24px); padding: 24px 20px; }
}

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

/* dvh, not vh: on phones 100vh includes the area under the browser's own toolbar, which pushed the
   bottom of every view (the chat message box included) off-screen. */
.app { display: flex; height: 100vh; height: 100dvh; overflow: hidden; }

.sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--bg-elev);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 16px 12px;
  overflow: hidden;
  white-space: nowrap;
  transition: width .18s ease, padding .18s ease;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  padding: 0 4px 16px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
.brand-logo { flex-shrink: 0; }
.sidebar-toggle {
  flex-shrink: 0;
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  background: none;
  border: none;
  border-radius: 8px;
  color: var(--text-dim);
  font-size: 18px;
  line-height: 1;
}
.sidebar-toggle:hover { background: var(--bg-elev-2); color: var(--text); }
.sidebar-backdrop { display: none; }

/* Collapsed: an icon-only rail. Every view is a flex child of .content, so they all simply get the
   extra width - nothing per-tab to recalculate, except the chatroom's absolutely-positioned floating
   widgets, which clamp themselves back into the stage whenever it resizes (see app.js). */
.sidebar-collapsed .sidebar { width: 60px; padding: 16px 8px; }
.sidebar-collapsed .brand { justify-content: center; padding: 0 0 16px; }
.sidebar-collapsed .brand-logo,
.sidebar-collapsed .brand-name,
.sidebar-collapsed .tab-label,
.sidebar-collapsed #whoami,
.sidebar-collapsed .sidebar-stats,
.sidebar-collapsed .sidebar-disk,
.sidebar-collapsed .btn-label { display: none; }
/* !important because switchTab sets the tree's display inline. */
.sidebar-collapsed .tree { display: none !important; }
.sidebar-collapsed .tab-btn { justify-content: center; padding: 9px 0; }
.sidebar-collapsed .tab-icon { font-size: 17px; width: auto; }
.sidebar-collapsed .tab-badge {
  position: absolute;
  top: 1px; right: 3px;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  font-size: 10px;
}
.sidebar-collapsed .sidebar-user { flex-direction: column; margin-top: auto; padding: 10px 0 0; }
.sidebar-collapsed .user-actions { flex-direction: column; align-items: center; }
.sidebar-collapsed .btn-icon { display: inline; }

/* Phone width: the sidebar floats over the content instead of squeezing it (60px rail when
   collapsed, a full overlay drawer with a tap-to-close backdrop when expanded). */
@media (max-width: 760px) {
  .sidebar { position: fixed; top: 0; bottom: 0; left: 0; z-index: 3000; }
  .content { margin-left: 60px; }
  :root:not(.sidebar-collapsed) .sidebar { box-shadow: 0 0 40px rgba(0,0,0,0.6); }
  :root:not(.sidebar-collapsed) .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.45);
    z-index: 2999;
  }
}

.tabnav {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.tab-btn {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  color: var(--text-dim);
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 13.5px;
  text-align: left;
  white-space: nowrap;
}
.tab-icon { width: 20px; text-align: center; flex-shrink: 0; }
.tab-label { overflow: hidden; text-overflow: ellipsis; }
.tab-badge {
  margin-left: auto;
  min-width: 18px; height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--danger);
  color: white;
  font-size: 11px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.btn-icon { display: none; }
.tab-btn:hover { background: var(--bg-elev-2); color: var(--text); }
.tab-btn.active { background: var(--bg-elev-2); color: var(--text); font-weight: 600; }

.tree { flex: 1; overflow-y: auto; }

.tree-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  border-radius: 8px;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 13.5px;
  white-space: nowrap;
}

.tree-item:hover { background: var(--bg-elev-2); color: var(--text); }
.tree-item.active { background: var(--bg-elev-2); color: var(--text); font-weight: 600; }
.tree-caret { width: 14px; text-align: center; opacity: 0.6; font-size: 10px; }

.sidebar-stats {
  font-size: 11.5px;
  color: var(--text-dim);
  padding: 10px 8px;
  border-top: 1px solid var(--border);
}
.sidebar-stats:empty { display: none; }

.sidebar-disk {
  padding: 2px 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.disk-row-label {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--text-dim);
  margin-bottom: 4px;
}
.disk-row-label .disk-name { color: var(--text); font-weight: 600; }
.disk-bar-track {
  height: 5px;
  background: var(--bg-elev-2);
  border-radius: 3px;
  overflow: hidden;
}
.disk-bar-fill {
  height: 100%;
  background: var(--accent-grad);
  transition: width .2s;
}
.disk-bar-fill.warn { background: linear-gradient(135deg, var(--warning), color-mix(in srgb, var(--warning) 60%, var(--danger))); }
.disk-bar-fill.critical { background: var(--danger-grad); }
.disk-row-sub {
  font-size: 10.5px;
  color: var(--text-dim);
  margin-top: 4px;
}

/* "Windows app" (the installer) in a browser on Windows, "Android app" on Android; "App settings"
   inside the Windows app. */
.sidebar-install {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  margin: 4px 8px 2px;
  padding: 7px 10px;
  border: 0;
  border-radius: 8px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.sidebar-install:hover { filter: brightness(1.08); }
.sidebar-app-settings { background: var(--bg-elev-2); color: var(--text); border: 1px solid var(--border); font-family: inherit; }
.sidebar-install-img { width: 18px; height: 18px; border-radius: 4px; flex-shrink: 0; }
.sidebar-install[hidden] { display: none; }
.sidebar-collapsed .sidebar-install { margin: auto 0 0; padding: 8px 0; }
.sidebar-collapsed .sidebar-install-label { display: none; }
/* Only the first visible install link takes the space that pushes these to the bottom. */
.sidebar-collapsed .sidebar-install:not([hidden]) ~ .sidebar-install,
.sidebar-collapsed .sidebar-install:not([hidden]) ~ .sidebar-user { margin-top: 0; }

/* Opened from the DC Gaming portal to install DC-Server Hub on its own (?install=1). */
.install-banner {
  position: fixed;
  top: 16px;
  left: 16px;
  right: 16px;
  margin: 0 auto;
  max-width: 520px;
  z-index: 7000;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  background: var(--bg-elev);
  border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: 14px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
  animation: slideIn .18s ease-out;
}
.install-banner[hidden] { display: none; }
/* Within thumb reach on a phone, and clear of the ?install=1 banner at the top. */
.install-banner-bottom { top: auto; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
.install-banner-icon { width: 44px; height: 44px; border-radius: 10px; flex-shrink: 0; }
.install-banner-text { flex: 1; min-width: 0; }
.install-banner-title { font-size: 14px; font-weight: 600; margin-bottom: 3px; }
.install-banner-sub { font-size: 12px; color: var(--text-dim); line-height: 1.45; white-space: normal; }
.install-banner-btn {
  flex-shrink: 0;
  padding: 8px 18px;
  border: 0;
  border-radius: 8px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.install-banner-btn:disabled { opacity: 0.4; cursor: default; }
.install-banner-btn[hidden] { display: none; }
.install-banner-close {
  flex-shrink: 0;
  align-self: flex-start;
  background: none;
  border: 0;
  color: var(--text-dim);
  font-size: 14px;
  padding: 2px 4px;
}
.install-banner-close:hover { color: var(--text); }
@media (max-width: 760px) {
  .install-banner { flex-wrap: wrap; }
  .install-banner-text { padding-right: 18px; }
  .install-banner-btn { width: 100%; text-align: center; }
  /* In the corner, rather than wrapped onto a line of its own under the full-width button. */
  .install-banner-close { position: absolute; top: 8px; right: 8px; }
}

.sidebar-user {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 8px 0;
  font-size: 12.5px;
  color: var(--text-dim);
}

.sidebar-user button {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 6px;
  padding: 5px 9px;
  font-size: 11.5px;
}
.sidebar-user button:hover { color: var(--text); border-color: var(--accent); }
.sidebar-user .user-actions { display: flex; gap: 6px; }

.content { flex: 1; display: flex; flex-direction: column; min-width: 0; position: relative; }
.view { flex: 1; display: flex; flex-direction: column; min-height: 0; }

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 22px;
  border-bottom: 1px solid var(--border);
}
.no-access-state { margin: auto; max-width: 420px; padding: 24px; line-height: 1.5; }

@media (max-width: 760px) {
  .topbar { flex-wrap: wrap; gap: 10px; padding: 10px 12px; }
  .search-wrap { width: 100%; order: 3; }
  .stream-status { flex-wrap: wrap; }
  .entries { padding: 12px; }
  .entries.list .row .date { display: none; }
  .modal, .modal.modal-wide { width: calc(100vw - 24px); padding: 22px 18px; }
  .yt-status { margin-left: 0; }
}

.breadcrumbs { display: flex; align-items: center; gap: 6px; font-size: 14px; flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; }
.breadcrumbs .crumb { color: var(--text-dim); cursor: pointer; }
.breadcrumbs .crumb:hover { color: var(--text); }
.breadcrumbs .crumb.last { color: var(--text); font-weight: 600; cursor: default; }
.breadcrumbs .sep { color: var(--border); }

.search-wrap { position: relative; width: 280px; }
.search-wrap input {
  width: 100%;
  padding: 8px 30px 8px 12px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 13.5px;
}
.search-wrap input:focus { outline: none; border-color: var(--accent); }
.search-wrap .ghost {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  background: none; border: none; color: var(--text-dim); padding: 4px 6px;
}

.view-controls { display: flex; gap: 8px; align-items: center; }
.view-controls select {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  padding: 7px 8px;
  font-size: 13px;
}
.icon-btn {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  width: 34px; height: 34px;
  font-size: 15px;
}
.icon-btn:hover { border-color: var(--accent); }

.toolbar {
  display: none;
  align-items: center;
  gap: 10px;
  padding: 10px 22px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.toolbar.visible { display: flex; }
.toolbar button {
  background: var(--accent-grad);
  border: none;
  color: var(--on-accent);
  border-radius: 7px;
  padding: 7px 12px;
  font-size: 12.5px;
  font-weight: 600;
}
.toolbar button.ghost {
  background: none;
  color: var(--text-dim);
  border: 1px solid var(--border);
}
.toolbar .spacer { flex: 1; }

.entries {
  flex: 1;
  overflow-y: auto;
  padding: 18px 22px;
}

.entries.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px;
}

.entries.list { display: flex; flex-direction: column; gap: 2px; }

/* Grid card */
.entries.grid .card {
  position: relative;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px;
  cursor: pointer;
  transition: border-color .12s, transform .12s;
}
.entries.grid .card:hover { border-color: var(--accent); transform: translateY(-2px); }
.entries.grid .card.selected { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent); }

.thumb {
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 7px;
  background: var(--bg-elev-2);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  overflow: hidden;
  margin-bottom: 8px;
}
.thumb img { width: 100%; height: 100%; object-fit: cover; }

.card .name { font-size: 12.5px; word-break: break-word; line-height: 1.3; max-height: 2.6em; overflow: hidden; }
.card .meta { font-size: 11px; color: var(--text-dim); margin-top: 4px; }

.card .checkbox {
  position: absolute;
  top: 8px; left: 8px;
  width: 18px; height: 18px;
  border-radius: 5px;
  border: 1.5px solid var(--border);
  background: color-mix(in srgb, var(--bg) 80%, transparent);
}
.card.selected .checkbox { background: var(--accent-grad); border-color: transparent; }
.card .checkbox::after {
  content: '';
  display: block;
}
.card.selected .checkbox::after {
  content: '✓';
  color: var(--on-accent);
  font-size: 12px;
  text-align: center;
  line-height: 17px;
}

.card .dl-btn {
  position: absolute;
  bottom: 8px; right: 8px;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: none;
  background: var(--bg-elev-2);
  color: var(--text);
  font-size: 13px;
  opacity: 0;
  transition: opacity .12s;
}
.entries.grid .card:hover .dl-btn { opacity: 1; }
.card .dl-btn:hover { background: var(--accent-grad); }
.card .del-btn {
  position: absolute;
  bottom: 8px; right: 40px;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: none;
  background: var(--bg-elev-2);
  color: var(--text);
  font-size: 13px;
  opacity: 0;
  transition: opacity .12s;
}
.entries.grid .card:hover .del-btn { opacity: 1; }
.card .del-btn:hover { background: var(--danger); }

/* List row */
.entries.list .row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-radius: 8px;
  cursor: pointer;
}
.entries.list .row:hover { background: var(--bg-elev); }
.entries.list .row.selected { background: color-mix(in srgb, var(--accent) 15%, transparent); }
.entries.list .row .checkbox {
  width: 16px; height: 16px;
  border-radius: 4px;
  border: 1.5px solid var(--border);
  flex-shrink: 0;
}
.entries.list .row.selected .checkbox { background: var(--accent-grad); border-color: transparent; }
.entries.list .row .icon { width: 26px; text-align: center; font-size: 16px; flex-shrink: 0; }
.entries.list .row .name { flex: 1; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entries.list .row .size { width: 90px; color: var(--text-dim); font-size: 12.5px; text-align: right; }
.entries.list .row .date { width: 140px; color: var(--text-dim); font-size: 12.5px; text-align: right; }
.entries.list .row .dl-btn {
  border: none; background: var(--bg-elev-2); color: var(--text);
  width: 28px; height: 28px; border-radius: 50%; font-size: 13px; flex-shrink: 0;
}
.entries.list .row .dl-btn:hover { background: var(--accent-grad); }
.entries.list .row .del-btn {
  border: none; background: var(--bg-elev-2); color: var(--text);
  width: 28px; height: 28px; border-radius: 50%; font-size: 13px; flex-shrink: 0;
}
.entries.list .row .del-btn:hover { background: var(--danger); }

.empty-state, .loading {
  text-align: center;
  color: var(--text-dim);
  padding: 60px 0;
  font-size: 14px;
}

/* ---------- Modal (change password) ---------- */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(5,5,8,0.7);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.modal {
  width: 360px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 28px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}
.modal.modal-wide { width: 460px; }
.modal h2 { margin: 0 0 6px; font-size: 18px; }
.modal-sub { color: var(--text-dim); font-size: 13px; margin: 0 0 18px; }
.modal label { display: block; font-size: 12px; color: var(--text-dim); margin: 12px 0 6px; }
.modal input {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 14px;
}
.modal input:focus { outline: none; border-color: var(--accent); }
.modal-error { color: var(--danger); font-size: 13px; margin-top: 12px; min-height: 16px; }
.modal-hint { color: var(--text-dim); font-size: 11.5px; margin: 6px 0 0; }
.modal-actions { display: flex; gap: 10px; margin-top: 18px; }
.modal-actions button {
  flex: 1;
  padding: 10px;
  border: none;
  border-radius: 8px;
  font-weight: 600;
  font-size: 13.5px;
}
.modal-actions button#pwSubmitBtn { background: var(--accent-grad); color: var(--on-accent); }
.modal-actions button.ghost { background: none; border: 1px solid var(--border); color: var(--text-dim); }

/* Toasts / download manager */
.toast-stack {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 999;
}
.toast {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 16px;
  font-size: 13px;
  box-shadow: 0 10px 30px rgba(0,0,0,0.4);
  min-width: 220px;
  animation: slideIn .18s ease-out;
}
.toast .toast-title { font-weight: 600; margin-bottom: 2px; }
.toast .toast-sub { color: var(--text-dim); font-size: 11.5px; }

@keyframes slideIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--text-dim) 28%, transparent); background-clip: padding-box; border-radius: 6px; border: 2px solid transparent; }
::-webkit-scrollbar-track { background: transparent; }

/* ---------- Shared upload ---------- */

.upload-zone {
  margin: 18px 22px 0;
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  padding: 40px 32px;
  text-align: center;
  color: var(--text-dim);
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.upload-zone:hover, .upload-zone.dragover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  color: var(--text);
}
.upload-zone-icon { font-size: 40px; margin-bottom: 10px; opacity: 0.85; }
.upload-zone-title { font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 4px; }
.upload-zone-sub { font-size: 12px; margin-bottom: 14px; }
.upload-zone-buttons { display: flex; gap: 10px; justify-content: center; }
.upload-zone-buttons button {
  padding: 9px 18px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  border: none;
  background: var(--accent-grad);
  color: var(--on-accent);
}
.upload-zone-buttons button.ghost {
  background: none;
  border: 1px solid var(--border);
  color: var(--text);
}
.upload-zone-buttons button:hover { filter: brightness(1.1); }

.upload-progress-list {
  margin: 0 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.upload-progress-item {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
  margin-top: 10px;
  font-size: 12.5px;
}
.upload-progress-item .upi-name { display: flex; justify-content: space-between; margin-bottom: 6px; }
.upload-progress-item .upi-bar-track { height: 5px; background: var(--bg-elev-2); border-radius: 3px; overflow: hidden; }
.upload-progress-item .upi-bar-fill { height: 100%; background: var(--accent-grad); width: 0%; transition: width .15s; }
.upload-progress-item.done .upi-bar-fill { background: var(--success); }
.upload-progress-item.error .upi-bar-fill { background: var(--danger); }
.upload-progress-item .upi-status { color: var(--text-dim); font-size: 11px; margin-top: 4px; }

/* ---------- YouTube Sync ---------- */

.yt-url-wrap { display: flex; gap: 8px; flex: 1; }
.yt-url-wrap input {
  flex: 1;
  padding: 8px 12px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 13.5px;
}
.yt-url-wrap input:focus { outline: none; border-color: var(--accent); }
.yt-url-wrap button {
  padding: 8px 18px;
  border: none;
  border-radius: 8px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-weight: 600;
  font-size: 13px;
}
.yt-status { font-size: 11.5px; color: var(--text-dim); white-space: nowrap; margin-left: 14px; }

.yt-clear-btn { margin-left: 10px; white-space: nowrap; padding: 8px 14px; border-radius: 8px; font-size: 12.5px; }
.yt-clear-btn:hover { border-color: var(--danger); color: var(--danger); }

.yt-extension-btn { margin-left: 10px; white-space: nowrap; padding: 8px 14px; border-radius: 8px; font-size: 12.5px; }
.yt-extension-btn:hover { border-color: var(--accent); }

.yt-extension-download {
  display: inline-block;
  margin: 4px 0 16px;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-weight: 600;
  font-size: 13px;
  text-decoration: none;
}
.yt-extension-steps { margin: 0 0 14px; padding-left: 20px; color: var(--text); font-size: 13px; line-height: 1.6; }
.yt-extension-steps li { margin-bottom: 6px; }
.yt-extension-steps code {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 12px;
}
.yt-extension-note { margin-bottom: 0; }

.yt-body {
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: center;
  gap: 20px;
  padding: 24px;
  overflow: auto;
}
/* The player grows with whatever width is available (e.g. the sidebar collapsing), capped so the
   whole 16:9 frame plus the controls under it still fit the window's height. */
.yt-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: max(480px, min(1600px, calc((100dvh - 200px) * 16 / 9)));
}
.yt-player-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
#ytPlayerContainer { width: 100%; height: 100%; }
.yt-audio-only-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-dim);
  cursor: pointer;
}
.yt-audio-only-row input { accent-color: var(--accent); width: 14px; height: 14px; cursor: pointer; }
.yt-empty {
  position: absolute;
  inset: 0;
  background: var(--bg-elev);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 14px;
  text-align: center;
  padding: 24px;
  pointer-events: none;
}
.yt-playlist-controls {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 16px;
  font-size: 13px;
  color: var(--text-dim);
}
.yt-playlist-controls button {
  padding: 7px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: none;
  color: var(--text);
  font-size: 13px;
}
.yt-playlist-controls button:hover { border-color: var(--accent); }

/* Watch history under the player: its own scroll area, so a long history doesn't push the page
   down forever. */
.yt-history {
  width: 100%;
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.yt-history-title {
  padding: 12px 14px;
  font-weight: 600;
  font-size: 13px;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
}
.yt-history-items { max-height: 380px; overflow-y: auto; }
.yt-history-empty { padding: 14px; font-size: 12.5px; color: var(--text-dim); }
.yt-history-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 8px 8px 12px;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.yt-history-item:last-child { border-bottom: none; }
.yt-history-item:hover { background: var(--bg-elev-2); }
.yt-history-item.active { background: var(--bg-elev-2); box-shadow: inset 3px 0 0 var(--accent); cursor: default; }
.yt-history-thumb { position: relative; width: 96px; height: 54px; flex-shrink: 0; border-radius: 5px; overflow: hidden; background: #000; }
.yt-history-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Stacked-cards badge, like YouTube's own playlist thumbnails. */
.yt-history-badge {
  position: absolute;
  right: 0; bottom: 0; top: 0;
  width: 40%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0,0,0,0.7);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
}
.yt-history-text { flex: 1; min-width: 0; }
.yt-history-name {
  font-size: 13px;
  line-height: 1.3;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.yt-history-sub { font-size: 11.5px; color: var(--text-dim); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.yt-history-now { color: var(--accent); font-weight: 600; }
.yt-history-remove {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 14px;
  padding: 6px 9px;
  border-radius: 6px;
  cursor: pointer;
}
.yt-history-remove:hover { background: color-mix(in srgb, var(--text) 10%, transparent); color: var(--danger); }

.yt-playlist-panel {
  width: 300px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  max-height: min(640px, calc(100vh - 160px));
}
.yt-playlist-panel-title {
  padding: 12px 14px;
  font-weight: 600;
  font-size: 13px;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.yt-playlist-items { overflow-y: auto; flex: 1; }
.yt-playlist-shuffle-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  color: var(--text);
  cursor: pointer;
  flex-shrink: 0;
}
.yt-playlist-shuffle-row input { accent-color: var(--accent); width: 14px; height: 14px; cursor: pointer; }
.yt-playlist-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.yt-playlist-item:last-child { border-bottom: none; }
.yt-playlist-item:hover { background: var(--bg-elev-2); }
.yt-playlist-item.active { background: var(--bg-elev-2); box-shadow: inset 3px 0 0 var(--accent); }
.yt-playlist-item-idx { width: 18px; flex-shrink: 0; text-align: right; font-size: 11px; color: var(--text-dim); }
.yt-playlist-item img { width: 64px; height: 36px; object-fit: cover; border-radius: 4px; flex-shrink: 0; background: #000; }
.yt-playlist-item-title {
  font-size: 12.5px;
  line-height: 1.3;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

@media (max-width: 900px) {
  .yt-body { flex-direction: column; align-items: center; padding: 12px; }
  .yt-main { max-width: 100%; }
  .yt-playlist-panel { width: 100%; max-width: 960px; max-height: 300px; }
  .yt-url-wrap { flex-basis: 100%; }
  .yt-clear-btn, .yt-extension-btn { margin-left: 0; }
}

/* ---------- Audio Stream ---------- */

.stream-status { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.stream-dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--text-dim);
  flex-shrink: 0;
}
.stream-dot.live { background: var(--success); box-shadow: 0 0 8px color-mix(in srgb, var(--success) 60%, transparent); }

/* Real audio-activity LEDs: lit from actual WebRTC audio-level stats (see
   updateChatAudioActivity), not from device/UI state - off if noise suppression is eating the
   signal, on only while genuine audio is actually flowing through the connection. Each one is
   wrapped in a bordered pill with the relevant username, so it's unambiguous which LED is whose
   even when neither is lit. */
.chat-audio-indicator {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 7px;
  border-radius: 12px;
  border: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-dim);
  max-width: 120px;
}
.chat-audio-indicator-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-audio-indicator-self { border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.chat-audio-indicator-remote { border-color: color-mix(in srgb, var(--info) 35%, transparent); }
.chat-audio-led {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--bg-elev2, var(--bg-elev));
  border: 1px solid var(--border);
  flex-shrink: 0;
  transition: background 0.08s ease, box-shadow 0.08s ease;
}
.chat-audio-led-self.active { background: var(--danger); border-color: var(--danger); box-shadow: 0 0 6px color-mix(in srgb, var(--danger) 80%, transparent); }
.chat-audio-led-remote.active { background: var(--info); border-color: var(--info); box-shadow: 0 0 6px color-mix(in srgb, var(--info) 80%, transparent); }
.chat-audio-led-atten.active { background: var(--success); border-color: var(--success); box-shadow: 0 0 6px color-mix(in srgb, var(--success) 80%, transparent); }

/* The gate LED + bar as a unit ("Noise Gate Indicator") - hidden entirely while noise suppression
   is off, since the gate isn't doing anything meaningful in that state. */
.chat-noise-gate-indicator { display: inline-flex; align-items: center; gap: 6px; }
.chat-noise-gate-indicator.hidden { display: none; }
.chat-noise-gate-label { font-size: 11px; color: var(--text-dim); white-space: nowrap; }

/* Mic-level-vs-threshold meter: a horizontal bar whose filled length is the current mic level,
   yellow up to the noise-floor threshold marker and green past it (i.e. green = "this would get
   through the gate"), plus a vertical line marking the threshold itself. Same structure at two
   sizes - compact in the topbar, larger on the settings page for mic testing. */
.chat-mic-meter { display: inline-flex; align-items: center; gap: 6px; }
.chat-mic-meter-compact { width: 90px; }
.chat-mic-meter-large { display: block; width: 100%; }
.chat-mic-meter-track {
  position: relative;
  flex: 1;
  height: 8px;
  border-radius: 4px;
  background: var(--bg-elev2, var(--bg-elev));
  border: 1px solid var(--border);
  overflow: hidden;
}
.chat-mic-meter-large .chat-mic-meter-track { display: block; width: 100%; height: 14px; border-radius: 6px; }
.chat-mic-meter-fill-yellow, .chat-mic-meter-fill-green {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 0%;
  transition: width 0.06s linear;
}
.chat-mic-meter-fill-yellow { background: var(--warning); }
.chat-mic-meter-fill-green { background: var(--success); }
.chat-mic-meter-threshold {
  position: absolute;
  top: -1px; bottom: -1px;
  left: 0%;
  width: 2px;
  background: var(--text);
  opacity: 0.85;
}

/* Centered with auto margins rather than justify-content:center - when the content is taller than
   the view (a large video frame), centering would push its top out of reach of the scrollbar. */
.stream-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  padding: 24px;
  overflow: auto;
}
.stream-body > :first-child { margin-top: auto; }
.stream-body > :last-child { margin-bottom: auto; }
@media (max-width: 760px) {
  .stream-body { padding: 12px; }
}
.stream-card {
  width: 100%;
  max-width: 420px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 36px 28px;
  text-align: center;
}
.stream-icon { font-size: 44px; margin-bottom: 12px; }
.stream-title { font-size: 18px; font-weight: 700; margin-bottom: 4px; }
.stream-sub { font-size: 13px; color: var(--text-dim); margin-bottom: 20px; }
.stream-play-btn {
  padding: 12px 32px;
  border: none;
  border-radius: 10px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-weight: 700;
  font-size: 14px;
}
.stream-play-btn[disabled] { opacity: 0.4; cursor: not-allowed; }
.stream-play-btn.listening { background: var(--danger-grad); }
.stream-listeners { font-size: 11.5px; color: var(--text-dim); margin-top: 14px; }
.stream-latency {
  font-size: 11.5px;
  color: var(--accent-2);
  margin-top: 8px;
  font-variant-numeric: tabular-nums;
}

.stream-buffer-control {
  width: 100%;
  max-width: 420px;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px 20px;
  text-align: center;
}
.stream-buffer-control select {
  margin-top: 4px;
  padding: 7px 10px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg-elev-2);
  color: var(--text);
  font-size: 12.5px;
}

.stream-download {
  width: 100%;
  max-width: 420px;
  border: 1px dashed var(--border);
  border-radius: 12px;
  padding: 16px 20px;
  text-align: center;
}
.stream-admin-title, .stream-download-title { font-size: 13px; font-weight: 600; margin-bottom: 4px; }
.stream-admin-sub, .stream-download-sub { font-size: 11.5px; color: var(--text-dim); margin-bottom: 12px; }
.stream-download button[disabled] { opacity: 0.4; cursor: not-allowed; }
.stream-download .ghost {
  padding: 8px 14px; border-radius: 8px; font: inherit; font-size: 13px;
  background: var(--bg-elev-2); border: 1px solid var(--border); color: var(--text);
}
.stream-download .ghost:hover { border-color: var(--accent); }

/* ---------- Video Stream ---------- */

/* Same idea as the YouTube player: use the available width, but keep the frame and the stats line
   under it within the window's height. */
.vid-stream-wrap {
  position: relative;
  flex-shrink: 0;
  width: 100%;
  max-width: max(480px, min(1920px, calc((100dvh - 190px) * 16 / 9)));
  aspect-ratio: 16 / 9;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.vid-stream-canvas { width: 100%; height: 100%; display: block; object-fit: contain; background: #000; }
.vid-stream-overlay {
  position: absolute;
  inset: 0;
  background: var(--bg-elev);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
}
.vid-stream-overlay.hidden { display: none; }

.vid-stream-wrap:fullscreen { max-width: none; border-radius: 0; border: none; }
.vid-stream-wrap:fullscreen .vid-stream-canvas { object-fit: contain; }

.vid-stream-fullscreen-btn {
  position: absolute;
  right: 10px;
  bottom: 10px;
  width: 34px;
  height: 34px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(0,0,0,0.55);
  color: #fff;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.vid-stream-wrap:hover .vid-stream-fullscreen-btn { opacity: 1; }
.vid-stream-fullscreen-btn:hover { background: rgba(0,0,0,0.75); }
.vid-stream-popout-btn { right: 52px; }

/* ---- The Windows app's mini player: while its small always-on-top window has this page, only
   the video shows - the Video Stream's or YouTube Sync's (see "Mini player" in app.js). ---- */
html.mini-mode, html.mini-mode body { background: #000; overflow: hidden; }
html.mini-mode body * { visibility: hidden; }
html.mini-mode .mini-target, html.mini-mode .mini-target * { visibility: visible; }
html.mini-mode .mini-host { display: flex !important; }
html.mini-mode .mini-target {
  position: fixed !important;
  inset: 0 !important;
  width: auto !important;
  height: auto !important;
  max-width: none !important;
  aspect-ratio: auto !important;
  z-index: 2147483000;
  border: none !important;
  border-radius: 0 !important;
  background: #000 !important;
}
html.mini-mode .mini-target .vid-stream-fullscreen-btn { display: none; }

/* The call in that window (the app's "Call mini window" - html.mini-call, #chatStage the mini-target):
   the other person fills it, your preview sits in a corner, and a compact bar keeps only the call's own
   buttons - mute, camera, stream, leave. !important: dragging writes inline positions. */
html.mini-call .chat-self-pip {
  left: auto !important; top: 8px !important; right: 8px !important; bottom: auto !important;
  width: 28% !important; min-width: 0 !important; max-width: 170px;
}
html.mini-call .chat-widget-bar {
  left: 50% !important; top: auto !important; bottom: 8px !important; transform: translateX(-50%) !important;
  width: auto !important; min-width: 0 !important; height: 40px; gap: 2px; padding: 0 4px; resize: none;
}
html.mini-call .chat-widget-bar .chat-bar-grab,
html.mini-call .chat-widget-bar .chat-bar-slider,
html.mini-call .chat-widget-bar .chat-bar-slider-icon,
html.mini-call #chatBarSettingsBtn,
html.mini-call #chatBarChatBtn,
html.mini-call #chatBarFullscreenBtn,
html.mini-call #chatBarPopoutBtn,
html.mini-call .chat-yt-widget,
html.mini-call .chat-stream-hint { display: none !important; }
html.mini-call .chat-widget-bar .chat-bar-btn { flex: 0 0 38px; height: 32px; font-size: 17px; }

/* The video and its stats panel. The panel sits under the video, as wide as it; on a screen with
   room to spare beside a (height-limited) video, it moves alongside instead (.side, set by
   layoutVidStage in app.js), so the stats are visible without scrolling. */
.vid-stage {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.vid-stage.side { flex-direction: row; align-items: flex-start; justify-content: center; gap: 16px; }
.vid-stage.side .vid-stream-wrap { width: var(--vid-w); max-width: none; }

.vid-stats {
  width: 100%;
  max-width: max(480px, min(1920px, calc((100dvh - 190px) * 16 / 9)));
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  font-size: 12.5px;
  --seg-encode: var(--accent);
  --seg-upload: var(--accent-2);
  --seg-viewer: var(--success);
}
.vid-stage.side .vid-stats { width: 300px; max-width: none; flex-shrink: 0; }

/* The same panel over a stream in a call (right-click it): floating top right of the stage, above
   the tiles and the floating widgets, and short of the widget bar's row at the bottom. */
.vid-stats.chat-stream-stats {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 300px;
  max-width: calc(100% - 24px);
  max-height: calc(100% - 88px);
  overflow-y: auto;
  z-index: 1002;
  box-shadow: 0 12px 32px rgba(0,0,0,0.5);
}
.vid-stats.chat-stream-stats .vid-stats-body { grid-template-columns: 1fr; }
.vid-stats.chat-stream-stats .vid-stats-head { padding-right: 40px; }
.vid-stats-close {
  position: absolute;
  top: 6px;
  right: 8px;
  z-index: 1;
  width: 26px; height: 26px;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text-dim);
  font-size: 12px;
}
.vid-stats-close:hover { background: var(--bg-elev-2); color: var(--text); }

.vid-stats-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  background: none;
  border: none;
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  text-align: left;
}
.vid-stats-head:hover { background: var(--bg-elev-2); }
.vid-stats-chevron { color: var(--text-dim); transition: transform 0.15s ease; }
.vid-stats-head[aria-expanded="false"] .vid-stats-chevron { transform: rotate(-90deg); }

/* 1px gaps over a border-coloured background draw the dividers between groups, whether they sit
   in a row (under the video) or a column (beside it). */
.vid-stats-body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1px;
  background: var(--border);
  border-top: 1px solid var(--border);
}
.vid-stage.side .vid-stats-body { grid-template-columns: 1fr; }
.vid-stats-group { background: var(--bg-elev); padding: 12px 14px 14px; min-width: 0; }
.vid-stats-group h4 {
  margin: 0 0 9px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.vid-stats-list { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.vid-stats-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.vid-stats-row dt { color: var(--text-dim); min-width: 0; }
.vid-stats-row dd {
  margin: 0;
  color: var(--text);
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.vid-stats-row .vid-stat-note { color: var(--text-dim); font-size: 11px; margin-left: 5px; }
.vid-stats-sub dt { padding-left: 15px; font-size: 12px; }
.vid-stats-sub dd { color: var(--text-dim); font-size: 12px; }
.vid-stats-row.vid-stat-warn dd { color: var(--warning); }

.vid-lat-total { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; margin-bottom: 9px; }
.vid-lat-total-value { font-size: 24px; font-weight: 700; line-height: 1.1; font-variant-numeric: tabular-nums; }
.vid-lat-total-value.vid-lat-high { color: var(--warning); }
.vid-lat-total-label { color: var(--text-dim); font-size: 11.5px; }
.vid-lat-bar {
  display: flex;
  height: 6px;
  margin-bottom: 11px;
  border-radius: 3px;
  overflow: hidden;
  background: var(--bg-elev-2);
}
.vid-lat-seg { height: 100%; width: 0; transition: width 0.4s ease; }

.vid-stats-group-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.vid-stats-group-head h4 { margin: 0; }
.vid-mode {
  display: inline-flex;
  padding: 2px;
  border-radius: 7px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
}
.vid-mode button {
  padding: 3px 9px;
  border: none;
  border-radius: 5px;
  background: none;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.vid-mode button:hover:not(:disabled) { color: var(--text); }
.vid-mode button[aria-checked="true"] { background: var(--seg-viewer); color: var(--bg); }
.vid-mode button[data-mode="smooth"][aria-checked="true"] { background: var(--seg-upload); }
.vid-mode button:disabled { opacity: 0.45; cursor: default; }
.vid-lat-control { margin: 10px 0 0; color: var(--text-dim); font-size: 11.5px; line-height: 1.4; }
.vid-lat-control:empty { display: none; }
.vid-lat-notice {
  margin: 9px 0 0;
  padding: 7px 9px;
  border-radius: 7px;
  border: 1px solid color-mix(in srgb, var(--warning) 35%, transparent);
  background: color-mix(in srgb, var(--warning) 10%, transparent);
  color: var(--warning);
  font-size: 11.5px;
  line-height: 1.4;
}
.vid-lat-key { display: inline-block; width: 8px; height: 8px; margin-right: 7px; border-radius: 2px; }
.vid-stats .seg-encode { background: var(--seg-encode); }
.vid-stats .seg-upload { background: var(--seg-upload); }
.vid-stats .seg-viewer { background: var(--seg-viewer); }

.vid-stream-unmute-btn {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  padding: 9px 16px;
  border-radius: 20px;
  border: 1px solid rgba(255,255,255,0.25);
  background: rgba(0,0,0,0.7);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.vid-stream-unmute-btn:hover { background: rgba(0,0,0,0.85); }
.vid-stream-overlay .stream-sub { max-width: 560px; line-height: 1.5; }

/* ---------- Chatroom ---------- */

/* The view is a row: the contact dock (when kept open) beside everything else. */
#chatroomView { position: relative; flex-direction: row; }
.chat-view-main {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

/* ---- Contact picker (shown before a private room is opened) ---- */

.chat-contacts {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
}
/* Call history: each call as a small centred line in the conversation, where it started. */
.chat-call-event {
  display: flex;
  justify-content: center;
  margin: 12px 14px 0;
}
.chat-call-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 4px 12px;
  font-size: 12px;
  color: var(--text-dim);
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.chat-call-icon { font-size: 13px; flex-shrink: 0; }
.chat-call-arrow { color: var(--success); font-weight: 700; }
.chat-call-detail { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-call-when { white-space: nowrap; flex-shrink: 0; }
.chat-call-event.missed .chat-call-detail,
.chat-call-event.missed .chat-call-arrow { color: var(--danger); }

/* ---- Contacts beside the chat: a column right of the sidebar, collapsible to just pictures ---- */
.chat-dock {
  width: 240px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-right: 1px solid var(--border);
  background: var(--bg);
}
.chat-dock-head {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 14px 10px 10px 16px;
  flex-shrink: 0;
}
.chat-dock-title { flex: 1; font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.chat-dock-btn {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 7px;
  background: none;
  color: var(--text-dim);
  font-size: 14px;
}
.chat-dock-btn:hover { background: var(--bg-elev-2); color: var(--text); }
.chat-dock-body { flex: 1; overflow-y: auto; padding: 0 8px 12px; }
.chat-dock .chat-self-contact-row { max-width: none; margin: 0 0 10px; padding: 8px 10px; gap: 10px; }
.chat-dock .chat-self-contact-row .chat-avatar-lg { width: 36px; height: 36px; font-size: 14px; }
.chat-dock .chat-contacts-list { max-width: none; gap: 2px; }
.chat-dock .chat-contact-row { padding: 8px 10px; gap: 10px; border-color: transparent; background: none; }
.chat-dock .chat-contact-row:hover { background: var(--bg-elev); border-color: transparent; }
.chat-dock .chat-contact-row.active { background: var(--bg-elev-2); border-color: var(--border); }
.chat-dock .chat-contact-call { font-size: 0; padding: 0; width: 9px; height: 9px; border-radius: 50%; background: var(--success); }
.chat-dock .chat-contacts-empty { margin-top: 12px; }
.chat-dock-placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 13.5px;
  padding: 24px;
  text-align: center;
}
/* Collapsed: just the pictures, with their unread bubbles and presence dots. */
.chat-dock.collapsed { width: 68px; }
.chat-dock.collapsed .chat-dock-head { flex-direction: column; padding: 12px 0 8px; gap: 2px; }
.chat-dock.collapsed .chat-dock-title,
.chat-dock.collapsed .chat-contact-text,
.chat-dock.collapsed .chat-self-contact-name,
.chat-dock.collapsed .chat-contact-call { display: none; }
.chat-dock.collapsed .chat-dock-body { padding: 0 6px 12px; }
.chat-dock.collapsed .chat-self-contact-row { justify-content: center; padding: 6px 0; border-style: none; }
.chat-dock.collapsed .chat-contact-row { justify-content: center; padding: 6px 0; }
.chat-dock.collapsed .chat-contact-unread { position: absolute; top: 0; right: 4px; margin: 0; }
@media (max-width: 760px) {
  .chat-dock { display: none !important; }
}

/* Unread bubble and presence dot on each contact. */
.chat-contact-row { position: relative; }
.chat-contact-row.active .chat-contact-name { font-weight: 600; }
.chat-contact-avatar-wrap { position: relative; flex-shrink: 0; }
.chat-contact-text { flex: 1; min-width: 0; }
.chat-contact-text .chat-contact-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-contact-status { font-size: 11.5px; color: var(--text-dim); margin-top: 1px; }
.chat-contact-status.online { color: var(--success); }
.chat-contact-status.away { color: var(--warning); }
.chat-contact-status.typing { color: var(--accent-2); font-style: italic; }
/* "Playing X" (the Windows app's game detection): one line, cut short if long. */
.chat-contact-status.playing { color: var(--accent-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-contact-row.unread .chat-contact-name { font-weight: 700; }
.chat-contact-unread {
  min-width: 20px; height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--danger);
  color: white;
  font-size: 11.5px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-shadow: 0 0 0 2px var(--bg);
}
.chat-contact-call + .chat-contact-unread { margin-left: 0; }
.chat-contact-text + .chat-contact-unread { margin-left: auto; }
.chat-presence-dot {
  position: absolute;
  right: -1px; bottom: -1px;
  width: 11px; height: 11px;
  border-radius: 50%;
  border: 2px solid var(--bg-elev);
  background: color-mix(in srgb, var(--text-dim) 60%, var(--bg-elev));
}
.chat-dock .chat-presence-dot { border-color: var(--bg); }
.chat-presence-dot.online { background: var(--success); }
.chat-presence-dot.away { background: var(--warning); }
.chat-self-contact-row {
  max-width: 480px;
  margin: 0 auto 18px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  cursor: pointer;
}
.chat-self-contact-row:hover { border-color: var(--accent); }
.chat-self-contact-name { font-size: 13.5px; color: var(--text-dim); }

.chat-contacts-list {
  max-width: 480px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.chat-contact-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
}
.chat-contact-row:hover { border-color: var(--accent); }
.chat-contact-name { font-size: 13.5px; }
.chat-contacts-empty { text-align: center; color: var(--text-dim); font-size: 13px; margin-top: 40px; }

/* Shared avatar circle: an initials div underneath, an <img> on top once/if one loads (see
   buildChatAvatarEl / refreshChatSelfAvatar). ".chat-avatar-lg" is used for the self-picture
   editor on the contacts page; the bare size below is the small per-contact-row circle. */
.chat-avatar, .chat-avatar-lg {
  position: relative;
  border-radius: 50%;
  background: var(--accent-grad);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}
.chat-avatar { width: 36px; height: 36px; font-size: 14px; }
.chat-avatar-lg { width: 52px; height: 52px; font-size: 18px; }
.chat-avatar-initials { color: var(--on-accent); font-weight: 700; }
.chat-avatar-img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

.chat-self-avatar-edit { cursor: pointer; }
.chat-avatar-edit-overlay {
  position: absolute;
  inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.45);
  opacity: 0;
  transition: opacity 0.15s ease;
  font-size: 18px;
}
.chat-self-avatar-edit:hover .chat-avatar-edit-overlay { opacity: 1; }

.chat-body {
  flex: 1;
  display: flex;
  padding: 24px;
  overflow: hidden;
  min-height: 0;
}

/* Not in a call: no stage, just the Call buttons above the messages, which take the full width. */
.chat-body.no-call { position: relative; flex-direction: column; }
.chat-body.no-call .chat-stage,
.chat-body.no-call .chat-text-resizer { display: none !important; }
/* The settings overlay then covers the whole conversation rather than the (now tiny) call area. */
.chat-body.no-call .chat-main-area { position: static; flex: none; }
.chat-body.no-call .chat-call-actions { justify-content: flex-end; margin: 0 0 12px; gap: 10px; }
.chat-body.no-call .chat-call-btn { min-width: 0; padding: 8px 16px; }
.chat-body.no-call .chat-text-panel { flex: 1; width: auto !important; display: flex !important; }

.chat-main-area {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.chat-stage {
  position: relative;
  flex: 1;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  min-height: 0;
}
.chat-stage-empty {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
  justify-content: center;
  padding: 0 24px;
  text-align: center;
  color: var(--text-dim);
  font-size: 13px;
  pointer-events: none;
}
.chat-stage.has-remote .chat-stage-empty { display: none; }
.chat-ring-again-btn {
  pointer-events: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 16px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.chat-ring-again-btn:hover { border-color: var(--accent); }

/* ---- Calls: contact-list badge and the incoming-call panel (see "Calls" in app.js) ---- */
.chat-contact-call {
  margin-left: auto;
  padding: 3px 9px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--success);
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
}
.chat-incoming-call {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: calc(100vw - 32px);
  padding: 14px 16px;
  background: var(--bg-elev);
  border: 1px solid var(--success);
  border-radius: 14px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
  animation: chatIncomingPulse 1.6s ease-in-out infinite;
}
@keyframes chatIncomingPulse {
  0%, 100% { box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5), 0 0 0 0 color-mix(in srgb, var(--success) 45%, transparent); }
  50% { box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5), 0 0 0 8px color-mix(in srgb, var(--success) 0%, transparent); }
}
.chat-incoming-text { min-width: 0; }
.chat-incoming-name { font-size: 15px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-incoming-sub { font-size: 12px; color: var(--text-dim); margin-top: 2px; }
.chat-incoming-btn {
  border: 0;
  border-radius: 999px;
  padding: 9px 16px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: white;
  cursor: pointer;
  white-space: nowrap;
}
.chat-incoming-btn.accept { background: #16a34a; }
.chat-incoming-btn.accept:hover { background: #22c55e; }
.chat-incoming-btn.decline { background: #e11d48; }
.chat-incoming-btn.decline:hover { background: #f43f5e; }
@media (max-width: 520px) {
  .chat-incoming-call { flex-wrap: wrap; justify-content: center; }
  .chat-incoming-text { flex-basis: calc(100% - 70px); }
}

/* Every tile in the stage - the self preview and each remote participant - is an independently
   draggable, aspect-locked, resizable floating window, so they can be repositioned freely and
   even stacked on top of one another. Only width is a hard size (px, set at creation/resize) -
   height is left to aspect-ratio to compute, and max-width/max-height (100% of the stage) let a
   resize grow all the way to the edges of the available window space. */
.chat-float-tile {
  position: absolute;
  aspect-ratio: 16 / 9;
  resize: horizontal;
  overflow: hidden;
  min-width: 160px;
  max-width: 100%;
  max-height: 100%;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg-elev2, var(--bg-elev));
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.chat-float-tile.dragging { cursor: grabbing; opacity: 0.88; }
.chat-float-tile video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: none;
  pointer-events: none;
}
.chat-float-tile.has-video video { display: block; }
.chat-tile-avatar {
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--accent-grad);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; font-weight: 700; color: var(--on-accent);
  flex-shrink: 0;
  pointer-events: none;
}
.chat-float-tile.has-video .chat-tile-avatar { display: none; }

/* The remote participant's tile is NOT a free-floating draggable window like the self preview -
   it always fills as much of the stage as it can while keeping its 16:9 aspect ratio, centered,
   and automatically resizes whenever the stage itself does (sidebar drag, window resize,
   fullscreen...) since this is pure CSS with no JS involved. Overrides the absolute-positioned,
   manually-draggable/resizable defaults from .chat-float-tile above. */
.chat-remote-tile {
  position: absolute;
  inset: 0;
  margin: auto;
  left: 0; top: 0; right: 0; bottom: 0;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  resize: none;
  cursor: default;
  touch-action: auto;
}
/* The other person's video keeps its own shape - a phone held upright sends portrait. The tile
   takes the video's aspect ratio (inline, from fitChatTileToVideo in app.js) and the picture is
   fitted, never cropped, including for the moment before the new shape is known. */
.chat-remote-tile video { object-fit: contain; }
.chat-remote-tile.has-video { background: #000; }

/* ---- A stream in the call: one of the stream and the other person's video fills the stage
   (.chat-stage-main), the other floats small and draggable (.chat-stage-pip). Clicking either
   swaps them (see "Streams in the call" in app.js). ---- */
.chat-stream-tile { background: #000; cursor: pointer; }
.chat-stream-tile video { display: block; object-fit: contain; }
.chat-stream-tile.chat-stage-main,
.chat-remote-tile.chat-stage-main {
  inset: 0;
  margin: auto;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  resize: none;
  cursor: pointer;
  z-index: 1 !important;
}
.chat-stage-pip {
  inset: auto;
  margin: 0;
  width: 260px;
  height: auto;
  max-width: 60%;
  resize: horizontal;
  cursor: grab;
  border: 2px solid var(--border);
  box-shadow: 0 8px 24px rgba(0,0,0,0.45);
}
.chat-remote-tile.chat-stage-pip { touch-action: none; }
.chat-stage-pip .chat-tile-stats, .chat-stage-pip .chat-tile-fullscreen-btn { display: none; }
.chat-stream-waiting {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-dim);
  font-size: 12.5px;
  pointer-events: none;
}
.chat-stream-tile.playing .chat-stream-waiting { display: none; }
.chat-stream-hint {
  position: absolute;
  top: 8px; left: 50%;
  transform: translateX(-50%);
  font-size: 11px;
  background: rgba(0,0,0,0.6); color: #fff;
  padding: 3px 9px;
  border-radius: 6px;
  opacity: 0;
  transition: opacity 0.15s ease;
  pointer-events: none;
  white-space: nowrap;
}
.chat-stage.has-stream-swap .chat-stream-tile:hover .chat-stream-hint,
.chat-stage.has-stream-swap .chat-remote-tile:hover .chat-stream-hint { opacity: 1; }
.chat-stream-close {
  position: absolute;
  top: 6px; right: 6px;
  width: 24px; height: 24px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(0,0,0,0.6);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.chat-stream-tile:hover .chat-stream-close { opacity: 1; }

/* z-index layering, back to front: remote tiles (dynamic, capped below 900) -> self preview
   (fixed 900, so it's always above every remote tile no matter what was clicked/dragged last) ->
   widget bar and YouTube mini player (1000/1001 - whichever was grabbed last is on top, see
   bringChatTileToFront) -> settings overlay + backdrop (4900/5000) -> image lightbox (6000). */
.chat-self-pip { width: 200px; border: 2px solid var(--accent); z-index: 900; }
.chat-self-pip.has-video video { display: block; }
.chat-self-pip.has-video .chat-tile-avatar { display: none; }

.chat-widget-bar {
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  /* Fixed, not content-driven - "resize: horizontal" below is meant to only ever change width,
     but height:auto left it sized off the buttons' emoji glyph metrics, which could shift (e.g.
     a fallback-vs-real glyph swap on load) and made the bar visibly taller/shorter on join or
     fullscreen. A fixed height plus the buttons being exactly that tall (see .chat-bar-btn)
     makes that impossible regardless of font metrics. */
  height: 48px;
  min-width: 380px;
  max-width: 100%;
  width: 500px;
  resize: horizontal;
  overflow: hidden;
  background: color-mix(in srgb, var(--bg-elev) 80%, transparent);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  cursor: default;
  user-select: none;
}
.chat-widget-bar.dragging { opacity: 0.85; }
/* Dragging the bar is only possible from the grab handle now - it used to be "anywhere that
   isn't a button", which also caught pointerdown on the volume sliders added later and made them
   impossible to actually drag (every click just moved the whole bar instead). */
.chat-bar-grab {
  flex-shrink: 0;
  display: grid;
  grid-template-columns: repeat(2, 4px);
  grid-template-rows: repeat(3, 4px);
  gap: 3px;
  padding: 0 8px;
  cursor: grab;
  touch-action: none;
  align-self: center;
}
.chat-widget-bar.dragging .chat-bar-grab { cursor: grabbing; }
.chat-bar-grab-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--text-dim); }
.chat-bar-btn {
  flex: 1;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  color: var(--text);
  font-size: 20px;
  line-height: 1;
  padding: 0 4px;
  border-radius: 8px;
  cursor: pointer;
  pointer-events: auto;
}
.chat-bar-btn:hover { background: color-mix(in srgb, var(--text) 10%, transparent); }
.chat-bar-btn.active { background: var(--accent-grad); }
.chat-bar-leave:hover { background: var(--danger); }
#chatBarMuteBtn.active { background: var(--danger); }
.chat-bar-slider-icon { flex-shrink: 0; font-size: 13px; line-height: 1; opacity: 0.75; pointer-events: none; }
.chat-bar-slider {
  flex: 0 0 54px;
  width: 54px;
  accent-color: var(--accent);
  cursor: pointer;
  pointer-events: auto;
  touch-action: none;
}

/* Fullscreen (the whole stage, not a single tile - see #chatBarFullscreenBtn): the self preview
   widget bar (only - the self preview stays fully visible) fades down to a thin sliver instead of
   disappearing, and only returns to full opacity when the mouse is actually near it (tracked in JS
   - CSS :hover alone can't do this, since the element still needs to be interactive before the
   cursor is technically "over" it). */
#chatStage:fullscreen { background: #000; }
.chat-stage.chat-fullscreen-active .chat-widget-bar,
.chat-stage.chat-fullscreen-active .chat-yt-widget {
  opacity: 0.1;
  transition: opacity 0.2s ease;
}
.chat-stage.chat-fullscreen-active .chat-widget-bar.chat-fs-visible,
.chat-stage.chat-fullscreen-active .chat-yt-widget.chat-fs-visible {
  opacity: 1;
}

/* YouTube Sync mini player: same floating/translucent/grab-handle treatment as the widget bar,
   a bit more see-through since it's informational most of the time. Shares the widget bar's tier,
   above the self preview and every video tile. */
.chat-yt-widget {
  position: absolute;
  left: 16px;
  top: 16px;
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 400px;
  max-width: calc(100% - 16px);
  height: 56px;
  padding: 0 6px 0 0;
  background: color-mix(in srgb, var(--bg-elev) 60%, transparent);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.35);
  user-select: none;
  transition: background 0.15s ease;
}
.chat-yt-widget:hover { background: color-mix(in srgb, var(--bg-elev) 88%, transparent); }
.chat-yt-widget.dragging { opacity: 0.85; }
.chat-yt-widget.dragging .chat-bar-grab { cursor: grabbing; }
.chat-yt-thumb { width: 64px; height: 36px; flex-shrink: 0; border-radius: 5px; object-fit: cover; background: #000; }
.chat-yt-info { flex: 1; min-width: 0; }
.chat-yt-title { font-size: 12px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-yt-sub { font-size: 10.5px; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.chat-yt-btn { flex: 0 0 32px; font-size: 16px; padding: 0; }
.chat-yt-volume { display: flex; align-items: center; flex-shrink: 0; }
.chat-yt-mute { flex-basis: 28px; width: 28px; font-size: 15px; }
/* Vertical, bottom = silent. It's only as tall as the mini player, so the mouse wheel over it
   steps the volume too (see initChatYtVolume). */
.chat-yt-volume-slider {
  writing-mode: vertical-lr;
  direction: rtl;
  width: 16px;
  height: 44px;
  margin: 0 2px 0 0;
  accent-color: var(--accent);
  cursor: pointer;
  touch-action: none;
}
.chat-yt-volume-slider.muted { opacity: 0.35; }

.chat-tile-name {
  position: absolute;
  left: 8px; bottom: 8px;
  font-size: 11.5px;
  background: rgba(0,0,0,0.55); color: #fff;
  padding: 3px 8px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  gap: 5px;
  pointer-events: none;
}
.chat-tile-mic-off::before { content: "🔇"; font-size: 10px; }

.chat-tile-stats {
  position: absolute;
  right: 8px; top: 8px;
  font-size: 10px;
  color: rgba(255,255,255,0.75);
  background: rgba(0,0,0,0.55);
  padding: 3px 7px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  gap: 5px;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  max-width: calc(100% - 16px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-tile-quality-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.chat-tile-quality-dot.good { background: var(--success); }
.chat-tile-quality-dot.fair { background: var(--warning); }
.chat-tile-quality-dot.poor { background: var(--danger); }

.chat-tile-fullscreen-btn {
  position: absolute;
  right: 8px; bottom: 8px;
  width: 28px; height: 28px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(0,0,0,0.55);
  color: #fff;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.chat-float-tile:hover .chat-tile-fullscreen-btn { opacity: 1; }
.chat-float-tile:fullscreen { aspect-ratio: unset; border-radius: 0; resize: none; position: static; }
.chat-float-tile:fullscreen video { object-fit: contain; }

/* ---- Starting a call: under the stage, while not in one ---- */
.chat-call-actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 14px;
  flex-shrink: 0;
}
.chat-call-btn { min-width: 170px; }

/* ---- Settings: an overlay, opened with the widget bar's (or the header's) gear ---- */

.chat-gear-btn {
  background: none; border: none; color: var(--text-dim);
  font-size: 18px; cursor: pointer; padding: 4px 8px; border-radius: 6px;
}
.chat-gear-btn:hover { background: var(--bg-elev2, var(--bg-elev)); color: var(--text); }

/* Message sound / Windows notification switches, top right of the Chatroom. */
.chat-alert-toggles {
  display: flex;
  gap: 6px;
  margin-left: auto;
  flex-shrink: 0;
}
.chat-alert-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: none;
  color: var(--text-dim);
  font-size: 12px;
  white-space: nowrap;
}
.chat-alert-toggle:hover { color: var(--text); background: var(--bg-elev-2); }
.chat-alert-toggle.on { color: var(--text); border-color: color-mix(in srgb, var(--accent) 55%, transparent); }
.chat-alert-toggle.ask { color: var(--on-accent); border-color: transparent; background: var(--accent-grad); }
.chat-alert-toggle.ask:hover { filter: brightness(1.08); }
@media (max-width: 760px) {
  .chat-alert-toggle .chat-alert-label { display: none; }
  .chat-alert-toggle.ask .chat-alert-label { display: inline; }
}

.chat-settings {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 100%;
  max-width: 720px;
  max-height: calc(100% - 32px);
  overflow-y: auto;
  z-index: 5000;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 20px 24px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
  display: none;
  flex-direction: column;
  gap: 4px;
  /* Translucent + blurred rather than solid, so it reads as an overlay on top of the call
     instead of a fully opaque panel blocking it out. */
  background: color-mix(in srgb, var(--bg-elev) 82%, transparent);
  backdrop-filter: blur(14px);
}
.chat-settings.open { display: flex; }
.chat-settings-backdrop {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.5);
  z-index: 4900;
}
.chat-settings-close-btn {
  position: absolute; right: 14px; top: 14px;
  background: none; border: none; color: var(--text-dim);
  font-size: 16px; cursor: pointer;
}

.chat-settings-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 10px;
}
.chat-field label { display: block; font-size: 11px; color: var(--text-dim); margin-bottom: 5px; }
.chat-field-label-row { display: flex; justify-content: space-between; align-items: baseline; }
.chat-field-value { font-size: 11px; color: var(--text-dim); }
.chat-field select, .chat-field input[type=range] { width: 100%; }
.chat-toggles { display: flex; flex-direction: row; flex-wrap: wrap; gap: 12px 24px; align-items: center; }
.chat-checkbox { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text-dim); cursor: pointer; }
.chat-mic-test-btn { width: 100%; white-space: nowrap; }
.chat-mic-test-btn.active { background: var(--danger-grad); color: white; border-color: transparent; }

/* ---- Text chat sidebar: horizontally resizable via the drag handle to its left ---- */

.chat-text-resizer {
  width: 6px;
  flex-shrink: 0;
  cursor: col-resize;
  border-radius: 3px;
  margin: 0 2px;
  touch-action: none;
}
.chat-text-resizer:hover, .chat-text-resizer.active { background: var(--accent); }

.chat-text-panel {
  position: relative;
  width: 300px;
  flex-shrink: 0;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
/* Messages arrived while reading further up: a pill just above the message box scrolls down. */
.chat-new-msg-pill {
  position: absolute;
  left: 50%;
  bottom: 64px;
  transform: translateX(-50%);
  z-index: 5;
  padding: 6px 14px;
  border: none;
  border-radius: 999px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 6px 18px rgba(0,0,0,0.45);
  animation: chatPillIn 0.18s ease-out;
}
.chat-new-msg-pill:hover { filter: brightness(1.1); }
@keyframes chatPillIn { from { opacity: 0; transform: translate(-50%, 6px); } }
.chat-text-tabs {
  display: flex;
  gap: 4px;
  padding: 10px 10px 0;
  flex-shrink: 0;
}
.chat-text-tab {
  flex: 1;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 12px;
  padding: 7px 4px;
  border-radius: 8px 8px 0 0;
  cursor: pointer;
  border-bottom: 2px solid transparent;
}
.chat-text-tab:hover { color: var(--text); }
.chat-text-tab.active { color: var(--text); border-bottom-color: var(--accent); }
.chat-text-search-row { padding: 8px 10px 0; flex-shrink: 0; }
.chat-text-search {
  width: 100%;
  background: var(--bg-elev2, var(--bg-elev));
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
  color: var(--text);
  font-size: 12px;
}
.chat-text-messages {
  flex: 1;
  overflow-y: auto;
  padding: 6px 0 14px;
  display: flex;
  flex-direction: column;
}

/* Messages the way Discord shows them (buildChatMessageEl): each row is the picture column, then the
   name and time (on a group's first message) and the text. Rows span the list's whole width, so the
   hover highlight does; the list's own side padding is theirs. */
.chat-text-msg {
  position: relative;
  display: flex;
  gap: 12px;
  padding: 2px 14px;
  font-size: 13px;
  line-height: 1.45;
  word-break: break-word;
}
.chat-text-msg.group-start { margin-top: 12px; padding-top: 4px; }
.chat-text-msg:hover { background: color-mix(in srgb, var(--text) 4%, transparent); }
.chat-msg-gutter {
  width: 36px;
  flex-shrink: 0;
  display: flex;
  justify-content: flex-end; /* a hover time wider than the column spills left, into the padding */
}
.chat-msg-avatar { margin-top: 2px; font-size: 13px; }
.chat-msg-body { flex: 1; min-width: 0; }
.chat-msg-header { display: flex; align-items: baseline; gap: 8px; min-width: 0; line-height: 1.35; margin-bottom: 1px; }
.chat-msg-time { font-size: 11px; color: var(--text-dim); white-space: nowrap; }
/* A group's later messages: their time in the picture column, on hover - drawn from data-time, so
   copying messages leaves it out. */
.chat-msg-hover-time { visibility: hidden; flex-shrink: 0; font-size: 10px; line-height: 18.85px; color: var(--text-dim); white-space: nowrap; }
.chat-msg-hover-time::before { content: attr(data-time); }
.chat-text-msg:hover .chat-msg-hover-time { visibility: visible; }
.chat-text-link { color: var(--accent-2); text-underline-offset: 2px; word-break: break-all; }

/* YouTube link preview under a message: fixed thumbnail size, so the list doesn't shift (and knock
   the view off the bottom) when the image finishes loading. */
.chat-yt-preview {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  padding: 6px;
  max-width: 320px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-elev-2);
  color: var(--text);
  text-decoration: none;
}
.chat-yt-preview:hover { border-color: var(--accent); }
.chat-yt-preview-thumb {
  position: relative;
  display: block;
  width: 112px;
  height: 63px;
  flex-shrink: 0;
  border-radius: 6px;
  overflow: hidden;
  background: #000;
}
.chat-yt-preview-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.chat-yt-preview-thumb::after {
  content: "▶";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 18px;
  text-shadow: 0 1px 4px rgba(0,0,0,0.8);
}
.chat-yt-preview-text { display: block; min-width: 0; }
.chat-yt-preview-title {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.chat-yt-preview-sub { display: block; font-size: 10.5px; color: var(--text-dim); margin-top: 3px; }
.chat-text-author { font-weight: 600; font-size: 13.5px; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-text-msg.self .chat-text-author { color: var(--text); }

/* Editing your own messages: the pencil shows at the top right of one you hover (where Discord's
   message buttons are); "(edited)" after changed ones. */
.chat-msg-edit-btn {
  position: absolute;
  top: 2px;
  right: 10px;
  width: 26px; height: 22px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-elev);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.chat-msg-edit-btn::before { content: "✏️"; }
.chat-text-msg:hover .chat-msg-edit-btn, .chat-msg-edit-btn:focus-visible { opacity: 0.8; }
.chat-msg-edit-btn:hover { opacity: 1; background: var(--bg-elev-2); border-color: var(--accent); }
@media (hover: none) {
  .chat-msg-edit-btn { opacity: 0.55; }
  .chat-text-msg:has(.chat-msg-edit-btn) .chat-msg-body { padding-right: 30px; } /* always shown: keep text clear of it */
}
.chat-text-edited { font-size: 11px; color: var(--text-dim); }
.chat-edit-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 12px 0;
  padding: 6px 8px 6px 12px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid var(--accent);
  font-size: 12px;
  flex-shrink: 0;
}
.chat-edit-bar[hidden] { display: none; }
.chat-edit-bar-hint { flex: 1; font-size: 10.5px; color: var(--text-dim); }
.chat-edit-cancel { border: none; background: none; color: var(--text-dim); cursor: pointer; font-size: 12px; padding: 2px 6px; border-radius: 6px; }
.chat-edit-cancel:hover { color: var(--text); background: var(--bg-elev-2); }

/* "Seen" under the newest of your messages the other person has read. */
.chat-seen { align-self: flex-end; margin: 1px 14px 0 0; font-size: 10.5px; color: var(--text-dim); }

/* Where the messages that were unread start. */
.chat-new-divider {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 12px 14px 0;
  color: var(--danger);
  font-size: 11px;
  font-weight: 600;
}
.chat-new-divider::before, .chat-new-divider::after { content: ""; flex: 1; height: 1px; background: var(--danger); opacity: 0.6; }

/* "bob is typing…" under the messages. */
.chat-typing { padding: 0 14px 6px; font-size: 11.5px; font-style: italic; color: var(--text-dim); flex-shrink: 0; }
.chat-typing[hidden] { display: none; }
.chat-text-msg-system { font-size: 11.5px; color: var(--text-dim); text-align: center; }
.chat-text-attachment {
  position: relative;
  display: inline-block;
  max-width: 100%;
}
.chat-text-image {
  display: block;
  max-width: 100%;
  max-height: 160px;
  border-radius: 8px;
  margin-top: 4px;
  cursor: zoom-in;
}
.chat-text-file-link {
  display: inline-block;
  margin-top: 4px;
  color: var(--accent);
  text-decoration: none;
  font-size: 12px;
}
.chat-text-file-link:hover { text-decoration: underline; }
.chat-attachment-delete-btn {
  width: 22px; height: 22px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(0,0,0,0.6);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
}
/* Image attachments: overlay the button in the top-right corner, faded in on hover. */
.chat-text-attachment-image { position: relative; display: inline-block; max-width: 100%; }
.chat-text-attachment-image .chat-attachment-delete-btn {
  position: absolute;
  top: 6px; right: 4px;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.chat-text-attachment-image:hover .chat-attachment-delete-btn { opacity: 1; }
/* File attachments: sits inline right after the download link, always visible. */
.chat-text-attachment-file { display: inline-flex; align-items: center; gap: 6px; }
/* Video attachments (an instant replay clip): a player, the file's link and the delete button under it. */
.chat-text-attachment-video { position: relative; display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; max-width: 100%; }
.chat-text-video { display: block; flex-basis: 100%; width: min(480px, 100%); max-height: 320px; border-radius: 10px; background: #000; }

.chat-text-dropzone {
  display: none;
  position: absolute;
  inset: 8px;
  border: 2px dashed var(--accent);
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  align-items: center;
  justify-content: center;
  font-size: 13px;
  color: var(--accent);
  pointer-events: none;
  z-index: 10;
}
.chat-text-panel.dragover .chat-text-dropzone { display: flex; }

.chat-upload-progress {
  padding: 8px 12px 0;
  flex-shrink: 0;
}
.chat-upload-progress-label {
  display: flex;
  gap: 10px;
  font-size: 11px;
  color: var(--text-dim);
  margin-bottom: 4px;
  white-space: nowrap;
}
.chat-upload-progress-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-upload-progress-stats {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.chat-upload-progress-track {
  height: 5px;
  border-radius: 3px;
  background: var(--bg-elev2, var(--bg-elev));
  overflow: hidden;
}
.chat-upload-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent-grad);
  transition: width 0.15s ease;
}

/* Files pasted with Ctrl+V, waiting for the message to be sent. */
.chat-paste-tray {
  padding: 10px 12px 0;
  flex-shrink: 0;
}
.chat-paste-items {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-height: 132px;
  overflow-y: auto;
}
.chat-paste-item {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 4px;
  background: var(--bg-elev2, var(--bg-elev));
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 11.5px;
}
.chat-paste-thumb {
  width: 40px; height: 40px;
  flex-shrink: 0;
  border-radius: 5px;
  object-fit: cover;
  background: #000;
}
.chat-paste-icon {
  width: 40px; height: 40px;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px;
}
.chat-paste-text { min-width: 0; }
.chat-paste-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
.chat-paste-size { color: var(--text-dim); font-size: 10.5px; margin-top: 1px; }
.chat-paste-remove {
  flex-shrink: 0;
  background: none; border: none;
  color: var(--text-dim);
  font-size: 13px;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 6px;
}
.chat-paste-remove:hover { background: color-mix(in srgb, var(--text) 10%, transparent); color: var(--text); }
.chat-paste-hint { font-size: 10.5px; color: var(--text-dim); margin-top: 5px; }

.chat-text-form {
  display: flex;
  gap: 8px;
  padding: 12px;
  border-top: 1px solid var(--border);
}
.chat-text-form input {
  flex: 1;
  min-width: 0; /* an input's intrinsic width otherwise pushes the Send button off a narrow panel */
  background: var(--bg-elev2, var(--bg-elev));
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  color: var(--text);
  font-size: 12.5px;
}
.chat-text-form button { padding: 0 12px; font-size: 13px; }
.chat-text-form button[type="submit"] { padding: 0 16px; border: 0; background: var(--accent-grad); color: var(--on-accent); font-weight: 600; }

/* ---- Phone width: stage, call buttons and messages stack vertically and the page scrolls,
   instead of the 300px message panel squeezing the stage to nothing beside it ---- */
@media (max-width: 760px) {
  .chat-contacts { padding: 12px; }
  .chat-noise-gate-label { display: none; }
  .chat-body { flex-direction: column; padding: 10px; gap: 10px; overflow-y: auto; }
  /* display:contents lifts the stage and the call buttons out of .chat-main-area so they can be
     ordered around the message panel: stage, call buttons, then messages (sized to fill the rest
     of the screen). The settings overlay then covers the whole chat view - fine on a phone. */
  .chat-main-area { display: contents; }
  .chat-stage { order: 1; flex: none; height: 38dvh; min-height: 200px; }
  .chat-call-actions { order: 1; margin-top: 0; gap: 8px; }
  .chat-call-btn { flex: 1; min-width: 0; padding: 12px 10px; }
  .chat-text-panel { order: 2; flex: none; height: calc(62dvh - 130px); min-height: 280px; }
  .chat-body.no-call { overflow: hidden; }
  .chat-body.no-call .chat-text-panel { flex: 1; height: auto; min-height: 0; }
  .chat-body.no-call .chat-call-actions { margin: 0; }
  .chat-settings { padding: 16px; }
  .chat-text-resizer { display: none !important; }
  /* !important: the desktop drag-to-resize handle writes an inline pixel width. */
  .chat-text-panel { width: auto !important; }
  .chat-settings-row { grid-template-columns: 1fr; gap: 10px; }
  .chat-self-pip { width: 120px; min-width: 96px; }
  /* The volume sliders are in the settings panel too - dropping them here is what lets every
     button still fit across a phone-width bar. */
  .chat-widget-bar { min-width: 0; width: calc(100% - 16px); padding: 0 4px; gap: 2px; }
  .chat-bar-slider, .chat-bar-slider-icon { display: none; }
  .chat-bar-btn { font-size: 17px; }
  .chat-yt-widget { width: 340px; gap: 6px; }
  .chat-yt-thumb { width: 48px; height: 27px; }
  .chat-yt-btn { flex-basis: 28px; }
  /* iOS zooms the whole page into any focused input with a font smaller than 16px. */
  .chat-text-form input, .chat-text-search { font-size: 16px; }
}

/* ---- Image lightbox: click a picture to fill the chatroom frame, click again to close ---- */

.chat-image-lightbox {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 6000;
  cursor: zoom-out;
}
.chat-image-lightbox img {
  max-width: 92%;
  max-height: 92%;
  border-radius: 8px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.6);
}

/* ---------- Admin (registration approval + per-account feature access) ---------- */

.admin-heading { flex: 1; font-weight: 600; font-size: 14px; }
.admin-refresh-btn {
  padding: 7px 12px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: none;
  color: var(--text-dim);
  font-size: 12.5px;
}
.admin-refresh-btn:hover { color: var(--text); border-color: var(--accent); }
.admin-body { flex: 1; overflow-y: auto; padding: 22px; display: flex; flex-direction: column; gap: 30px; }
.admin-section { width: 100%; max-width: 1000px; }
.admin-section-title { display: flex; align-items: center; gap: 8px; margin: 0 0 4px; font-size: 15px; }
.admin-section-sub { margin: 0 0 14px; font-size: 12px; color: var(--text-dim); line-height: 1.45; }
.admin-count { padding: 1px 8px; border-radius: 10px; background: var(--danger); color: white; font-size: 11.5px; }
.admin-count:empty { display: none; }
.admin-empty { padding: 6px 0; font-size: 13px; color: var(--text-dim); }
.admin-pending-list { display: flex; flex-direction: column; gap: 10px; }
.admin-request {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 18px;
  padding: 14px 16px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.admin-request-who { min-width: 150px; }
.admin-request-name { font-size: 14px; font-weight: 600; }
.admin-request-when { margin-top: 2px; font-size: 11.5px; color: var(--text-dim); }
.admin-feature-chips { flex: 1; display: flex; flex-wrap: wrap; gap: 6px; }
.admin-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: 16px;
  font-size: 12px;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
}
.admin-chip input { margin: 0; accent-color: var(--accent); }
.admin-chip:has(input:checked) { color: var(--text); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.admin-request-actions { display: flex; gap: 8px; }
.admin-approve-btn {
  padding: 8px 14px;
  border: none;
  border-radius: 8px;
  background: var(--accent-grad);
  color: var(--on-accent);
  font-size: 12.5px;
  font-weight: 600;
}
.admin-reject-btn {
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: none;
  color: var(--text-dim);
  font-size: 12.5px;
}
.admin-reject-btn:hover { border-color: var(--danger); color: var(--danger); }
.admin-approve-btn:disabled, .admin-reject-btn:disabled { opacity: 0.5; cursor: default; }
.admin-table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 12px; }
.admin-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.admin-table th, .admin-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  text-align: center;
  white-space: nowrap;
}
.admin-table th { background: var(--bg-elev); color: var(--text-dim); font-size: 11.5px; font-weight: 600; }
.admin-table th:first-child, .admin-table td:first-child { text-align: left; }
.admin-table tr:last-child td { border-bottom: none; }
.admin-table input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
.admin-table input:disabled { cursor: default; opacity: 0.55; }
.admin-note { margin-left: 6px; font-size: 11px; color: var(--text-dim); }
.admin-rename-btn {
  margin-left: 4px;
  padding: 1px 5px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  font-size: 11px;
  cursor: pointer;
  opacity: 0.6;
}
.admin-rename-btn:hover { opacity: 1; border-color: var(--accent); }
/* The other sites that sign in with these accounts (PZ Server Manager), after the sidebar tabs. */
.admin-table .admin-site-start { border-left: 1px solid var(--border); }
.admin-chip.admin-site-start { margin-left: 10px; }
@media (max-width: 760px) {
  .admin-body { padding: 12px; }
  .admin-request-actions { width: 100%; }
  .admin-request-actions button { flex: 1; }
}
/* ---------- Music Player Sync (see "Music Player Sync" in app.js) ---------- */

/* The sidebar tab's "playing here" bars. */
.tab-eq { margin-left: auto; display: inline-flex; align-items: flex-end; gap: 2px; height: 12px; }
.tab-eq i { width: 3px; background: var(--accent-2); border-radius: 1px; animation: musicEq 0.9s ease-in-out infinite; }
.tab-eq i:nth-child(2) { animation-delay: -0.3s; }
.tab-eq i:nth-child(3) { animation-delay: -0.6s; }
.sidebar-collapsed .tab-eq { position: absolute; bottom: 3px; right: 5px; height: 9px; }
.sidebar-collapsed .tab-eq i { width: 2px; }
@keyframes musicEq { 0%, 100% { height: 30%; } 50% { height: 100%; } }
.m-eq { display: inline-flex; align-items: flex-end; gap: 2px; height: 12px; width: 13px; }
.m-eq i { width: 3px; background: var(--accent-2); border-radius: 1px; height: 40%; }
.m-eq.on i { animation: musicEq 0.9s ease-in-out infinite; }
.m-eq.on i:nth-child(2) { animation-delay: -0.3s; }
.m-eq.on i:nth-child(3) { animation-delay: -0.6s; }

#musicView { min-height: 0; }
.music-topbar { gap: 14px; }
.music-search { width: auto; flex: 1; max-width: 520px; }
.music-search input { padding-left: 32px; height: 38px; border-radius: 19px; font-size: 14px; }
.music-search-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-52%); color: var(--text-dim); font-size: 17px; pointer-events: none; }
.music-listeners { display: flex; align-items: center; margin-left: auto; min-width: 0; }
.music-listeners-label { font-size: 12px; color: var(--text-dim); margin-right: 8px; white-space: nowrap; }
.music-listener { position: relative; width: 28px; height: 28px; border-radius: 50%; margin-left: -6px; border: 2px solid var(--bg); display: flex; align-items: center; justify-content: center; font-size: 10.5px; overflow: hidden; flex-shrink: 0; }
.music-listener:first-of-type { margin-left: 0; }
.music-listener-more { background: var(--bg-elev-2); color: var(--text-dim); font-weight: 700; }
.music-upload-btn {
  display: inline-flex; align-items: center; gap: 7px;
  border: none; border-radius: 19px; height: 38px; padding: 0 16px;
  background: var(--accent-grad); color: var(--on-accent); font-weight: 600; font-size: 13.5px; white-space: nowrap;
}
.music-upload-btn:hover { filter: brightness(1.1); }

.music-body { flex: 1; display: flex; min-height: 0; }
.music-side { width: 230px; flex-shrink: 0; border-right: 1px solid var(--border); display: flex; flex-direction: column; min-height: 0; padding: 14px 10px; gap: 4px; }
.music-nav { display: flex; flex-direction: column; gap: 2px; }
.music-nav button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: none; border-radius: 8px; padding: 8px 10px;
  color: var(--text-dim); font-size: 13.5px; text-align: left;
}
.music-nav button:hover { background: var(--bg-elev-2); color: var(--text); }
.music-nav button.active { background: var(--bg-elev-2); color: var(--text); font-weight: 600; }
.music-nav-icon { width: 18px; text-align: center; font-size: 14px; }
.music-nav .music-nav-playlists { display: none; }
.music-side-head {
  display: flex; align-items: center; justify-content: space-between;
  margin: 14px 4px 4px 10px; font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dim);
}
.music-side-head button { background: none; border: 1px solid var(--border); color: var(--text); border-radius: 7px; width: 26px; height: 26px; font-size: 15px; line-height: 1; }
.music-side-head button:hover { border-color: var(--accent); }
.music-side-playlists { flex: 1; overflow-y: auto; min-height: 0; margin: 0 -4px; padding: 0 4px; }
.music-side-empty { font-size: 12px; color: var(--text-dim); padding: 6px 10px; line-height: 1.45; }
.msp-item { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 8px; cursor: pointer; }
.msp-item:hover { background: var(--bg-elev-2); }
.msp-item.active { background: var(--bg-elev-2); box-shadow: inset 3px 0 0 var(--accent); }
.msp-item .m-cover { width: 38px; height: 38px; border-radius: 6px; font-size: 14px; }
.msp-text { flex: 1; min-width: 0; }
.msp-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msp-item.playing .msp-name { color: var(--accent-2); }
.msp-sub { font-size: 11px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 1px; }

.music-main { flex: 1; min-width: 0; overflow-y: auto; padding: 18px 26px 30px; position: relative; }
.music-loading, .music-empty { color: var(--text-dim); text-align: center; padding: 60px 20px; font-size: 14px; line-height: 1.6; }
.music-empty-icon { font-size: 44px; opacity: 0.6; margin-bottom: 8px; }
.music-empty button { margin-top: 14px; }

/* Covers: the song's picture, or a colored square with a note when it has none. */
.m-cover {
  position: relative; flex-shrink: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,0.85); font-size: 18px;
  background: linear-gradient(135deg, hsl(var(--m-hue, 260) 45% 32%), hsl(calc(var(--m-hue, 260) + 50) 50% 22%));
}
.m-cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.m-cover.m-mosaic { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.m-cover.m-mosaic img { position: static; }

.mpage-head { display: flex; align-items: flex-end; gap: 14px; margin-bottom: 14px; flex-wrap: wrap; }
.mpage-title { font-size: 24px; font-weight: 700; margin: 0; }
.mpage-sub { font-size: 12.5px; color: var(--text-dim); margin-top: 4px; }
.mpage-tools { margin-left: auto; display: flex; gap: 8px; align-items: center; }
.music-select, .mpage-tools select {
  background: var(--bg-elev-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 8px; padding: 7px 8px; font-size: 13px;
}
.modal .music-select { width: 100%; padding: 9px 10px; font-size: 13.5px; }
.m-back { background: none; border: none; color: var(--text-dim); font-size: 13px; padding: 4px 0; margin-bottom: 10px; }
.m-back:hover { color: var(--text); }

.mhero { display: flex; gap: 22px; align-items: flex-end; margin-bottom: 20px; }
.mhero .m-cover { width: 184px; height: 184px; border-radius: 10px; font-size: 56px; box-shadow: 0 12px 34px rgba(0,0,0,0.45); }
.mhero.m-artist-hero .m-cover { border-radius: 50%; }
.mhero-text { min-width: 0; flex: 1; }
.mhero-kind { font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim); }
.mhero-title { font-size: 34px; font-weight: 800; margin: 4px 0 8px; line-height: 1.12; word-break: break-word; }
.mhero-sub { font-size: 13px; color: var(--text-dim); }
.mhero-sub b { color: var(--text); font-weight: 600; }
.mhero-actions { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap; align-items: center; }
.m-btn {
  display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 16px;
  border-radius: 18px; border: 1px solid var(--border); background: var(--bg-elev-2); color: var(--text);
  font-size: 13px; font-weight: 600; white-space: nowrap;
}
.m-btn:hover { border-color: var(--accent); }
.m-btn.m-primary { background: var(--accent-grad); border: none; color: var(--on-accent); }
.m-btn.m-primary:hover { filter: brightness(1.1); }
.m-btn.m-danger:hover { border-color: var(--danger); color: var(--danger); }
.m-btn svg { width: 16px; height: 16px; }
.m-btn:disabled { opacity: 0.5; cursor: default; }

.msection { margin-top: 26px; }
.msection:first-child { margin-top: 0; }
.msection-title { display: flex; align-items: baseline; gap: 10px; font-size: 17px; font-weight: 700; margin: 0 0 10px; }
.msection-title button { margin-left: auto; background: none; border: none; color: var(--text-dim); font-size: 12.5px; font-weight: 600; }
.msection-title button:hover { color: var(--text); }

/* Song lists. */
.msongs { display: flex; flex-direction: column; }
.msong {
  display: grid; align-items: center; gap: 12px;
  grid-template-columns: 30px 40px minmax(0, 1.6fr) minmax(0, 1fr) 84px 52px 64px;
  padding: 5px 8px; border-radius: 8px; min-height: 52px; cursor: default;
}
.msongs.m-no-album .msong { grid-template-columns: 30px 40px minmax(0, 1fr) 84px 52px 64px; }
.msongs.m-no-album .msong-album { display: none; }
.msong-head { min-height: 0; padding-top: 0; padding-bottom: 6px; border-bottom: 1px solid var(--border); border-radius: 0; margin-bottom: 4px; font-size: 11.5px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; }
.msong-head > div:last-child { text-align: right; }
.msong:not(.msong-head):hover { background: color-mix(in srgb, var(--text) 5%, transparent); }
.msong.selected { background: color-mix(in srgb, var(--accent) 16%, transparent) !important; }
.msong.current .msong-title { color: var(--accent-2); }
.msong.missing { opacity: 0.45; }
.msong-num { position: relative; text-align: center; color: var(--text-dim); font-size: 13px; font-variant-numeric: tabular-nums; }
.msong-num .m-num-text { display: inline-block; }
.msong-num input { display: none; width: 16px; height: 16px; margin: 0; accent-color: var(--accent); cursor: pointer; }
.msong-num .m-row-play { display: none; background: none; border: none; color: var(--text); padding: 0; width: 24px; height: 24px; }
.msong-num .m-row-play svg { width: 16px; height: 16px; }
.msongs.m-selectable .msong:hover .msong-num .m-num-text,
.msongs.m-selectable.m-selecting .msong-num .m-num-text { display: none; }
.msongs.m-selectable .msong:hover .msong-num input,
.msongs.m-selectable.m-selecting .msong-num input { display: inline-block; }
.msongs.m-playable .msong:hover .msong-num .m-num-text { display: none; }
.msongs.m-playable .msong:hover .msong-num .m-row-play { display: inline-flex; align-items: center; justify-content: center; }
/* Library lists are both: hovering a song shows ▶, and the tick boxes show once songs are being picked. */
.msongs.m-selectable.m-playable .msong:hover .msong-num input { display: none; }
.msongs.m-selectable.m-playable.m-selecting .msong-num input,
.msongs.m-selectable.m-playable.m-selecting .msong:hover .msong-num input { display: inline-block; }
.msongs.m-selectable.m-playable.m-selecting .msong:hover .msong-num .m-row-play { display: none; }
.msong .m-cover { width: 40px; height: 40px; border-radius: 5px; font-size: 14px; }
.msong-main { min-width: 0; }
.msong-title { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: flex; align-items: center; gap: 7px; }
.msong-title span { overflow: hidden; text-overflow: ellipsis; }
.msong-artist, .msong-album { font-size: 12.5px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msong-artist a, .msong-album a { color: inherit; text-decoration: none; cursor: pointer; }
.msong-artist a:hover, .msong-album a:hover { color: var(--text); text-decoration: underline; }
.msong-dur { font-size: 12.5px; color: var(--text-dim); text-align: right; font-variant-numeric: tabular-nums; }
.msong-actions { display: flex; justify-content: flex-end; gap: 2px; }
.m-icon-btn {
  width: 30px; height: 30px; border-radius: 50%; border: none; background: none; color: var(--text-dim);
  display: inline-flex; align-items: center; justify-content: center; font-size: 16px; padding: 0;
}
.m-icon-btn svg { width: 17px; height: 17px; }
.m-icon-btn:hover { background: color-mix(in srgb, var(--text) 10%, transparent); color: var(--text); }
.msong .m-icon-btn { opacity: 0; }
.msong:hover .m-icon-btn, .msong .m-icon-btn:focus-visible, .msong .m-icon-btn.m-open { opacity: 1; }
.msong-drag { cursor: grab; }
.msong.m-dragging { opacity: 0.4; }
.msong.m-drop-before { box-shadow: inset 0 2px 0 var(--accent); }
.msong.m-drop-after { box-shadow: inset 0 -2px 0 var(--accent); }
.m-more-rows { text-align: center; padding: 14px; color: var(--text-dim); font-size: 12.5px; }

/* Quality: FLAC above CD quality is "hi-res". */
.mq { display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em; padding: 2px 6px; border-radius: 5px; border: 1px solid var(--border); color: var(--text-dim); white-space: nowrap; }
.mq.flac { color: var(--info); border-color: color-mix(in srgb, var(--info) 35%, transparent); }
.mq.hires { color: var(--warning); border-color: color-mix(in srgb, var(--warning) 40%, transparent); }

/* Selection bar. */
.msel-bar {
  position: sticky; top: -18px; z-index: 5; margin: -18px -26px 12px; padding: 10px 26px;
  display: flex; align-items: center; gap: 10px; font-size: 13px;
  background: color-mix(in srgb, var(--bg-elev) 94%, transparent); border-bottom: 1px solid var(--border); backdrop-filter: blur(6px);
}
.msel-bar .m-btn { height: 32px; }
.msel-bar .m-link { margin-left: auto; }
.m-link { background: none; border: none; color: var(--text-dim); font-size: 12.5px; }
.m-link:hover { color: var(--text); }

/* Cards: albums, artists, playlists. */
.mgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 18px 16px; }
.mcard { min-width: 0; cursor: pointer; border-radius: 10px; padding: 10px; margin: -10px; transition: background .12s; }
.mcard:hover { background: var(--bg-elev-2); }
.mcard .m-cover { width: 100%; height: auto; aspect-ratio: 1; border-radius: 8px; font-size: 40px; box-shadow: 0 6px 18px rgba(0,0,0,0.35); }
.mcard.m-round .m-cover { border-radius: 50%; }
.mcard-foot { display: flex; align-items: flex-start; gap: 4px; margin-top: 9px; }
.mcard-text { flex: 1; min-width: 0; }
.mcard-title { font-size: 13.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mcard-sub { font-size: 12px; color: var(--text-dim); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mcard.m-round .mcard-title, .mcard.m-round .mcard-sub { text-align: center; }
/* A round (artist) tile's ⋯ sits on the right without pushing its centred name off-centre. */
.mcard.m-round .mcard-foot { position: relative; padding: 0 30px; }
.mcard.m-round .mcard-more { position: absolute; right: 0; top: 0; }
.mcard-more { flex-shrink: 0; width: 28px; height: 28px; margin: 2px -4px 0 0; opacity: 0.55; }
.mcard:hover .mcard-more, .mcard-more.m-open, .mcard-more:focus-visible { opacity: 1; }
.mcard-play {
  position: absolute; right: 8px; bottom: 8px; width: 42px; height: 42px; border-radius: 50%; border: none;
  background: var(--accent-grad); color: var(--on-accent); display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 16px rgba(0,0,0,0.45); opacity: 0; transform: translateY(6px); transition: opacity .15s, transform .15s;
}
.mcard-play svg { width: 18px; height: 18px; }
.mcard:hover .mcard-play, .mcard-play.m-on { opacity: 1; transform: none; }

/* Pop-up menus (add to playlist, a song's ⋯). */
.mmenu {
  position: fixed; z-index: 1100; min-width: 220px; max-width: 300px; max-height: min(420px, 70vh);
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 16px 44px rgba(0,0,0,0.55);
  padding: 5px; animation: slideIn .12s ease-out;
}
.mmenu-title { font-size: 11px; font-weight: 700; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.06em; padding: 7px 10px 5px; }
.mmenu-filter { margin: 2px 4px 5px; padding: 7px 9px; border-radius: 7px; border: 1px solid var(--border); background: var(--bg-elev-2); color: var(--text); font-size: 13px; }
.mmenu-filter:focus { outline: none; border-color: var(--accent); }
.mmenu-items { overflow-y: auto; }
.mmenu-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  background: none; border: none; color: var(--text); padding: 8px 10px; border-radius: 7px; font-size: 13px;
}
.mmenu-item:hover, .mmenu-item:focus-visible { background: var(--bg-elev-2); outline: none; }
.mmenu-item .mmenu-sub { margin-left: auto; font-size: 11.5px; color: var(--text-dim); white-space: nowrap; }
.mmenu-item.m-danger { color: var(--danger); }
.mmenu-item:disabled { opacity: 0.45; cursor: default; background: none; }
.mmenu-sep { height: 1px; background: var(--border); margin: 4px 6px; }
.mmenu-empty { padding: 8px 10px; font-size: 12.5px; color: var(--text-dim); }

/* The player bar. */
.music-player {
  /* The right side (Broadcasting, Listening, volume) takes what it needs; the song's name gives way. */
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(260px, 1.3fr) auto; align-items: center; gap: 18px;
  padding: 10px 18px; border-top: 1px solid var(--border); background: var(--bg-elev); min-height: 84px;
}
.mp-now { display: flex; align-items: center; gap: 12px; min-width: 0; }
.mp-art { width: 56px; height: 56px; border-radius: 7px; flex-shrink: 0; overflow: hidden; }
.mp-art .m-cover { width: 100%; height: 100%; font-size: 22px; }
.mp-art.m-clickable { cursor: pointer; }
.mp-text { min-width: 0; }
.mp-title { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mp-sub { font-size: 12px; color: var(--text-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.mp-sub a { color: inherit; text-decoration: none; cursor: pointer; }
.mp-sub a:hover { color: var(--text); text-decoration: underline; }
.mp-center { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
.mp-controls { display: flex; align-items: center; gap: 12px; }
.mp-btn {
  width: 34px; height: 34px; border-radius: 50%; border: none; background: none; color: var(--text-dim);
  display: inline-flex; align-items: center; justify-content: center; padding: 0; position: relative;
}
.mp-btn svg { width: 19px; height: 19px; }
.mp-btn:hover:not(:disabled) { color: var(--text); }
.mp-btn:disabled { opacity: 0.35; cursor: default; }
.mp-btn.mp-play { width: 40px; height: 40px; background: var(--text); color: var(--bg); }
.mp-btn.mp-play svg { width: 18px; height: 18px; }
.mp-btn.mp-play:hover:not(:disabled) { transform: scale(1.05); color: var(--bg); }
.mp-toggle.on { color: var(--accent-2); }
.mp-toggle.on::after { content: ''; position: absolute; bottom: 1px; left: 50%; width: 4px; height: 4px; margin-left: -2px; border-radius: 50%; background: var(--accent-2); }
.mp-seek { display: flex; align-items: center; gap: 10px; width: 100%; max-width: 560px; }
.mp-time { font-size: 11.5px; color: var(--text-dim); font-variant-numeric: tabular-nums; min-width: 38px; }
.mp-time:first-child { text-align: right; }
.music-player input[type="range"] {
  -webkit-appearance: none; appearance: none; flex: 1; height: 4px; border-radius: 2px; cursor: pointer; margin: 0;
  background: linear-gradient(to right, var(--text) var(--m-fill, 0%), color-mix(in srgb, var(--text) 18%, transparent) var(--m-fill, 0%));
}
.music-player input[type="range"]:hover { background: linear-gradient(to right, var(--accent-2) var(--m-fill, 0%), color-mix(in srgb, var(--text) 18%, transparent) var(--m-fill, 0%)); }
.music-player input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--text); opacity: 0; transition: opacity .1s; }
.music-player input[type="range"]:hover::-webkit-slider-thumb, .music-player input[type="range"]:active::-webkit-slider-thumb { opacity: 1; }
.music-player input[type="range"]::-moz-range-thumb { width: 12px; height: 12px; border: none; border-radius: 50%; background: var(--text); }
.music-player input[type="range"]:disabled { cursor: default; opacity: 0.5; }
.mp-right { display: flex; align-items: center; justify-content: flex-end; gap: 12px; min-width: 0; }
/* The Broadcasting switch - meant to be seen: bright and live when on, plain with a lock when private. */
.mp-broadcast {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 14px; border-radius: 17px;
  border: 1px solid var(--border); background: var(--bg-elev-2); color: var(--text); font-size: 13px; font-weight: 700; white-space: nowrap; flex-shrink: 0;
}
.mp-broadcast svg { width: 17px; height: 17px; }
.mp-broadcast:hover { border-color: var(--accent); }
.mp-broadcast.on { background: var(--accent-grad); border-color: transparent; color: var(--on-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.mp-broadcast.on:hover { filter: brightness(1.08); }
.mp-live-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; animation: mLive 1.6s ease-in-out infinite; }
@keyframes mLive { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.music-player.m-private { box-shadow: inset 0 2px 0 color-mix(in srgb, var(--text-dim) 45%, transparent); }
.mp-listen {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px; border-radius: 16px;
  border: 1px solid var(--border); background: none; color: var(--text-dim); font-size: 12.5px; font-weight: 600; white-space: nowrap;
}
.mp-listen svg { width: 16px; height: 16px; }
.mp-listen.on { color: var(--accent-2); border-color: color-mix(in srgb, var(--accent-2) 40%, transparent); background: color-mix(in srgb, var(--accent-2) 8%, transparent); }
.mp-listen.m-attention { color: var(--on-accent); background: var(--accent-grad); border-color: transparent; animation: mPulse 1.6s ease-in-out infinite; }
@keyframes mPulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 50%, transparent); } 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 0%, transparent); } }
.mp-volume { display: flex; align-items: center; gap: 6px; width: 140px; }
.mp-small { width: 30px; height: 30px; }
.mp-small svg { width: 18px; height: 18px; }

/* Uploading. */
.music-upload-modal { max-height: 90vh; display: flex; flex-direction: column; }
.music-drop { margin: 4px 0 0; padding: 26px 20px; }
.music-upload-summary { font-size: 12.5px; color: var(--text-dim); margin-top: 12px; min-height: 16px; }
.music-upload-list { margin-top: 6px; overflow-y: auto; min-height: 0; max-height: 34vh; display: flex; flex-direction: column; gap: 6px; }
.mup-row { background: var(--bg-elev-2); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; font-size: 12.5px; }
.mup-top { display: flex; gap: 10px; justify-content: space-between; }
.mup-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.mup-state { color: var(--text-dim); white-space: nowrap; }
.mup-bar { height: 3px; border-radius: 2px; background: color-mix(in srgb, var(--text) 8%, transparent); margin-top: 6px; overflow: hidden; }
.mup-bar div { height: 100%; width: 0; background: var(--accent-grad); transition: width .15s; }
.mup-row.done .mup-bar div { background: var(--success); width: 100%; }
.mup-row.dup .mup-bar div { background: var(--text-dim); width: 100%; }
.mup-row.error .mup-bar div { background: var(--danger); width: 100%; }
.msong-disc { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dim); padding: 14px 8px 6px; }
.msong-head + .msong-disc { padding-top: 6px; }

/* Editing albums: picking albums to combine, and the dialog. */
.mcard.m-pickable .m-cover { outline: 2px solid transparent; outline-offset: 2px; transition: outline-color .12s; }
.mcard.m-picked .m-cover { outline-color: var(--accent); }
.m-pick {
  position: absolute; top: 8px; left: 8px; width: 26px; height: 26px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--text) 80%, transparent); background: color-mix(in srgb, var(--bg) 55%, transparent);
  color: var(--on-accent); font-size: 12.5px; font-weight: 700; display: flex; align-items: center; justify-content: center;
}
.mcard.m-picked .m-pick { background: var(--accent-grad); border-color: transparent; }
.mcard.m-round .m-pick { top: 13%; left: 13%; } /* inside the circle */
.modal label.music-check { display: flex; align-items: center; gap: 8px; margin-top: 16px; color: var(--text); font-size: 13px; cursor: pointer; }
.modal label.music-check input { width: 16px; height: 16px; margin: 0; padding: 0; accent-color: var(--accent); }
.music-disc-list { margin: 8px 0 0; padding-left: 22px; font-size: 12.5px; max-height: 30vh; overflow-y: auto; }
.music-disc-list li { padding: 2px 0; }
.music-disc-list li::marker { color: var(--text-dim); }
.music-disc-list li span { display: inline-block; max-width: calc(100% - 70px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
.music-disc-list .m-icon-btn { width: 24px; height: 24px; font-size: 13px; vertical-align: middle; }
.music-disc-list .m-icon-btn:disabled { opacity: 0.3; cursor: default; }
.music-disc-list.m-off { opacity: 0.45; }
.music-album-modal { max-height: 90vh; overflow-y: auto; }

.mup-row.error .mup-top { flex-wrap: wrap; row-gap: 2px; }
.mup-row.error .mup-state { color: var(--danger); white-space: normal; flex-basis: 100%; }
.modal-actions button.primary, .modal-actions button#nameSubmitBtn { background: var(--accent-grad); color: var(--on-accent); }

@media (max-width: 1100px) {
  .msong { grid-template-columns: 30px 40px minmax(0, 1fr) 84px 52px 64px; }
  .msong-album { display: none; }
  .mp-volume { width: 96px; flex-shrink: 1; min-width: 60px; }
  .mp-listen span { display: none; }
  .mp-listen { padding: 0 9px; }
}
@media (max-width: 900px) {
  .music-player { grid-template-columns: minmax(0, 1fr) auto; }
  .mp-center { grid-column: 1 / -1; grid-row: 2; }
  .mp-right { grid-column: 2; grid-row: 1; }
}
@media (max-width: 760px) {
  .music-body { flex-direction: column; }
  .music-side { width: auto; border-right: none; border-bottom: 1px solid var(--border); padding: 8px 12px; }
  .music-nav { flex-direction: row; gap: 6px; overflow-x: auto; scrollbar-width: none; }
  .music-nav::-webkit-scrollbar { display: none; }
  .music-nav button { width: auto; flex-shrink: 0; border: 1px solid var(--border); border-radius: 16px; padding: 5px 11px; font-size: 12.5px; }
  .music-nav-icon { display: none; }
  .music-nav button.active { border-color: var(--accent); }
  .music-nav .music-nav-playlists { display: flex; }
  .music-side-head, .music-side-playlists { display: none; }
  .music-main { padding: 14px 12px 24px; }
  .msel-bar { top: -14px; margin: -14px -12px 12px; padding: 10px 12px; }
  .music-listeners-label { display: none; }
  .music-upload-btn { padding: 0 12px; }
  .music-upload-btn #musicUploadBtnLabel { display: none; }
  .music-search { max-width: none; }
  .msong { grid-template-columns: 26px 40px minmax(0, 1fr) 40px; gap: 10px; padding: 5px 4px; }
  .msongs.m-no-album .msong { grid-template-columns: 26px 40px minmax(0, 1fr) 40px; }
  .msong-quality, .msong-dur, .msong-head { display: none; }
  .msong .m-icon-btn { opacity: 1; }
  .msong-actions .m-add-btn { display: none; }
  .mhero { flex-direction: column; align-items: flex-start; gap: 14px; }
  .mhero .m-cover { width: 150px; height: 150px; }
  .mhero-title { font-size: 26px; }
  .mgrid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 16px 12px; }
  .music-player { padding: 8px 12px; gap: 6px 12px; }
  .mp-art { width: 44px; height: 44px; }
  .mp-volume { display: none; }
  .mp-listen span { display: none; }
  .mp-listen { padding: 0 9px; }
  .mp-controls { gap: 8px; }
  .mp-broadcast { padding: 0 11px; }
  .mp-broadcast .mp-broadcast-label { display: none; }
}
@media (hover: none) {
  .msong .m-icon-btn { opacity: 1; }
  .mcard-play { opacity: 1; transform: none; }
  .mcard-more { opacity: 1; }
  /* No hover on a touch screen: ▶ shows all the time (until songs are being picked). */
  .msongs.m-playable:not(.m-selecting) .msong-num .m-num-text { display: none; }
  .msongs.m-playable:not(.m-selecting) .msong-num .m-row-play { display: inline-flex; align-items: center; justify-content: center; }
}

/* ---------- Themes: the account's colour scheme (see "Themes" in app.js and themes.js). In a browser the
   🎨 button beside ✏️/🔑 opens the picker; the Windows app has it in File > Preferences and View > Theme
   instead. Each card is drawn in its own theme's colours. ---------- */

.modal.theme-modal { width: 680px; max-width: calc(100vw - 32px); max-height: calc(100vh - 48px); display: flex; flex-direction: column; padding: 24px 24px 20px; }
.theme-modal-body { overflow-y: auto; margin: 0 -6px; padding: 0 6px 2px; }
.theme-group-title { font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--text-dim); margin: 14px 0 8px; }
.theme-group-title:first-child { margin-top: 0; }
.theme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(142px, 1fr)); gap: 10px; }
.theme-card {
  position: relative; display: flex; flex-direction: column; gap: 7px; padding: 7px 7px 9px;
  background: var(--bg-elev-2); border: 1px solid var(--border); border-radius: 12px;
  color: var(--text); font: inherit; font-size: 12.5px; font-weight: 600; text-align: left; cursor: pointer;
  transition: border-color .12s, transform .12s;
}
.theme-card:hover { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); transform: translateY(-1px); }
.theme-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-card[aria-checked="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.theme-card[aria-checked="true"]::after {
  content: "✓"; position: absolute; top: 12px; right: 12px; width: 18px; height: 18px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 11px;
  background: var(--accent-grad); color: var(--on-accent);
}
.theme-card:disabled { cursor: default; opacity: .55; transform: none; }
.theme-name { padding: 0 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A tiny window in the theme's colours: sidebar, two lines of text and a button. */
.theme-preview { display: flex; height: 64px; border-radius: 7px; overflow: hidden; border: 1px solid; }
.theme-preview .tp-side { width: 30%; display: flex; flex-direction: column; gap: 5px; padding: 8px 6px; }
.theme-preview .tp-side i { display: block; height: 4px; border-radius: 2px; }
.theme-preview .tp-main { flex: 1; display: flex; flex-direction: column; gap: 5px; padding: 9px 8px; }
.theme-preview .tp-main i { display: block; height: 5px; border-radius: 3px; }
.theme-preview .tp-main i.tp-short { width: 60%; }
.theme-preview .tp-main i.tp-btn { margin-top: auto; width: 46%; height: 11px; border-radius: 4px; }
.theme-preview .tp-dots { display: flex; gap: 3px; margin-top: auto; }
.theme-preview .tp-dots b { width: 6px; height: 6px; border-radius: 50%; }

/* ---------- Shared Codebase (see "Shared Codebase" in app.js) ---------- */

.cb-topbar { gap: 12px; }
.cb-crumbs .crumb { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
.cb-search { width: 260px; }
.cb-contents-toggle { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-dim); white-space: nowrap; cursor: pointer; }
.cb-contents-toggle input { accent-color: var(--accent); }
.cb-recent-btn { display: flex; align-items: center; gap: 8px; padding: 7px 12px; font-size: 13px; white-space: nowrap; }
.cb-live-dot, .cb-status-dot, .cb-tree-dot, .cb-note-dot {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
  background: color-mix(in srgb, var(--text-dim) 55%, transparent);
}
.cb-live-dot.on, .cb-status.live .cb-status-dot, .cb-tree-dot, .cb-note-dot {
  background: var(--success);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 60%, transparent);
  animation: cb-pulse 1.8s ease-out infinite;
}
@keyframes cb-pulse { 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }

.cb-status {
  display: flex; align-items: center; gap: 8px; width: 100%; min-width: 0;
  padding: 7px 22px; border: none; border-bottom: 1px solid var(--border);
  background: var(--bg-elev); color: var(--text-dim); font-size: 12.5px; text-align: left;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cb-status:hover { color: var(--text); }
.cb-status b { color: var(--text); font-weight: 600; }
.cb-status.live { background: color-mix(in srgb, var(--success) 9%, var(--bg-elev)); }
.cb-status-path { font-family: ui-monospace, Consolas, monospace; color: var(--text); }

.cb-body { flex: 1; display: flex; min-height: 0; }
.cb-tree {
  width: 250px; flex-shrink: 0; overflow: auto; padding: 10px 6px 20px;
  border-right: 1px solid var(--border); font-size: 13px;
}
.cb-tree-item {
  display: flex; align-items: center; gap: 4px; padding: 4px 8px 4px 6px; border-radius: 6px;
  color: var(--text-dim); cursor: pointer; white-space: nowrap;
}
.cb-tree-item:hover { background: var(--bg-elev-2); color: var(--text); }
.cb-tree-item.active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--text); font-weight: 600; }
.cb-tree-build { opacity: .62; }
.cb-tree-caret { width: 14px; flex-shrink: 0; text-align: center; font-size: 11px; color: var(--text-dim); }
.cb-tree-name { overflow: hidden; text-overflow: ellipsis; }
.cb-tree-dot { width: 7px; height: 7px; margin-left: 4px; }

.cb-main { flex: 1; min-width: 0; overflow: auto; padding: 18px 24px 40px; }
.cb-page { max-width: 1400px; margin: 0 auto; display: flex; flex-direction: column; gap: 14px; }
.cb-empty { color: var(--text-dim); text-align: center; padding: 56px 20px; font-size: 14px; line-height: 1.6; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.cb-empty-small { padding: 24px; }
.cb-empty-icon { font-size: 40px; opacity: .7; }
.cb-empty button:not(.ghost) { background: var(--accent-grad); color: var(--on-accent); border: none; border-radius: 8px; padding: 8px 16px; font-weight: 600; }
.cb-empty .ghost { padding: 7px 14px; }

.cb-page-head { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.cb-page-titles { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.cb-page-title { display: flex; align-items: center; gap: 9px; font-size: 19px; font-weight: 700; min-width: 0; }
.cb-page-icon { font-size: 20px; }
.cb-page-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-page-meta { color: var(--text-dim); font-size: 12.5px; line-height: 1.5; }
.cb-page-actions { position: relative; display: flex; gap: 8px; flex-wrap: wrap; }
.cb-page-actions .ghost { padding: 7px 12px; font-size: 13px; white-space: nowrap; }
.cb-linkish { background: none; border: none; padding: 0; color: var(--accent); font-size: inherit; text-decoration: underline; }

.cb-edit-badge {
  display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0;
  padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; letter-spacing: .01em;
  color: var(--success); background: color-mix(in srgb, var(--success) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 35%, transparent);
}
.cb-edit-badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.cb-edit-badge[hidden] { display: none; }

.cb-list { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--bg-elev); }
.cb-row {
  display: grid; grid-template-columns: 26px minmax(0, 1fr) 118px 86px 30px; align-items: center; gap: 10px;
  padding: 7px 12px; border-top: 1px solid var(--border); cursor: pointer; font-size: 13.5px;
}
.cb-row:first-child { border-top: none; }
.cb-row:hover { background: var(--bg-elev-2); }
.cb-row-build { opacity: .7; }
.cb-row-up { color: var(--text-dim); }
.cb-row-icon { text-align: center; }
.cb-row-name { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* The name keeps its room; a folder path beside it gives way first (cut from its start). */
.cb-row-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex-shrink: 0; max-width: 72%; }
.cb-row-name > .cb-row-label:only-child, .cb-row-name > .cb-row-label:first-child:nth-last-child(2) { max-width: 100%; flex-shrink: 1; min-width: 0; }
.cb-row-sub { color: var(--text-dim); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 0 1 auto; direction: rtl; text-align: left; }
.cb-row-tag { flex-shrink: 0; font-size: 10.5px; padding: 1px 7px; border-radius: 999px; color: var(--text-dim); border: 1px solid var(--border); }
.cb-row-when, .cb-row-size { color: var(--text-dim); font-size: 12.5px; white-space: nowrap; text-align: right; }
.cb-row-dl {
  width: 28px; height: 26px; border-radius: 6px; border: 1px solid transparent; background: none;
  color: var(--text-dim); font-size: 13px; opacity: 0; transition: opacity .12s;
}
.cb-row:hover .cb-row-dl { opacity: 1; }
.cb-row-dl:hover { border-color: var(--border); color: var(--text); background: var(--bg-elev-2); }
@media (hover: none) { .cb-row-dl { opacity: 1; } }

.cb-group-title { margin-top: 4px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }

.cb-zip-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 30; width: 330px;
  display: flex; flex-direction: column; gap: 6px; padding: 10px;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 14px 38px rgba(0, 0, 0, .35); font-size: 13px;
}
.cb-zip-measuring { color: var(--text-dim); padding: 8px; }
.cb-zip-title { font-weight: 700; padding: 2px 4px 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-zip-opt {
  display: flex; flex-direction: column; gap: 3px; text-align: left; width: 100%;
  padding: 9px 11px; border-radius: 8px; border: 1px solid var(--border); background: var(--bg-elev-2); color: var(--text);
}
.cb-zip-opt:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--bg-elev-2)); }
.cb-zip-opt-top { display: flex; justify-content: space-between; gap: 10px; }
.cb-zip-opt-top span { color: var(--text-dim); font-size: 12px; white-space: nowrap; }
.cb-zip-opt-about { color: var(--text-dim); font-size: 12px; line-height: 1.4; }
.cb-zip-foot { color: var(--text-dim); font-size: 11.5px; padding: 2px 4px; line-height: 1.4; }

.cb-note {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap; padding: 9px 13px; border-radius: 9px; font-size: 13px;
  background: color-mix(in srgb, var(--success) 10%, var(--bg-elev)); border: 1px solid color-mix(in srgb, var(--success) 35%, var(--border));
}
.cb-note .ghost { padding: 4px 10px; font-size: 12.5px; margin-left: auto; }
.cb-note-gone { background: color-mix(in srgb, var(--warning) 10%, var(--bg-elev)); border-color: color-mix(in srgb, var(--warning) 40%, var(--border)); }

/* Code: line numbers and a line per row; changed lines get a bar and a tint. */
.cb-code {
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-elev);
  overflow-x: auto; padding: 8px 0; font-family: ui-monospace, 'Cascadia Code', Consolas, 'Courier New', monospace;
  font-size: 12.8px; line-height: 1.55; tab-size: 4; font-variant-ligatures: none;
}
.cb-line { display: flex; min-width: max-content; border-left: 3px solid transparent; }
.cb-ln {
  flex-shrink: 0; width: var(--cb-ln-width, 5ch); padding: 0 12px 0 8px; box-sizing: content-box;
  text-align: right; color: color-mix(in srgb, var(--text-dim) 70%, transparent); user-select: none; cursor: pointer;
}
.cb-ln:hover { color: var(--text); }
.cb-lc { white-space: pre; padding-right: 24px; }
.cb-line.cb-changed { border-left-color: var(--success); background: color-mix(in srgb, var(--success) 11%, transparent); }
.cb-line.cb-removed-above { box-shadow: inset 0 2px 0 color-mix(in srgb, var(--danger) 80%, transparent); }
.cb-line.cb-removed-below { box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--danger) 80%, transparent); }
.cb-line.cb-selected { background: color-mix(in srgb, var(--accent) 16%, transparent); border-left-color: var(--accent); }
.cb-line.cb-flash { animation: cb-flash 2.2s ease-out; }
@keyframes cb-flash { 0%, 35% { background: color-mix(in srgb, var(--warning) 30%, transparent); } 100% { background: transparent; } }
.cb-t-k { color: var(--accent); }
.cb-t-s { color: var(--success); }
.cb-t-c { color: var(--text-dim); font-style: italic; }
.cb-t-n { color: var(--warning); }
.cb-t-t { color: var(--info); }
.cb-t-a { color: color-mix(in srgb, var(--info) 55%, var(--text)); }
.cb-t-v { color: color-mix(in srgb, var(--warning) 60%, var(--danger)); }
.cb-t-p { color: color-mix(in srgb, var(--accent) 55%, var(--danger)); }
.cb-t-f { color: color-mix(in srgb, var(--accent-2) 75%, var(--text)); }

.cb-image { display: flex; justify-content: center; padding: 20px; border: 1px solid var(--border); border-radius: var(--radius);
  background: repeating-conic-gradient(var(--bg-elev) 0% 25%, var(--bg-elev-2) 0% 50%) 50% / 20px 20px; }
.cb-image img { max-width: 100%; max-height: 70vh; image-rendering: auto; }

/* Search results inside files. */
.cb-hit-file { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--bg-elev); }
.cb-hit-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer; font-size: 13.5px; border-bottom: 1px solid var(--border); min-width: 0; }
.cb-hit-head:hover { background: var(--bg-elev-2); }
.cb-hit-line { display: flex; gap: 4px; padding: 3px 0; cursor: pointer; font-family: ui-monospace, Consolas, monospace; font-size: 12.5px; }
.cb-hit-line:hover { background: var(--bg-elev-2); }
.cb-hit-line .cb-ln { width: 6ch; }
.cb-hit-text { white-space: pre; overflow: hidden; text-overflow: ellipsis; min-width: 0; padding-right: 12px; }
.cb-mark { background: color-mix(in srgb, var(--warning) 35%, transparent); color: var(--text); border-radius: 3px; padding: 0 1px; }

/* README and .md pages. */
.cb-readme { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--bg-elev); }
.cb-readme-head { padding: 9px 14px; border-bottom: 1px solid var(--border); font-size: 13px; font-weight: 600; cursor: pointer; }
.cb-readme-head:hover { color: var(--accent); }
.cb-readme .cb-md { padding: 6px 26px 22px; }
.cb-md-page { border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-elev); padding: 8px 30px 26px; }
.cb-md { font-size: 14px; line-height: 1.65; color: var(--text); max-width: 980px; overflow-wrap: break-word; }
.cb-md h1, .cb-md h2, .cb-md h3, .cb-md h4 { line-height: 1.3; margin: 1.3em 0 .5em; }
.cb-md h1 { font-size: 1.7em; padding-bottom: .3em; border-bottom: 1px solid var(--border); }
.cb-md h2 { font-size: 1.35em; padding-bottom: .25em; border-bottom: 1px solid var(--border); }
.cb-md h3 { font-size: 1.12em; }
.cb-md p, .cb-md ul, .cb-md ol, .cb-md pre, .cb-md blockquote, .cb-md-table { margin: .6em 0; }
.cb-md ul, .cb-md ol { padding-left: 1.6em; }
.cb-md li { margin: .25em 0; }
.cb-md li > ul, .cb-md li > ol { margin: .2em 0; }
.cb-md a { color: var(--accent); }
.cb-md code { font-family: ui-monospace, Consolas, monospace; font-size: .88em; padding: .1em .4em; border-radius: 5px; background: var(--bg-elev-2); border: 1px solid var(--border); }
.cb-md pre { padding: 12px 14px; border-radius: 8px; background: var(--bg); border: 1px solid var(--border); overflow-x: auto; }
.cb-md pre code { padding: 0; border: none; background: none; font-size: 12.8px; }
.cb-md blockquote { padding: .2em 1em; border-left: 3px solid var(--accent); color: var(--text-dim); }
.cb-md hr { border: none; border-top: 1px solid var(--border); margin: 1.5em 0; }
.cb-md-table { overflow-x: auto; }
.cb-md table { border-collapse: collapse; font-size: 13px; }
.cb-md th, .cb-md td { border: 1px solid var(--border); padding: 6px 10px; text-align: left; vertical-align: top; }
.cb-md th { background: var(--bg-elev-2); }

@media (max-width: 1000px) {
  .cb-tree { display: none; }
  .cb-row { grid-template-columns: 24px minmax(0, 1fr) 84px 28px; }
  .cb-row-size { display: none; }
}
@media (max-width: 760px) {
  .cb-search { width: auto; flex: 1; min-width: 150px; }
  .cb-crumbs { flex-basis: 100%; }
  .cb-status { padding: 6px 12px; }
  .cb-main { padding: 12px 12px 30px; }
  .cb-row { grid-template-columns: 22px minmax(0, 1fr) 70px 28px; gap: 8px; padding: 8px 10px; }
  .cb-row-sub { display: none; }
  .cb-page-head { flex-direction: column; align-items: stretch; gap: 10px; }
  .cb-page-actions .cb-zip-menu { left: 0; right: auto; }
  /* "editing now" as just its dot, so names keep the room. */
  .cb-row .cb-edit-badge { font-size: 0; padding: 0; border: none; background: none; gap: 0; }
  .cb-row .cb-edit-badge::before { width: 8px; height: 8px; }
  .cb-md-page { padding: 4px 16px 18px; }
  .cb-readme .cb-md { padding: 4px 16px 18px; }
  .cb-zip-menu { width: min(330px, calc(100vw - 32px)); }
}