/* Onyx — Sleek dark UI, channel side menu */
:root {
  --bg-base: #0d0e10;
  --bg-primary: #141518;
  --bg-secondary: #111214;
  --bg-elevated: #1a1b1e;
  --bg-hover: rgba(255, 255, 255, 0.04);
  --bg-active: rgba(255, 255, 255, 0.06);
  --border: rgba(255, 255, 255, 0.06);
  --text-primary: #e8e9ea;
  --text-secondary: #8b8d92;
  --text-tertiary: #5c5e64;
  --accent: #7c8bff;
  --accent-muted: rgba(124, 139, 255, 0.2);
  --radius-sm: 6px;
  --radius-md: 8px;
  --server-list-width: 56px;
  --channel-list-width: 252px;
  --channel-list-min-width: 252px;
  --channel-list-max-width: 360px;
  --members-list-width: 200px;
  --main-header-height: 52px;
  /* The user pill and the message box are the two boxes on the bottom row of
     the window. They share this height, and the bars around them share the
     same 6px of padding and a 1px rule on top, so the two boxes start and end
     on the same lines however the panels are sized. */
  --bottom-box-height: 44px;
  /* The DM button at the top of the server strip. It is centred in the header
     band so it sits level with the channel header and the channel name. */
  --dm-hub-size: 48px;
  --font-ui: "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

/* ── Color themes ───────────────────────────────────────────────────────────
   A theme overrides only the 12 color variables; layout/sizing vars above are
   theme-invariant. The default (no data-theme, or data-theme="onyx") is the
   base :root palette. Selection is persisted as localStorage "onyx_theme" and
   applied to <html data-theme="…"> at boot (see index.html head + app.js). */
:root[data-theme="midnight"] {
  --bg-base: #0a0c14;
  --bg-primary: #10131f;
  --bg-secondary: #0d0f18;
  --bg-elevated: #161a29;
  --bg-hover: rgba(255, 255, 255, 0.045);
  --bg-active: rgba(255, 255, 255, 0.07);
  --border: rgba(255, 255, 255, 0.07);
  --text-primary: #e6e8f0;
  --text-secondary: #8a8fa6;
  --text-tertiary: #565b73;
  --accent: #5c7cfa;
  --accent-muted: rgba(92, 124, 250, 0.2);
}
:root[data-theme="slate"] {
  --bg-base: #17181a;
  --bg-primary: #1e1f23;
  --bg-secondary: #1a1b1e;
  --bg-elevated: #26272c;
  --bg-hover: rgba(255, 255, 255, 0.05);
  --bg-active: rgba(255, 255, 255, 0.08);
  --border: rgba(255, 255, 255, 0.08);
  --text-primary: #e9eaec;
  --text-secondary: #9a9ca1;
  --text-tertiary: #6a6c72;
  --accent: #7d8aa3;
  --accent-muted: rgba(125, 138, 163, 0.22);
}
:root[data-theme="nord"] {
  --bg-base: #2e3440;
  --bg-primary: #3b4252;
  --bg-secondary: #343b48;
  --bg-elevated: #434c5e;
  --bg-hover: rgba(255, 255, 255, 0.05);
  --bg-active: rgba(255, 255, 255, 0.09);
  --border: rgba(255, 255, 255, 0.09);
  --text-primary: #eceff4;
  --text-secondary: #aab2c3;
  --text-tertiary: #727c90;
  --accent: #88c0d0;
  --accent-muted: rgba(136, 192, 208, 0.22);
}
:root[data-theme="crimson"] {
  --bg-base: #0f0d0e;
  --bg-primary: #171416;
  --bg-secondary: #131011;
  --bg-elevated: #1d181a;
  --bg-hover: rgba(255, 255, 255, 0.04);
  --bg-active: rgba(255, 255, 255, 0.06);
  --border: rgba(255, 255, 255, 0.07);
  --text-primary: #ece8e9;
  --text-secondary: #a08d90;
  --text-tertiary: #6e5c5f;
  --accent: #f0616d;
  --accent-muted: rgba(240, 97, 109, 0.2);
}
:root[data-theme="forest"] {
  --bg-base: #0c0f0d;
  --bg-primary: #131715;
  --bg-secondary: #0f1310;
  --bg-elevated: #1a201c;
  --bg-hover: rgba(255, 255, 255, 0.04);
  --bg-active: rgba(255, 255, 255, 0.06);
  --border: rgba(255, 255, 255, 0.07);
  --text-primary: #e6ece8;
  --text-secondary: #8b9a90;
  --text-tertiary: #5c6b61;
  --accent: #4fb477;
  --accent-muted: rgba(79, 180, 119, 0.2);
}
:root[data-theme="light"] {
  --bg-base: #f2f3f5;
  --bg-primary: #ffffff;
  --bg-secondary: #ebedf0;
  --bg-elevated: #ffffff;
  --bg-hover: rgba(0, 0, 0, 0.04);
  --bg-active: rgba(0, 0, 0, 0.06);
  --border: rgba(0, 0, 0, 0.09);
  --text-primary: #1a1b1e;
  --text-secondary: #5c5e64;
  --text-tertiary: #8b8d92;
  --accent: #5865f2;
  --accent-muted: rgba(88, 101, 242, 0.16);
}
:root[data-theme="contrast"] {
  --bg-base: #000000;
  --bg-primary: #0a0a0a;
  --bg-secondary: #050505;
  --bg-elevated: #151515;
  --bg-hover: rgba(255, 255, 255, 0.12);
  --bg-active: rgba(255, 255, 255, 0.18);
  --border: rgba(255, 255, 255, 0.4);
  --text-primary: #ffffff;
  --text-secondary: #d4d4d4;
  --text-tertiary: #a3a3a3;
  --accent: #ffd400;
  --accent-muted: rgba(255, 212, 0, 0.25);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  font-family: var(--font-ui);
  font-size: 15px;
  color: var(--text-primary);
  background: var(--bg-base);
  -webkit-font-smoothing: antialiased;
}

/* ——— Onboarding (first-run username) ——— */
.onboarding-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.onboarding-overlay[hidden] {
  display: none !important;
}

.onboarding-backdrop {
  position: absolute;
  inset: 0;
  background: var(--bg-base);
}

.onboarding-card {
  position: relative;
  width: 100%;
  max-width: 400px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 32px;
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.4);
}

.onboarding-title {
  margin: 0 0 8px;
  font-size: 24px;
  font-weight: 600;
  color: var(--text-primary);
}

.onboarding-desc {
  margin: 0 0 24px;
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.45;
}

.onboarding-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.onboarding-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}

.onboarding-label-hint {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}

.onboarding-input {
  width: 100%;
  padding: 10px 12px;
  font-size: 15px;
  color: var(--text-primary);
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.onboarding-input::placeholder {
  color: var(--text-tertiary);
}

.onboarding-input-tag {
  max-width: 80px;
}

.onboarding-error {
  margin: 0;
  font-size: 13px;
  color: #e74c3c;
}

.onboarding-submit {
  margin-top: 8px;
  padding: 12px 20px;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.onboarding-submit:hover {
  filter: brightness(1.1);
}

/* Google sign-in button */
.onboarding-google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 20px;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  background: #4285F4;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  width: 100%;
  transition: filter 0.15s;
}
.onboarding-google-btn:hover {
  filter: brightness(1.1);
}
.onboarding-logo {
  text-align: center;
  margin-bottom: 16px;
}

#app {
  display: flex;
  height: 100vh;
  width: 100vw;
}

/* ——— Desktop title bar ———
   The desktop shell draws no frame of its own on Windows and Linux, so this
   strip is the window's title bar: the app name, the region the window is
   dragged by, and the minimise / maximise / close buttons, all in the theme.
   The buttons are sized to the strip, so they can never spill over the
   header line beneath. theme-init.js marks the root with .desktop-titlebar
   only in the desktop shell (the browser build never shows the strip) and
   with .custom-window-controls only off macOS, which keeps its native
   traffic lights and needs room for them on the left. */
.app-titlebar {
  display: none;
}
:root.desktop-titlebar {
  --titlebar-height: 32px;
}
:root.desktop-titlebar .app-titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  height: var(--titlebar-height);
  padding-left: 12px;
  background-color: var(--bg-secondary);
  color: var(--text-primary);
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  user-select: none;
  -webkit-app-region: drag;
}
:root.desktop-titlebar:not(.custom-window-controls) .app-titlebar {
  padding-left: 78px; /* clear of the macOS traffic lights */
}
:root.desktop-titlebar #app {
  height: calc(100vh - var(--titlebar-height));
}

/* The window buttons. Each is exactly the strip's height, 46px wide as on a
   native bar, and drawn from a 10px glyph in the theme's text colour. */
.app-titlebar-controls {
  display: none;
  align-self: stretch;
  -webkit-app-region: no-drag;
}
:root.custom-window-controls .app-titlebar-controls {
  display: flex;
}
.win-btn {
  width: 46px;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: default;
  transition: background 0.1s ease, color 0.1s ease;
}
.win-btn:hover {
  background: var(--bg-elevated);
  color: var(--text-primary);
}
.win-btn:active {
  background: var(--bg-tertiary, var(--bg-elevated));
}
.win-btn-close:hover {
  background: #c42b1c;
  color: #fff;
}
.win-btn-close:active {
  background: #9f2216;
  color: #fff;
}
.win-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: -2px;
}
/* The maximise button shows a single square, or two overlapping ones once
   the window is maximised and the action is "restore". */
.win-glyph-restore { display: none; }
.app-titlebar.is-maximized .win-glyph-max { display: none; }
.app-titlebar.is-maximized .win-glyph-restore { display: block; }
:root.desktop-titlebar .voice-banner {
  top: calc(var(--titlebar-height) + 10px);
}

/* ——— Workspace strip (left) ——— */
/* No top padding and no gap: the DM button and the rule under it are placed
   by hand so the button sits inside the header band, level with the channel
   header and the channel name across the rest of the window. */
.server-list {
  width: var(--server-list-width);
  min-width: var(--server-list-width);
  background: var(--bg-secondary);
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow-x: hidden;
  padding: 0 0 12px;
  gap: 0;
  border-right: 1px solid var(--border);
}

.server-logo {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-primary);
  padding: 8px 0;
  display: block;
}

.server-icon {
  width: 40px;
  height: 40px;
  min-width: 40px;
  min-height: 40px;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 500;
  font-size: 15px;
  overflow: hidden;
  position: relative;
  transition: background 0.15s ease, color 0.15s ease;
}

.server-icon:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.server-icon.add {
  color: var(--text-tertiary);
}

.server-icon.add:hover {
  background: var(--bg-hover);
  color: var(--accent);
}

.server-sep {
  width: 24px;
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

.server-icons {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  flex: 1;
  min-height: 0;
  width: 100%; /* span full column so badges don't overflow the container */
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none; /* Firefox */
}
.server-icons::-webkit-scrollbar {
  display: none; /* Chrome / WebView2 */
}

.server-icons .server-icon {
  flex-shrink: 0;
}

/* ——— Channel list (side menu) ——— */
.channel-list {
  flex: 0 0 var(--channel-list-width);
  width: var(--channel-list-width);
  min-width: var(--channel-list-min-width);
  max-width: var(--channel-list-max-width);
  background: var(--bg-secondary);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-right: 1px solid var(--border);
}

.channel-list-header {
  height: var(--main-header-height);
  padding: 0 0 0 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  flex-shrink: 0;
}

.server-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 0.01em;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.server-name-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  margin-left: -8px;
  padding: 4px 0 4px 8px;
  border-radius: var(--radius-sm);
  position: relative;
}

.server-name-wrap:hover {
  background: var(--bg-hover);
}

.server-name-chevron {
  flex-shrink: 0;
  color: var(--text-tertiary);
  transition: transform 0.15s ease;
}

.server-name-wrap.open .server-name-chevron {
  transform: rotate(180deg);
}

.server-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 4px;
  min-width: 200px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0,0,0,0.3);
  padding: 4px 0;
  z-index: 100;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.2s ease, opacity 0.15s ease;
}

.server-dropdown.open {
  max-height: 400px;
  opacity: 1;
  pointer-events: auto;
}

.server-dropdown:not(.open) {
  pointer-events: none;
}

.server-dropdown-item {
  display: block;
  width: 100%;
  padding: 8px 14px;
  border: none;
  background: transparent;
  color: var(--text-primary);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: background 0.1s;
}

.server-dropdown-item:hover {
  background: var(--bg-hover);
}

.channel-list-header {
  position: relative;
}

.channel-invite-btn {
  flex-shrink: 0;
  margin-left: auto;
  width: 36px;
  height: var(--main-header-height);
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 0;
  transition: background 0.12s, color 0.12s;
}

.channel-invite-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.channel-list-header-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

.channel-list-empty {
  padding: 16px 14px;
  font-size: 13px;
  color: var(--text-tertiary);
}

.channel-list-content {
  padding: 12px 0;
}

.channel-nav {
  flex: 1;
  overflow-y: auto;
  padding: 12px 0;
}

.channel-nav-label {
  display: block;
  padding: 0 14px 8px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.channel-group {
  margin-bottom: 16px;
}

.channel-group-label {
  display: block;
  padding: 0 14px 6px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.channel-items {
  list-style: none;
  margin: 0;
  padding: 0;
}

.channel-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  margin: 1px 6px;
  color: var(--text-secondary);
  text-decoration: none;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.25;
  border-radius: var(--radius-sm);
  transition: color 0.12s ease, background 0.12s ease;
}

.channel-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.channel-item:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.channel-item.active {
  background: var(--bg-active);
  color: var(--text-primary);
}

.channel-icon {
  flex-shrink: 0;
  width: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.6;
  line-height: 1;
}

.channel-hash {
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  display: flex;
  align-items: center;
  color: inherit;
}

.channel-item:hover .channel-icon,
.channel-item.active .channel-icon {
  opacity: 1;
}

.channel-item.voice-active {
  color: #3ba55d;
}

.channel-list-footer {
  padding: 10px 8px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg-secondary);
}

.user-pill {
  display: flex;
  min-height: var(--bottom-box-height);
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  min-width: 0;
}

.user-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent-muted);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 600;
  flex-shrink: 0;
  transition: box-shadow 0.15s;
  overflow: hidden;
}

.user-avatar.speaking {
  box-shadow: 0 0 0 2.5px #3ba55d;
}

.user-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  overflow: hidden;
}

.user-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  line-height: 1.25;
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

/* ——— Main area ——— */
.main-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-primary);
}

.main-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.main-empty-inner {
  text-align: center;
  max-width: 400px;
}

.main-empty-title {
  margin: 0 0 12px;
  font-size: 24px;
  font-weight: 600;
  color: var(--text-primary);
}

.main-empty-desc {
  margin: 0 0 24px;
  font-size: 15px;
  color: var(--text-secondary);
  line-height: 1.45;
}

.main-empty-actions {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: center;
}

.main-empty-btn {
  padding: 12px 24px;
  border: none;
  border-radius: var(--radius-md);
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
  min-width: 200px;
  transition: opacity 0.12s;
}

.main-empty-btn:hover {
  opacity: 0.9;
}

.main-empty-btn.secondary {
  background: var(--bg-elevated);
  color: var(--text-primary);
  border: 1px solid var(--border);
}

.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  position: relative;
}

.settings-btn.danger {
  background: #c0392b;
  color: #fff;
  border: none;
}

.settings-btn.danger:hover {
  background: #a93226;
}

.video-preview-box {
  position: relative;
  margin-top: 10px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: #1a1b1e;
  max-width: 360px;
  aspect-ratio: 16 / 9;
}
.video-preview-box video {
  display: none;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-sm);
  transform: scaleX(-1);
}
.video-preview-box video.active {
  display: block;
}
.video-preview-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: #5c5e64;
  pointer-events: none;
}
.video-preview-placeholder span {
  font-size: 13px;
}
.video-preview-box video.active ~ .video-preview-placeholder {
  display: none;
}
.video-preview-btn {
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  padding: 6px 14px;
  border: none;
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  backdrop-filter: blur(4px);
  transition: background 0.15s;
  z-index: 1;
}
.video-preview-btn:hover {
  background: rgba(0, 0, 0, 0.8);
}

.settings-section-title.danger {
  color: #e74c3c;
}

/* Full-screen server settings */
.server-settings-fullscreen {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--bg-base);
  display: flex;
  flex-direction: column;
}

.server-settings-fullscreen[hidden] {
  display: none !important;
}

.server-settings-header {
  height: 48px;
  padding: 0 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.server-settings-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}

.server-settings-close {
  padding: 8px 12px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 14px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  gap: 8px;
}

.server-settings-close:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.server-settings-close-kbd {
  font-size: 11px;
  color: var(--text-tertiary);
}

.server-settings-body {
  flex: 1;
  display: flex;
  min-height: 0;
}

.server-settings-nav {
  width: 220px;
  min-width: 220px;
  padding: 16px 0;
  border-right: 1px solid var(--border);
  background: var(--bg-secondary);
  overflow-y: auto;
}

.server-settings-nav-server {
  margin: 0 16px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.server-settings-nav-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.server-settings-nav-cat {
  margin: 12px 16px 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.server-settings-nav-item {
  padding: 8px 16px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}

.server-settings-nav-item:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.server-settings-nav-item.active {
  background: var(--bg-hover);
  color: var(--accent);
}

.server-settings-nav-item.danger {
  color: #e74c3c;
}

.server-settings-content {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
}

.server-settings-page {
  display: none;
  max-width: 720px;
}

.server-settings-page.active {
  display: block;
}

#server-settings-page-members.server-settings-page,
#server-settings-page-roles.server-settings-page {
  max-width: none;
}

.server-settings-page-title {
  margin: 0 0 8px;
  font-size: 20px;
  font-weight: 600;
  color: var(--text-primary);
}

.server-settings-page-desc {
  margin: 0 0 24px;
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.45;
}

.settings-block-spaced {
  margin-bottom: 24px;
}

.settings-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.members-search-input {
  width: 260px;
}

.settings-select {
  width: 100%;
  min-width: 110px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-size: 12px;
}

.settings-block-danger {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid rgba(231, 76, 60, 0.25);
}

.members-table-wrap {
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: visible;
}

.members-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.members-table th {
  padding: 10px 12px;
  text-align: left;
  font-weight: 600;
  color: var(--text-tertiary);
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border);
}

.members-filter-row th {
  padding: 8px 10px;
  background: var(--bg-base);
}

.members-table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text-primary);
  vertical-align: middle;
}

.members-table tr:last-child td {
  border-bottom: none;
}

.members-empty {
  padding: 24px;
  text-align: center;
  color: var(--text-tertiary);
  font-size: 14px;
}

.member-table-name {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 180px;
}

.member-table-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  font-size: 13px;
}

.member-table-username {
  font-weight: 600;
  color: var(--text-primary);
}

.member-table-tag {
  margin-top: 2px;
  font-size: 12px;
  color: var(--text-tertiary);
}

.member-role-cell {
  position: relative;
  min-width: 180px;
}

.member-role-chips {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

.member-role-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 160px;
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-size: 12px;
  white-space: nowrap;
}

.role-color-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}

.member-role-menu {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 20;
  width: 220px;
  max-height: 260px;
  overflow-y: auto;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.34);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 0.12s, transform 0.12s;
}

.member-role-cell:hover .member-role-menu,
.member-role-menu:hover {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.member-role-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.member-role-menu-item:hover {
  background: var(--bg-hover);
}

.member-role-menu-item input {
  accent-color: var(--accent);
}

.roles-settings-layout {
  display: grid;
  grid-template-columns: minmax(260px, 340px) minmax(420px, 1fr);
  gap: 20px;
  align-items: start;
}

.roles-list-panel,
.role-editor {
  min-width: 0;
}

.roles-list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.roles-list {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.role-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
  cursor: pointer;
}

.role-row:hover,
.role-row.active {
  border-color: var(--accent);
  background: var(--bg-hover);
}

.role-row-info {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
}

.role-row .role-edit-btn {
  margin-left: auto;
}

.role-editor {
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
}

.role-editor[hidden] {
  display: none !important;
}

.role-editor-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
}

.role-editor-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

.role-editor-tab {
  padding: 8px 10px;
  border: none;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 13px;
}

.role-editor-tab:hover,
.role-editor-tab.active {
  color: var(--text-primary);
  border-bottom-color: var(--accent);
}

.role-editor-panel {
  display: none;
}

.role-editor-panel.active {
  display: block;
}

.settings-field-label {
  display: block;
  margin: 14px 0 6px;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
}

.role-color-section {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 16px 0;
}

.role-color-main {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.24);
  cursor: pointer;
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.18);
}

.role-color-native {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

.role-color-presets {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.role-color-preset {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
  cursor: pointer;
}

.role-hex-input {
  max-width: 160px;
}

.role-toggle-row {
  margin-top: 18px;
}

.role-permissions-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 16px 0;
  max-height: 520px;
  overflow-y: auto;
}

.role-perm-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  color: var(--text-primary);
  cursor: pointer;
}

.role-perm-switch {
  position: relative;
  display: inline-block;
  width: 42px;
  height: 22px;
  flex-shrink: 0;
}

.role-perm-switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.role-perm-slider {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: #3c4048;
  transition: background 0.18s;
}

.role-perm-slider::before {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  left: 3px;
  top: 3px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.18s;
}

.role-perm-switch input:checked + .role-perm-slider {
  background: var(--accent);
}

.role-perm-switch input:checked + .role-perm-slider::before {
  transform: translateX(20px);
}

.role-members-list {
  display: flex;
  flex-direction: column;
  max-height: 520px;
  overflow-y: auto;
}

.role-member-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  color: var(--text-primary);
  font-size: 14px;
}

.role-member-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.role-delete-btn {
  margin-top: 18px;
}

.main-header {
  height: var(--main-header-height);
  padding: 0 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

#app.workspace-transition-down .channel-list,
#app.workspace-transition-down .main-content,
#app.workspace-transition-down .members-list {
  animation: workspaceDropIn 170ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

#app.workspace-transition-up .channel-list,
#app.workspace-transition-up .main-content,
#app.workspace-transition-up .members-list {
  animation: workspaceLiftIn 170ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

.main-content.chat-transition-slide {
  animation: chatSlideIn 130ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

@keyframes workspaceDropIn {
  from {
    opacity: 0.86;
    transform: translateY(-16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes workspaceLiftIn {
  from {
    opacity: 0.86;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes chatSlideIn {
  from {
    opacity: 0.88;
    transform: translateX(-18px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  #app.workspace-transition-down .channel-list,
  #app.workspace-transition-down .main-content,
  #app.workspace-transition-down .members-list,
  #app.workspace-transition-up .channel-list,
  #app.workspace-transition-up .main-content,
  #app.workspace-transition-up .members-list,
  .main-content.chat-transition-slide {
    animation: none;
  }
}

.main-channel-name {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 0.01em;
}

.main-header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.dm-header-btn {
  width: 32px;
  height: 32px;
  color: var(--text-secondary);
}
.dm-header-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.main-header-search {
  width: 160px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: 13px;
  outline: none;
  transition: border-color 0.15s ease;
}

.main-header-search:focus {
  border-color: var(--text-tertiary);
}

.main-header-search::placeholder {
  color: var(--text-tertiary);
}

.messages-container {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 24px;
  position: relative;
  min-height: 0;
}

.messages-inner {
}

.message-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 3px 0;
  position: relative;
}

.message-group:hover {
  background: var(--bg-hover);
  margin-left: -12px;
  margin-right: -12px;
  padding-left: 12px;
  padding-right: 12px;
  border-radius: var(--radius-sm);
}

.message-unread-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 10px;
  color: var(--danger);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: uppercase;
}

.message-unread-divider::before,
.message-unread-divider::after {
  content: "";
  height: 1px;
  background: var(--danger);
  flex: 1;
  opacity: 0.9;
}

.message-unread-divider span {
  flex: 0 0 auto;
  line-height: 1;
}

.message-group.message-system {
  align-items: center;
  padding: 8px 0;
}
.message-group.message-system:hover {
  background: transparent;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}
.message-system-bar {
  max-width: 720px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-secondary);
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1.4;
  padding: 7px 10px;
  text-align: center;
}

.dm-call-toast {
  position: fixed;
  right: 20px;
  top: 72px;
  width: min(360px, calc(100vw - 40px));
  z-index: 700;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-elevated);
  box-shadow: 0 10px 28px rgba(0,0,0,0.35);
  padding: 14px;
}
.dm-call-toast-title {
  color: var(--text-primary);
  font-size: 14px;
  font-weight: 700;
  margin-bottom: 4px;
}
.dm-call-toast-meta {
  color: var(--text-secondary);
  font-size: 12px;
  line-height: 1.4;
  margin-bottom: 12px;
}
.dm-call-toast-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Voice pull-down banner — persistent top-center notice for cross-device
   voice sessions and connection loss. Slides down from the top edge. */
.voice-banner {
  position: fixed;
  top: 10px;
  left: 50%;
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(560px, calc(100vw - 40px));
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-elevated);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35);
  transform: translate(-50%, -16px);
  opacity: 0;
  transition: transform 0.18s ease, opacity 0.18s ease;
  pointer-events: none;
}
.voice-banner.is-visible {
  transform: translate(-50%, 0);
  opacity: 1;
  pointer-events: auto;
}
.voice-banner[hidden] {
  display: none;
}
.voice-banner-icon {
  display: inline-flex;
  align-items: center;
  color: var(--accent);
  flex-shrink: 0;
}
.voice-banner[data-kind="kicked"] .voice-banner-icon,
.voice-banner[data-kind="disconnected"] .voice-banner-icon {
  color: #e0a458;
}
.voice-banner-message {
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.voice-banner-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.voice-banner-btn {
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  padding: 4px 12px;
  cursor: pointer;
}
.voice-banner-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}
.voice-banner-btn.primary {
  border-color: transparent;
  background: var(--accent);
  color: #fff;
}
.voice-banner-btn.primary:hover {
  background: var(--accent);
  filter: brightness(1.1);
  color: #fff;
}

.message-avatar {
  position: absolute;
  left: 0;
  top: 4px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--bg-elevated);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 500;
  flex-shrink: 0;
  overflow: hidden;
}

/* Shared img style for all circular avatar elements.
   Uses absolute positioning so it reliably fills any parent layout (flex, block, etc.) */
.avatar-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: inherit;
}

.message-body {
  min-width: 0;
  padding-left: 62px;
}

.message-meta {
  display: block;
  padding-left: 62px;
  line-height: 1.5;
  margin-bottom: 2px;
}

.message-author {
  display: inline;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}

.message-time {
  font-size: 11px;
  color: var(--text-tertiary);
  display: inline-block;
  width: 62px;
  margin-left: -62px;
  vertical-align: baseline;
  white-space: nowrap;
  cursor: default;
  position: relative;
}

.message-time::after {
  content: attr(data-tooltip);
  position: absolute;
  left: 0;
  bottom: calc(100% + 6px);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 12px;
  line-height: 1.4;
  padding: 4px 8px;
  white-space: nowrap;
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s 0s;
}

.message-time:hover::after {
  opacity: 1;
  transition: opacity 0.15s 2s;
}

.message-content {
  display: inline;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-primary);
  white-space: normal;
  word-break: break-word;
  margin-left: 6px;
}

.message-group.msg-layout-block .message-content {
  display: block;
  margin-left: 0;
}

/* Inline links */
.msg-link {
  color: #7289da;
  text-decoration: none;
}
.msg-link:hover {
  text-decoration: underline;
}

/* Inline code */
.inline-code {
  background: rgba(255,255,255,0.07);
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 3px;
  font-family: 'Consolas', 'Fira Code', 'Courier New', monospace;
  font-size: 12.5px;
  padding: 1px 4px;
  color: #e6c07b;
}

/* Fenced code block */
.code-block-wrap {
  position: relative;
  margin: 6px 0 4px;
  border-radius: var(--radius-md);
  background: #1e1f22;
  border: 1px solid rgba(255,255,255,0.08);
  overflow: hidden;
}
.code-lang-label {
  display: block;
  padding: 4px 12px 3px;
  font-size: 11px;
  font-family: 'Consolas', monospace;
  color: var(--text-tertiary);
  background: rgba(255,255,255,0.04);
  border-bottom: 1px solid rgba(255,255,255,0.06);
  text-transform: lowercase;
}
.code-block {
  margin: 0;
  padding: 10px 14px;
  overflow-x: auto;
  font-family: 'Consolas', 'Fira Code', 'Courier New', monospace;
  font-size: 13px;
  line-height: 1.55;
  color: #abb2bf;
  white-space: pre;
  background: transparent;
}
/* Override highlight.js background so it matches our code-block-wrap */
.code-block code.hljs {
  background: transparent;
  padding: 0;
}
.code-block code {
  background: none;
  border: none;
  padding: 0;
  font-size: inherit;
  color: inherit;
  font-family: inherit;
}

/* ── Message action buttons (edit / delete) ── */
.message-actions {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  gap: 2px;
  align-items: center;
  opacity: 0;
  pointer-events: none;
  transition: none;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 2px 6px;
  z-index: 1;
  max-width: 420px;
  white-space: nowrap;
}

.message-group:hover .message-actions {
  opacity: 1;
  pointer-events: auto;
  right: 12px;
}

.message-action-btn {
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: 12px;
  padding: 3px 7px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  line-height: 1;
  white-space: nowrap;
}

.message-action-btn:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.message-action-btn.danger:hover {
  color: #e74c3c;
}

.message-edited-tag {
  font-size: 11px;
  color: var(--text-tertiary);
  margin-left: 4px;
}

/* Inline edit area */
.message-edit-area {
  width: 100%;
  background: var(--bg-base);
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 14px;
  font-family: inherit;
  line-height: 1.5;
  padding: 6px 8px;
  resize: none;
  outline: none;
  min-height: 40px;
  max-height: 200px;
  overflow-y: auto;
  box-sizing: border-box;
}

.message-edit-footer {
  display: flex;
  gap: 8px;
  margin-top: 4px;
  font-size: 12px;
  color: var(--text-secondary);
}

.message-edit-save,
.message-edit-cancel {
  background: none;
  border: none;
  font-size: 12px;
  padding: 0;
  cursor: pointer;
}

.message-edit-save { color: var(--accent); }
.message-edit-cancel { color: var(--text-secondary); }

/* Inline delete confirmation */
.delete-confirm-text {
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
  margin-right: 2px;
}

.delete-confirm-nag {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--text-tertiary);
  cursor: pointer;
  white-space: nowrap;
  margin-left: 4px;
}

/* Inline edit error message */
.edit-error-msg {
  font-size: 11px;
  color: #e74c3c;
  margin-left: 6px;
}

/* Jump-to-present button — sticky inside the scroll container */
.scroll-to-bottom-wrap {
  position: sticky;
  bottom: 16px;
  display: flex;
  justify-content: flex-end;
  pointer-events: none;
  height: 0;
  overflow: visible;
}

.scroll-to-bottom-btn {
  pointer-events: auto;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 20px;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 500;
  padding: 6px 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.35);
  transition: opacity 0.15s, background 0.12s;
  opacity: 0;
  transform: translateY(-4px);
}

.scroll-to-bottom-btn.visible {
  opacity: 1;
  transform: translateY(0);
}

.scroll-to-bottom-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

/* The bottom bar of the chat pane. Its padding matches .left-footer-channel-col
   so the message box lands on exactly the same lines as the user pill. */
.message-composer {
  padding: 6px 20px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 10px;
}

.composer-input-wrap {
  flex: 1;
  min-height: var(--bottom-box-height);
  display: flex;
  align-items: flex-end;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0 14px;
  background: var(--bg-base);
  transition: border-color 0.15s ease;
}

.composer-input-wrap:focus-within {
  border-color: var(--text-tertiary);
}

/* Two pixels short of the box, which adds its own 1px border top and bottom. */
.composer-input {
  flex: 1;
  height: calc(var(--bottom-box-height) - 2px);
  min-height: calc(var(--bottom-box-height) - 2px);
  max-height: 120px;
  padding: 11px 0;
  border: none;
  background: transparent;
  color: var(--text-primary);
  font-size: 14px;
  font-family: inherit;
  line-height: 20px;
  outline: none;
  resize: none;
  overflow-y: auto;
}

.composer-input::placeholder {
  color: var(--text-tertiary);
}

.composer-send {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  border: none;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: opacity 0.15s ease, background 0.15s ease;
}

.composer-send:hover {
  opacity: 0.9;
  background: #6b7aeb;
}

/* ——— Members list ——— */
.members-list {
  width: var(--members-list-width);
  min-width: var(--members-list-width);
  background: var(--bg-secondary);
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--border);
}

.members-header {
  height: var(--main-header-height);
  padding: 0 10px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.members-search {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: 13px;
  outline: none;
}

.members-search::placeholder {
  color: var(--text-tertiary);
}

.members-section {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0;
}

.members-section-label {
  padding: 8px 14px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.members-items {
  list-style: none;
  margin: 0;
  padding: 0;
}

.member-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 14px;
  margin: 0 6px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.12s ease;
}

.member-item:hover {
  background: var(--bg-hover);
}

.member-avatar {
  position: relative;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bg-elevated);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 500;
  flex-shrink: 0;
}

.presence-dot {
  position: absolute;
  bottom: -1px;
  right: -1px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 2px solid var(--bg-secondary);
}
.presence-dot.online  { background: #3ba55d; }
.presence-dot.offline { background: #747f8d; }

.member-item.offline .member-name   { color: var(--text-secondary); }
.member-item.offline .member-avatar { opacity: 0.6; }

.members-section-header {
  padding: 16px 16px 4px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
  list-style: none;
}

.member-name-wrap {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.member-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
}

.member-status {
  font-size: 11px;
  color: var(--text-tertiary);
}

/* ——— Icon button ——— */
.icon-btn {
  width: 32px;
  height: 32px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s ease, color 0.12s ease;
}

.icon-btn:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

/* Scrollbars. One themed style for every scrolling region — search results,
   pickers, settings and dialogs included — so nothing falls back to the
   browser's white default. This is the standard pair the message list has
   always used; it is on the universal selector because scrollbar-width does
   not inherit, and at zero specificity so any region that hides its bar
   (.server-icons) or sizes it differently (the emoji picker) still wins.
   Modern Chromium, including the desktop shell, draws from these two
   properties and ignores ::-webkit-scrollbar once they are set; the ::-webkit
   rules below only serve older engines. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--bg-elevated) transparent;
}

::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--bg-elevated);
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--text-tertiary);
}

/* ——— Invite / Join modals ——— */
.invite-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.invite-overlay[hidden] {
  display: none !important;
}

.invite-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  cursor: pointer;
}

.invite-panel {
  position: relative;
  width: 100%;
  max-width: 420px;
  background: var(--bg-secondary);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.4);
  overflow: hidden;
}

.invite-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}

.invite-title {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
}

.invite-close {
  font-size: 22px;
  line-height: 1;
  color: var(--text-tertiary);
}

.invite-body {
  padding: 20px;
}

.invite-desc {
  margin: 0 0 16px;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.45;
}

.invite-link-wrap,
.invite-code-wrap {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.invite-input {
  flex: 1;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: 14px;
  outline: none;
}

.invite-code-input {
  font-family: ui-monospace, monospace;
}

.invite-copy {
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s;
}

.invite-copy:hover {
  background: var(--bg-hover);
  border-color: var(--text-tertiary);
}

.invite-submit {
  width: 100%;
  margin-top: 8px;
  padding: 10px 14px;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.12s;
}

.invite-submit:hover {
  opacity: 0.9;
}

.invite-error {
  margin: 0 0 8px;
  font-size: 13px;
  color: #e74c3c;
}

/* ——— Settings modal ——— */
.settings-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.settings-overlay[hidden] {
  display: none !important;
}

.settings-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  cursor: pointer;
}

.settings-panel {
  position: relative;
  width: 100%;
  max-width: 880px;
  max-height: 88vh;
  background: var(--bg-secondary);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.4);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.settings-title {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
}

.settings-close {
  font-size: 22px;
  line-height: 1;
  color: var(--text-tertiary);
}

.settings-close:hover {
  color: var(--text-primary);
}

.settings-body {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.settings-nav {
  width: 180px;
  min-width: 180px;
  padding: 12px 0;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--bg-base);
}

.settings-nav-item {
  width: 100%;
  padding: 8px 20px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-size: 14px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}

.settings-nav-item:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.settings-nav-item.active {
  color: var(--accent);
  background: var(--accent-muted);
}

.settings-content {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
}

.settings-section {
  display: none;
}

.settings-section.active {
  display: block;
}

.settings-section-title {
  margin: 0 0 20px;
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
}

.settings-block {
  margin-bottom: 20px;
}

.settings-block-title {
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.settings-description {
  margin: 0 0 10px;
  font-size: 13px;
  color: var(--text-secondary);
  line-height: 1.45;
}

.settings-row {
  margin-top: 8px;
}

.settings-input,
.settings-select {
  width: 100%;
  max-width: 360px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: 13px;
  font-family: inherit;
  outline: none;
}

.settings-input:focus,
/* The noise mode select sits beside its description like a toggle would. */
.noise-mode-select {
  width: auto;
  min-width: 190px;
  flex-shrink: 0;
  margin-left: 16px;
}

.settings-select:focus {
  border-color: var(--text-tertiary);
}

.settings-input::placeholder {
  color: var(--text-tertiary);
}

.settings-select {
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='%235c5e64' d='M6 8L2 4h8z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}

.settings-btn {
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  background: var(--bg-base);
  color: var(--text-primary);
  transition: background 0.12s, border-color 0.12s;
}

.settings-btn.secondary:hover {
  background: var(--bg-hover);
  border-color: var(--text-tertiary);
}

.settings-toggle-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.settings-toggle-row .settings-block-title,
.settings-toggle-row .settings-description {
  margin-bottom: 0;
}

.settings-toggle {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
}

.settings-toggle-input {
  opacity: 0;
  width: 0;
  height: 0;
}

.settings-toggle-slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background: var(--bg-elevated);
  border-radius: 11px;
  transition: background 0.2s;
}

.settings-toggle-slider::before {
  content: "";
  position: absolute;
  height: 16px;
  width: 16px;
  left: 3px;
  bottom: 3px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.2s;
}

.settings-toggle-input:checked + .settings-toggle-slider {
  background: var(--accent);
}

.settings-toggle-input:checked + .settings-toggle-slider::before {
  transform: translateX(18px);
}

.settings-range {
  width: 100%;
  max-width: 360px;
  height: 5px;
  -webkit-appearance: none;
  appearance: none;
  background: var(--bg-elevated);
  border-radius: 3px;
  outline: none;
}

.settings-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-primary);
  cursor: pointer;
}

.settings-range::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-primary);
  cursor: pointer;
  border: none;
}

/* Input sensitivity row */
.sensitivity-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
  max-width: 100%;
}

/* Normal full-width slider (input volume, etc.) — distinct from the absolutely
   positioned .sensitivity-range knob that overlays the sensitivity bar. */
.settings-range {
  width: 100%;
  height: 5px;
  margin: 4px 0;
  appearance: none;
  -webkit-appearance: none;
  background: var(--accent-muted);
  border-radius: 3px;
  accent-color: var(--accent);
  cursor: pointer;
  outline: none;
}
.settings-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 3px rgba(0,0,0,0.6);
  cursor: ew-resize;
}
.settings-range::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: none;
  box-shadow: 0 0 3px rgba(0,0,0,0.6);
  cursor: ew-resize;
}

/* Input sensitivity bar */
.sensitivity-bar-wrap {
  position: relative;
  flex: 1;
  height: 5px;
  border-radius: 3px;
  background: linear-gradient(to right, #faa61a 0%, #faa61a 50%, #3ba55d 50%, #3ba55d 100%);
  overflow: visible;
}

.sensitivity-level {
  position: absolute;
  top: 0; right: 0;
  height: 100%;
  border-radius: 0 3px 3px 0;
  background: #1a1b1e;
  width: 100%;
  pointer-events: none;
  transition: width 0.08s linear;
}

.sensitivity-range {
  position: absolute;
  top: 50%;
  /* Extend 7px (half thumb width) beyond each edge so the thumb center at
     value=0 sits at 0% and at value=100 sits at 100% of the bar width.
     Without this, the browser's dead-zone shifts the thumb ~7px right at 0
     and ~7px left at 100, causing the visual threshold to lag the cursor. */
  left: -7px;
  width: calc(100% + 14px);
  transform: translateY(-50%);
  height: 20px;
  margin: 0;
  padding: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: pointer;
  outline: none;
}

.sensitivity-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  cursor: ew-resize;
  box-shadow: 0 0 3px rgba(0,0,0,0.6);
  margin-top: -4.5px;
}

.sensitivity-range::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  cursor: ew-resize;
  box-shadow: 0 0 3px rgba(0,0,0,0.6);
  border: none;
}

.sensitivity-range::-webkit-slider-runnable-track {
  background: transparent;
  height: 5px;
}

.sensitivity-range::-moz-range-track {
  background: transparent;
  height: 5px;
}

/* Auto sensitivity mode keeps the knob draggable so the user can tune the VAD
   open-threshold for their own voice/mic (levels differ per person). The bar
   itself is a binary voice-detected indicator (solid green when speech is
   recognized), driven by the overlay in renderSensitivityMeter(). */

.profile-preview {
  display: flex;
  align-items: center;
  gap: 20px;
}

.settings-avatar-large {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--accent-muted);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  font-weight: 600;
  flex-shrink: 0;
  overflow: hidden;
}

.settings-profile-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.settings-username {
  font-size: 18px;
  font-weight: 600;
  color: var(--text-primary);
}

.settings-tag {
  font-size: 13px;
  color: var(--text-tertiary);
}

.settings-actions {
  margin-top: 12px;
}


.settings-radio {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-primary);
  cursor: pointer;
}

.settings-radio input {
  cursor: pointer;
}

/* ——— Left panel wrapper (server-strip + channel list + footer) ——— */
.left-panel {
  display: flex;
  flex-direction: column;
  width: calc(var(--server-list-width) + var(--channel-list-width));
  min-width: calc(var(--server-list-width) + var(--channel-list-min-width));
  max-width: calc(var(--server-list-width) + var(--channel-list-max-width));
  background: var(--bg-secondary);
  border-right: 1px solid var(--border);
  flex-shrink: 0;
  position: relative;
}

/* Horizontal separator across the channel column, level with the main-header
   border-bottom. It begins where the channel column begins, and the matching
   rule above the user pill (see .left-footer-channel-col) begins at the very
   same x, so the two lines bracketing the channel list read as one pair. */
.left-panel::after {
  content: '';
  position: absolute;
  top: calc(var(--main-header-height) - 1px);
  left: var(--server-list-width);
  right: 0;
  height: 1px;
  background: var(--border);
  pointer-events: none;
  z-index: 2;
}

.left-panel-body {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* Remove the right border from channel-list since left-panel provides the outer border */
.left-panel .channel-list {
  border-right: none;
}

.channel-pane-resizer {
  position: absolute;
  top: 0;
  right: -3px;
  bottom: 0;
  width: 7px;
  z-index: 8;
  cursor: col-resize;
  touch-action: none;
}

.channel-pane-resizer::after {
  content: '';
  position: absolute;
  top: 0;
  right: 3px;
  width: 1px;
  height: 100%;
  background: transparent;
  transition: background 0.12s ease;
}

.channel-pane-resizer:hover::after,
.channel-pane-resizer:focus-visible::after,
body.is-resizing-channel-pane .channel-pane-resizer::after {
  background: var(--accent);
}

body.is-resizing-channel-pane {
  cursor: col-resize;
  user-select: none;
}

.left-panel-footer {
  display: flex;
  align-items: stretch;
  background: var(--bg-secondary);
  flex-shrink: 0;
}

.left-footer-server-col {
  width: var(--server-list-width);
  min-width: var(--server-list-width);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 0;
  border-right: 1px solid var(--border);
  flex-shrink: 0;
}

/* The rule above the user pill. It lives on this column rather than on the
   footer so it spans exactly the channel list, lining up with the separator
   under the channel header; the server strip stays one unbroken column from
   the top of the window to the bottom. */
.left-footer-channel-col {
  border-top: 1px solid var(--border);
  flex: 1;
  min-width: 0;
  padding: 6px 12px 6px 8px;
}

/* ——— Voice-connected bar ——— */
.voice-connected-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 8px 6px 14px;
  background: rgba(59, 165, 93, 0.07);
  border-top: 1px solid rgba(59, 165, 93, 0.18);
  flex-shrink: 0;
  transition: background 0.2s, border-top-color 0.2s;
  position: relative; /* required for stats panel absolute positioning */
}

.voice-connected-bar[hidden] {
  display: none;
}

/* ── Connecting state (amber) ── */
.voice-connected-bar.voice-bar-connecting {
  background: rgba(250, 168, 26, 0.07);
  border-top-color: rgba(250, 168, 26, 0.25);
}

.voice-connected-bar.voice-bar-connecting .voice-connected-icon,
.voice-connected-bar.voice-bar-connecting .voice-connected-status {
  color: #faa81a;
}

/* ── Error / Failed state (red) ── */
.voice-connected-bar.voice-bar-error {
  background: rgba(237, 66, 69, 0.07);
  border-top-color: rgba(237, 66, 69, 0.25);
}

.voice-connected-bar.voice-bar-error .voice-connected-icon,
.voice-connected-bar.voice-bar-error .voice-connected-status {
  color: #ed4245;
}

.voice-connected-info {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  cursor: pointer;
  user-select: none;
}

/* ── Hover slide-up animation for "Voice Statistics" text ── */
/* Uses an inner-wrapper translate so overflow:hidden reliably clips both spans
   without depending on the absolute+transform compositing behaviour in Electron. */
.voice-status-wrap {
  display: inline-block;
  overflow: hidden;
  height: 1.2em;       /* shows exactly one line at a time */
  vertical-align: bottom;
}

.voice-status-inner {
  display: flex;
  flex-direction: column;
  transition: transform 0.2s ease;
}

.voice-status-default,
.voice-status-hover {
  display: block;
  line-height: 1.2;
  white-space: nowrap;
  flex-shrink: 0;
}

.voice-connected-info:hover .voice-status-inner {
  transform: translateY(-1.2em);   /* slide up to reveal "Voice Statistics" */
}

/* State color overrides target the default text only */
.voice-bar-connecting .voice-status-default { color: #faa81a; }
.voice-bar-error      .voice-status-default { color: #ed4245; }

.voice-connected-icon {
  flex-shrink: 0;
  color: #3ba55d; /* default green; overridden by state modifier classes */
}

.voice-connected-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.voice-connected-channel {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-primary);
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.voice-connected-status {
  font-size: 11px;
  color: #3ba55d; /* default green; overridden by state modifier classes */
  line-height: 1.2;
}

.voice-disconnect-btn {
  width: 26px;
  height: 26px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.12s, color 0.12s;
}

.voice-disconnect-btn:hover {
  background: rgba(237, 66, 69, 0.15);
  color: #ed4245;
}

/* ── Voice stats panel ── */
.voice-stats-panel {
  display: none;  /* hidden by default; .is-open makes it visible */
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  background: #18191c;
  border: 1px solid #2a2b2e;
  border-bottom: none;
  border-radius: 6px 6px 0 0;
  padding: 10px 12px 8px;
  font-size: 12px;
  color: #dcddde;
  z-index: 10;
}

.voice-stats-panel.is-open {
  display: block;
  animation: statsSlideIn 0.18s ease;
}

@keyframes statsSlideIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* E2EE badge states */
.voice-e2e-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 3px;
  font-size: 11px;
  font-weight: 600;
  margin-bottom: 6px;
}
.voice-e2e-active          { background: #1a3d2b; color: #3ba55d; }
.voice-e2e-unverified      { background: #3d3500; color: #faa61a; }
.voice-e2e-identity-change { background: #3d1a1a; color: #ed4245; }
.voice-e2e-disabled        { background: #2a2b2e; color: #72767d; }

/* Verify code row */
.voice-verify-row {
  font-size: 11px;
  color: #96989d;
  margin-bottom: 6px;
}
.voice-verify-code {
  font-family: 'Courier New', monospace;
  color: #dcddde;
  font-size: 12px;
}

/* Ping sparkline row */
.voice-ping-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}
.voice-ping-label  { color: #96989d; font-size: 11px; }
.voice-ping-sparkline {
  width: 120px;
  height: 40px;
  background: #111213;
  border: 1px solid #2a2b2e;
  border-radius: 3px;
}
.voice-ping-value  { font-size: 11px; color: #dcddde; }

/* Video stats section */
.voice-video-stats {
  border-top: 1px solid #2a2b2e;
  margin-top: 6px;
  padding-top: 6px;
}
.voice-video-stats-title {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #72767d;
  margin-bottom: 4px;
}
.voice-video-stats-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2px;
}
.voice-video-stats-label { font-size: 11px; color: #72767d; }
.voice-video-stats-value { font-size: 11px; color: #dcddde; font-variant-numeric: tabular-nums; }
.voice-video-warn        { color: #ed4245; }

/* Debug button */
.voice-debug-btn {
  font-size: 11px;
  padding: 2px 8px;
  border: 1px solid #4f545c;
  border-radius: 3px;
  background: transparent;
  color: #96989d;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.voice-debug-btn:hover {
  background: rgba(255,255,255,0.06);
  color: #dcddde;
}

/* ——— Mute / Deafen active state ——— */
.mute-btn.active,
.deafen-btn.active {
  color: #ed4245;
}

.mute-btn.active:hover,
.deafen-btn.active:hover {
  background: rgba(237, 66, 69, 0.15);
  color: #ed4245;
}

.video-toggle-btn.active {
  color: #3ba55d;
}
.video-toggle-btn.active:hover {
  background: rgba(59, 165, 93, 0.15);
  color: #3ba55d;
}

/* ——— Voice/Video stage ——— */
.voice-stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
  background: #000;
  min-height: 0;
  overflow: hidden;
}
.voice-stage[hidden] {
  display: none;
}
.voice-stage-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  background: #000;
  border-bottom: 0;
  flex-shrink: 0;
}
.voice-stage-header-left {
  display: flex;
  align-items: center;
  gap: 8px;
}
.voice-stage-icon { color: #3ba55d; }
.voice-stage-channel {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.voice-stage-status {
  font-size: 12px;
  color: #3ba55d;
}
.voice-stage-header-right {
  display: flex;
  gap: 4px;
}
.voice-stage-header-btn {
  width: 32px; height: 32px;
  border: none; border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.12s, color 0.12s;
}
.voice-stage-header-btn:hover {
  background: rgba(255,255,255,0.08);
  color: var(--text-primary);
}

/* Grid of participant tiles */
.voice-stage-grid {
  flex: 1;
  display: grid;
  gap: 8px;
  padding: 4px;
  grid-auto-rows: minmax(96px, 1fr);
  align-content: center;
  justify-items: center;
  min-height: 0;
  overflow: hidden;
  background: #000;
}
.voice-stage-grid.has-spotlight {
  padding-bottom: 0;
}

/* Participant tile */
.voice-stage-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: auto;
  min-height: 0;
  max-width: none;
  max-height: 100%;
  aspect-ratio: 16 / 9;
  align-self: center;
  justify-self: center;
  border-radius: 8px;
  background: var(--tile-bg, #243447);
  cursor: pointer;
  transition: box-shadow 0.2s, transform 0.15s, background 0.12s;
  overflow: hidden;
}
.voice-stage-tile:hover {
  background: var(--tile-bg, #243447);
}
.voice-stage-tile.speaking {
  box-shadow: 0 0 0 3px #3ba55d;
}
@keyframes speaking-pulse {
  0%, 100% { box-shadow: 0 0 0 3px #3ba55d; }
  50% { box-shadow: 0 0 0 5px rgba(59, 165, 93, 0.4); }
}
.voice-stage-tile.speaking {
  animation: speaking-pulse 1.2s ease-in-out infinite;
}
.voice-stage-tile.screen-share-tile.speaking {
  animation: none;
  box-shadow: none;
}

/* Selected tile fills the stage; the other tiles sit in the bottom strip. */
.voice-stage-tile.spotlight {
  max-width: none;
  max-height: none;
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
}

/* Avatar in tile (voice-only, no video) */
.voice-stage-tile-avatar {
  width: 80px; height: 80px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 32px; font-weight: 600;
  color: #fff;
  flex-shrink: 0;
  overflow: hidden;
}
.voice-stage-tile-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  text-align: center;
  max-width: 90%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.voice-stage-tile-badges {
  display: flex;
  gap: 4px;
  position: absolute;
  top: 8px;
  right: 8px;
}
.voice-stage-tile-badges span {
  display: none;
  font-size: 14px;
  opacity: 0.8;
}
.voice-stage-tile.has-video .badge-video,
.voice-stage-tile.muted     .badge-muted,
.voice-stage-tile.deafened  .badge-deafened {
  display: inline;
}

/* Video inside tile — hidden by default; .has-video makes it visible */
.voice-stage-tile video {
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  z-index: 1;
  background: #000;
  background-color: #000;
}
.voice-stage-tile.has-video video {
  display: block;
}
.voice-stage-tile.local video {
  transform: scaleX(-1);
}
.voice-stage-tile.screen-share-tile video {
  object-fit: contain;
  background: #000 !important;
  background-color: #000 !important;
}
.voice-stage-tile.screen-share-tile {
  background: #000;
}
.voice-stage-tile.has-video {
  background: #000;
}
.voice-stage-tile.local.screen-share-tile video {
  transform: none;
}
.screen-watch-btn {
  position: absolute;
  left: 50%;
  bottom: 18px;
  z-index: 3;
  min-width: 120px;
  height: 34px;
  padding: 0 14px;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 6px;
  background: #5865f2;
  color: #fff;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  transform: translateX(-50%);
  cursor: pointer;
}
.screen-watch-btn:hover {
  background: #4752c4;
}
.voice-stage-tile.screen-share-tile.has-video .screen-watch-btn {
  bottom: 46px;
  background: rgba(32,34,37,0.82);
}
.voice-stage-tile.screen-share-tile.screen-share-watching:not(.has-video)::after,
.voice-stage-tile.screen-share-tile.screen-share-loading:not(.has-video)::after {
  content: "Connecting stream";
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(5,6,8,0.72);
  color: var(--text-secondary);
  font-size: 13px;
  font-weight: 600;
}
.voice-stage-tile-label {
  display: none;
  position: absolute;
  bottom: 8px;
  left: 8px;
  padding: 2px 8px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  pointer-events: none;
  z-index: 2;
}
.voice-stage-tile.has-video:hover .voice-stage-tile-label,
.voice-stage-tile.has-video:focus-within .voice-stage-tile-label {
  display: block;
}
/* Avatar + name hidden when video is active */
.voice-stage-tile.has-video .voice-stage-tile-avatar,
.voice-stage-tile.has-video .voice-stage-tile-name {
  display: none;
}

/* Spotlight strip (non-spotlighted participants) */
.voice-stage-spotlight-strip[hidden] {
  display: none;
}
.voice-stage-spotlight-strip {
  display: flex;
  flex-direction: row;
  gap: 6px;
  position: static;
  z-index: 4;
  max-width: 100%;
  padding: 8px 12px 0;
  transform: none;
  overflow-x: auto;
  flex-shrink: 0;
  justify-content: center;
  background: #000;
  border: 0;
}
.voice-stage-spotlight-strip .voice-stage-tile {
  width: 132px;
  min-width: 132px;
  max-width: 132px;
  height: auto;
  min-height: 0;
  aspect-ratio: 16 / 9;
}
.voice-stage-spotlight-strip .voice-stage-tile-avatar {
  width: 40px; height: 40px;
  font-size: 16px;
}
.voice-stage-spotlight-strip .voice-stage-tile-name {
  font-size: 10px;
}

/* Hover-only floating call controls. */
.voice-stage-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  position: static;
  z-index: 5;
  padding: 8px 0 12px;
  flex-shrink: 0;
  background: #000;
  border: 0;
  transform: translateY(8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.14s ease, transform 0.14s ease;
}
.voice-stage:hover .voice-stage-controls,
.voice-stage:focus-within .voice-stage-controls {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.voice-stage-ctrl-btn {
  width: 34px; height: 34px;
  border: none; border-radius: 50%;
  background: rgba(35, 37, 41, 0.92);
  color: var(--text-primary);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 16px rgba(0,0,0,0.35);
  transition: background 0.15s, color 0.15s;
}
.voice-stage-ctrl-btn svg {
  width: 17px;
  height: 17px;
}
.voice-stage-ctrl-btn:hover {
  background: #4e5058;
}
.voice-stage-ctrl-btn.active {
  background: #fff;
  color: #1a1b1e;
}
.voice-stage-ctrl-btn.muted {
  background: #ed4245;
  color: #fff;
}
.voice-stage-ctrl-btn.muted:hover {
  background: #d63638;
}
.voice-stage-ctrl-sep {
  display: none;
}
.voice-stage-ctrl-disconnect {
  background: #ed4245;
  color: #fff;
}
.voice-stage-ctrl-disconnect:hover {
  background: #d63638;
}

@media (max-width: 720px) {
  .voice-stage-grid {
    grid-auto-rows: minmax(120px, 1fr);
  }
  .voice-stage-spotlight-strip {
    flex-direction: column;
    align-items: center;
    max-height: 34vh;
    overflow-x: hidden;
    overflow-y: auto;
  }
  .voice-stage-spotlight-strip .voice-stage-tile {
    width: 108px;
    min-width: 108px;
    max-width: 108px;
    height: auto;
    min-height: 0;
  }
}

.voice-stage.voice-stage-narrow .voice-stage-spotlight-strip {
  flex-direction: column;
  align-items: center;
  max-height: 34vh;
  overflow-x: hidden;
  overflow-y: auto;
}
.voice-stage.voice-stage-narrow .voice-stage-spotlight-strip .voice-stage-tile {
  width: 108px;
  min-width: 108px;
  max-width: 108px;
}

/* Screen-share source picker */
.screen-picker-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(5, 6, 8, 0.78);
}
.screen-picker-panel {
  width: min(880px, calc(100vw - 48px));
  height: min(680px, calc(100vh - 48px));
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 18px 60px rgba(0,0,0,0.55);
}
.screen-share-action-panel {
  width: min(360px, 100%);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 18px 60px rgba(0,0,0,0.55);
}
.screen-share-action {
  height: 38px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: #383a40;
  color: var(--text-primary);
  font: inherit;
  cursor: pointer;
}
.screen-share-action:hover {
  background: #4e5058;
}
.screen-share-action.danger {
  background: #ed4245;
  border-color: #ed4245;
  color: #fff;
}
.screen-share-action.danger:hover {
  background: #d63638;
}
.screen-picker-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}
.screen-picker-tabs {
  display: flex;
  flex: 1;
  min-width: 0;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-base);
}
.screen-picker-tab {
  flex: 1;
  min-width: 0;
  height: 30px;
  padding: 0 12px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.screen-picker-tab:hover {
  color: var(--text-primary);
}
.screen-picker-tab.active {
  background: #383a40;
  color: var(--text-primary);
}
.screen-picker-settings {
  position: relative;
  flex: 0 0 auto;
}
.screen-picker-settings-btn {
  width: 34px;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--bg-base);
  color: var(--text-secondary);
  font: inherit;
  font-size: 15px;
  cursor: pointer;
}
.screen-picker-settings-btn:hover,
.screen-picker-settings-btn.active {
  background: #383a40;
  color: var(--text-primary);
}
.screen-picker-settings-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 5;
  width: 260px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-elevated);
  box-shadow: 0 14px 42px rgba(0,0,0,0.45);
}
.screen-picker-settings-menu[hidden] {
  display: none;
}
.screen-picker-setting-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.screen-picker-setting-label {
  color: var(--text-tertiary);
  font-size: 12px;
  font-weight: 600;
}
.screen-picker-setting-options {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}
.screen-picker-setting-choice {
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-base);
  color: var(--text-secondary);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.screen-picker-setting-choice:hover,
.screen-picker-setting-choice.active {
  background: #383a40;
  color: var(--text-primary);
  border-color: rgba(255,255,255,0.18);
}
.screen-picker-audio-option {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  color: var(--text-secondary);
  font-size: 13px;
}
.screen-picker-audio-option input {
  width: 14px;
  height: 14px;
}
.screen-picker-audio-option.disabled {
  opacity: 0.55;
}
.screen-picker-grid {
  position: relative;
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  grid-auto-rows: 146px;
  align-content: start;
  gap: 10px;
  min-height: 0;
  overflow: auto;
  padding: 2px 4px 2px 2px;
  border-radius: 8px;
}
.screen-picker-grid.loading {
  display: flex;
  align-items: center;
  justify-content: center;
}
.screen-picker-grid.loading::before {
  content: "";
  width: 28px;
  height: 28px;
  border: 3px solid rgba(255,255,255,0.18);
  border-top-color: var(--text-primary);
  border-radius: 50%;
  animation: screen-picker-spin 0.8s linear infinite;
}
@keyframes screen-picker-spin {
  to { transform: rotate(360deg); }
}
.screen-picker-source {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  min-height: 0;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #2b2d31;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
}
.screen-picker-source:hover,
.screen-picker-source:focus-visible {
  border-color: var(--accent);
  background: #34373d;
  outline: none;
}
.screen-picker-source img {
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 0;
  object-fit: cover;
  border-radius: 5px;
  background: #111214;
}
.screen-picker-source span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
}
.screen-picker-footer {
  min-height: 34px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
}
.screen-picker-summary {
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
.screen-picker-status {
  color: var(--text-tertiary);
  font-size: 12px;
  flex: 1;
  min-width: 0;
}
.screen-picker-cancel {
  min-width: 90px;
  height: 34px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: #383a40;
  color: var(--text-primary);
  font: inherit;
  cursor: pointer;
}
.screen-picker-cancel:hover {
  background: #4e5058;
}

/* ——— Voice stage fullscreen overlay (undocked mode) ——— */
.voice-stage.voice-stage-fullscreen {
  position: fixed !important;
  top: 0; left: 0; right: 0; bottom: 0;
  width: 100vw !important;
  height: 100vh !important;
  z-index: 900;
  border-radius: 0;
}

/* ——— Voice PiP (picture-in-picture) overlay ——— */
.voice-pip {
  position: fixed;
  bottom: 80px;
  right: 16px;
  width: 260px;
  min-width: 180px;
  min-height: 120px;
  display: flex;
  flex-direction: column;
  background: #1a1b1e;
  border-radius: 10px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.55);
  border: 1px solid var(--border);
  overflow: hidden;
  resize: both;       /* user-resizable via the browser's native resize handle */
  z-index: 1000;
  user-select: none;
}
.voice-pip-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  background: #2b2d31;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  border-bottom: 1px solid var(--border);
  cursor: grab;
  flex-shrink: 0;
}
.voice-pip-header:active { cursor: grabbing; }
.voice-pip-icon { color: #3ba55d; font-style: normal; }
.voice-pip-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.voice-pip-video {
  display: block;
  width: 100%;
  flex: 1;
  min-height: 0;
  object-fit: cover;
  background: #000;
}
.voice-pip-video.screen-share-pip {
  object-fit: contain;
  background: #000;
}
.voice-pip-footer {
  padding: 6px 10px;
  font-size: 11px;
  color: var(--text-secondary);
  flex-shrink: 0;
}

/* ——— Voice participants list (inside channel list, under a voice channel) ——— */
.voice-participants {
  padding: 2px 0 6px 28px;
}

.voice-participant {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  font-size: 12px;
  line-height: 1.25;
  color: var(--text-secondary);
}

.voice-participant-avatar {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--accent-muted);
  color: var(--accent);
  font-size: 10px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: box-shadow 0.15s;
}

.voice-participant.speaking .voice-participant-avatar {
  box-shadow: 0 0 0 2px #3ba55d;
}

.voice-participant-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Participant badge spans — always in DOM, hidden by default, shown via parent class */
.voice-participant .voice-participant-muted,
.voice-participant .voice-participant-deafened,
.voice-participant .voice-participant-video,
.voice-participant .voice-participant-screen,
.voice-participant .voice-participant-server-locked {
  display: none;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  font-style: normal;
}
.voice-participant.muted         .voice-participant-muted         { display: flex; }
.voice-participant.deafened      .voice-participant-deafened      { display: flex; }
.voice-participant.has-video     .voice-participant-video         { display: flex; }
.voice-participant.has-screen    .voice-participant-screen        { display: flex; }
.voice-participant.server-locked .voice-participant-server-locked { display: flex; }

.voice-participant-muted {
  color: #ed4245;
}

.voice-participant-muted::before {
  content: '🎙';
  font-size: 11px;
  opacity: 0.7;
  text-decoration: line-through;
}

.voice-participant-deafened {
  color: #ed4245;
}

.voice-participant-deafened::before {
  content: '🎧';
  font-size: 11px;
  opacity: 0.7;
}

/* ── Composer emoji button ── */
.composer-emoji-btn {
  width: 36px;
  height: 36px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  font-size: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.1s;
  line-height: 1;
  padding: 0;
}
.composer-emoji-btn:hover {
  background: var(--bg-hover);
}

/* ── Emoji picker popup ── */
.emoji-picker {
  position: fixed;
  z-index: 9999;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 40px rgba(0,0,0,0.6);
  display: none;
  flex-direction: column;
  overflow: hidden;
  /* width and max-height are set dynamically in JS */
}
.emoji-search {
  flex-shrink: 0;
  margin: 10px 10px 6px;
  padding: 7px 10px;
  background: var(--bg-base);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: 13px;
  font-family: inherit;
  outline: none;
  box-sizing: border-box;
  width: calc(100% - 20px);
}
.emoji-search:focus {
  border-color: var(--accent);
}
.emoji-picker-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 0 8px 8px;
  scrollbar-width: thin;
  scrollbar-color: rgba(180,180,180,0.25) transparent;
}
.emoji-picker-body::-webkit-scrollbar {
  width: 4px;
}
.emoji-picker-body::-webkit-scrollbar-track {
  background: transparent;
}
.emoji-picker-body::-webkit-scrollbar-thumb {
  background: rgba(180,180,180,0.25);
  border-radius: 2px;
}
.emoji-picker-body::-webkit-scrollbar-thumb:hover {
  background: rgba(180,180,180,0.45);
}
.emoji-section-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 6px 2px 4px;
}
.emoji-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
  overflow: hidden;
}
.emoji-option {
  background: none;
  border: none;
  font-size: 22px;
  width: 36px;
  height: 36px;
  cursor: pointer;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s;
  padding: 0;
}
.emoji-option:hover {
  background: var(--bg-hover);
}
.slacko-option {
  font-size: 0; /* hide text fallback */
}
.slacko-img {
  width: 28px;
  height: 28px;
  object-fit: contain;
  border-radius: 3px;
}
.emoji-loading {
  font-size: 12px;
  color: var(--text-tertiary);
  padding: 6px 4px;
  display: block;
}

/* ── Reactions ── */
.message-reactions {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 0;
}
.message-reactions:not(:empty) {
  margin-top: 5px;
}
.reaction-bubble {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 10px;
  padding: 3px 8px 3px 6px;
  font-size: 16px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
  color: var(--text-primary);
  line-height: 1;
  height: 28px;
}
.reaction-bubble:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.22);
}
.reaction-bubble.reacted {
  background: rgba(88, 101, 242, 0.22);
  border-color: rgba(88, 101, 242, 0.55);
}
.reaction-img {
  width: 20px;
  height: 20px;
  object-fit: contain;
  border-radius: 2px;
}
.reaction-count {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  line-height: 1;
}
.react-btn {
  font-size: 15px;
  padding: 3px 6px;
  opacity: 0.8;
}
.react-btn:hover {
  opacity: 1;
}

/* ── Load-more indicator (infinite scroll) ── */
.load-more-indicator {
  text-align: center;
  padding: 10px 0;
  font-size: 12px;
  color: var(--text-tertiary);
  animation: pulse 1.4s infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 0.5; }
  50%       { opacity: 1;   }
}

/* ── Message attachments ── */
.msg-attachment {
  margin-top: 6px;
  margin-left: 8px;
  max-width: 480px;
}
.msg-image-wrap img.msg-image {
  display: block;
  max-width: 100%;
  max-height: 360px;
  border-radius: 6px;
  object-fit: contain;
  cursor: pointer;
  background: rgba(0,0,0,0.15);
}
.msg-video-wrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.msg-video {
  display: block;
  max-width: 100%;
  max-height: 360px;
  border-radius: 6px;
  background: #000;
  outline: none;
}
.msg-attachment-name {
  font-size: 12px;
  color: var(--text-tertiary);
  truncate: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
.msg-file-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-subtle);
  border-radius: 6px;
}
.msg-file-link {
  color: var(--accent);
  text-decoration: none;
  font-size: 13px;
  word-break: break-all;
}
.msg-file-link:hover { text-decoration: underline; }

/* ── Text / code file preview ── */
.msg-text-preview {
  margin-top: 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  max-width: 520px;
  background: var(--bg-elevated);
}
.msg-text-preview-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-secondary);
}
.msg-text-preview-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-primary);
  font-weight: 500;
}
.msg-text-preview-dl {
  color: var(--accent);
  text-decoration: none;
  font-size: 11px;
  flex-shrink: 0;
}
.msg-text-preview-dl:hover { text-decoration: underline; }
.msg-text-preview-pre {
  margin: 0;
  padding: 10px 12px;
  overflow-x: auto;
  font-size: 12px;
  line-height: 1.5;
  max-height: 140px;
  overflow-y: hidden;
}
.msg-text-preview.is-expanded .msg-text-preview-pre {
  max-height: none;
  overflow-y: visible;
}
.msg-text-preview-code {
  font-family: 'Consolas', 'Fira Code', monospace;
  white-space: pre;
}
.msg-text-preview-expand {
  display: block;
  width: 100%;
  padding: 5px;
  background: transparent;
  border: none;
  border-top: 1px solid var(--border);
  color: var(--accent);
  font-size: 12px;
  cursor: pointer;
  text-align: center;
}
.msg-text-preview-expand:hover { background: var(--bg-hover); }
.msg-text-preview-expand[hidden] { display: none; }

/* ── Composer outer wrap + attachment preview ── */
/* The rule that continues the one above the user pill across the chat pane. */
.composer-outer {
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.composer-attachment-preview {
  padding: 8px 20px 0;
}
/* ── Composer code preview ── */
.composer-preview {
  margin: 0 12px 6px;
  padding: 10px 14px;
  background: #1a1b1e;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: var(--radius-md);
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-primary);
  max-height: 220px;
  overflow-y: auto;
  scrollbar-width: thin;
}
.composer-preview .code-block-wrap {
  margin: 4px 0;
}
.composer-preview .inline-code {
  font-size: 12px;
}
.attach-preview-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 10px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-subtle);
  border-radius: 8px;
  max-width: 360px;
}
.attach-preview-img {
  width: 60px;
  height: 60px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
  background: rgba(0,0,0,0.2);
}
.attach-preview-video {
  width: 120px;
  height: 68px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
  background: #000;
}
.attach-preview-icon {
  flex-shrink: 0;
  color: var(--text-tertiary);
  margin-top: 4px;
}
.attach-preview-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.attach-preview-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.attach-preview-size {
  font-size: 11px;
  color: var(--text-tertiary);
}
.attach-preview-status {
  font-size: 11px;
  color: var(--text-tertiary);
}
.attach-preview-remove {
  background: none;
  border: none;
  color: var(--text-tertiary);
  cursor: pointer;
  font-size: 14px;
  padding: 2px 4px;
  line-height: 1;
  border-radius: 4px;
  flex-shrink: 0;
}
.attach-preview-remove:hover { color: var(--text-primary); background: var(--bg-hover); }

/* ── Composer attach button ── */
.composer-attach-btn {
  width: 36px;
  height: 36px;
  border: none;
  background: transparent;
  color: var(--text-tertiary);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}
.composer-attach-btn:hover { color: var(--text-primary); background: var(--bg-hover); }

/* ── Drag-and-drop overlay ── */
.drag-overlay {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 500;
  background: rgba(88, 101, 242, 0.10);
  border: 2px dashed var(--accent);
  border-radius: var(--radius-md);
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.drag-overlay.active {
  display: flex;
}
.drag-overlay-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
}
.drag-overlay-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 28px 48px;
  background: rgba(88, 101, 242, 0.12);
  border: 2px solid var(--accent);
  border-radius: var(--radius-md);
  font-size: 18px;
  font-weight: 600;
  text-shadow: 0 1px 4px rgba(0,0,0,0.4);
}

/* ── Lightbox overlay ── */
.lightbox-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox-overlay[hidden] { display: none; }
.lightbox-bg {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  cursor: pointer;
}
.lightbox-img-wrap {
  position: relative;
  z-index: 1;
  max-width: 90vw;
  max-height: 90vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox-img {
  display: block;
  max-width: 90vw;
  max-height: 90vh;
  border-radius: 6px;
  object-fit: contain;
  user-select: none;
}
.lightbox-toolbar {
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 2;
  display: flex;
  gap: 8px;
  align-items: center;
}
.lightbox-btn {
  background: rgba(0, 0, 0, 0.6);
  border: none;
  color: #fff;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background 0.15s;
  flex-shrink: 0;
}
.lightbox-btn:hover { background: rgba(0, 0, 0, 0.85); }

/* ── Inline image/GIF embeds (URL in message text) ── */
.msg-inline-img-wrap { margin-top: 6px; margin-left: 8px; }
.msg-inline-img {
  display: block;
  max-width: 100%;
  max-height: 360px;
  border-radius: 6px;
  object-fit: contain;
  cursor: pointer;
  background: rgba(0, 0, 0, 0.15);
}

/* ── Link preview card ── */
.link-preview-card {
  display: flex;
  gap: 12px;
  margin-top: 8px;
  margin-left: 8px;
  max-width: 480px;
  background: var(--bg-secondary);
  border-left: 4px solid var(--accent);
  border-radius: 4px;
  padding: 10px 12px;
  overflow: hidden;
}
.link-preview-thumb {
  width: 80px;
  height: 80px;
  flex-shrink: 0;
  object-fit: cover;
  border-radius: 4px;
  background: var(--bg-tertiary);
}
.link-preview-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  justify-content: center;
}
.link-preview-site {
  font-size: 11px;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.link-preview-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.link-preview-title:hover { text-decoration: underline; }
.link-preview-desc {
  font-size: 12px;
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Video embed link (shown above all video embeds) ── */
.video-embed-link {
  display: block;
  margin-bottom: 4px;
  font-size: 13px;
  word-break: break-all;
}

/* ── YouTube embed card ── */
.yt-embed { display: block; margin: 6px 0; max-width: 480px; }
.yt-thumb-wrap {
  position: relative;
  aspect-ratio: 16/9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: #000;
  cursor: pointer;
}
.yt-thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.yt-play-btn {
  position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; background: transparent; border: none; cursor: pointer;
  transition: transform 0.1s;
}
.yt-play-btn:hover { transform: scale(1.1); }
.yt-loading {
  display: flex; align-items: center; justify-content: center;
  height: 100%; color: var(--text-tertiary); font-size: 13px;
}
.yt-player {
  width: 100%; aspect-ratio: 16/9; display: block;
  border: none; background: #000;
}

/* ── Instagram reel card (click-to-play, mirrors YouTube card) ── */
.ig-embed { display: block; margin: 6px 0; width: 325px; max-width: 100%; }
.ig-thumb-wrap {
  position: relative;
  aspect-ratio: 9/16;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: #111;
  cursor: pointer;
}
.ig-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ig-thumb-loading {
  width: 100%;
  height: 100%;
  background: #1c1c1e;
}
.ig-play-btn {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  cursor: pointer;
  transition: transform 0.1s;
}
.ig-play-btn:hover { transform: scale(1.1); }
.ig-player {
  width: 100%;
  height: 100%;
  display: block;
  background: #000;
}

/* ── TikTok Reel embed (portrait iframe) ── */
.reel-embed {
  display: block;
  margin: 6px 0;
  width: 325px;
  max-width: 100%;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: #000;
}
.reel-thumb-wrap {
  width: 100%;
  min-height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
}
/* Native <video> element for reels */
.reel-thumb-wrap video.reel-player {
  display: block;
  width: 100%;
  max-height: 600px;
  border: none;
  background: #000;
}
/* TikTok iframe */
iframe.reel-player {
  display: block;
  width: 100%;
  height: 575px;
  border: none;
  background: #000;
}
.reel-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  color: var(--text-tertiary);
  font-size: 13px;
  text-align: center;
}

/* ── Server icon image (custom icon / GIF) ── */
.server-icon-img, .server-icon-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  pointer-events: none;
}

/* ── Server settings: icon upload ── */
.server-icon-upload-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
}
.server-icon-preview {
  width: 64px;
  height: 64px;
  border-radius: var(--radius-md);
  background: var(--bg-elevated) center/cover no-repeat;
  border: 1px solid var(--border);
  flex-shrink: 0;
}

/* ── Add-server choice modal: secondary button ── */
.invite-submit-secondary {
  background: var(--bg-elevated);
  color: var(--text-secondary);
  margin-top: 8px;
  border: 1px solid var(--border);
}
.invite-submit-secondary:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

/* ─── DM Hub & Server List Divider ────────────────────────────────────────── */
.dm-hub-icon {
  width: var(--dm-hub-size);
  height: var(--dm-hub-size);
  margin-top: calc((var(--main-header-height) - var(--dm-hub-size)) / 2);
  border-radius: 50%;
  background: var(--bg-elevated);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  border: none;
  transition: border-radius 0.15s ease, background 0.15s ease;
  overflow: visible;
  flex-shrink: 0;
  position: relative;
}
.dm-hub-icon:hover,
.dm-hub-icon.active {
  border-radius: 30%;
  background: var(--accent);
}
/* Unread DM count badge on the server-list DM hub button */
.dm-hub-badge {
  position: absolute;
  bottom: -4px;
  right: -4px;
  background: #111;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 8px;
  padding: 0 4px;
  min-width: 16px;
  height: 16px;
  line-height: 16px;
  text-align: center;
  box-sizing: border-box;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
  border: 2px solid var(--bg-sidebar, #1e1f22);
}
.dm-hub-img {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 50%;
  pointer-events: none;
}
/* The same gap the button has below it, less the separator's own pixel, so it
   lands on the header band's last row — level with the rule under the channel
   header and with the main header's bottom border. */
.server-list-divider {
  width: 32px;
  height: 1px;
  background: var(--border);
  margin: calc((var(--main-header-height) - var(--dm-hub-size)) / 2 - 1px) auto 0;
  flex-shrink: 0;
}

/* ─── DM Panel ─────────────────────────────────────────────────────────────── */
/* By default the DM panel is hidden; the server channel UI is shown */
.dm-panel {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.server-channel-ui {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
/* When .dm-mode is on the aside, swap visibility */
.channel-list.dm-mode .dm-panel {
  display: flex;
}
.channel-list.dm-mode .server-channel-ui {
  display: none;
}
.dm-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 12px 8px;
  font-weight: 600;
  font-size: 13px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  flex-shrink: 0;
}
.dm-panel-title {
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.dm-new-btn {
  color: var(--text-secondary);
}
.dm-new-btn:hover {
  color: var(--text-primary);
}
.dm-list {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  flex: 1;
}
.dm-item {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 1px 6px;
  padding: 8px 10px 8px 4px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.1s;
}
.dm-item:hover,
.dm-item.active {
  background: var(--bg-hover);
}
.dm-item.muted .dm-item-name {
  color: var(--text-secondary);
}
.dm-item-avatar {
  position: relative;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--accent-muted, rgba(88,101,242,0.2));
  color: var(--accent, #5865F2);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  flex-shrink: 0;
  text-transform: uppercase;
}
.dm-item-info {
  flex: 1;
  min-width: 0;
}
.dm-item-name {
  font-size: 12px;
  font-weight: 500;
  line-height: 1.25;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dm-item-muted {
  margin-top: 2px;
  font-size: 11px;
  color: var(--text-muted, #72767d);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dm-item-preview {
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ─── @mention chips ───────────────────────────────────────────────────────── */
.msg-mention {
  background: rgba(88, 101, 242, 0.2);
  color: #7289da;
  border-radius: 3px;
  padding: 0 3px;
  font-weight: 500;
  cursor: default;
}
.msg-mention-self {
  background: rgba(250, 168, 26, 0.25);
  color: #faa81a;
}
.msg-mention-role {
  background: rgba(114, 137, 218, 0.15);
  color: #7289da;
}
.message-group.self-mentioned {
  background: rgba(250, 168, 26, 0.04);
  border-left: 2px solid #faa81a;
  padding-left: 10px;
  margin-left: -12px;
}

/* ─── @mention autocomplete popup ─────────────────────────────────────────── */
.mention-popup {
  position: fixed;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 6px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
  z-index: 500;
  min-width: 220px;
  max-height: 280px;
  overflow-y: auto;
}
.mention-list {
  list-style: none;
  margin: 0;
  padding: 4px 0;
}
.mention-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  cursor: pointer;
  font-size: 14px;
}
.mention-item:hover,
.mention-item.active {
  background: var(--bg-hover);
}
.mention-item-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent-muted, rgba(88,101,242,0.2));
  color: var(--accent, #5865F2);
  font-size: 11px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-transform: uppercase;
}
.mention-item-label {
  font-weight: 500;
  color: var(--text-primary);
}
.mention-item-tag {
  font-size: 11px;
  color: var(--text-tertiary, var(--text-secondary));
}
.mention-item-role-badge {
  font-size: 10px;
  background: var(--accent-muted, rgba(88,101,242,0.15));
  color: var(--accent, #5865F2);
  border-radius: 3px;
  padding: 1px 4px;
  font-weight: 600;
}

/* ─── DM search modal ─────────────────────────────────────────────────────── */
.dm-search-results {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  max-height: 240px;
  overflow-y: auto;
}
.dm-search-results li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  cursor: pointer;
  border-radius: 6px;
  transition: background 0.1s;
}
.dm-search-results li:hover {
  background: var(--bg-hover);
}
.dm-search-result-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--accent-muted, rgba(88,101,242,0.2));
  color: var(--accent, #5865F2);
  font-size: 13px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  text-transform: uppercase;
}
.dm-search-result-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
}
.dm-search-result-tag {
  font-size: 12px;
  color: var(--text-secondary);
}

/* ─── Modal overlay (generic) ─────────────────────────────────────────────── */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 400;
}
.modal-overlay[hidden] {
  display: none;
}
.modal-box {
  background: var(--bg-elevated);
  border-radius: var(--radius, 8px);
  border: 1px solid var(--border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
  min-width: 440px;
  max-width: 560px;
  width: 100%;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 20px 12px;
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  flex-shrink: 0;
}
.modal-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.modal-close-btn {
  font-size: 18px;
  color: var(--text-secondary);
  width: 28px;
  height: 28px;
}
.modal-close-btn:hover {
  color: var(--text-primary);
}

/* ─── DM New Message modal ─────────────────────────────────────────────────── */
.dm-new-modal-box {
  min-width: 460px;
  max-width: 600px;
}
.dm-people-modal-box {
  min-width: 460px;
  max-width: 620px;
}
.dm-rename-modal-box {
  min-width: 420px;
  max-width: 520px;
  transform-origin: left center;
  animation: dmRenameWipeIn 120ms ease-out;
}
.dm-rename-body {
  padding: 0 20px 12px;
}
.dm-rename-label {
  display: block;
  margin-bottom: 8px;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.dm-rename-error {
  margin: 8px 0 0;
  color: #ed4245;
  font-size: 12px;
}
@keyframes dmRenameWipeIn {
  from {
    clip-path: inset(0 100% 0 0);
    opacity: 0.7;
    transform: translateX(-6px);
  }
  to {
    clip-path: inset(0 0 0 0);
    opacity: 1;
    transform: translateX(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .dm-rename-modal-box {
    animation: none;
  }
}
.dm-people-controls {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  padding: 0 20px 12px;
}
.dm-history-select {
  width: 100%;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  font-size: 13px;
  padding: 8px 10px;
  outline: none;
}
.dm-people-list {
  max-height: 340px;
  overflow-y: auto;
}
.dm-people-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px 18px;
  border-top: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 13px;
}
.dm-people-checkbox {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
}
.dm-search-wrap {
  padding: 0 20px 12px;
  flex-shrink: 0;
}
.dm-search-bar {
  width: 100%;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  font-size: 14px;
  padding: 8px 12px;
  outline: none;
  box-sizing: border-box;
}
.dm-search-bar:focus {
  border-color: var(--accent, #5865F2);
}
.dm-modal-tabs {
  display: flex;
  gap: 4px;
  padding: 0 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.dm-modal-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-secondary);
  font-size: 14px;
  font-weight: 500;
  padding: 8px 12px;
  cursor: pointer;
  margin-bottom: -1px;
  transition: color 0.15s, border-color 0.15s;
  display: flex;
  align-items: center;
  gap: 6px;
}
.dm-modal-tab:hover { color: var(--text-primary); }
.dm-modal-tab.active {
  color: var(--text-primary);
  border-bottom-color: var(--accent, #5865F2);
}
.dm-requests-badge {
  background: #ed4245;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border-radius: 10px;
  padding: 1px 5px;
  min-width: 16px;
  text-align: center;
}

/* ── Unread message count badges ─────────────────────────────────────── */
.server-icon-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.unread-badge {
  background: #111;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 8px;
  padding: 0 4px;
  min-width: 16px;
  height: 16px;
  line-height: 16px;
  text-align: center;
  box-sizing: border-box;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}
/* Server icon: bottom-right corner, bordered to lift off the icon */
.server-icon-wrap .unread-badge {
  position: absolute;
  bottom: -3px;
  right: -3px;
  border: 2px solid var(--bg-sidebar, #1e1f22);
}
/* DM item: pushed to the far right of the flex row */
.dm-item .unread-badge {
  flex-shrink: 0;
  margin-left: auto;
}

.channel-item .unread-badge {
  flex-shrink: 0;
  margin-left: auto;
}
.dm-tab-panel {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0;
}
.dm-tab-panel[hidden] {
  display: none;
}
.dm-friends-list {
  list-style: none;
  margin: 0;
  padding: 0 8px;
}
.dm-friend-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: 6px;
  cursor: default;
  transition: background 0.1s;
}
.dm-friend-item:hover { background: var(--bg-hover); }
.dm-friend-avatar {
  position: relative;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--accent-muted, rgba(88,101,242,0.2));
  color: var(--accent, #5865F2);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 600;
  flex-shrink: 0;
  text-transform: uppercase;
}
.dm-friend-info {
  flex: 1;
  min-width: 0;
}
.dm-friend-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text-primary);
}
.dm-friend-tag {
  font-size: 12px;
  color: var(--text-secondary);
}
.dm-friend-actions {
  display: flex;
  gap: 6px;
}
.dm-friend-action-btn {
  padding: 5px 12px;
  border-radius: 4px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  border: none;
  transition: background 0.1s, color 0.1s;
}
.dm-friend-action-btn.primary {
  background: var(--accent, #5865F2);
  color: #fff;
}
.dm-friend-action-btn.primary:hover {
  background: var(--accent-hover, #4752c4);
}
.dm-friend-action-btn.secondary {
  background: var(--bg-hover);
  color: var(--text-primary);
  border: 1px solid var(--border);
}
.dm-friend-action-btn.secondary:hover {
  background: var(--bg-secondary);
}
.dm-friend-action-btn.danger {
  background: none;
  color: #ed4245;
  border: 1px solid #ed4245;
}
.dm-friend-action-btn.danger:hover {
  background: rgba(237,66,69,0.1);
}
.dm-modal-empty {
  text-align: center;
  color: var(--text-secondary);
  font-size: 14px;
  padding: 32px 20px;
}

/* ─── Right-click context menu ─────────────────────────────────────────────── */
.context-menu {
  position: fixed;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm, 6px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
  z-index: 600;
  min-width: 180px;
  padding: 4px 0;
  user-select: none;
}
.context-menu[hidden] {
  display: none;
}
.context-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 14px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-primary);
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  transition: background 0.1s;
}
.context-menu-item:hover {
  background: var(--bg-hover);
}
.context-menu-item-danger {
  color: #ed4245;
}
.context-menu-item-danger:hover {
  background: rgba(237,66,69,0.1);
}
.context-menu-label {
  padding: 6px 14px 4px;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.dm-context-menu {
  min-width: 220px;
}

/* ── Voice participant context menu ─────────────────────────────────────────── */
.voice-ctx-menu { min-width: 220px; }
.voice-ctx-header {
  padding: 4px 12px 2px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.voice-ctx-volume-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px 8px;
}
.voice-ctx-volume-row input[type=range] { flex: 1; }
#voice-ctx-volume-label {
  font-size: 11px;
  color: var(--text-secondary);
  min-width: 36px;
  text-align: right;
}
.voice-ctx-local-mute-row {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.voice-ctx-local-mute-row input[type=checkbox] { pointer-events: none; }
.context-menu-divider { height: 1px; background: var(--border); margin: 4px 0; }

.ctx-dm-quick-wrap {
  padding: 6px 8px 2px;
}
.ctx-dm-input {
  width: 100%;
  box-sizing: border-box;
  padding: 6px 10px;
  font-size: 13px;
  background: var(--bg-tertiary, #1e1f22);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-primary);
  outline: none;
  font-family: inherit;
}
.ctx-dm-input::placeholder { color: var(--text-muted, #72767d); }
.ctx-dm-input:focus { border-color: var(--accent, #5865f2); }

/* Lock icon on mute/deafen buttons when server-applied */
.icon-btn.server-locked { position: relative; }
.icon-btn.server-locked::after {
  content: '🔒';
  position: absolute;
  bottom: -2px;
  right: -2px;
  font-size: 9px;
  line-height: 1;
  pointer-events: none;
}

/* Video badge on voice participant */
.voice-participant-video {
  color: #3ba55d;
}
.voice-participant-video::before {
  content: '📹';
  font-size: 11px;
}

.voice-participant-screen {
  color: #57f287;
}
.voice-participant-screen::before {
  content: '▣';
  font-size: 12px;
}

/* Lock badge on voice participant */
.voice-participant-server-locked {
  font-size: 10px;
  opacity: 0.8;
}

/* ── Toast notifications ─────────────────────────────────────────────────────── */
.toast-container {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 10000;
  pointer-events: none;
}
.toast {
  background: #111;
  color: #fff;
  font-size: 13px;
  padding: 8px 16px;
  border-radius: 6px;
  opacity: 0;
  transition: opacity 0.2s ease;
  max-width: 320px;
  text-align: center;
  pointer-events: none;
  white-space: pre-wrap;
}
.toast.toast-visible { opacity: 1; }

/* ── Splash / update-check overlay ──────────────────────────────────────────── */
.splash-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--bg-base, #0d0e10);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.3s ease;
}
.splash-overlay.hidden {
  opacity: 0;
  pointer-events: none;
}
.splash-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}
.splash-logo {
  width: 80px;
  height: 80px;
  border-radius: 18px;
}
.splash-app-name {
  font-size: 26px;
  font-weight: 700;
  color: var(--text-primary, #e8e9ea);
  letter-spacing: 0.5px;
}
.splash-status {
  font-size: 13px;
  color: var(--text-secondary, #8b8d92);
}
.splash-spinner {
  width: 26px;
  height: 26px;
  border: 3px solid rgba(255, 255, 255, 0.15);
  border-top-color: var(--accent, #7c8bff);
  border-radius: 50%;
  animation: splash-spin 0.8s linear infinite;
}
@keyframes splash-spin {
  to { transform: rotate(360deg); }
}

/* ——— Avatar shared overrides ——— */
.dm-item-avatar { position: relative; }
.user-avatar    { position: relative; }
.voice-stage-tile-avatar { position: relative; }

/* Settings avatar — make it clickable with an upload overlay */
.settings-avatar-large {
  position: relative;
  cursor: pointer;
}
.settings-avatar-upload-hint {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: rgba(0,0,0,0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.15s;
  font-size: 10px;
  font-weight: 600;
  color: #fff;
  text-align: center;
  line-height: 1.2;
  pointer-events: none;
}
.settings-avatar-large:hover .settings-avatar-upload-hint {
  opacity: 1;
}

/* ——— Avatar crop modal ——— */
.avatar-crop-overlay {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0,0,0,0.75);
}
.avatar-crop-overlay[hidden] { display: none !important; }
.avatar-crop-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 340px;
  max-width: calc(100vw - 32px);
}
.avatar-crop-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
}
.avatar-crop-canvas-wrap {
  position: relative;
  width: 256px;
  height: 256px;
  margin: 0 auto;
  border-radius: 50%;
  overflow: hidden;
  background: #111;
  cursor: grab;
}
.avatar-crop-canvas-wrap:active { cursor: grabbing; }
.avatar-crop-canvas {
  position: absolute;
  top: 0; left: 0;
  touch-action: none;
}
.avatar-crop-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 4px var(--accent);
  pointer-events: none;
}
.avatar-crop-zoom-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}
.avatar-crop-zoom-wrap label {
  font-size: 12px;
  color: var(--text-secondary);
  flex-shrink: 0;
}
.avatar-crop-zoom {
  flex: 1;
  accent-color: var(--accent);
}
.avatar-crop-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.avatar-crop-save {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  padding: 8px 18px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.avatar-crop-save:hover { opacity: 0.85; }
.avatar-crop-cancel {
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  font-size: 14px;
  cursor: pointer;
}
.avatar-crop-cancel:hover { background: var(--bg-hover); }

/* ── Theme picker (User Settings › Chat) ─────────────────────────────────── */
.theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 10px;
  margin-top: 10px;
}
.theme-option {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.theme-option:hover { background: var(--bg-hover); }
.theme-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.theme-option:has(input:checked),
.theme-option.is-selected {
  border-color: var(--accent);
  background: var(--accent-muted);
}
.theme-option:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.theme-name {
  font-size: 12px;
  color: var(--text-secondary);
  text-align: center;
}
.theme-option:has(input:checked) .theme-name,
.theme-option.is-selected .theme-name { color: var(--text-primary); }
.theme-swatch {
  width: 100%;
  height: 44px;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.theme-swatch--onyx     { background: linear-gradient(135deg, #141518 0 62%, #7c8bff 62% 100%); }
.theme-swatch--midnight { background: linear-gradient(135deg, #10131f 0 62%, #5c7cfa 62% 100%); }
.theme-swatch--slate    { background: linear-gradient(135deg, #1e1f23 0 62%, #7d8aa3 62% 100%); }
.theme-swatch--nord     { background: linear-gradient(135deg, #3b4252 0 62%, #88c0d0 62% 100%); }
.theme-swatch--crimson  { background: linear-gradient(135deg, #171416 0 62%, #f0616d 62% 100%); }
.theme-swatch--forest   { background: linear-gradient(135deg, #131715 0 62%, #4fb477 62% 100%); }
.theme-swatch--light    { background: linear-gradient(135deg, #ffffff 0 62%, #5865f2 62% 100%); border-color: rgba(0, 0, 0, 0.12); }
.theme-swatch--contrast { background: linear-gradient(135deg, #0a0a0a 0 62%, #ffd400 62% 100%); }

/* ── Channel categories (sidebar) ────────────────────────────────────────── */
.channel-category {
  list-style: none;
  margin: 10px 6px 2px;
}
.channel-category:first-child { margin-top: 4px; }
.channel-category-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  padding: 4px 8px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-tertiary);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: left;
  cursor: pointer;
  transition: color 0.12s ease, background 0.12s ease;
}
.channel-category-toggle:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}
.channel-category-chevron {
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.channel-category.collapsed .channel-category-chevron { transform: rotate(-90deg); }
.channel-category-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.channel-in-category[hidden] { display: none; }

/* Create-channel modal rows */
.create-channel-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
}
.create-channel-label {
  min-width: 64px;
  font-size: 12px;
  color: var(--text-secondary);
}
.create-channel-select { flex: 1; }

/* Channel drag-and-drop reordering (Manage Channels) */
.channel-items > li.drag-source > a { opacity: 0.4; }
.channel-items > li.drop-before > a { box-shadow: inset 0 2px 0 0 var(--accent); }
.channel-items > li.drop-after > a { box-shadow: inset 0 -2px 0 0 var(--accent); }
.channel-category.drop-target .channel-category-toggle {
  background: var(--accent-muted);
  color: var(--text-primary);
}

/* ── Notification settings ────────────────────────────────────────────────── */
.channel-item.muted { opacity: 0.55; }
.notif-level-options { display: flex; gap: 16px; flex-wrap: wrap; }
.notif-level-options-stack { flex-direction: column; gap: 8px; margin: 6px 0 12px; }
.notif-overrides-list { list-style: none; margin: 8px 0 0; padding: 0; }
.notif-override-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-secondary);
  margin-bottom: 6px;
}
.notif-override-scope { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--text-primary); }
.notif-override-detail { font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
.notif-override-remove { padding: 4px 10px; font-size: 12px; }
.notif-overrides-empty[hidden] { display: none; }
#server-notif-status { margin-left: 10px; }

/* ── Message search ───────────────────────────────────────────────────────── */
.search-popover {
  position: fixed;
  z-index: 650;
  width: min(440px, calc(100vw - 16px));
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  padding: 10px 12px;
}
.search-popover[hidden] { display: none; }
.search-popover-section + .search-popover-section { border-top: 1px solid var(--border); margin-top: 10px; padding-top: 10px; }
.search-popover-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
  margin-bottom: 8px;
}
.search-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.search-chip {
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  color: var(--text-primary);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
}
.search-chip span { color: var(--text-secondary); }
.search-chip:hover { background: var(--bg-hover); border-color: var(--text-tertiary); }
.search-custom-toggle {
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
}
.search-custom { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.search-row { display: flex; align-items: center; gap: 10px; }
.search-label { min-width: 68px; font-size: 12px; color: var(--text-secondary); }
.search-row .invite-input, .search-row .settings-select { flex: 1; min-width: 0; }
.search-checks { display: flex; gap: 14px; font-size: 12px; color: var(--text-primary); }
.search-checks label { display: flex; align-items: center; gap: 4px; }
.search-row-actions { justify-content: flex-end; gap: 8px; margin-top: 4px; }
.search-row-actions .invite-submit { width: auto; padding: 6px 14px; }
.search-popover-hint { margin: 10px 0 0; font-size: 11px; color: var(--text-tertiary); }
.search-popover-hint code { color: var(--text-secondary); }

.search-results {
  position: fixed;
  right: 0;
  z-index: 640;
  width: min(400px, 100vw);
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
  border-left: 1px solid var(--border);
  box-shadow: -6px 0 20px rgba(0, 0, 0, 0.25);
}
.search-results[hidden] { display: none; }
.search-results-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.search-results-title { font-size: 14px; font-weight: 700; color: var(--text-primary); }
.search-results-scope { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.search-results-body { flex: 1; overflow-y: auto; padding: 10px 12px 16px; }
.search-status { font-size: 12px; color: var(--text-secondary); padding: 6px 2px 10px; }
.search-results-list { display: flex; flex-direction: column; gap: 8px; }
.search-result {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.search-result:hover { background: var(--bg-hover); border-color: var(--text-tertiary); }
.search-result-meta { display: flex; align-items: baseline; gap: 8px; }
.search-result-author { font-size: 13px; font-weight: 600; color: var(--text-primary); }
.search-result-time { font-size: 11px; color: var(--text-tertiary); }
.search-result-channel { font-size: 11px; color: var(--accent); margin: 2px 0 6px; }
.search-result-body { font-size: 13px; color: var(--text-primary); line-height: 1.4; word-break: break-word; }
.search-result-body img, .search-result-body video { max-width: 100%; }
.search-load-more { margin-top: 10px; }

.message-group.message-jump-highlight {
  animation: message-jump-flash 2.5s ease-out;
}
@keyframes message-jump-flash {
  0% { background: var(--accent-muted); }
  100% { background: transparent; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Mobile layout
   ───────────────────────────────────────────────────────────────────────────
   Phones get the same markup, re-arranged: the left panel (servers, channels,
   call controls, user pill) and the members list become drawers over a
   full-width conversation, reachable by button or edge swipe. Desktop is
   unaffected — the Electron window has a 900px minimum, below the breakpoint.
   ═══════════════════════════════════════════════════════════════════════════ */

/* `.icon-btn` sets `display: flex`, which outranks the user-agent rule for the
   `hidden` attribute — so buttons the app hides (the DM call actions in a
   server channel, the in-call video and screen-share toggles) were still being
   painted. Restoring `hidden` matters most on a phone header, where those
   buttons crowd out the channel name, but it is a fix on every screen size. */
.icon-btn[hidden] {
  display: none !important;
}

/* Mobile-only chrome stays out of the way on wide screens. */
.mobile-nav-btn,
.mobile-members-btn,
.mobile-scrim,
.mobile-call-bar {
  display: none;
}

/* The same override applies to the elements introduced below, which are shown
   by media query but must still obey `hidden`. */
.mobile-scrim[hidden],
.mobile-call-bar[hidden] {
  display: none !important;
}

@media (max-width: 860px) {
  /* Dynamic viewport units track the browser's collapsing toolbars, so the
     composer is not pushed under the address bar. */
  #app {
    height: 100vh;
    height: 100dvh;
    /* The on-screen keyboard shrinks the visual viewport but not the layout
       viewport, so dvh still measures the full screen and the composer ends up
       floating above a band of dead space. --app-height is set from the visual
       viewport while a keyboard is open (see app.js). */
    height: var(--app-height, 100dvh);
    position: relative;
    overflow: hidden;
  }

  .main-area {
    width: 100%;
    min-width: 0;
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
  }

  /* ── Drawers ── */
  .left-panel,
  .members-list {
    position: fixed;
    top: 0;
    bottom: 0;
    z-index: 60;
    transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
    will-change: transform;
  }
  .left-panel {
    left: 0;
    width: min(86vw, 336px);
    transform: translateX(-100%);
    box-shadow: 8px 0 28px rgba(0, 0, 0, 0.45);
    padding-left: env(safe-area-inset-left);
  }
  .members-list {
    right: 0;
    width: min(80vw, 300px);
    min-width: 0;
    transform: translateX(100%);
    box-shadow: -8px 0 28px rgba(0, 0, 0, 0.45);
    padding-right: env(safe-area-inset-right);
  }
  body.mobile-nav-open .left-panel,
  body.mobile-members-open .members-list {
    transform: translateX(0);
  }
  /* While dragging, the drawer follows the finger without easing. */
  body.mobile-swiping .left-panel,
  body.mobile-swiping .members-list {
    transition: none;
  }

  /* The channel list fills whatever the rail leaves rather than holding its
     desktop width, which would overflow the drawer. */
  .left-panel .channel-list,
  .channel-list {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    max-width: none;
  }

  .mobile-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgba(0, 0, 0, 0.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity 200ms ease;
  }
  body.mobile-nav-open .mobile-scrim,
  body.mobile-members-open .mobile-scrim {
    opacity: 1;
    pointer-events: auto;
  }

  /* ── Header ── */
  .main-header {
    padding: 0 6px;
    gap: 4px;
    position: relative;
  }
  .mobile-nav-btn,
  .mobile-members-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    color: var(--text-secondary);
  }
  .mobile-nav-btn:hover,
  .mobile-members-btn:hover {
    color: var(--text-primary);
  }
  .main-channel-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 15px;
  }
  .main-header-actions {
    gap: 2px;
    min-width: 0;
    flex: 0 0 auto;
  }
  /* Search keeps a magnifier and enough width to be recognisable as a search
     field, rather than shrinking to an unlabelled box. It still expands across
     the header on focus, so typing has room. */
  .main-header-search {
    width: 132px;
    flex: 0 1 132px;
    min-width: 0;
    padding: 8px 10px 8px 30px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%238a8d93'%3E%3Cpath d='M15.5 14h-.79l-.28-.27A6.47 6.47 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19zm-6 0A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14z'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 9px center;
    background-size: 14px 14px;
    transition: width 180ms ease;
  }
  .main-header-search:focus {
    flex: none;
  }
  .main-header-search:focus {
    position: absolute;
    left: 6px;
    right: 6px;
    width: auto;
    z-index: 6;
  }

  /* ── Touch targets ── */
  .icon-btn {
    min-width: 36px;
    min-height: 36px;
  }
  .channel-item,
  .dm-item,
  .server-icon {
    touch-action: manipulation;
  }

  /* ── Dialogs ──
     Every modal box carries a desktop minimum width (440–460px), which is
     wider than a phone screen — so "New Message" and its siblings spilled off
     both edges. Drop the minimum and leave a margin so a dialog reads as a
     window on top of the app rather than filling it. */
  .modal-overlay {
    padding: 16px;
  }
  .modal-box,
  .dm-new-modal-box,
  .dm-people-modal-box,
  .dm-rename-modal-box {
    min-width: 0;
    width: 100%;
    max-width: 100%;
    max-height: calc(100dvh - 32px);
  }
  .modal-header {
    padding-left: 14px;
    padding-right: 8px;
  }
  .dm-search-wrap {
    padding-left: 14px;
    padding-right: 14px;
  }

  /* ── Direct messages ──
     A DM row spends most of its width on fixed boxes: the avatar, the gaps and
     the unread badge. In portrait that left barely enough for a name, so group
     conversations — whose name is every participant joined together — were cut
     off. Trim the fixed parts and let the name use two lines instead of being
     clipped to one. */
  /* Narrow the workspace rail by moving the variable rather than the element:
     the footer's "+" column and the divider between rail and channel list are
     both sized from it, and overriding only .server-list left them 8px wider
     than the rail above them. */
  :root {
    --server-list-width: 48px;
  }
  .dm-panel-header {
    padding: 12px 10px 6px;
  }
  .dm-item {
    margin: 1px 4px;
    padding: 6px 8px 6px 4px;
    gap: 8px;
  }
  .dm-item-avatar {
    width: 30px;
    height: 30px;
  }
  .dm-item-name {
    font-size: 13px;
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .channel-item {
    min-height: 40px;
  }

  /* ── Docked call controls ──
     Part of the main column's flow, so it never covers the composer. */
  .mobile-call-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding: 8px 10px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom));
    background: var(--bg-secondary);
    border-top: 1px solid var(--border);
  }
  .mobile-call-open {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
    padding: 4px 6px;
    background: none;
    border: 0;
    border-radius: var(--radius-sm);
    color: var(--online, #3ba55d);
    text-align: left;
    cursor: pointer;
  }
  .mobile-call-open:hover {
    background: var(--bg-hover);
  }
  .mobile-call-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
  }
  .mobile-call-channel {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .mobile-call-status {
    font-size: 11px;
    color: var(--online, #3ba55d);
  }
  .mobile-call-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
  }
  .mobile-call-btn {
    width: 40px;
    height: 40px;
    color: var(--text-secondary);
  }
  .mobile-call-btn.active {
    color: var(--danger, #ed4245);
  }
  .mobile-call-hangup {
    color: #fff;
    background: var(--danger, #ed4245);
  }
  .mobile-call-hangup:hover {
    background: #c03537;
  }

  /* ── Content density ── */
  .messages-container {
    padding-left: 10px;
    padding-right: 10px;
  }
  .composer-outer {
    padding: 8px 10px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom));
  }
  /* The stage is the whole screen on a phone; its own narrow rules handle
     tile sizing. */
  .voice-stage-header {
    padding: 8px 10px;
  }
  /* Touch has no hover, so the stage's own controls must stay on screen
     instead of waiting for a pointer that never arrives. */
  .voice-stage-controls {
    opacity: 1;
    pointer-events: auto;
    transform: none;
  }
  /* Popping the stage into a second window needs the desktop shell. */
  #voice-stage-undock {
    display: none;
  }
}

/* Very narrow phones: the search field gives up width but stays present and
   still shows its magnifier. Hiding it here used to leave no way to search at
   all, since the field is the only entry point to the search popover. */
@media (max-width: 400px) {
  .main-header-search {
    width: 104px;
    flex: 0 1 104px;
    padding-right: 6px;
  }
  .left-panel {
    width: min(92vw, 320px);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Mobile settings and back navigation
   ═══════════════════════════════════════════════════════════════════════════ */

/* The drill-down back control only exists on narrow screens, where the two
   panes are shown one at a time. */
.settings-back-btn {
  display: none;
}

@media (max-width: 860px) {
  /* ── Workspace switch animation ──
     The drawers are positioned by `transform`, and an animation's transform
     wins over a declared one. Running the workspace drop/lift on them would
     therefore slide a drawer into view for the length of the animation, which
     is what flashed when switching between servers and direct messages. The
     conversation still animates; only the drawers opt out. */
  #app.workspace-transition-down .channel-list,
  #app.workspace-transition-up .channel-list,
  #app.workspace-transition-down .members-list,
  #app.workspace-transition-up .members-list {
    animation: none !important;
  }

  /* ── One pane at a time ──
     Both settings surfaces are a nav list beside a content pane. On a phone
     that split leaves neither readable, so the nav becomes a full-screen menu
     and a chosen entry replaces it, with the header offering the way back. */
  .settings-overlay {
    padding: 0;
  }
  .settings-panel {
    width: 100%;
    max-width: none;
    height: 100vh;
    height: 100dvh;
    max-height: none;
    border: 0;
    border-radius: 0;
  }
  .settings-header,
  .server-settings-header {
    gap: 4px;
    padding-left: 6px;
    padding-top: env(safe-area-inset-top);
  }
  .settings-body,
  .server-settings-body {
    flex-direction: column;
  }

  /* Menu view: the nav fills the panel as a list of rows. */
  .settings-nav,
  .server-settings-nav {
    width: 100%;
    min-width: 0;
    max-width: none;
    flex: 1;
    border-right: 0;
    overflow-y: auto;
    padding: 8px 0;
    padding-bottom: calc(8px + env(safe-area-inset-bottom));
  }
  .settings-nav-item,
  .server-settings-nav-item {
    min-height: 48px;
    padding: 12px 16px;
    font-size: 15px;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  /* A chevron marks each row as leading somewhere. */
  .settings-nav-item::after,
  .server-settings-nav-item::after {
    content: "";
    width: 7px;
    height: 7px;
    margin-left: 12px;
    flex: 0 0 auto;
    border-right: 2px solid var(--text-tertiary);
    border-bottom: 2px solid var(--text-tertiary);
    transform: rotate(-45deg);
  }
  /* In the menu a row is a destination, not a current selection, so the
     last-visited entry must not read as chosen. */
  #settings-overlay[data-view="menu"] .settings-nav-item.active,
  #server-settings-fullscreen[data-view="menu"] .server-settings-nav-item.active {
    background: transparent;
    color: var(--text-secondary);
  }
  #server-settings-fullscreen[data-view="menu"] .server-settings-nav-item.danger.active,
  #server-settings-fullscreen .server-settings-nav-item.danger {
    color: var(--danger, #ed4245);
  }

  .settings-content,
  .server-settings-content {
    flex: 1;
    padding: 16px 14px;
    padding-bottom: calc(16px + env(safe-area-inset-bottom));
    overflow-y: auto;
  }

  /* Exactly one pane is shown, chosen by the container's view state. */
  #settings-overlay[data-view="menu"] .settings-content,
  #server-settings-fullscreen[data-view="menu"] .server-settings-content {
    display: none;
  }
  #settings-overlay[data-view="section"] .settings-nav,
  #server-settings-fullscreen[data-view="section"] .server-settings-nav {
    display: none;
  }
  /* Back is offered only when there is somewhere to go back to. */
  #settings-overlay[data-view="section"] .settings-back-btn,
  #server-settings-fullscreen[data-view="section"] .settings-back-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
  }
  /* The section's own heading would repeat the header title. */
  #settings-overlay[data-view="section"] .settings-section-title,
  #server-settings-fullscreen[data-view="section"] .server-settings-page-title {
    display: none;
  }

  .settings-title,
  .server-settings-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* Sub-panels inside server settings (the role editor) need room too. */
  .server-settings-fullscreen {
    padding-top: 0;
  }

  /* Full-screen surfaces should not be cropped by a notch. */
  .server-settings-fullscreen,
  .settings-overlay {
    padding-bottom: 0;
  }
}

/* Shown while a newly selected server's channels are being fetched, so the
   previous server's list is never displayed under the new server's name. */
.channel-list-pending {
  padding: 10px 16px;
  color: var(--text-tertiary);
  font-size: 13px;
}

/* Ongoing call banner shown above the conversation when a call is already
   running in the direct message you have open. */
.dm-ongoing-call {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  padding: 8px 14px;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border);
}
.dm-ongoing-call[hidden] {
  display: none !important;
}
.dm-ongoing-call-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
  background: var(--online, #3ba55d);
  box-shadow: 0 0 0 3px rgba(59, 165, 93, 0.18);
}
.dm-ongoing-call-text {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  color: var(--text-secondary);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.dm-ongoing-call-join {
  flex: 0 0 auto;
  padding: 6px 14px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--online, #3ba55d);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.dm-ongoing-call-join:hover {
  filter: brightness(1.08);
}

/* The tag beneath a name in the add-friend search, so two people with the
   same display name can be told apart. */
.dm-friend-sub {
  font-size: 11px;
  color: var(--text-tertiary);
}

/* ── Notifications bell ───────────────────────────────────────────────────── */
.notif-bell-btn {
  position: relative;
  color: var(--text-secondary);
}
.notif-bell-btn:hover,
.notif-bell-btn.has-unread {
  color: var(--text-primary);
}
.notif-bell-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--danger, #ed4245);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
  white-space: nowrap;
  pointer-events: none;
}
.notif-bell-badge[hidden] {
  display: none !important;
}

.notif-panel {
  position: fixed;
  top: calc(var(--main-header-height) + 6px);
  right: 12px;
  z-index: 70;
  width: min(360px, calc(100vw - 24px));
  max-height: min(70vh, 520px);
  display: flex;
  flex-direction: column;
  background: var(--bg-elevated, var(--bg-secondary));
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
.notif-panel[hidden] {
  display: none !important;
}
.notif-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 8px 10px 14px;
  border-bottom: 1px solid var(--border);
}
.notif-panel-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.notif-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 6px 0;
}
.notif-section-label {
  padding: 8px 14px 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.notif-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 14px;
  border: 0;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.notif-item:hover {
  background: var(--bg-hover);
}
.notif-item-avatar {
  position: relative;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  flex: 0 0 auto;
  overflow: hidden;
  /* Centre the fallback initials the way the DM and friend lists do. */
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-muted, rgba(88, 101, 242, 0.2));
  color: var(--accent, #5865f2);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
}
.notif-item-info {
  flex: 1;
  min-width: 0;
}
.notif-item-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.notif-item-sub {
  font-size: 12px;
  color: var(--text-secondary);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.notif-item-actions {
  display: flex;
  gap: 6px;
  flex: 0 0 auto;
}
.notif-item-btn {
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: 12px;
  cursor: pointer;
}
.notif-item-btn.primary {
  background: var(--accent, #5865f2);
  border-color: var(--accent, #5865f2);
  color: #fff;
}
.notif-item-count {
  flex: 0 0 auto;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--danger, #ed4245);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}
.notif-empty {
  padding: 22px 14px;
  text-align: center;
  font-size: 13px;
  color: var(--text-tertiary);
}

@media (max-width: 860px) {
  /* Full-width sheet under the header rather than a floating card. */
  .notif-panel {
    right: 8px;
    left: 8px;
    width: auto;
    max-height: min(74vh, 560px);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Classic chrome — shared by the Retro and Steam themes
   ───────────────────────────────────────────────────────────────────────────
   The bevels, square corners, caption bars and wells below are the same
   period furniture for both themes; only the palette differs. They key off
   the `chrome-classic` class, which applyTheme() puts on <html> for any theme
   that wants this treatment, so a second skin costs a palette rather than a
   duplicated stylesheet.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════════
   Retro theme — late-90s / early-2000s desktop skin
   ───────────────────────────────────────────────────────────────────────────
   Every other theme swaps twelve colour variables and nothing else. This one
   also changes shape, because the era it borrows from is defined by its edges:
   square corners, chiselled bevels, a gradient title bar and a small UI face.
   All of it is scoped under the theme attribute, so no other theme is touched.

   The bevel is the whole trick. A raised control lights its top and left and
   shades its bottom and right; a sunken well does the reverse. Two extra
   variables carry those two greys so the pattern stays consistent.
   ═══════════════════════════════════════════════════════════════════════════ */

:root[data-theme="retro"] {
  --bg-base: #1a1a1a;
  --bg-primary: #2b2b2b;
  --bg-secondary: #232323;
  --bg-elevated: #303030;
  --bg-hover: rgba(255, 255, 255, 0.07);
  --bg-active: rgba(51, 221, 102, 0.14);
  --border: #454545;
  --text-primary: #dcdcdc;
  --text-secondary: #9b9b9b;
  --text-tertiary: #6f6f6f;
  --accent: #33dd66;
  --accent-muted: rgba(51, 221, 102, 0.22);

  /* Shape, not just colour. */
  --radius-sm: 0;
  --radius-md: 0;
  --font-ui: Tahoma, "MS Sans Serif", Geneva, Verdana, sans-serif;

  /* Bevel greys and the title-bar gradient. */
  --retro-light: #6e6e6e;
  --retro-shadow: #0d0d0d;
  --retro-face: #303030;
  --retro-title-a: #0b2a4a;
  --retro-title-b: #2277c4;
}

/* Nothing is rounded. Scoped to the theme and limited to corner radius, so it
   changes shape without touching any other property. */
:root.chrome-classic *,
:root.chrome-classic *::before,
:root.chrome-classic *::after {
  border-radius: 0 !important;
}

:root.chrome-classic body {
  font-size: 14px;
}

/* ── Raised surfaces: dialogs, popovers, menus ── */
:root.chrome-classic .modal-box,
:root.chrome-classic .invite-panel,
:root.chrome-classic .settings-panel,
:root.chrome-classic .notif-panel,
:root.chrome-classic .context-menu,
:root.chrome-classic .server-dropdown,
:root.chrome-classic .search-popover,
:root.chrome-classic .screen-picker-panel {
  background: var(--retro-face);
  border: 2px solid;
  border-color: var(--retro-light) var(--retro-shadow) var(--retro-shadow) var(--retro-light);
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.55);
}

/* ── Title bars ──
   The gradient caption is the single strongest cue of the era. */
:root.chrome-classic .modal-header,
:root.chrome-classic .invite-header,
:root.chrome-classic .settings-header,
:root.chrome-classic .notif-panel-header,
:root.chrome-classic .server-settings-header {
  background: linear-gradient(90deg, var(--retro-title-a), var(--retro-title-b));
  border-bottom: 2px solid var(--retro-shadow);
  color: #fff;
  padding-top: 4px;
  padding-bottom: 4px;
}
:root.chrome-classic .modal-header span,
:root.chrome-classic .invite-title,
:root.chrome-classic .settings-title,
:root.chrome-classic .notif-panel-title,
:root.chrome-classic .server-settings-title {
  color: #fff;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
}

/* ── Controls: raised at rest, pressed in on activation ── */
:root.chrome-classic .settings-btn,
:root.chrome-classic .invite-submit,
:root.chrome-classic .invite-copy,
:root.chrome-classic .dm-friend-action-btn,
:root.chrome-classic .notif-item-btn,
:root.chrome-classic .main-empty-btn,
:root.chrome-classic .voice-stage-ctrl-btn,
:root.chrome-classic .dm-ongoing-call-join,
:root.chrome-classic .mobile-call-btn,
:root.chrome-classic .icon-btn {
  background: var(--retro-face);
  border: 2px solid;
  border-color: var(--retro-light) var(--retro-shadow) var(--retro-shadow) var(--retro-light);
  color: var(--text-primary);
}
:root.chrome-classic .settings-btn:active,
:root.chrome-classic .invite-submit:active,
:root.chrome-classic .invite-copy:active,
:root.chrome-classic .dm-friend-action-btn:active,
:root.chrome-classic .notif-item-btn:active,
:root.chrome-classic .main-empty-btn:active,
:root.chrome-classic .voice-stage-ctrl-btn:active,
:root.chrome-classic .dm-ongoing-call-join:active,
:root.chrome-classic .mobile-call-btn:active,
:root.chrome-classic .icon-btn:active {
  border-color: var(--retro-shadow) var(--retro-light) var(--retro-light) var(--retro-shadow);
  /* Nudge the label so the button reads as physically pressed. */
  padding-top: 1px;
  padding-left: 1px;
}

/* ── Wells: anything you type into is recessed ── */
:root.chrome-classic .settings-input,
:root.chrome-classic .invite-input,
:root.chrome-classic .dm-search-bar,
:root.chrome-classic .members-search,
:root.chrome-classic .main-header-search,
:root.chrome-classic .composer-input,
:root.chrome-classic .settings-select,
:root.chrome-classic textarea {
  background: #141414;
  border: 2px solid;
  border-color: var(--retro-shadow) var(--retro-light) var(--retro-light) var(--retro-shadow);
  color: var(--text-primary);
  caret-color: var(--accent);
}
:root.chrome-classic .composer-box {
  background: #141414;
  border: 2px solid;
  border-color: var(--retro-shadow) var(--retro-light) var(--retro-light) var(--retro-shadow);
}

/* ── Chassis: the panels around the content ── */
:root.chrome-classic .left-panel,
:root.chrome-classic .members-list,
:root.chrome-classic .main-header,
:root.chrome-classic .server-list,
:root.chrome-classic .left-footer-server-col {
  border-color: var(--retro-shadow);
}
:root.chrome-classic .main-header,
:root.chrome-classic .channel-list-header,
:root.chrome-classic .members-header {
  border-bottom: 2px solid var(--retro-shadow);
  box-shadow: inset 0 1px 0 var(--retro-light);
}
/* Keep the pair of rules bracketing the channel list the same weight and
   colour as the rest of the classic chassis. */
:root.chrome-classic .left-panel::after {
  top: calc(var(--main-header-height) - 2px);
  height: 2px;
  background: var(--retro-shadow);
}
:root.chrome-classic .left-footer-channel-col,
:root.chrome-classic .composer-outer {
  border-top: 2px solid var(--retro-shadow);
}
:root.chrome-classic .server-list-divider {
  height: 2px;
  background: var(--retro-shadow);
  margin-top: calc((var(--main-header-height) - var(--dm-hub-size)) / 2 - 2px);
}
:root.chrome-classic .server-icon {
  border: 2px solid;
  border-color: var(--retro-light) var(--retro-shadow) var(--retro-shadow) var(--retro-light);
  background: var(--retro-face);
}
:root.chrome-classic .server-icon.active {
  border-color: var(--retro-shadow) var(--retro-light) var(--retro-light) var(--retro-shadow);
}

/* ── Selection: a solid block, the way a list row highlighted back then ── */
:root.chrome-classic .channel-item.active,
:root.chrome-classic .dm-item.active {
  background: var(--retro-title-a);
  color: #fff;
  box-shadow: inset 0 0 0 1px var(--retro-title-b);
}
:root.chrome-classic .channel-item.active .channel-name,
:root.chrome-classic .dm-item.active .dm-item-name {
  color: #fff;
}

/* ── The green readout Winamp is remembered for ── */
:root.chrome-classic .voice-connected-status,
:root.chrome-classic .voice-connected-channel,
:root.chrome-classic .mobile-call-status,
:root.chrome-classic .voice-verify-code,
:root.chrome-classic .voice-e2e-badge {
  color: var(--accent);
  font-family: "Lucida Console", Consolas, monospace;
  letter-spacing: 0.02em;
}
:root.chrome-classic .voice-connected-bar,
:root.chrome-classic .mobile-call-bar {
  background: #141414;
  border: 2px solid;
  border-color: var(--retro-shadow) var(--retro-light) var(--retro-light) var(--retro-shadow);
}

/* ── Chunky scrollbars ── */
:root.chrome-classic ::-webkit-scrollbar {
  width: 16px;
  height: 16px;
}
:root.chrome-classic ::-webkit-scrollbar-track {
  background: #1e1e1e;
}
:root.chrome-classic ::-webkit-scrollbar-thumb {
  background: var(--retro-face);
  border: 2px solid;
  border-color: var(--retro-light) var(--retro-shadow) var(--retro-shadow) var(--retro-light);
}
/* The bevelled bars above are ::-webkit rules, which Chromium only honours
   when the standard scrollbar properties are left at auto — so the period
   chrome resets the app-wide thin/themed pair to get its chunky bars back. */
:root.chrome-classic * {
  scrollbar-width: auto;
  scrollbar-color: auto;
}

/* ── The main window wears the same caption bar as the dialogs ──
   Confining the gradient to modals left the app itself looking merely square.
   Giving the channel header and the conversation header the same treatment is
   what makes the whole window read as period, not just its dialogs. */
:root.chrome-classic .main-header,
:root.chrome-classic .channel-list-header {
  background: linear-gradient(90deg, var(--retro-title-a), var(--retro-title-b));
  box-shadow: none;
}
:root.chrome-classic .main-channel-name,
:root.chrome-classic .server-name {
  color: #fff;
  font-weight: 700;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
}
:root.chrome-classic .main-header .icon-btn,
:root.chrome-classic .channel-list-header .icon-btn,
:root.chrome-classic .channel-invite-btn {
  color: #fff;
}

/* The window's own title bar is the caption bar of the era. The solid colour
   under the gradient is what the shell reads to paint the window controls,
   which sit at the gradient's right-hand end. */
:root.chrome-classic .app-titlebar {
  background-color: var(--retro-title-b);
  background-image: linear-gradient(90deg, var(--retro-title-a), var(--retro-title-b));
  color: #fff;
  font-weight: 700;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
  border-bottom: 2px solid var(--retro-shadow);
}
/* Caption buttons of the era: small raised bevels sitting inside the
   caption, black glyphs, and they press in. */
:root.chrome-classic .app-titlebar-controls {
  align-self: center;
  gap: 2px;
  padding-right: 4px;
}
:root.chrome-classic .win-btn {
  width: 20px;
  height: 18px;
  background: var(--retro-face);
  color: #000;
  border: 2px solid;
  border-color: var(--retro-light) var(--retro-shadow) var(--retro-shadow) var(--retro-light);
  box-sizing: border-box;
  transition: none;
}
:root.chrome-classic .win-btn svg {
  width: 8px;
  height: 8px;
}
:root.chrome-classic .win-btn:hover,
:root.chrome-classic .win-btn-close:hover {
  background: var(--retro-face);
  color: #000;
}
:root.chrome-classic .win-btn:active,
:root.chrome-classic .win-btn-close:active {
  background: var(--retro-face);
  color: #000;
  border-color: var(--retro-shadow) var(--retro-light) var(--retro-light) var(--retro-shadow);
}
:root.chrome-classic .win-btn-close {
  margin-left: 2px;
}

/* The conversation itself sits in a recessed well, the way a list control did. */
:root.chrome-classic .messages-container {
  box-shadow: inset 1px 1px 0 var(--retro-shadow), inset -1px -1px 0 var(--retro-light);
}

/* The composer box already provides the well; a second bevel on the field
   inside it produced a doubled frame. */
:root.chrome-classic .composer-input {
  border: 0;
  background: transparent;
}

/* The swatch in the theme picker: metal face, green readout, square. */
.theme-swatch--retro {
  background: linear-gradient(135deg, #2b2b2b 0 62%, #33dd66 62% 100%);
  border-color: #6e6e6e;
}

/* Custom emoji rendered inside a message. Sized to the text so a line of
   emoji sits on the same baseline as the words around it. */
.msg-emoji {
  height: 1.45em;
  width: auto;
  max-width: 96px;
  vertical-align: -0.32em;
  object-fit: contain;
}
/* A message that is nothing but emoji shows them larger, the way chat apps do. */
.message-content.emoji-only .msg-emoji {
  height: 2.6em;
  vertical-align: -0.5em;
}

/* ── GIF picker ───────────────────────────────────────────────────────────── */
.composer-gif-btn {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}
.composer-gif-btn:hover {
  color: var(--text-primary);
}
.composer-gif-btn[hidden] {
  display: none !important;
}

.gif-picker {
  position: fixed;
  z-index: 500;
  right: 16px;
  bottom: 84px;
  width: min(380px, calc(100vw - 32px));
  max-height: min(60vh, 460px);
  display: flex;
  flex-direction: column;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
.gif-picker[hidden] {
  display: none !important;
}
.gif-picker-header {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px;
  border-bottom: 1px solid var(--border);
}
.gif-picker-search {
  flex: 1;
  min-width: 0;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  color: var(--text-primary);
  font-size: 13px;
  outline: none;
}
.gif-picker-body {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
  /* Two columns of thumbnails, each keeping its own aspect ratio. */
  column-count: 2;
  column-gap: 8px;
}
.gif-picker-item {
  display: block;
  width: 100%;
  margin: 0 0 8px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--bg-base);
  cursor: pointer;
  overflow: hidden;
  break-inside: avoid;
}
.gif-picker-item:hover {
  border-color: var(--accent);
}
.gif-picker-item img {
  display: block;
  width: 100%;
  height: auto;
}
.gif-picker-status {
  padding: 22px 12px;
  text-align: center;
  font-size: 13px;
  color: var(--text-tertiary);
  column-span: all;
}
.gif-picker-footer {
  padding: 6px 10px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-tertiary);
  text-align: right;
}

@media (max-width: 860px) {
  .gif-picker {
    left: 8px;
    right: 8px;
    width: auto;
    bottom: 76px;
    max-height: 56vh;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Steam theme — the olive-grey Steam client of the early 2000s
   ───────────────────────────────────────────────────────────────────────────
   Same chrome as Retro (see chrome-classic above): square, bevelled, blocky.
   What changes is the palette — the desaturated olive greys of the original
   client, its lighter panel face, and the green it used for emphasis.
   ═══════════════════════════════════════════════════════════════════════════ */
:root[data-theme="steam"] {
  --bg-base: #292e24;
  --bg-primary: #3a4433;
  --bg-secondary: #323a2b;
  --bg-elevated: #4a5540;
  --bg-hover: rgba(255, 255, 255, 0.06);
  --bg-active: rgba(158, 196, 75, 0.16);
  --border: #59654d;
  --text-primary: #d9e0cb;
  --text-secondary: #a6b094;
  --text-tertiary: #7d8870;
  --accent: #9ec44b;
  --accent-muted: rgba(158, 196, 75, 0.22);

  --radius-sm: 0;
  --radius-md: 0;
  --font-ui: Tahoma, "MS Sans Serif", Geneva, Verdana, sans-serif;

  /* Bevels take their light and shade from the olive face rather than grey. */
  --retro-light: #7c8a6a;
  --retro-shadow: #1c2016;
  --retro-face: #4a5540;
  /* Steam's caption bar was a flat olive band, not a blue gradient. */
  --retro-title-a: #4b5a3c;
  --retro-title-b: #66784f;
}

/* Steam put its green on the selected row rather than a blue highlight. */
:root[data-theme="steam"] .channel-item.active,
:root[data-theme="steam"] .dm-item.active {
  background: #5c6b47;
  box-shadow: inset 0 0 0 1px #7f9159;
}

.theme-swatch--steam {
  background: linear-gradient(135deg, #3a4433 0 62%, #9ec44b 62% 100%);
  border-color: #59654d;
}

/* File-attachment icon. The rule lives here rather than as a style attribute
   on the inline SVG because the message sanitizer forbids style attributes
   outright (see DOMPURIFY_CONFIG in app.js). */
.file-icon-svg {
  flex-shrink: 0;
}
