/*
 * Vroxy public stylesheet — served by Propshaft as a single bundle.
 * Sectioned by component. Admin chrome lives in admin.css.
 */

/* ───────── Theme tokens ───────── */
:root {
  --bg: #fff;
  --surface: #f8f8f8;
  --border: #e0e0e0;
  --text: #222;
  --text-muted: #666;
  --btn: #333;
  --btn-secondary: #777;
  --danger: #b00;
  --success: #2a7d2a;
  --radius: 8px;
}
[data-theme="dark"] {
  --bg: #1a1a1a;
  --surface: #252525;
  --border: #3a3a3a;
  --text: #e0e0e0;
  --text-muted: #999;
  --btn: #e0e0e0;
  --btn-secondary: #888;
  --danger: #e44;
  --success: #4a4;
}
/* Cuh is a dark-first brand. Align the global tokens with the
   landing's near-black + purple palette so navbar / footer / forms
   pick up the same surfaces and don't show a different dark shade
   around the bento. Vroxy keeps the neutral dark above. */
[data-theme="dark"][data-brand="cuh"] {
  --bg: #07050d;
  --surface: #120c1f;
  --border: #2a1f3f;
  --text: #f4f0ff;
  --text-muted: #9c8cb8;
}
[data-theme="dark"] .btn-primary { background: #e0e0e0; color: #1a1a1a; }
[data-theme="dark"] .flash.notice { background: #1a2e1a; color: #6c6; border-color: #2a4a2a; }
[data-theme="dark"] .flash.alert { background: #2e1a1a; color: #e88; border-color: #4a2a2a; }

/* ───────── Base ───────── */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.container { max-width: 1100px; margin: 0 auto; padding: 24px; width: 100%; flex: 1 0 auto; }

/* ───────── Navbar ───────── */
.navbar {
  padding: 12px 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
}
.navbar .brand {
  font-size: 1.2em;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 6px;
}
.navbar .brand img { width: 22px; height: 22px; }

/* SVG wordmark rendered via CSS mask so the asset (brand/<key>/<name>-wordmark.svg,
   copied into public/ at boot by config/initializers/brand_assets.rb) inherits
   currentColor — letting the wordmark adapt to dark/light theme without inlining
   the SVG. Caller sets `height:` inline; aspect-ratio keeps width auto-correct. */
.brand-wordmark {
  display: inline-block;
  background-color: currentColor;
  width: auto;
}
.brand-wordmark-cuh {
  -webkit-mask: url(/cuh-wordmark.svg) no-repeat center / contain;
          mask: url(/cuh-wordmark.svg) no-repeat center / contain;
  aspect-ratio: 1455 / 1410;
}
.navbar .brand-bar { display: flex; align-items: center; gap: 16px; }
.navbar .nav-link-dashboard { color: var(--text-muted); text-decoration: none; font-size: 0.9em; }
.navbar .nav-link-friends { color: var(--text-muted); text-decoration: none; font-size: 0.9em; }
.navbar .nav-link-admin {
  color: var(--text-muted); text-decoration: none; font-size: 0.75em;
  padding: 3px 8px; border: 1px solid var(--border);
  border-radius: 10px; text-transform: uppercase; letter-spacing: 0.5px;
  margin-left: auto;
}
.navbar .nav-link-admin:hover { color: var(--text); border-color: var(--text-muted); }
.navbar .nav-links { display: flex; gap: 16px; align-items: center; }
.navbar a { color: var(--text-muted); text-decoration: none; font-size: 0.9em; }
.navbar a:hover { color: var(--text); }

/* Mobile-only icon menu: the Vroxy logo on the left of the mobile
   navbar, which doubles as a dropdown trigger for Dashboard / Friends /
   Admin. Hidden on desktop where the inline brand-bar links serve the
   same purpose. */
.nav-icon-menu { display: none; }
.nav-icon-menu-btn {
  background: none; border: none; cursor: pointer;
  padding: 4px; display: flex; align-items: center;
}
.nav-icon-menu-btn img { width: 26px; height: 26px; }

/* Mobile-only "Vroxy" text in the middle of the navbar. */
.nav-brand-mobile {
  display: none;
  font-size: 1.05em; font-weight: 600;
  color: var(--text); text-decoration: none;
}

/* Action buttons inside a nav dropdown menu (theme + push toggles). */
.nav-dropdown-action {
  display: block; width: 100%;
  background: none; border: none; cursor: pointer;
  text-align: left; padding: 8px 14px;
  font: inherit; color: var(--text);
}
.nav-dropdown-action:hover { background: var(--surface-hover, rgba(0,0,0,0.06)); }
.theme-toggle-icon { display: inline-block; width: 20px; }

@media (max-width: 768px) {
  .navbar { padding: 10px 14px; }
  .navbar .brand-bar { gap: 8px; flex: 0 0 auto; }
  .nav-desktop-only { display: none !important; }
  .nav-icon-menu { display: block; }
  .nav-brand-mobile { display: inline-block; flex: 1; text-align: center; }

  /* User dropdown button on mobile shows just the avatar + conn dot.
     The display name and chevron are hidden to save space. */
  .navbar .nav-dropdown-user-btn .nav-user-name,
  .navbar .nav-dropdown-user-btn .nav-user-chevron { display: none; }

  /* Dropdown menus on mobile span the right edge of the screen rather
     than overflowing past it. The icon-menu opens left-anchored. */
  .nav-icon-menu .nav-dropdown-menu { left: 0; right: auto; }
  .nav-dropdown-menu { max-width: 90vw; min-width: 200px; }
}

/* ───────── Flash + forms ───────── */
.flash { padding: 12px 16px; border-radius: var(--radius); margin-bottom: 16px; font-size: 0.9em; border: 1px solid; }
.flash.notice { background: #f0f8f0; color: #2a5a2a; border-color: #c8e6c8; }
.flash.alert { background: #fdf0f0; color: #8b1a1a; border-color: #f0c8c8; }
input[type="text"], input[type="email"], input[type="password"],
input[type="url"], input[type="search"], input[type="tel"], input[type="number"],
input[type="date"],
.form-group textarea, .modal-section textarea,
.form-group select, .modal-section select {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px;
  color: var(--text);
  font-size: 0.95em;
  width: 100%;
  font-family: inherit;
  box-sizing: border-box;
}
.form-group textarea, .modal-section textarea { resize: vertical; min-height: 64px; line-height: 1.4; }
input:focus,
.form-group textarea:focus, .modal-section textarea:focus,
.form-group select:focus, .modal-section select:focus { outline: none; border-color: #999; }
label { display: block; margin-bottom: 6px; font-size: 0.85em; color: var(--text-muted); }
.form-group { margin-bottom: 16px; }

/* ───────── Buttons ───────── */
.btn {
  display: inline-block;
  padding: 10px 20px;
  border-radius: var(--radius);
  border: none;
  cursor: pointer;
  font-size: 0.9em;
  text-decoration: none;
  transition: opacity 0.2s;
}
.btn:hover { opacity: 0.8; }
.btn-primary { background: var(--btn); color: #fff; }
.btn-secondary { background: var(--bg); color: var(--text); border: 1px solid var(--border); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-sm { padding: 6px 12px; font-size: 0.8em; }
.btn-block { display: block; width: 100%; box-sizing: border-box; text-align: center; }

/* ───────── Cards ───────── */
.card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
}
.card-empty { text-align: center; padding: 40px; }
.room-card {
  display: flex; justify-content: space-between; align-items: center;
  cursor: pointer; transition: border-color 0.15s;
}
.room-card:hover { border-color: var(--text-muted); }
.room-card-body { display: flex; gap: 12px; align-items: center; min-width: 0; flex: 1; }
.room-card-icon { font-size: 1.8em; line-height: 1; flex-shrink: 0; }
.room-card-text { min-width: 0; flex: 1; }
.room-card-text h3 { margin-bottom: 4px; display: flex; align-items: center; gap: 8px; }
.room-card-topic { color: var(--text); font-size: 0.88em; margin: 0 0 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-card-meta { color: var(--text-muted); font-size: 0.85em; }
.room-card-chevron { color: var(--text-muted); font-size: 1.2em; }
.room-card-avatars { display: flex; align-items: center; flex-shrink: 0; }
.room-card-avatars img,
.room-card-avatars .room-card-avatar-initials {
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--surface);
  margin-left: -6px; flex-shrink: 0; object-fit: cover;
}
.room-card-avatars img:first-child,
.room-card-avatars .room-card-avatar-initials:first-child { margin-left: 0; }
.room-card-avatar-initials {
  background: var(--border); display: inline-flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 0.5em; color: var(--text-muted);
}
.room-card-avatar-more {
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--surface);
  margin-left: -6px; flex-shrink: 0; background: var(--border);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.5em; font-weight: 600; color: var(--text-muted);
}

/* ───────── Devise ───────── */
.devise-links { margin-top: 16px; font-size: 0.85em; }
.devise-links a { color: var(--text-muted); }
.devise-links a:hover { color: var(--text); }

/* ───────── Theme toggle + nav buttons ───────── */
.theme-toggle {
  background: none; border: 1px solid var(--border); border-radius: var(--radius);
  cursor: pointer; padding: 4px 8px; font-size: 1em; line-height: 1;
  color: var(--text-muted); transition: opacity 0.2s;
}
.theme-toggle:hover { opacity: 0.7; }
.push-toggle { font-size: 0.9em; }

/* ───────── Badges ───────── */
.nav-badge {
  background: var(--danger); color: #fff; font-size: 0.65em; font-weight: 700;
  padding: 1px 5px; border-radius: 8px; margin-left: -4px; vertical-align: super;
}
.unread-badge {
  display: inline-block; background: var(--danger); color: #fff;
  font-size: 0.7em; font-weight: 700; padding: 1px 7px;
  border-radius: 10px; line-height: 1.4;
}
/* The HTML `hidden` attribute defaults to display:none in the user
   agent stylesheet, but the .unread-badge / .nav-badge `display`
   declarations above override it. Restore the hide behavior so a
   zero-count badge actually disappears. */
.unread-badge[hidden],
.nav-badge[hidden] { display: none; }

/* ───────── Breadcrumbs (vbread) ─────────
   Vanilla rules so the widget works on the non-Bootstrap public layout.
   The same widget includes Bootstrap classes so the admin layout still
   picks up its native styles. */
.vbread {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; padding: 8px 14px; margin-bottom: 16px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); font-size: 0.85em;
}
.vbread-list {
  display: flex; flex-wrap: wrap; gap: 6px;
  list-style: none; margin: 0; padding: 0;
}
.vbread-item { color: var(--text-muted); }
.vbread-item + .vbread-item::before { content: "/"; padding-right: 6px; opacity: 0.5; }
.vbread-item a { color: var(--text-muted); text-decoration: none; }
.vbread-item a:hover { color: var(--text); text-decoration: underline; }
.vbread-item.vbread-active { color: var(--text); font-weight: 600; }
.vbread-actions { display: flex; gap: 6px; }
.vbread-actions a {
  font-size: 0.85em; color: var(--text-muted); text-decoration: none;
  padding: 3px 8px; border: 1px solid var(--border); border-radius: var(--radius);
}
.vbread-actions a:hover { color: var(--text); border-color: var(--text-muted); }

/* ───────── Guest dropdown ───────── */
.nav-guest-notice { position: relative; }
.nav-guest-btn {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  cursor: pointer; padding: 4px 10px; font-size: 0.85em; line-height: 1;
  color: var(--text); display: inline-flex; align-items: center; gap: 6px;
}
.nav-guest-btn:hover { opacity: 0.85; }
.nav-guest-label { font-weight: 600; }
.nav-guest-tag {
  font-size: 0.7em; font-weight: 600; text-transform: uppercase;
  background: var(--border); color: var(--text-muted);
  padding: 1px 5px; border-radius: 4px; letter-spacing: 0.4px;
}
.nav-guest-menu { min-width: 256px; padding: 10px 0; }
.nav-nickname-form { padding: 4px 12px 8px; }
.nav-nickname-form label {
  display: block; font-size: 0.75em; color: var(--text-muted);
  margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.3px;
}
.nav-nickname-form .nav-nickname-row { display: flex; gap: 6px; }
.nav-nickname-form input[type="text"] {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 6px 10px; color: var(--text); font-size: 0.9em; flex: 1; min-width: 0;
}
.nav-guest-save { padding: 8px 12px; }
.nav-guest-save-hint {
  font-size: 0.78em; color: var(--text-muted); margin: 8px 0 0; text-align: center;
}
.nav-guest-save-hint a { color: var(--text); font-weight: 600; }
.nav-guest-expires {
  display: block; padding: 6px 12px; color: var(--text-muted); font-size: 0.85em;
}

@media (max-width: 720px) {
  .nav-guest-btn { font-size: 0.78em; padding: 3px 8px; }
  .nav-guest-menu { min-width: 256px; }
}

/* ───────── Generic dropdown ───────── */
.nav-dropdown { position: relative; }
.nav-dropdown-btn {
  background: none; border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text-muted); font-size: 0.85em; padding: 4px 10px; cursor: pointer;
}
.nav-dropdown-btn:hover { color: var(--text); }
.nav-dropdown-user-btn {
  display: flex; align-items: center; gap: 6px; padding: 3px 10px 3px 3px;
}
.nav-dropdown-menu {
  display: none; position: absolute; right: 0; top: 100%; margin-top: 4px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  min-width: 256px; z-index: 100; box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.nav-dropdown-menu a {
  display: block; padding: 8px 14px; font-size: 0.85em;
  color: var(--text); text-decoration: none;
}
.nav-dropdown-menu a:hover { background: var(--surface); }
.nav-dropdown.open .nav-dropdown-menu { display: block; }
.nav-dropdown-divider { height: 1px; background: var(--border); margin: 4px 0; }
.nav-avatar {
  width: 24px; height: 24px; border-radius: 50%; object-fit: cover;
  flex-shrink: 0; display: inline-block;
}
.nav-avatar-initials {
  background: var(--border); display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 0.6em; color: var(--text-muted);
}

/* ───────── Connection status dot ─────────
   Tiny dot rendered inside the user-dropdown button. Replaces the older
   wide pill. Same #conn-chip id + data-state attribute, so the JS in
   cross_room_toasts.js doesn't need to change.
*/
.conn-dot {
  display: inline-block; width: 8px; height: 8px;
  border-radius: 50%; background: #888;
  vertical-align: middle; margin-right: 4px;
  box-shadow: 0 0 0 1px var(--surface, #fff);
}
.conn-dot[data-state="live"]       { background: #2a7d2a; }
.conn-dot[data-state="connecting"] { background: #c98a16; }
.conn-dot[data-state="degraded"]   { background: #c98a16; animation: pulse-degraded 1.2s ease-in-out infinite; }
.conn-dot[data-state="offline"]    { background: #b00; }
@keyframes pulse-degraded { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

/* ───────── Global toast stack (UserChannel cross-room + room toasts) ───────── */
.toast-stack {
  position: fixed; top: 64px; right: 16px; z-index: 1100;
  display: flex; flex-direction: column; gap: 8px;
  max-width: 320px; pointer-events: none;
}
.toast-item {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 10px 14px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.18);
  font-size: 0.85em; color: var(--text);
  opacity: 0; transform: translateX(20px);
  transition: opacity 0.2s, transform 0.2s;
  cursor: pointer; pointer-events: auto;
  text-decoration: none;
}
.toast-item.show { opacity: 1; transform: translateX(0); }
.toast-item-title { font-weight: 600; margin-bottom: 2px; font-size: 0.95em; }
.toast-item-body { color: var(--text-muted); font-size: 0.9em; word-break: break-word; }

/* ───────── Dashboard join-room <dialog> modal ───────── */
dialog.vmodal {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  padding: 24px;
  max-width: 420px;
  width: calc(100% - 32px);
  box-shadow: 0 10px 40px rgba(0,0,0,0.25);
  /* The global `* { margin: 0 }` reset on line 35 clobbers the
     browser default `margin: auto` that top-layer dialogs rely on
     for centering — restore it explicitly or the modal anchors
     top-left / top-right instead of centering. */
  margin: auto;
}
dialog.vmodal::backdrop { background: rgba(0,0,0,0.5); }
dialog.vmodal h3 { margin: 0 0 8px; font-size: 1.1em; }
dialog.vmodal p { color: var(--text-muted); font-size: 0.9em; margin: 0 0 16px; }
dialog.vmodal input[type="text"] {
  text-transform: uppercase; letter-spacing: 2px; text-align: center;
}
dialog.vmodal .vmodal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }

/* ───────── DM rooms ───────── */
.dm-avatar {
  width: 40px; height: 40px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.dm-avatar-initials {
  background: var(--border); display: flex;
  align-items: center; justify-content: center;
  font-weight: 600; font-size: 0.85em; color: var(--text-muted);
}
.dm-header-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0; display: inline-block;
}
.dm-header-link { color: var(--text); text-decoration: none; }
.dm-header-link:hover { text-decoration: underline; }
.dm-readonly-banner {
  padding: 8px 16px; background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-size: 0.85em; color: var(--text-muted); text-align: center;
}
.dashboard-section-title {
  font-size: 0.78em; text-transform: uppercase;
  color: var(--text-muted); letter-spacing: 0.5px;
  margin: 16px 0 8px; font-weight: 600;
  display: flex; align-items: center; gap: 8px;
}
.dashboard-section-title:first-child { margin-top: 0; }
.dashboard-section-action {
  margin-left: auto;
  font-size: 0.95em;
  color: var(--text-muted); text-decoration: none;
  text-transform: none; letter-spacing: normal;
  font-weight: 400;
}
.dashboard-section-action:hover { color: var(--text); text-decoration: underline; }

.dashboard-friend-actions {
  display: flex; gap: 6px; align-items: center;
  margin-left: auto; padding-left: 12px;
}
.dashboard-friend-actions form { margin: 0; }

.dashboard-friends-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.dashboard-friend-tile {
  display: flex; flex-direction: column; align-items: center;
  gap: 6px; padding: 12px 8px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none; color: var(--text);
  transition: border-color 0.15s;
}
.dashboard-friend-tile:hover { border-color: var(--text-muted); }
.dashboard-friend-avatar-wrap {
  position: relative;
  width: 48px; height: 48px;
  flex-shrink: 0;
}
.dashboard-friend-avatar {
  width: 48px; height: 48px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.dashboard-friend-presence-dot {
  position: absolute;
  bottom: 0; right: 0;
  width: 12px; height: 12px;
  border-radius: 50%;
  border: 2px solid var(--surface);
  box-sizing: content-box;
}
.dashboard-friend-name {
  font-size: 0.82em; text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 100%;
}

/* ───────── Dashboard layout helpers ───────── */
.dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; }
.dashboard-header-actions { display: flex; gap: 8px; align-items: center; }
.dashboard-empty-actions { display: flex; gap: 8px; justify-content: center; }
.dashboard-empty-hint { font-size: 0.82em; color: var(--text-muted); margin-top: 16px; }
.dashboard-room-link { text-decoration: none; color: inherit; display: flex; align-items: stretch; gap: 4px; }
.dashboard-room-link-inner { flex: 1; text-decoration: none; color: inherit; min-width: 0; }
.dashboard-sortable { display: flex; flex-direction: column; gap: 8px; }
.dashboard-sortable .dashboard-room-link.dragging { opacity: 0.4; }
.drag-handle {
  display: flex; align-items: center; justify-content: center;
  width: 18px; color: var(--text-muted, #888);
  cursor: grab; user-select: none; font-size: 1em;
  letter-spacing: -2px;
  flex-shrink: 0;
}
.drag-handle:active { cursor: grabbing; }
.dashboard-room-link[draggable="true"] .dashboard-room-link-inner { pointer-events: auto; }

/* ───────── Color swatches (rooms/new + room settings modal) ───────── */
.color-swatches { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.color-swatch {
  width: 24px; height: 24px; border-radius: 50%;
  border: 2px solid var(--border); cursor: pointer; padding: 0;
}
.color-swatch-clear {
  width: 24px; height: 24px; border-radius: 50%;
  border: 2px dashed var(--border); background: transparent;
  cursor: pointer; padding: 0; color: var(--text-muted); font-size: 0.7em;
}

/* ───────── Settings page ───────── */
.settings-shell {
  display: flex; gap: 24px;
  max-width: 1100px; margin: 0 auto;
  align-items: flex-start;
}
.settings-sidebar {
  width: 180px; flex-shrink: 0;
  position: sticky; top: 24px;
}
.settings-sidebar-title {
  font-size: 1.1em; margin: 0 0 12px;
  color: var(--text);
}
.settings-sidebar nav { display: flex; flex-direction: column; gap: 2px; }
.settings-nav-link {
  display: block; padding: 8px 12px;
  color: var(--text-muted); text-decoration: none;
  font-size: 0.9em; border-radius: var(--radius);
  border-left: 3px solid transparent;
}
.settings-nav-link:hover { background: var(--surface); color: var(--text); }
.settings-nav-link.active {
  background: var(--surface); color: var(--text); font-weight: 600;
  border-left-color: var(--btn);
}
.settings-content { flex: 1; min-width: 0; }
.settings-content .card:first-child { margin-top: 0; }

@media (max-width: 720px) {
  .settings-shell { flex-direction: column; }
  .settings-sidebar { position: static; width: 100%; }
  .settings-sidebar nav { flex-direction: row; flex-wrap: wrap; }
  .settings-nav-link { border-left: none; border-bottom: 3px solid transparent; }
  .settings-nav-link.active { border-left: none; border-bottom-color: var(--btn); }
}

/* legacy single-column wrapper, still used by a few one-off pages */
.settings-page { max-width: 640px; margin: 24px auto; }
.settings-page h2 { margin-bottom: 20px; }
.settings-card-title { font-size: 1em; margin-bottom: 16px; }
.settings-help { font-size: 0.82em; color: var(--text-muted); margin-bottom: 16px; }
.settings-help-tight { font-size: 0.78em; color: var(--text-muted); margin-bottom: 16px; }
.settings-actions { display: flex; gap: 8px; }

/* Webhook (and similar) list tables on settings pages. The user-facing
   layout doesn't load Bootstrap, so the bare `.table` class rendered
   unstyled — this gives the list real padding, header treatment, and
   row hover without pulling in a framework. */
.settings-table { width: 100%; border-collapse: collapse; font-size: 0.88em; }
.settings-table thead th {
  text-align: left; padding: 8px 12px;
  font-size: 0.72em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-muted); border-bottom: 1px solid var(--border); white-space: nowrap;
}
.settings-table tbody td { padding: 10px 12px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.settings-table tbody tr:last-child td { border-bottom: none; }
.settings-table tbody tr:hover { background: var(--bg); }
.settings-table td.num, .settings-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.settings-table .name-link { color: var(--text); font-weight: 600; text-decoration: none; }
.settings-table .name-link:hover { text-decoration: underline; }
.settings-table-actions { display: flex; gap: 6px; justify-content: flex-end; }
.settings-table-actions form { display: inline; margin: 0; }

/* On/off status pill, used in webhook lists and detail headers. */
.settings-pill {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-size: 0.74em; font-weight: 600; line-height: 1.6; white-space: nowrap;
}
.settings-pill-on  { color: var(--success); border: 1px solid var(--success); }
.settings-pill-off { color: var(--text-muted); border: 1px solid var(--border); }

/* Stat tiles for webhook detail pages. */
.settings-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.settings-stat { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; }
.settings-stat-label { font-size: 0.7em; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); margin-bottom: 6px; }
.settings-stat-value { font-size: 1.35em; font-weight: 700; color: var(--text); line-height: 1.2; }
.settings-stat-sub { font-size: 0.76em; color: var(--text-muted); margin-top: 4px; }
.settings-meta-row { display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; font-size: 0.85em; color: var(--text-muted); }
.settings-meta-row code { font-size: 0.95em; }

/* Reveal/copy widget for a webhook's secret token. */
.webhook-token-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.webhook-token-value {
  flex: 1 1 280px; min-width: 0; user-select: all; word-break: break-all;
  padding: 7px 10px; font-size: 0.85em; letter-spacing: 0.04em;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
}
.settings-readonly-value {
  display: block; padding: 10px 14px;
  font-size: 0.95em; color: var(--text-muted);
}
[data-theme="dark"] input[type="date"] {
  color-scheme: dark;
}
.settings-select {
  width: 100%; padding: 10px 14px; background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text); font-size: 0.95em;
}
.avatar-row { display: flex; align-items: center; gap: 16px; margin-bottom: 12px; }
.avatar-preview {
  width: 56px; height: 56px; border-radius: 50%;
  object-fit: cover; border: 1px solid var(--border);
}
.avatar-preview-initials {
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--border); display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 1em; color: var(--text-muted);
}
.avatar-remove-btn {
  color: var(--danger); background: none; border: none;
  font-size: 0.82em; cursor: pointer;
}

/* ───────── Room avatars (#208) ───────── */
.room-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px; flex-shrink: 0; vertical-align: middle;
  overflow: hidden; line-height: 1; color: #fff; font-weight: 600;
}
img.room-avatar { object-fit: cover; }
.room-avatar-emoji { font-size: 1em; background: var(--border); }
.room-avatar-initials { font-size: 0.78em; letter-spacing: 0.02em; background: var(--border); }
.sidebar-room-avatar { margin-right: 6px; border-radius: 4px; }
.share-modal-room-avatar { margin: 0 4px; vertical-align: -4px; }
.profile-room-avatar { margin-right: 6px; }

/* ───────── Rooms / new ───────── */
.form-narrow { max-width: 500px; margin: 24px auto; }
.icon-input { width: 80px; text-align: center; font-size: 1.4em; }
.color-input { width: 120px; }
.icon-row { display: flex; gap: 8px; align-items: center; }
.icon-hint { font-size: 0.82em; color: var(--text-muted); }
.public-toggle { display: flex; align-items: center; gap: 8px; }
.public-toggle input { width: auto; }
.create-hint { font-size: 0.82em; color: var(--text-muted); margin-bottom: 16px; }

/* ───────── User profile ───────── */
.profile-page {
  max-width: 720px;
  margin: 0 auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px;
}
.profile-header {
  display: flex; gap: 16px; align-items: center;
  margin-bottom: 16px;
}
.profile-avatar {
  width: 72px; height: 72px; border-radius: 50%;
  object-fit: cover; border: 1px solid var(--border);
  flex-shrink: 0;
}
.profile-avatar-initials {
  background: var(--border); display: flex;
  align-items: center; justify-content: center;
  font-weight: 600; font-size: 1.4em; color: var(--text-muted);
}
.profile-header-text { min-width: 0; flex: 1; }
.profile-qr-link {
  flex-shrink: 0; display: block; line-height: 0;
  border-radius: var(--radius); border: 1px solid var(--border);
  padding: 4px; background: #fff;
}
.profile-qr-img { width: 88px; height: 88px; display: block; }
.profile-name {
  font-size: 1.4em; margin: 0 0 4px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.profile-pronouns {
  font-size: 0.6em; color: var(--text-muted); font-weight: 400;
}
.profile-presence-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: #888; display: inline-block;
}
.profile-presence-online { background: var(--success); }
.profile-presence-away { background: #c98a16; }
.profile-presence-offline, .profile-presence-hidden { background: #888; }
.profile-tagline { font-size: 0.95em; color: var(--text); margin: 0 0 4px; }
.profile-meta { font-size: 0.82em; color: var(--text-muted); margin: 0; }
.profile-actions {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-bottom: 20px;
}
.profile-actions form { margin: 0; }
.profile-friend-tag {
  font-size: 0.82em; color: var(--text-muted);
  padding: 4px 10px; border: 1px solid var(--border); border-radius: var(--radius);
}
.profile-section { margin-top: 20px; }
.profile-section-title {
  font-size: 0.78em; text-transform: uppercase;
  color: var(--text-muted); letter-spacing: 0.5px;
  margin-bottom: 8px; font-weight: 600;
}
.profile-bio { font-size: 0.92em; line-height: 1.5; }
.profile-rooms { list-style: none; padding: 0; margin: 0; }
.profile-rooms li { padding: 4px 0; }
.profile-room-link {
  color: var(--text); text-decoration: none; font-size: 0.9em;
}
.profile-room-link:hover { text-decoration: underline; }
.profile-room-tag {
  font-size: 0.7em; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 4px;
  padding: 1px 5px; margin-left: 6px;
}
.profile-stub .profile-header { margin-bottom: 0; }

/* Friends inbox */
.friends-page { max-width: 720px; margin: 0 auto; }
.friends-tabs {
  display: flex; gap: 4px; border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}
.friends-tab {
  padding: 8px 14px; color: var(--text-muted); text-decoration: none;
  font-size: 0.9em; border-bottom: 2px solid transparent;
}
.friends-tab:hover { color: var(--text); }
.friends-tab.active { color: var(--text); border-bottom-color: var(--btn); font-weight: 600; }
.friends-tab .friends-tab-count {
  font-size: 0.7em; background: var(--border);
  padding: 1px 6px; border-radius: 10px; margin-left: 4px;
}
.friends-list { list-style: none; padding: 0; margin: 0; }
.friends-list li {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--border);
  border-radius: var(--radius); margin-bottom: 8px;
  background: var(--surface);
}
.friends-list .friends-list-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.friends-list .friends-list-text { flex: 1; min-width: 0; }
.friends-list .friends-list-name { font-weight: 600; font-size: 0.92em; }
.friends-list .friends-list-name a { color: var(--text); text-decoration: none; }
.friends-list .friends-list-name a:hover { text-decoration: underline; }
.friends-list .friends-list-meta { font-size: 0.78em; color: var(--text-muted); }
.friends-list .friends-list-actions { display: flex; gap: 6px; }
.friends-list .friends-list-actions form { margin: 0; }
.friends-empty {
  padding: 30px; text-align: center;
  color: var(--text-muted); font-size: 0.9em;
}
.friends-search {
  display: flex; gap: 8px; margin-bottom: 16px;
}
.friends-search input { flex: 1; }

/* Profile-edit card on the settings page */
.settings-textarea {
  width: 100%; padding: 10px 14px;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius); color: var(--text);
  font-size: 0.95em; font-family: inherit;
  min-height: 80px; resize: vertical;
}
.settings-checkbox-row { display: flex; align-items: center; gap: 8px; }
.settings-checkbox-row input { width: auto; }
.settings-checkbox-row label { margin: 0; font-size: 0.88em; color: var(--text); }

/* ════════════════════════════════════════════════════════════════════
   ROOM SHOW PAGE
   ════════════════════════════════════════════════════════════════════ */
body.room-page .container { max-width: 100%; padding: 0; }
body.room-page .flash {
  position: fixed; top: 56px; left: 50%; transform: translateX(-50%);
  z-index: 1100; margin: 0; padding: 8px 24px; font-size: 0.85em;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  animation: flash-fade 3s ease-in-out forwards;
  pointer-events: none;
}
@keyframes flash-fade { 0%{opacity:1} 70%{opacity:1} 100%{opacity:0} }

.app-shell { display: flex; height: calc(100vh - 130px); overflow: hidden; }

/* ───────── Sidebar ───────── */
.sidebar {
  width: 240px; flex-shrink: 0; background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column; overflow: hidden;
}
.sidebar-header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 14px; font-size: 0.9em; border-bottom: 1px solid var(--border);
}
.sidebar-new-btn {
  width: 24px; height: 24px; border-radius: 4px; background: var(--border);
  display: flex; align-items: center; justify-content: center;
  color: var(--text); text-decoration: none; font-size: 1.1em; line-height: 1;
}
.sidebar-rooms { overflow-y: auto; padding: 6px 0; }

/* Always-on-top version badge in the bottom-left. pointer-events: none
   so it never intercepts clicks — high z so it's never hidden behind
   modals, toasts, or the room sidebar. */
/* Friend search typeahead on the dashboard (#10) — small input above
   the friends grid plus a result list anchored below it. */
.dashboard-friend-search {
  position: relative;
  margin: 12px 0 16px;
}
.dashboard-friend-search input {
  width: 100%;
  padding: 8px 12px;
  font-size: 0.9em;
}
.dashboard-friend-search-results {
  margin-top: 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  max-height: 320px;
  overflow-y: auto;
}
.dashboard-friend-search-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
}
.dashboard-friend-search-row:last-child { border-bottom: 0; }
.dashboard-friend-search-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.dashboard-friend-search-avatar-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent, #1f6feb); color: #fff;
  font-size: 0.75em; font-weight: 600;
}
.dashboard-friend-search-name { flex: 1; font-size: 0.9em; }
.dashboard-friend-search-empty {
  padding: 12px; font-size: 0.8em; color: var(--text-muted);
  text-align: center;
}

/* Cable connect-timeout hint (#21) — thin yellow strip pinned to the
   top of the page when the WS handshake hasn't completed in 10s. */
.conn-timeout-hint {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 9000;
  background: #fff7d6;
  color: #6a5b00;
  border-bottom: 1px solid #e5d088;
  padding: 6px 14px;
  font-size: 0.8em;
  text-align: center;
}
.conn-timeout-hint a { color: #6a5b00; text-decoration: underline; }

/* Typing indicator (#14) — thin row above the input bar that flashes
   when the other DM member is typing. Hidden by default. */
.typing-indicator {
  font-size: 0.75em; color: var(--text-muted);
  font-style: italic; padding: 4px 14px;
}

/* #43 — Channel scanner page. Sits at /scan, lists every room the
   user is a member of as a checklist; the scan_controller stimulus
   subscribes to one RoomChannel per checked row and serializes
   incoming audio into a single FIFO playback queue. */
.scan-page { max-width: 720px; margin: 0 auto; padding: 16px; }
.scan-header h2 { margin: 0 0 4px; }
.scan-help { color: var(--text-muted, #888); font-size: 0.9em; margin: 0 0 16px; }
.scan-now-playing {
  padding: 14px 16px;
  background: rgba(31, 111, 235, 0.06);
  border: 1px solid rgba(31, 111, 235, 0.2);
  border-radius: 8px;
  margin-bottom: 18px;
  font-size: 0.95em;
  min-height: 44px;
  display: flex; align-items: center;
}
.scan-idle { color: var(--text-muted, #888); font-style: italic; }
.scan-playing strong { color: #1f6feb; }
.scan-queue { margin-left: 8px; font-size: 0.85em; color: var(--text-muted); }
.scan-room-list { display: flex; flex-direction: column; gap: 6px; }
.scan-room-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  background: var(--card-bg, #1a1a1a);
  border: 1px solid var(--border, #333);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.1s;
}
.scan-room-row:hover { background: rgba(31, 111, 235, 0.05); }
.scan-room-icon { font-size: 1.2em; }
.scan-room-name { flex: 1; font-weight: 500; }
.scan-room-group { font-size: 0.8em; color: var(--text-muted); }
.scan-room-jump {
  margin-left: auto; font-size: 0.8em;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  text-decoration: none;
  color: var(--text-muted);
}
.scan-room-jump:hover { background: var(--border); color: var(--text); }
.scan-empty { color: var(--text-muted); padding: 24px 0; text-align: center; }

/* Squelch / "channel busy" indicator (#43) — same row position as
   the typing indicator but with a green pulse, to mirror the
   channel-busy LED on a real radio. Hidden by default. */
.transmitting-indicator {
  font-size: 0.78em; color: #2a7d2a;
  font-weight: 600;
  padding: 4px 14px;
  animation: vroxy-pulse 1.2s ease-in-out infinite;
}
@keyframes vroxy-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

/* Read receipt indicator (#13) — small "Seen" tag on the messages I
   sent in DMs once the other side has read them. */
.msg-seen {
  display: inline-block; font-size: 0.7em;
  color: var(--text-muted); margin-top: 2px;
  font-style: italic;
}
.msg-seen::before { content: "✓ "; }

/* Notification preferences (#12) — muted rooms list in settings. */
.muted-rooms-list { list-style: none; padding: 0; margin: 8px 0 0; }
.muted-rooms-item {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px; margin-bottom: 6px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface);
}
.muted-rooms-name { flex: 1; font-weight: 500; }
.muted-rooms-name a { color: var(--text); text-decoration: none; }
.muted-rooms-name a:hover { text-decoration: underline; }
.muted-rooms-until { color: var(--text-muted); font-size: 0.85em; }
.settings-section { margin-top: 24px; }
.settings-section h3 { margin-bottom: 6px; font-size: 1em; }
.settings-section-help { color: var(--text-muted); font-size: 0.85em; margin: 0 0 8px; }

/* Per-room mute (#52) — small bell button in the room header that
   opens a dropdown of durations. Muted sidebar rooms get a 🔕 next to
   their name (rendered server-side) and slightly faded text. */
.room-mute-btn {
  background: none; border: none; cursor: pointer;
  font-size: 1em; padding: 2px 4px; color: var(--text);
}
.sidebar-room.muted { opacity: 0.6; }
.sidebar-room.muted .sidebar-room-name { color: var(--text-muted); }

/* Priority — admin-only "Send as urgent" toggle in the PTT area, and
   the red border applied to received urgent messages (#42). */
.priority-toggle {
  display: flex; align-items: center; gap: 6px;
  font-size: 0.78em; color: var(--text-muted);
  padding: 4px 14px; cursor: pointer;
}
.priority-toggle input { margin: 0; }
.msg.msg-urgent {
  border-left: 3px solid #c00;
  background: rgba(204, 0, 0, 0.04);
}
.msg.msg-urgent .msg-header strong::after {
  content: " · 🚨 URGENT";
  color: #c00; font-weight: 600; font-size: 0.85em;
}
/* #41 — All-call announcements. Distinct from urgent: announcement
   is group-scoped (one click, every room), urgent is per-message.
   Visual treatment uses a blue bar + a tag so the two can't be
   confused at a glance. */
.msg.msg-announcement {
  border-left: 3px solid #1f6feb;
  background: rgba(31, 111, 235, 0.06);
}
.msg.msg-announcement .msg-header strong::after {
  content: " · 📢 ANNOUNCEMENT";
  color: #1f6feb; font-weight: 600; font-size: 0.85em;
}
/* #43 — Horn chip. Compact single-line render, distinct yellow tint
   so a horn message reads as "attention grab", not as audio or text. */
.msg.msg-horn { border-left: 3px solid #c98a16; background: rgba(201, 138, 22, 0.06); }
.msg-horn-chip {
  display: inline-block;
  font-size: 0.95em;
  color: #c98a16;
  font-weight: 600;
  letter-spacing: 0.02em;
}
/* Horn button in the room input bar — sits next to the PTT button. */
.horn-button {
  background: transparent;
  border: 1px solid var(--border, #444);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 1.1em;
  cursor: pointer;
  transition: background 0.1s, transform 0.05s;
}
.horn-button:hover { background: rgba(201, 138, 22, 0.15); }
.horn-button:active { transform: scale(0.94); }
.horn-button[disabled] { opacity: 0.5; cursor: not-allowed; }

/* Horn-clip picker (long-press / right-click on .horn-button). */
.horn-picker {
  position: absolute;
  bottom: 70px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--bg-card, #1a1d21);
  border: 1px solid var(--border, #30363d);
  border-radius: 10px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
  min-width: 240px;
  max-width: 320px;
  max-height: 60vh;
  overflow-y: auto;
  z-index: 50;
  padding: 6px 0;
}
.horn-picker[hidden] { display: none; }
.horn-picker-header {
  font-size: 12px; color: var(--text-muted, #8b949e);
  padding: 4px 12px 6px; text-transform: uppercase; letter-spacing: 0.05em;
}
.horn-picker-list { list-style: none; padding: 0; margin: 0; }
.horn-picker-item {
  display: flex; flex-direction: column; gap: 2px;
  width: 100%; text-align: left; padding: 8px 12px;
  background: transparent; border: 0; color: var(--text, #e6edf3);
  cursor: pointer; font-size: 14px;
}
.horn-picker-item:hover { background: rgba(255, 255, 255, 0.06); }
.horn-picker-name { font-weight: 600; }
.horn-picker-meta { font-size: 11px; color: var(--text-muted, #8b949e); }
.horn-picker-badge {
  display: inline-block; margin-top: 2px; align-self: flex-start;
  font-size: 10px; padding: 1px 6px; border-radius: 999px;
  background: rgba(42, 125, 42, 0.18); color: #8ad08a;
}
.horn-picker-empty { padding: 10px 12px; color: var(--text-muted, #8b949e); font-size: 13px; }
.horn-picker-loading { padding: 10px 12px; color: var(--text-muted, #8b949e); font-size: 13px; list-style: none; }

/* Horn-clip mint dialog (opened from message actions menu). */
.horn-clip-dialog {
  background: var(--bg-card, #1a1d21);
  color: var(--text, #e6edf3);
  border: 1px solid var(--border, #30363d);
  border-radius: 10px;
  padding: 20px;
  max-width: 440px;
  width: 92vw;
}
.horn-clip-dialog::backdrop { background: rgba(0, 0, 0, 0.55); }
.horn-clip-dialog .form-group { margin-bottom: 12px; }
.horn-clip-dialog input[type="text"],
.horn-clip-dialog input[type="number"],
.horn-clip-dialog select {
  width: 100%; padding: 6px 10px;
  background: var(--bg-input, #0d1117); color: inherit;
  border: 1px solid var(--border, #30363d); border-radius: 6px;
}

/* Location button + message */
.location-button {
  background: transparent;
  border: 1px solid var(--border, #444);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 1.1em;
  cursor: pointer;
  transition: background 0.1s;
}
.location-button:hover { background: rgba(60, 160, 60, 0.15); }
.msg-location { margin: 4px 0; }
.msg-location-link {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  background: var(--bg-soft, #2a2a2a);
  border-radius: 8px;
  color: var(--text, #eee);
  text-decoration: none;
  font-size: 0.88em;
  transition: background 0.1s;
}
.msg-location-link:hover { background: var(--bg-hover, #333); }
.msg-location-pin { font-size: 1.2em; }
.msg-location-coords { font-family: monospace; font-size: 0.9em; }
.msg-location-label { color: var(--text-muted, #888); font-size: 0.9em; }

/* #71 — Attachment button */
.attach-button {
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid var(--border, #444);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 1.1em;
  cursor: pointer;
  transition: background 0.1s;
}
.attach-button:hover { background: rgba(100, 100, 200, 0.15); }

/* #71 — Attachment message rendering */
.msg-attachment { margin: 4px 0; }
.msg-attachment-image-link {
  display: inline-block;
  max-width: 100%;
  line-height: 0;
}
.msg-attachment-image {
  max-width: 320px; max-height: 280px;
  border-radius: 8px;
  object-fit: contain;
  cursor: zoom-in;
}

/* Image attachment lightbox modal. Click on a thumbnail opens
   here; backdrop / X button / ESC closes. The wrapping <a> on
   each thumbnail still works for middle/right click and is
   surfaced as the small ↗ "open original in new tab" button
   inside the lightbox too. */
.image-lightbox {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(0,0,0,0.9);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 32px 32px 16px;
  gap: 12px;
  opacity: 0; transition: opacity 0.15s ease;
}
.image-lightbox.open { opacity: 1; }
.image-lightbox[hidden] { display: none; }
.image-lightbox-stage {
  flex: 1 1 auto;
  display: flex; align-items: center; justify-content: center;
  width: 100%;
  min-height: 0;
}
.image-lightbox-img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  border-radius: 4px;
  box-shadow: 0 8px 40px rgba(0,0,0,0.5);
}
.image-lightbox-info {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  width: 100%;
  max-width: 900px;
  padding: 10px 14px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  color: #eee;
  font-size: 0.9em;
}
.image-lightbox-meta {
  display: flex; align-items: baseline; gap: 10px;
  min-width: 0;
}
.image-lightbox-filename {
  font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.image-lightbox-size {
  color: rgba(255,255,255,0.55);
  font-size: 0.85em;
  white-space: nowrap;
}
.image-lightbox-actions {
  display: flex; align-items: center; gap: 8px;
  flex-shrink: 0;
}
.image-lightbox-actions a {
  color: #fff;
  text-decoration: none;
  padding: 6px 12px;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 6px;
  background: rgba(0,0,0,0.4);
  font-size: 0.9em;
  white-space: nowrap;
}
.image-lightbox-actions a:hover { background: rgba(255,255,255,0.1); }
.image-lightbox-close {
  position: absolute; top: 16px; right: 16px;
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.6);
  color: #fff; border: 1px solid rgba(255,255,255,0.2);
  border-radius: 50%;
  font-size: 1.4em; line-height: 1;
  cursor: pointer; text-decoration: none;
  z-index: 1;
}
.image-lightbox-close:hover { background: rgba(0,0,0,0.85); }
body.image-lightbox-locked { overflow: hidden; }
.msg-attachment-video {
  max-width: 360px; max-height: 280px;
  border-radius: 8px;
}
.msg-attachment-file {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  background: var(--bg-soft, #2a2a2a);
  border-radius: 8px;
  color: var(--text, #eee);
  text-decoration: none;
  font-size: 0.85em;
  transition: background 0.1s;
}
.msg-attachment-file:hover { background: var(--bg-hover, #333); }
.msg-attachment-file-icon { font-size: 1.3em; }
.msg-attachment-file-name { font-weight: 500; word-break: break-all; }
.msg-attachment-file-size { color: var(--text-muted, #888); font-size: 0.9em; }

/* Agent badge — small bot icon (and optional "Agent" label) rendered
   next to display names anywhere a member can be an agent. Lives next
   to message senders, room member lists, friend lists, sidebar DMs,
   and the dashboard friend tiles. */
/* Gradient chip — deterministic color per value. Used in admin
   grids to make repeated values visually obvious at a glance. */
.gradient-chip {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78em;
  padding: 1px 6px;
  border-radius: 6px;
  color: #fff;
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
  white-space: nowrap;
  letter-spacing: 0.01em;
}

.agent-badge {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 0.78em; color: var(--text-muted);
  padding: 1px 5px; border-radius: 8px;
  background: var(--mention-bg, rgba(31, 111, 235, 0.1));
}
.agent-badge-icon { font-size: 0.95em; line-height: 1; }
.agent-badge.agent-badge-icon {
  background: none; padding: 0; gap: 0;
  font-size: 1em;
}

.app-version-badge {
  position: fixed; bottom: 8px; left: 10px;
  font-size: 1em; color: #888; opacity: 0.7;
  pointer-events: none;
  z-index: 9999;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.02em;
}
.sidebar-room-wrap {
  display: flex; align-items: stretch;
}
.sidebar-room-wrap .drag-handle-sm {
  display: flex; align-items: center; justify-content: center;
  width: 14px; color: var(--text-muted, #888);
  cursor: grab; user-select: none; font-size: 0.7em; letter-spacing: -2px;
  opacity: 0; transition: opacity 0.1s;
  flex-shrink: 0;
}
.sidebar-room-wrap:hover .drag-handle-sm { opacity: 0.8; }
.sidebar-room-wrap .drag-handle-sm:active { cursor: grabbing; }
.sidebar-room-wrap.dragging { opacity: 0.4; }
.sidebar-room {
  flex: 1; min-width: 0;
  display: flex; justify-content: space-between; align-items: center;
  padding: 6px 14px 6px 4px; color: var(--text); text-decoration: none;
  font-size: 0.85em; border-left: 3px solid transparent;
  transition: background 0.1s;
}
.sidebar-room:hover { background: var(--border); }
.sidebar-room.active { background: var(--bg); border-left-color: var(--btn); font-weight: 600; }
.sidebar-room-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-room-meta { font-size: 0.8em; color: var(--text-muted); flex-shrink: 0; }
.sidebar-room .unread-badge {
  background: var(--danger); color: #fff; font-size: 0.7em; font-weight: 700;
  padding: 1px 6px; border-radius: 10px;
}
.sidebar-members {
  border-top: 1px solid var(--border); padding: 8px 0;
  overflow-y: auto; max-height: 200px;
}
.sidebar-section-title {
  font-size: 0.7em; text-transform: uppercase; color: var(--text-muted);
  padding: 4px 14px; letter-spacing: 0.5px;
}
.sidebar-member {
  display: flex; align-items: center; gap: 8px;
  padding: 3px 14px; font-size: 0.82em; color: var(--text-muted);
  cursor: default;
}
.sidebar-member:hover { background: var(--border); }
.sidebar-member-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.sidebar-member-tag { color: var(--text-muted); font-size: 0.85em; }

/* Avatar circle shared between DM rows and member rows in the sidebar */
.sidebar-avatar {
  width: 18px; height: 18px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.sidebar-avatar-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent, #1f6feb); color: #fff;
  font-size: 0.62em; font-weight: 600; line-height: 1;
}
.sidebar-room .sidebar-avatar { margin-right: 6px; }

/* Right-click context menu — used by the user-context elements in the sidebar */
.user-ctx-menu {
  position: fixed; z-index: 1100;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 4px;
  min-width: 180px; box-shadow: 0 4px 16px rgba(0,0,0,0.18);
  display: flex; flex-direction: column; gap: 1px;
}
.user-ctx-menu[hidden] { display: none; }
.user-ctx-item {
  background: none; border: none; text-align: left;
  padding: 8px 12px; font-size: 0.85em; color: var(--text);
  cursor: pointer; border-radius: 4px;
}
.user-ctx-item:hover { background: var(--border); }
.user-ctx-item-danger { color: var(--danger); }
.user-ctx-item[hidden] { display: none; }

/* ───────── Main + room header ───────── */
.main-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; min-width: 0; }
.room-header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 16px; border-bottom: 1px solid var(--border);
  background: var(--bg); flex-shrink: 0;
}
.room-header h2 { font-size: 1.05em; margin: 0; display: flex; align-items: center; gap: 6px; }
.room-header .room-meta { font-size: 0.75em; color: var(--text-muted); }
.room-header .room-meta-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-header-left { display: flex; gap: 10px; align-items: center; min-width: 0; flex: 1; }
.room-header-icon { font-size: 1.4em; line-height: 1; }
.room-header-titles { min-width: 0; }
.room-header-actions { display: flex; gap: 8px; align-items: center; }
.room-header-actions button { background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 1.1em; padding: 4px; }
.room-header-actions button:hover { color: var(--text); }
.mobile-sidebar-btn { display: none; background: none; border: none; cursor: pointer; font-size: 1.2em; color: var(--text-muted); }
.master-volume-wrap { font-size: 0.75em; color: var(--text-muted); display: flex; align-items: center; gap: 4px; }
.master-volume-wrap input[type="range"] { width: 60px; height: 14px; accent-color: var(--success); }

/* ───────── Messages area ───────── */
.messages-area-wrap {
  flex: 1; min-height: 0; position: relative;
  display: flex; flex-direction: column;
}
.messages-area {
  flex: 1; overflow-y: auto; padding: 6px 16px;
  display: flex; flex-direction: column; gap: 2px;
  -webkit-overflow-scrolling: touch; min-height: 0;
}
.jump-to-recent {
  position: absolute; right: 16px; bottom: 12px; z-index: 50;
  background: var(--primary); color: var(--primary-contrast, #fff);
  border: none; border-radius: 999px; cursor: pointer;
  padding: 6px 14px; font-size: 0.82em; font-weight: 600;
  box-shadow: 0 4px 12px rgba(0,0,0,0.18);
  display: inline-flex; align-items: center; gap: 6px;
}
.jump-to-recent[hidden] { display: none; }
.jump-to-recent:hover { filter: brightness(1.08); }
.jtr-count {
  background: rgba(255,255,255,0.22); padding: 0 6px;
  border-radius: 999px; font-size: 0.9em; min-width: 18px; text-align: center;
}
.jtr-count[hidden] { display: none; }
.msg {
  display: flex; gap: 8px; padding: 2px 4px;
  align-items: flex-start; border-radius: 6px; position: relative;
}
.msg:hover { background: var(--surface); }
.msg.playing { background: var(--surface); border-left: 3px solid var(--success); }
.msg-avatar {
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--border); display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 0.6em; color: var(--text-muted); flex-shrink: 0;
  margin-top: 2px;
}
.msg-body { flex: 1; min-width: 0; }
.msg-header { font-size: 0.75em; color: var(--text-muted); margin-bottom: 1px; }
.msg-header strong { color: var(--text); }
.msg-sender-link { color: inherit; text-decoration: none; }
.msg-sender-link:hover { text-decoration: underline; }
.msg-text { font-size: 0.88em; word-wrap: break-word; }
.msg-text code {
  background: rgba(255,255,255,0.07);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 0.9em;
  font-family: "SFMono-Regular", "Consolas", "Liberation Mono", "Menlo", monospace;
}
.msg-text pre {
  background: rgba(255,255,255,0.06);
  border-radius: 6px;
  padding: 10px 12px;
  margin: 6px 0;
  overflow-x: auto;
  font-size: 0.85em;
}
.msg-text pre code {
  background: none;
  padding: 0;
  border-radius: 0;
  font-size: inherit;
}
.msg-text del { opacity: 0.6; }
.msg-text .msg-header {
  font-weight: 700; margin: 4px 0 2px; line-height: 1.3;
}
.msg-text h1.msg-header { font-size: 1.35em; }
.msg-text h2.msg-header { font-size: 1.2em; }
.msg-text h3.msg-header { font-size: 1.1em; }
.msg-text h4.msg-header { font-size: 1.0em; }
.msg-text h5.msg-header { font-size: 0.95em; }
.msg-text h6.msg-header { font-size: 0.9em; color: var(--text-muted); }
.msg-text table.msg-table {
  border-collapse: collapse;
  margin: 6px 0;
  font-size: 0.92em;
  width: auto;
  max-width: 100%;
  overflow-x: auto;
  display: block;
}
.msg-text .msg-table th,
.msg-text .msg-table td {
  border: 1px solid rgba(255,255,255,0.15);
  padding: 4px 10px;
  text-align: left;
}
.msg-text .msg-table th {
  background: rgba(255,255,255,0.08);
  font-weight: 600;
}
.msg-text .msg-table tr:nth-child(even) td {
  background: rgba(255,255,255,0.03);
}
.msg-mention {
  display: inline-block;
  padding: 0 4px;
  border-radius: 3px;
  background: var(--mention-bg, rgba(31, 111, 235, 0.15));
  color: var(--mention-fg, var(--accent, #1f6feb));
  font-weight: 500;
  text-decoration: none;
}
.msg-mention:hover { text-decoration: underline; }
.msg.mentioned-me { background: var(--mention-row-bg, rgba(31, 111, 235, 0.06)); }

/* Guest lockout banner — shown on the dashboard when an
   expired guest comes back. The cookie still resolves them
   so we know who they are, but writes are blocked at the
   service layer. The banner is the conversion CTA. */
.guest-lockout-banner {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 18px; margin-bottom: 16px;
  border: 1px solid #f0c87a;
  background: #fff8e6;
  color: #5a4400;
  border-radius: var(--radius);
  flex-wrap: wrap;
}
[data-theme="dark"] .guest-lockout-banner {
  background: #2e2510; border-color: #5a4400; color: #f0c87a;
}
.guest-lockout-banner-text { flex: 1; min-width: 220px; font-size: 0.9em; line-height: 1.4; }
.guest-lockout-banner-actions { display: flex; gap: 8px; flex-shrink: 0; }

/* Issue #117 — autolinked URLs and OG preview cards. */
.msg-link {
  color: var(--accent, #1f6feb);
  text-decoration: underline;
  text-decoration-color: rgba(31, 111, 235, 0.4);
  word-break: break-all;
}
.msg-link:hover { text-decoration-color: var(--accent, #1f6feb); }
.msg-link-previews { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.msg-link-preview {
  display: flex; gap: 10px; padding: 8px 10px;
  border: 1px solid var(--border); border-left: 3px solid var(--accent, #1f6feb);
  border-radius: var(--radius); background: var(--surface);
  text-decoration: none; color: var(--text);
  max-width: 480px;
}
.msg-link-preview:hover { background: var(--bg); }
.msg-link-preview-img {
  width: 64px; height: 64px; object-fit: cover; border-radius: 4px;
  flex-shrink: 0; background: var(--border);
}
.msg-link-preview-text { min-width: 0; flex: 1; }
.msg-link-preview-site { font-size: 0.7em; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.msg-link-preview-title { font-size: 0.85em; font-weight: 600; margin: 1px 0 2px; line-height: 1.25; }
.msg-link-preview-desc {
  font-size: 0.78em; color: var(--text-muted); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.msg-link-preview-wrap { position: relative; max-width: 480px; }
.msg-link-preview-dismiss {
  position: absolute; top: 4px; right: 4px;
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface); color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 50%;
  font-size: 0.9em; line-height: 1; cursor: pointer;
  opacity: 0; transition: opacity 0.15s;
}
.msg-link-preview-wrap:hover .msg-link-preview-dismiss { opacity: 1; }
.msg-link-preview-collapsed {
  opacity: 0.55; border-left-color: var(--border);
  padding: 4px 10px; font-size: 0.82em;
}
.msg-link-preview-collapsed .msg-link-preview-title { font-weight: 500; }
.msg-link-preview-collapsed .msg-link-preview-desc { font-style: italic; }
.msg-link-preview-pending { opacity: 0.7; }
.msg-link-preview-pending .msg-link-preview-desc::after {
  content: ""; display: inline-block; width: 8px; height: 8px;
  border-radius: 50%; background: var(--border); margin-left: 4px;
  animation: msgLinkPulse 1s ease-in-out infinite;
}
@keyframes msgLinkPulse { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }

/* @mention autocomplete popover */
.mention-popover {
  position: absolute;
  z-index: 200;
  min-width: 220px;
  max-width: 320px;
  background: var(--surface, #fff);
  border: 1px solid var(--border, #d0d7de);
  border-radius: 6px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  padding: 4px 0;
  font-size: 0.85em;
}
.mention-popover-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  cursor: pointer;
  color: var(--text, #1f2328);
}
.mention-popover-item.active,
.mention-popover-item:hover {
  background: var(--surface-hover, rgba(31, 111, 235, 0.1));
}
.mention-popover-avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.mention-popover-avatar-fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent, #1f6feb);
  color: #fff;
  font-size: 0.7em;
  font-weight: 600;
}
.mention-popover-name { flex: 1; font-weight: 500; }
.mention-popover-handle { color: var(--text-muted, #656d76); font-size: 0.85em; }

/* Cross-room toast: mentioned-you variant */
.toast-item-mention { border-left: 3px solid var(--accent, #1f6feb) !important; }
.toast-mention-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 0.7em;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #fff;
  background: var(--accent, #1f6feb);
  border-radius: 3px;
  vertical-align: middle;
}

/* Custom audio player */
.msg-player { display: flex; align-items: center; gap: 6px; padding: 1px 0; }
.msg-player audio { display: none; }
.mp-play {
  background: none; border: none; cursor: pointer;
  font-size: 0.9em; color: var(--text); padding: 0;
  width: 18px; text-align: center; line-height: 1;
}
.mp-bar { flex: 1; height: 4px; background: var(--border); border-radius: 2px; cursor: pointer; position: relative; }
.mp-progress { height: 100%; background: var(--success); border-radius: 2px; width: 0%; transition: width 0.1s linear; }
.mp-wave { flex: 1; height: 20px; cursor: pointer; min-width: 100px; max-width: 500px; }
.mp-wave > div { width: 100%; }
.mp-time { font-size: 0.7em; color: var(--text-muted); min-width: 28px; text-align: right; }

.msg-transcript { font-size: 0.78em; color: var(--text-muted); font-style: italic; margin-top: 1px; }
.msg-transcript-label { font-size: 0.85em; opacity: 0.7; margin-right: 4px; font-style: normal; }
.msg-tts-label { font-size: 0.72em; color: var(--text-muted); opacity: 0.7; display: block; margin-top: 2px; }
.msg-source-badge { font-size: 0.78em; opacity: 0.7; margin-left: 2px; cursor: help; }
.msg-filter-chip { font-size: 0.7em; background: var(--surface); color: var(--text-muted); padding: 1px 6px; border-radius: 8px; margin-left: 4px; text-transform: uppercase; letter-spacing: 0.05em; }

/* #96 — mobile smart banner */
.smart-banner { position: sticky; top: 0; z-index: 50; background: var(--surface, #161b22); border-bottom: 1px solid var(--border, #30363d); }
.smart-banner-inner { display: flex; align-items: center; gap: 10px; padding: 8px 12px; max-width: 640px; margin: 0 auto; }
.smart-banner-icon { width: 34px; height: 34px; flex: none; }
.smart-banner-text { flex: 1; line-height: 1.2; }
.smart-banner-title { font-weight: 600; font-size: 14px; }
.smart-banner-subtitle { font-size: 12px; color: var(--text-muted, #7d8590); }
.smart-banner-cta { padding: 6px 12px; font-size: 13px; }
.smart-banner-close { background: none; border: 0; color: var(--text-muted, #7d8590); font-size: 20px; line-height: 1; padding: 4px 8px; cursor: pointer; }

/* #199 — site-wide alert banner + click-through modal. Severity
   variants tint a left-border accent and the leading icon; everything
   else inherits the design-system palette so light/dark themes adapt. */
.site-alert-banner {
  position: sticky;
  top: 0;
  z-index: 49;
  display: flex;
  align-items: stretch;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  border-left: 4px solid var(--text-muted);
}
.site-alert-banner--info     { border-left-color: var(--btn-secondary, #7d8590); }
.site-alert-banner--warning  { border-left-color: #d97706; }
.site-alert-banner--critical { border-left-color: var(--danger, #b00); background: color-mix(in srgb, var(--danger) 8%, var(--surface)); }
.site-alert-banner-body {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: none;
  border: 0;
  text-align: left;
  font: inherit;
  color: var(--text);
  cursor: pointer;
}
.site-alert-banner-body[disabled] { cursor: default; }
.site-alert-banner-body:hover:not([disabled]) { background: color-mix(in srgb, var(--text) 4%, transparent); }
.site-alert-banner-icon {
  font-size: 18px;
  line-height: 1;
  flex: none;
  color: var(--text-muted);
}
.site-alert-banner--warning  .site-alert-banner-icon { color: #d97706; }
.site-alert-banner--critical .site-alert-banner-icon { color: var(--danger, #b00); }
.site-alert-banner-text { flex: 1; line-height: 1.35; font-size: 14px; }
.site-alert-banner-cta { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.site-alert-banner-close {
  background: none;
  border: 0;
  color: var(--text-muted);
  font-size: 22px;
  line-height: 1;
  padding: 4px 12px;
  cursor: pointer;
}
.site-alert-banner-close:hover { color: var(--text); }

.site-alert-modal { max-width: 640px; padding: 0; border: 1px solid var(--border); border-radius: 10px; }
.site-alert-modal-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  background: var(--surface);
}
.site-alert-modal-header strong { flex: 1; font-size: 15px; }
.site-alert-modal-header--warning  { border-bottom-color: #d97706; }
.site-alert-modal-header--critical { border-bottom-color: var(--danger, #b00); }
.site-alert-modal-close {
  background: none;
  border: 0;
  color: var(--text-muted);
  font-size: 22px;
  line-height: 1;
  padding: 0 4px;
  cursor: pointer;
}
.site-alert-modal-body { padding: 16px 18px; max-height: 60vh; overflow-y: auto; line-height: 1.55; font-size: 14px; }
.site-alert-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 18px;
  border-top: 1px solid var(--border);
  background: var(--bg);
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
}

/* #48 — room webhooks section */
.room-webhooks-list { list-style: none; padding: 0; margin: 8px 0; }
.room-webhooks-row { border: 1px solid var(--border, #30363d); border-radius: 6px; padding: 8px 10px; margin-bottom: 6px; }
.room-webhooks-url code { font-size: 12px; word-break: break-all; }
.room-webhooks-meta { font-size: 11px; color: var(--text-muted, #7d8590); margin-top: 2px; display: flex; gap: 6px; flex-wrap: wrap; }
.room-webhooks-meta .chip { background: var(--surface, #161b22); padding: 1px 6px; border-radius: 10px; }
.room-webhooks-meta .chip-muted { opacity: 0.6; }
.room-webhooks-actions { display: flex; gap: 4px; margin-top: 6px; flex-wrap: wrap; }
.room-webhooks-actions .btn-xs { padding: 2px 8px; font-size: 11px; }
.room-webhooks-empty { color: var(--text-muted, #7d8590); font-style: italic; font-size: 12px; }
.room-webhooks-form { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border, #30363d); }
.room-webhooks-form-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.room-webhooks-form-row label { font-size: 12px; color: var(--text-muted, #7d8590); }

/* #92 — listener mode feed */
.listen-status { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: #ef4444; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; }
.listen-live-dot { width: 8px; height: 8px; border-radius: 50%; background: #ef4444; animation: pulse-listen 1.5s ease-in-out infinite; }
@keyframes pulse-listen { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
.listen-feed { display: flex; flex-direction: column; gap: 14px; margin-top: 12px; }
.listen-row { border-top: 1px solid var(--border, #30363d); padding-top: 12px; }
.listen-row:first-child { border-top: 0; padding-top: 0; }
.listen-row-header { display: flex; justify-content: space-between; margin-bottom: 4px; font-size: 14px; }
.listen-row-time { color: var(--text-muted, #7d8590); font-size: 12px; }

/* #91 — public clip page */
.clip-body { background: var(--bg, #0d1117); color: var(--text, #e6edf3); min-height: 100vh; margin: 0; }
.clip-page { max-width: 540px; margin: 0 auto; padding: 40px 20px; font-family: -apple-system, system-ui, sans-serif; }
.clip-brand { margin-bottom: 32px; }
.clip-logo { font-size: 24px; font-weight: 700; text-decoration: none; color: var(--accent, #1f6feb); }
.clip-card { background: var(--surface, #161b22); border: 1px solid var(--border, #30363d); border-radius: 12px; padding: 24px; margin-bottom: 24px; }
.clip-sender { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.clip-avatar { width: 44px; height: 44px; border-radius: 50%; background: var(--accent, #1f6feb); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; }
.clip-sender-name { font-weight: 600; font-size: 16px; }
.clip-timestamp { font-size: 12px; color: var(--text-muted, #7d8590); }
.clip-audio { width: 100%; margin: 12px 0; }
.clip-transcript { font-style: italic; color: var(--text-muted, #7d8590); border-left: 3px solid var(--accent, #1f6feb); padding: 8px 12px; margin: 12px 0 0; }
.clip-empty { color: var(--text-muted, #7d8590); font-style: italic; }
.clip-cta { text-align: center; margin-top: 32px; }
.clip-cta .btn { padding: 12px 28px; font-size: 16px; }
.clip-cta-hint { font-size: 12px; color: var(--text-muted, #7d8590); margin-top: 8px; }

/* Reactions */
.msg-reactions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.msg-reaction-pill {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 7px; font-size: 0.8em; background: var(--surface);
  border-radius: 10px; border: 1px solid var(--border);
}
.msg-reaction-pill .rp-name { font-size: 0.8em; color: var(--text-muted); }
.msg-quote {
  font-size: 0.78em; color: var(--text-muted);
  border-left: 2px solid var(--border); padding: 1px 8px;
  margin-bottom: 3px; font-style: italic;
}
.msg-actions-wrap { position: absolute; top: 2px; right: 2px; }
.msg-actions-btn {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 4px; cursor: pointer; font-size: 0.7em;
  padding: 1px 5px; color: var(--text-muted);
  opacity: 0; transition: opacity 0.1s; line-height: 1;
}
.msg:hover .msg-actions-btn { opacity: 1; }
.msg-actions-menu {
  display: none; position: absolute; right: 0; top: 100%; z-index: 100;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 4px 12px rgba(0,0,0,0.12); padding: 6px; min-width: 180px;
}
/* Flipped upward when the button is too close to the bottom of the
   scroll container — see toggleMsgActions() in vroxy_controller.js. */
.msg-actions-menu.up { top: auto; bottom: 100%; }
.msg-actions-menu.open { display: block; }
.msg-actions-emojis { display: flex; gap: 2px; margin-bottom: 6px; }
.msg-actions-emojis button {
  background: none; border: none; cursor: pointer;
  font-size: 1.2em; padding: 4px 6px; border-radius: 4px;
}
.msg-actions-emojis button:hover { background: var(--surface); }
.msg-actions-menu-item {
  display: block; width: 100%; text-align: left; background: none; border: none;
  cursor: pointer; padding: 6px 8px; font-size: 0.85em;
  color: var(--text); border-radius: 4px;
}
.msg-actions-menu-item:hover { background: var(--surface); }
.msg-actions-menu-item.danger { color: var(--danger); }

/* Text input bar */
.room-input-bar {
  display: flex; gap: 8px; padding: 6px 16px; align-items: center;
  border-top: 1px solid var(--border); flex-shrink: 0;
}
.room-input-bar input[type="text"] { flex: 1; padding: 6px 10px; font-size: 0.88em; margin: 0; }
.room-input-bar .btn { padding: 6px 14px; flex-shrink: 0; }
.reply-preview {
  display: none; padding: 4px 16px; background: var(--surface);
  border-top: 1px solid var(--border); font-size: 0.78em;
  color: var(--text-muted); align-items: center; gap: 8px; flex-shrink: 0;
}
.reply-preview.active { display: flex; }
.reply-preview-text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: italic; }
.reply-preview-close { background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 1em; padding: 2px; }

/* Bottom: PTT */
.ptt-section {
  flex-shrink: 0; border-top: 2px solid var(--border); background: var(--surface);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 12px 16px; gap: 8px; min-height: 180px;
  position: relative; /* anchor for the corner mic-picker */
}

/* Mic picker — small icon button anchored to the top-right corner of the
   PTT section. The current device label lives in the title attribute so
   it doesn't take up visual space. Click toggles a popover menu listing
   available input devices. */
.mic-picker { position: absolute; top: 8px; right: 8px; z-index: 5; }
.mic-picker-btn {
  background: var(--bg); border: 1px solid var(--border);
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0; font-size: 0.95em;
  color: var(--text-muted);
  transition: color 0.15s, border-color 0.15s;
}
.mic-picker-btn:hover { color: var(--text); border-color: var(--text-muted); }
.mic-picker-menu {
  position: absolute; top: 100%; right: 0; margin-top: 4px;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: 0 4px 12px rgba(0,0,0,0.12);
  list-style: none; padding: 4px; margin: 4px 0 0;
  min-width: 200px; max-width: 280px;
  font-size: 0.82em;
}
.mic-picker-menu[hidden] { display: none; }
.mic-picker-item {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 8px; border-radius: 4px; cursor: pointer;
  color: var(--text);
}
.mic-picker-item:hover { background: var(--surface); }
.mic-picker-item.selected { font-weight: 600; }
.mic-picker-check {
  width: 14px; flex-shrink: 0; text-align: center;
  color: var(--success); font-size: 0.9em;
}
.mic-picker-label {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mic-picker-empty {
  padding: 8px 10px; color: var(--text-muted); font-style: italic;
}
.ptt-big {
  width: 100px; height: 100px; border-radius: 50%; background: var(--btn); color: #fff;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; user-select: none; -webkit-user-select: none;
  transition: all 0.12s ease; box-shadow: 0 3px 12px rgba(0,0,0,0.2);
  font-size: 0.7em; font-weight: 700; border: none; letter-spacing: 0.5px;
}
.ptt-big:active, .ptt-big.recording {
  background: var(--danger); transform: scale(1.06);
  box-shadow: 0 3px 20px rgba(220,53,69,0.45);
}
.ptt-big.sleeping { background: var(--text-muted); opacity: 0.65; }
.ptt-big.sleeping:active { background: var(--btn); opacity: 1; }
.ptt-status-main { font-size: 0.78em; color: var(--text-muted); }
.now-playing { font-size: 0.78em; color: var(--success); font-weight: 600; min-height: 16px; }
.ptt-bottom-row { display: flex; align-items: center; gap: 12px; }
.ptt-waveform-main {
  border-radius: 6px; background: var(--bg);
  border: 1px solid var(--border); width: 180px; height: 32px;
}
.autoplay-toggle {
  font-size: 0.75em; color: var(--text-muted);
  display: flex; align-items: center; gap: 4px; cursor: pointer;
}
.autoplay-toggle input { width: auto; }
.playback-speed-select {
  font-size: 0.75em;
  color: var(--text-muted);
  background: var(--surface, #fff);
  border: 1px solid var(--border, #d0d7de);
  border-radius: 4px;
  padding: 1px 4px;
  cursor: pointer;
  height: 22px;
}

/* Toast (in-room) */
.toast-msg {
  position: fixed; bottom: 200px; left: 50%; transform: translateX(-50%);
  background: #333; color: #fff; padding: 8px 20px; border-radius: 20px;
  font-size: 0.85em; opacity: 0; transition: opacity 0.3s;
  pointer-events: none; z-index: 900;
}
.toast-msg.show { opacity: 0.9; }

/* Modals */
.modal-overlay {
  display: none; position: fixed; inset: 0;
  background: rgba(0,0,0,0.4); z-index: 1000;
  justify-content: center; align-items: center;
}
.modal-overlay.open { display: flex; }
.modal-box {
  background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 24px;
  width: 92%; max-width: 720px; max-height: 85vh; overflow-y: auto;
}
.modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.modal-close-btn { background: none; border: none; cursor: pointer; font-size: 1.2em; color: var(--text-muted); }
.modal-section { margin-bottom: 20px; }
.modal-section-label { font-weight: 600; margin-bottom: 8px; }
.modal-share-row { display: flex; gap: 6px; align-items: center; }
.modal-share-input { flex: 1; font-size: 0.85em; padding: 6px 10px; background: var(--surface); }
.modal-room-code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 1.15em; font-weight: 700; letter-spacing: 0.15em; text-align: center; text-transform: uppercase; }
.modal-qr-wrap { text-align: center; margin-top: 12px; }
.modal-qr-img { width: 140px; height: 140px; border-radius: var(--radius); border: 1px solid var(--border); }
.modal-members-list { font-size: 0.85em; color: var(--text-muted); }
.modal-member { padding: 3px 0; }
.modal-member-owner { opacity: 0.5; }
.modal-invite-form { display: flex; gap: 8px; }
.modal-section-help { font-size: 0.78em; color: var(--text-muted); margin: -4px 0 8px; }
.modal-agent-list { display: flex; flex-direction: column; gap: 6px; }
.modal-agent-row { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.modal-agent-avatar { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.modal-agent-avatar-fallback { display: inline-flex; align-items: center; justify-content: center; background: var(--accent, #1f6feb); color: #fff; font-size: 0.72em; font-weight: 600; }
.modal-agent-meta { flex: 1; min-width: 0; }
.modal-agent-name { font-size: 0.88em; font-weight: 500; color: var(--text); }
.modal-agent-tagline { font-size: 0.74em; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.modal-danger-zone { padding-top: 16px; border-top: 1px solid var(--border); }

/* Share modal — invite by friend search */
.share-friend-filter { width: 100%; margin-bottom: 8px; }
.share-friend-list {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 240px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 6px; background: var(--surface);
}
.share-friend-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 8px; border-radius: var(--radius);
}
.share-friend-row:hover { background: var(--bg); }
.share-friend-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.share-friend-avatar-fallback {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent, #1f6feb); color: #fff;
  font-size: 0.7em; font-weight: 600;
}
.share-friend-name { flex: 1; min-width: 0; font-size: 0.88em; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.share-friend-name small { color: var(--text-muted); margin-left: 4px; }
.share-friend-empty { font-size: 0.82em; color: var(--text-muted); padding: 8px; text-align: center; }

/* Dashboard pending room invites */
.room-invites-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 24px; }
.room-invite-card {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 12px 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.room-invite-meta { display: flex; align-items: center; gap: 12px; min-width: 0; flex: 1; }
.room-invite-icon { font-size: 1.4em; flex-shrink: 0; }
.room-invite-text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.room-invite-text strong { font-size: 0.95em; color: var(--text); }
.room-invite-text small { font-size: 0.78em; color: var(--text-muted); }
.room-invite-topic { font-style: italic; }
.room-invite-actions { display: flex; gap: 6px; flex-shrink: 0; }
.room-invite-actions form { margin: 0; }
.modal-room-settings { margin-bottom: 20px; padding-top: 16px; border-top: 1px solid var(--border); }

@media (max-width: 767px) {
  .sidebar { display: none; }
  .sidebar.mobile-open {
    display: flex; position: fixed; left: 0; top: 49px; bottom: 0;
    z-index: 500; width: 260px; box-shadow: 4px 0 12px rgba(0,0,0,0.15);
  }
  .mobile-overlay {
    display: none; position: fixed; inset: 0; top: 49px;
    background: rgba(0,0,0,0.3); z-index: 499;
  }
  .mobile-overlay.open { display: block; }
  .ptt-section { min-height: 150px; padding: 10px; }
  .ptt-big { width: 80px; height: 80px; font-size: 0.6em; }
  .ptt-waveform-main { width: 120px; height: 28px; }
}


/* #159 — Global footer. Hidden on rooms#show via `show_site_footer?`. */
.site-footer {
  margin-top: 48px;
  padding: 32px 20px 16px;
  background: var(--surface);
  border-top: 1px solid var(--border);
  color: var(--text);
}
.site-footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.2fr 2fr;
  gap: 32px;
}
.site-footer-brand-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
}
.site-footer-logo { width: 22px; height: 22px; }
.site-footer-tagline {
  margin: 8px 0 0;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.5;
  max-width: 320px;
}
.site-footer-nav {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}
.site-footer-col h4 {
  margin: 0 0 8px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  font-weight: 600;
}
.site-footer-col ul { list-style: none; padding: 0; margin: 0; }
.site-footer-col li { margin: 4px 0; }
.site-footer-col a {
  color: var(--text);
  text-decoration: none;
  font-size: 14px;
}
.site-footer-col a:hover { text-decoration: underline; }
.site-footer-meta {
  max-width: 1100px;
  margin: 24px auto 0;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  color: var(--text-muted);
  font-size: 12px;
}
@media (max-width: 640px) {
  .site-footer-inner { grid-template-columns: 1fr; }
  .site-footer-nav { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Slim footer variant — toggled by the `slim_footer` brand flag.
   Single row, transparent, just brand + Legal links. Pinned to the
   viewport bottom on short pages via the body flex column above. */
.site-footer-slim {
  margin-top: 0;
  padding: 12px 20px;
  background: transparent;
  flex-shrink: 0;
}
.site-footer-slim .site-footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.site-footer-slim .site-footer-nav { display: flex; gap: 18px; }
.site-footer-slim .site-footer-col h4 { display: none; }
.site-footer-slim .site-footer-col ul {
  display: flex; gap: 14px; margin: 0;
}
.site-footer-slim .site-footer-col li { margin: 0; }
.site-footer-slim .site-footer-col a { font-size: 12px; color: var(--text-muted); }
.site-footer-slim .site-footer-meta {
  margin: 4px auto 0;
  padding-top: 0;
  border-top: 0;
  font-size: 11px;
  opacity: 0.7;
}


/* #162 — branded error pages */
.error-page {
  min-height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
}
.error-page-inner {
  max-width: 520px;
  text-align: center;
}
.error-page-code {
  font-size: 84px;
  font-weight: 700;
  line-height: 1;
  color: var(--text-muted);
  letter-spacing: -0.02em;
  margin-bottom: 12px;
}
.error-page-headline {
  font-size: 22px;
  margin: 0 0 8px;
  color: var(--text);
}
.error-page-body {
  color: var(--text-muted);
  margin: 0 0 24px;
}
.error-page-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
}
.error-page-btn {
  display: inline-block;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  text-decoration: none;
  font-size: 14px;
  background: var(--surface);
}
.error-page-btn:hover { background: var(--bg); }
.error-page-btn-primary {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}
.error-page-btn-primary:hover { opacity: 0.9; background: var(--text); }

/* ───────── Support chat widget (#260) ─────────
   Floating persistent chat launcher + panel.  Kept self-contained
   (single `.sc-*` prefix) so the same CSS ships identically in
   admin.css without collisions.  No Bootstrap classes — this widget
   must render on both the semantic-CSS public layout and the
   Bootstrap-only admin layout. */
.sc-widget {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 2147483000; /* above app-version-badge (which has pointer-events:none) */
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
  color: var(--text, #222);
}
.sc-launcher {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 0;
  background: var(--btn, #333);
  color: #fff;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0,0,0,.2);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .15s ease;
}
.sc-launcher:hover { transform: scale(1.05); }
.sc-launcher-icon { font-size: 22px; line-height: 1; }

.sc-panel {
  display: none;
  position: absolute;
  right: 0;
  bottom: 64px;
  width: 360px;
  max-width: calc(100vw - 40px);
  height: 520px;
  max-height: calc(100vh - 100px);
  background: var(--bg, #fff);
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 12px;
  box-shadow: 0 12px 40px rgba(0,0,0,.25);
  flex-direction: column;
  overflow: hidden;
}
.sc-widget.sc-open .sc-panel { display: flex; }

/* Drag-to-resize handle at the top-left of the panel. Panel is
   anchored bottom-right so dragging up + left grows the widget.
   Semi-transparent so it doesn't visually compete with the
   header, but hits are generous (14×14) so it's easy to grab. */
.sc-resize {
  position: absolute;
  top: 0;
  left: 0;
  width: 14px;
  height: 14px;
  cursor: nwse-resize;
  z-index: 2;
  background: transparent;
  touch-action: none;
}
.sc-resize::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 6px;
  height: 6px;
  border-top:  2px solid var(--border, #cfd4dc);
  border-left: 2px solid var(--border, #cfd4dc);
  border-top-left-radius: 3px;
  opacity: .7;
}
.sc-resize:hover::before { opacity: 1; }
.sc-widget.sc-resizing { user-select: none; }
.sc-widget.sc-resizing .sc-panel { transition: none; }

.sc-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border, #e0e0e0);
  background: var(--surface, #f8f8f8);
}
.sc-title { font-weight: 600; }
.sc-header-actions { display: flex; gap: 6px; }
.sc-header-actions button {
  background: transparent;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 2px 8px;
  cursor: pointer;
  color: inherit;
  font-size: 13px;
  line-height: 1.4;
}
.sc-header-actions button:hover { background: var(--bg, #fff); }
.sc-close { border: 0 !important; font-size: 20px !important; padding: 0 8px !important; }

.sc-log {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--bg, #fff);
}
.sc-msg { display: flex; }
.sc-msg-user { justify-content: flex-end; }
.sc-msg-assistant { justify-content: flex-start; }
.sc-bubble {
  max-width: 85%;
  padding: 8px 10px;
  border-radius: 12px;
  white-space: pre-wrap;
  word-wrap: break-word;
  line-height: 1.45;
}
.sc-msg-user .sc-bubble {
  background: var(--btn, #333);
  color: #fff;
  border-bottom-right-radius: 4px;
}
.sc-msg-assistant .sc-bubble {
  background: var(--surface, #f0f0f0);
  color: var(--text, #222);
  border-bottom-left-radius: 4px;
}

.sc-status {
  min-height: 18px;
  padding: 0 12px;
  font-size: 12px;
  color: var(--text-muted, #666);
}

.sc-form {
  display: flex;
  gap: 6px;
  padding: 8px;
  border-top: 1px solid var(--border, #e0e0e0);
  background: var(--surface, #f8f8f8);
}
.sc-input {
  flex: 1;
  resize: none;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 8px;
  padding: 8px;
  font: inherit;
  color: inherit;
  background: var(--bg, #fff);
}
.sc-send {
  background: var(--btn, #333);
  color: #fff;
  border: 0;
  border-radius: 8px;
  padding: 0 14px;
  cursor: pointer;
  font-weight: 600;
}
.sc-send:disabled { opacity: .5; cursor: default; }

@media (max-width: 480px) {
  .sc-widget { right: 12px; bottom: 12px; }
  .sc-panel { width: calc(100vw - 24px); height: calc(100vh - 100px); }
}

/* ─ Support chat: AFK banner + rating panel + ended notice (#260) ─ */
.sc-afk {
  padding: 8px 12px;
  background: color-mix(in srgb, var(--danger, #b00) 15%, var(--surface, #fff));
  border-bottom: 1px solid var(--border, #e0e0e0);
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.sc-afk-text { flex: 1; }
.sc-afk-actions { display: flex; gap: 6px; }
.sc-afk-actions button {
  border: 1px solid var(--border, #e0e0e0);
  background: var(--bg, #fff);
  border-radius: 6px;
  padding: 3px 8px;
  cursor: pointer;
  font-size: 12px;
  color: inherit;
}
.sc-afk-actions .sc-afk-end {
  background: var(--danger, #b00);
  color: #fff;
  border-color: var(--danger, #b00);
}

.sc-rating {
  padding: 12px;
  border-top: 1px solid var(--border, #e0e0e0);
  background: var(--surface, #f8f8f8);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sc-rating-prompt { font-weight: 600; }
.sc-rating-stars { display: flex; gap: 4px; }
.sc-star {
  background: transparent;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  width: 34px;
  height: 34px;
  cursor: pointer;
  font-size: 18px;
  color: var(--text-muted, #999);
  line-height: 1;
}
.sc-star.sc-star-on { color: #f5b301; border-color: #f5b301; background: color-mix(in srgb, #f5b301 15%, transparent); }
.sc-rating-comment {
  resize: none;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 6px;
  font: inherit;
  background: var(--bg, #fff);
  color: inherit;
}
.sc-rating-actions { display: flex; justify-content: flex-end; gap: 6px; }
.sc-rating-actions button {
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  background: var(--bg, #fff);
  padding: 4px 10px;
  cursor: pointer;
  color: inherit;
}
.sc-rating-actions .sc-rating-submit {
  background: var(--btn, #333);
  color: #fff;
  border-color: var(--btn, #333);
}
.sc-rating-actions .sc-rating-submit:disabled { opacity: .5; cursor: default; }

.sc-ended-notice {
  align-self: center;
  padding: 10px 0;
  color: var(--text-muted, #666);
  font-size: 13px;
  text-align: center;
}
.sc-start-new {
  border: 1px solid var(--border, #e0e0e0);
  background: var(--bg, #fff);
  border-radius: 6px;
  padding: 3px 10px;
  cursor: pointer;
  color: inherit;
  margin-left: 6px;
}

/* ─ Support chat tool-invocation chip (admin-only, #260) ─ */
.sc-tool-chip {
  align-self: center;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 12px;
  background: color-mix(in srgb, #6f42c1 12%, var(--surface, #f0f0f0));
  border: 1px solid color-mix(in srgb, #6f42c1 25%, var(--border, #ccc));
  font-size: 12px;
  max-width: 95%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sc-tool-chip.sc-tool-error {
  background: color-mix(in srgb, var(--danger, #b00) 12%, var(--surface, #f0f0f0));
  border-color: color-mix(in srgb, var(--danger, #b00) 30%, var(--border, #ccc));
}
.sc-tool-chip .sc-tool-icon { font-size: 13px; }
.sc-tool-chip .sc-tool-name { font-family: ui-monospace, monospace; font-size: 11px; opacity: .85; }
.sc-tool-chip .sc-tool-arrow { opacity: .5; }
.sc-tool-chip .sc-tool-result { font-weight: 600; }

/* #260 — when the chat is ended the send form must actually go away.
   The `hidden` HTML attribute is defeated by `.sc-form { display: flex }`
   above; this rule wins because it's more specific + comes later. */
.sc-widget.sc-ended .sc-form { display: none !important; }

/* ───────── Admin UI Inspector (#260) ─────────
   Only rendered when cuog.admin?  Floating 🎯 launcher, crosshair
   inspect mode, hover-outline that follows the pointer, note panel
   anchored near the click.  Prefix `aui-` so nothing collides with
   the support-chat widget's `sc-` styles. */
/* #260 — The launcher moved into the support-chat header; the
   inspector root exists only to host the fixed-position overlays
   (hover outline, cancel chip, note panel) which each own their
   layout.  `display: contents` collapses the container to zero
   layout impact so it doesn't sit in the bottom-right catching
   clicks. */
.aui-widget {
  display: contents;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 14px;
}

/* Inspect-mode global cursor + block text-select while picking.
   IMPORTANT: an earlier revision set `pointer-events: none` on
   links / buttons / inputs during inspect mode to "avoid triggering
   normal UI".  That silently ate click events entirely and the
   picker's capture-phase listener never fired.  We now rely on the
   capture-phase handler in admin_ui_inspector.js to call
   preventDefault + stopPropagation, which blocks the target's
   default action WITHOUT blocking the click event itself.  Do NOT
   re-add pointer-events: none here. */
html.aui-inspecting, html.aui-inspecting * { cursor: crosshair !important; user-select: none !important; }

/* Hover outline — fixed positioned; JS updates transform+size. */
.aui-hover-outline {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  outline: 2px solid #6f42c1;
  outline-offset: 0;
  background: rgba(111, 66, 193, .1);
  z-index: 2147482999;
  transition: transform .05s linear, width .05s linear, height .05s linear;
}

.aui-cancel-chip {
  position: fixed;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  background: #212529;
  color: #fff;
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 13px;
  z-index: 2147483001;
  box-shadow: 0 3px 10px rgba(0,0,0,.3);
}
.aui-cancel-chip .aui-cancel {
  background: transparent;
  color: #fff;
  border: 0;
  text-decoration: underline;
  cursor: pointer;
  padding: 0 4px;
}
.aui-cancel-chip .aui-hint { opacity: .6; font-size: 11px; margin-left: 4px; }

/* Note-composer panel — position:fixed; JS sets left/top per click. */
.aui-note-panel {
  position: fixed;
  width: 340px;
  max-width: calc(100vw - 24px);
  background: var(--bg, #fff);
  color: var(--text, #222);
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 10px;
  box-shadow: 0 10px 32px rgba(0,0,0,.25);
  z-index: 2147483002;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.aui-note-header { display: flex; justify-content: space-between; align-items: center; }
.aui-note-close { background: transparent; border: 0; font-size: 18px; cursor: pointer; color: inherit; }
.aui-note-target {
  background: var(--surface, #f8f8f8);
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 12px;
}
.aui-note-target-line { margin: 2px 0; word-break: break-all; }
.aui-note-target-tag {
  display: inline-block;
  background: #6f42c1;
  color: #fff;
  border-radius: 3px;
  padding: 0 4px;
  font-family: ui-monospace, monospace;
  margin-right: 4px;
}
.aui-note-target-preview { color: var(--text-muted, #666); font-style: italic; }
.aui-note-target-template { color: var(--text-muted, #666); font-family: ui-monospace, monospace; font-size: 11px; }
.aui-note-text {
  width: 100%;
  resize: vertical;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 6px 8px;
  font: inherit;
  background: var(--bg, #fff);
  color: inherit;
}
.aui-note-actions { display: flex; justify-content: flex-end; gap: 6px; }
.aui-note-actions button {
  border: 1px solid var(--border, #e0e0e0);
  background: var(--bg, #fff);
  border-radius: 6px;
  padding: 4px 12px;
  cursor: pointer;
  color: inherit;
}
.aui-note-actions .aui-note-submit {
  background: #6f42c1;
  color: #fff;
  border-color: #6f42c1;
  font-weight: 600;
}
.aui-note-actions .aui-note-submit:disabled { opacity: .5; cursor: default; }

.aui-flash {
  position: fixed;
  top: 20px;
  right: 20px;
  background: #198754;
  color: #fff;
  padding: 8px 14px;
  border-radius: 6px;
  z-index: 2147483003;
  font-size: 13px;
  box-shadow: 0 3px 10px rgba(0,0,0,.2);
  animation: aui-fade .3s;
}
@keyframes aui-fade { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

/* #260 — admin-only inspector launcher inside the support-chat
   header.  Same visual shape as `.sc-clear` above so it sits in the
   header actions row cleanly. */
.sc-inspect {
  background: transparent;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 2px 8px;
  cursor: pointer;
  color: inherit;
  font-size: 13px;
  line-height: 1.4;
}
.sc-inspect[aria-pressed="true"] { background: #6f42c1; color: #fff; border-color: #6f42c1; }

/* #260 — the HTML `hidden` attribute is defeated by any explicit
   `display` in the more-specific class rule below (`.aui-note-panel
   { display: flex }` etc).  These overrides restore `hidden` for
   the three panels that (a) render conditionally and (b) set an
   explicit display.  Same class of bug we hit earlier on `.sc-form`
   (the ended-chat form regression).  Do NOT rely on `hidden` alone
   with a `display: flex` sibling rule — either add a matching
   [hidden] override here, or toggle a visibility class in JS. */
.aui-note-panel[hidden],
.aui-note-target[hidden],
.sc-feedback-menu[hidden],
.sc-rating[hidden],
.sc-afk[hidden] { display: none !important; }

/* #260 — screenshot attach UI inside the UI-feedback note panel. */
.aui-attach-row { display: flex; align-items: center; gap: 6px; }
.aui-attach {
  background: transparent;
  border: 1px dashed var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 4px 10px;
  cursor: pointer;
  color: inherit;
  font-size: 12px;
}
.aui-attach-hint { color: var(--text-muted, #666); font-size: 11px; }
.aui-thumbs { display: flex; flex-wrap: wrap; gap: 6px; }
.aui-thumb {
  position: relative;
  width: 60px;
  height: 60px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--border, #e0e0e0);
}
.aui-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.aui-thumb-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  background: rgba(0, 0, 0, .6);
  color: #fff;
  border: 0;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  cursor: pointer;
  line-height: 1;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* #260 — support-chat image attachments (paste + drag-drop). */
.sc-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 4px 8px 0 8px;
}
.sc-thumbs:empty { padding: 0; }
.sc-thumb {
  position: relative;
  width: 56px;
  height: 56px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--border, #e0e0e0);
}
.sc-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sc-thumb-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  background: rgba(0, 0, 0, .6);
  color: #fff;
  border: 0;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  cursor: pointer;
  line-height: 1;
  font-size: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Inline preview of images the user just sent, appears above the
   assistant reply.  Thumbnails only — the transcript admin view
   is where full-size images live. */
.sc-msg-images {
  display: flex;
  gap: 4px;
  padding: 0 10px;
  justify-content: flex-end;
}
.sc-msg-images img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--border, #e0e0e0);
}

/* Drop-zone overlay — covers the entire chat panel while a drag
   is active.  pointer-events: none by default so it doesn't block
   the input; activated via `.sc-dragover` on the panel. */
.sc-dropzone {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--btn, #333) 12%, transparent);
  border: 2px dashed color-mix(in srgb, var(--btn, #333) 40%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity .1s ease;
  z-index: 2;
  color: var(--btn, #333);
  font-weight: 600;
}
.sc-panel.sc-dragover .sc-dropzone { opacity: 1; }

/* #260 — feedback launcher (💡) + menu inside chat header. */
.sc-feedback-wrap { position: relative; }
.sc-feedback {
  background: transparent;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 2px 8px;
  cursor: pointer;
  color: inherit;
  font-size: 13px;
  line-height: 1.4;
}
.sc-feedback[aria-expanded="true"] {
  background: #ffc107;
  border-color: #ffc107;
  color: #212529;
}
.sc-feedback-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 200px;
  background: var(--bg, #fff);
  color: var(--text, #222);
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0,0,0,.18);
  padding: 4px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sc-feedback-menu-item {
  background: transparent;
  border: 0;
  text-align: left;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  color: inherit;
  font-size: 13px;
}
.sc-feedback-menu-item:hover { background: var(--surface, #f5f5f5); }

/* #260 — capture button style in the note panel. */
.aui-capture {
  background: transparent;
  border: 1px dashed var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 4px 10px;
  cursor: pointer;
  color: inherit;
  font-size: 12px;
}
.aui-capture:disabled { opacity: .5; cursor: default; }

/* #260 — code-proposal card rendered under an assistant bubble
   when vroxy_dispatch replies with a structured proposal. */
.sc-proposal {
  margin-top: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 8px;
  background: var(--surface, #fafafa);
  font-size: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.sc-proposal-header { display: flex; align-items: center; gap: 6px; }
.sc-proposal-badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 3px;
  background: #6f42c1;
  color: #fff;
  font-size: 10px;
  text-transform: uppercase;
}
.sc-proposal[data-proposal-mode="pull_request"] .sc-proposal-badge { background: #0d6efd; }
/* Summary is now a top-level child of .sc-proposal (which is
   `display: flex; flex-direction: column`), so it takes the full
   card width and wraps long text onto multiple lines instead of
   being pinched inside a flex row between the badge + state chip. */
.sc-proposal-summary {
  font-size: 12px;
  line-height: 1.35;
  word-break: break-word;
}
.sc-proposal-state {
  padding: 1px 6px;
  border-radius: 3px;
  background: #ffc107;
  color: #212529;
  font-size: 10px;
}
.sc-proposal-state-rejected  { background: #dc3545; color: #fff; }
.sc-proposal-state-shipped   { background: #198754; color: #fff; }
.sc-proposal-files summary { cursor: pointer; color: var(--text-muted, #666); }
.sc-proposal-files ul { margin: 4px 0 0 0; padding-left: 20px; }
.sc-proposal-files code { font-size: 11px; }
.sc-proposal-notes { font-style: italic; color: var(--text-muted, #666); }
.sc-proposal-actions { display: flex; gap: 4px; flex-wrap: wrap; }
.sc-proposal-actions button {
  border: 1px solid var(--border, #e0e0e0);
  background: var(--bg, #fff);
  border-radius: 6px;
  padding: 3px 8px;
  cursor: pointer;
  color: inherit;
  font-size: 11px;
}
.sc-proposal-actions .sc-proposal-ship { background: #198754; color: #fff; border-color: #198754; }
.sc-proposal-actions .sc-proposal-reject { color: #dc3545; }
.sc-proposal.sc-proposal-previewing .sc-proposal-preview { background: #6f42c1; color: #fff; }

/* #260 — Resume-a-topic dropdown (support-chat header). */
.sc-topics-wrap { position: relative; display: inline-block; }
.sc-topics-toggle {
  background: transparent;
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 6px;
  padding: 2px 8px;
  cursor: pointer;
  color: inherit;
  font-size: 13px;
  line-height: 1.4;
}
.sc-topics-toggle[aria-expanded="true"] { background: var(--surface, #f5f5f5); }
.sc-topics-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 240px;
  max-width: 320px;
  max-height: 340px;
  overflow: auto;
  background: var(--bg, #fff);
  color: var(--text, #222);
  border: 1px solid var(--border, #e0e0e0);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0,0,0,.18);
  padding: 4px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sc-topics-new {
  background: transparent;
  border: 0;
  text-align: left;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  color: inherit;
  font-size: 13px;
  font-weight: 600;
}
.sc-topics-new:hover { background: var(--surface, #f5f5f5); }
.sc-topics-list { display: flex; flex-direction: column; gap: 2px; }
.sc-topics-item {
  background: transparent;
  border: 0;
  text-align: left;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  color: inherit;
  font-size: 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sc-topics-item:hover { background: var(--surface, #f5f5f5); }
.sc-topics-item-current { background: color-mix(in srgb, var(--btn, #333) 12%, transparent); }
.sc-topics-item-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-topics-item-meta  { color: var(--text-muted, #666); font-size: 11px; }
.sc-topics-empty { padding: 8px 10px; color: var(--text-muted, #666); font-size: 12px; }

/* #260 — the note on `[hidden]` overrides for elements that set an
   explicit `display` also applies here.  Add the topics menu. */
.sc-topics-menu[hidden] { display: none !important; }

/* #260 — launcher badge for pending code proposals. */
.sc-launcher { position: relative; }
.sc-launcher-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 20px;
  height: 20px;
  padding: 0 4px;
  border-radius: 10px;
  background: #dc3545;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
  pointer-events: none;
}
.sc-launcher-badge[hidden] { display: none !important; }

/* #260 — expandable tool chip.  Header is always inline; expanded
   body drops below.  Overrides the earlier `.sc-tool-chip` rule
   (which set `white-space: nowrap`) for the expanded state. */
.sc-tool-chip.sc-tool-chip-expandable { flex-direction: column; align-items: stretch; white-space: normal; }
.sc-tool-chip-header { display: flex; align-items: center; gap: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sc-tool-toggle {
  background: transparent;
  border: 0;
  color: inherit;
  cursor: pointer;
  padding: 0 2px;
  opacity: .6;
  font-size: 11px;
  line-height: 1;
}
.sc-tool-toggle:hover { opacity: 1; }
.sc-tool-body {
  display: none;
  margin: 6px 0 0 0;
  padding: 6px 8px;
  background: color-mix(in srgb, currentColor 6%, transparent);
  border-radius: 4px;
  font-size: 11px;
  line-height: 1.4;
  max-height: 240px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
}
.sc-tool-chip.sc-tool-open .sc-tool-body,
.sc-tool-chip.sc-tool-open .sc-tool-diffstat { display: block; }

.sc-tool-diffstat {
  display: none;
  margin-top: 6px;
  padding: 4px 8px;
  background: color-mix(in srgb, currentColor 6%, transparent);
  border-radius: 4px;
  font-size: 11px;
}
.sc-tool-diffstat-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 2px 0;
}
.sc-tool-diffstat-path { font-family: ui-monospace, monospace; opacity: .9; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-tool-diffstat-count { flex: 0 0 auto; font-family: ui-monospace, monospace; }
.sc-tool-diffstat-plus  { color: #16a34a; }
.sc-tool-diffstat-minus { color: #dc2626; }
.sc-tool-diffstat-summary { margin-top: 4px; opacity: .7; font-size: 10px; }
