/* MFChat — JenChat design port (2026-06-12).
   Visual system lifted from the JenChat SwiftUI app (Sources/Views/Theme.swift,
   ChannelSidebar.swift, MessagesView.swift, MessageBodyView.swift):
   near-black surfaces, Inter, Discord-blurple accent, per-agent colors.
   No framework, no build step — CSS variables + grid. */

/* ── Inter (bundled, same family JenChat ships) ─────────────────────────── */
@font-face {
  font-family: 'Inter';
  src: url('/mfchat/vendor/fonts/Inter-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/mfchat/vendor/fonts/Inter-Medium.ttf') format('truetype');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/mfchat/vendor/fonts/Inter-SemiBold.ttf') format('truetype');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Inter';
  src: url('/mfchat/vendor/fonts/Inter-Bold.ttf') format('truetype');
  font-weight: 700 900;
  font-display: swap;
}

:root {
  /* DiscordTheme — exact conversions from Theme.swift */
  --bg-deep:    #000000;               /* outer / sidebar header / chat */
  --bg-mid:     #0a0a0d;               /* channel list — barely-off-black */
  --bg-chat:    #000000;               /* messages area */
  --bg-input:   #1a1a1f;               /* input field lift */
  --bg-float:   #121217;               /* menus, modals, popovers */
  --bg-panel:   #0a0a0d;               /* legacy alias */
  --bg-hover:   rgba(255,255,255,0.06);
  --bg-active:  rgba(255,255,255,0.14); /* selected channel row */
  --border:     rgba(255,255,255,0.08);

  --text-bright: #f2f2f2;              /* textBright 0.95 */
  --text:        #d6d6db;              /* textNormal */
  --text-muted:  #858a94;              /* textMuted */
  --text-dim:    #52525c;              /* textCategory */
  --ch-row:      #9e9ea8;              /* textChannelRow */
  --ch-row-dim:  #666670;              /* textChannelRowDim */

  --accent:       #5865f2;             /* Discord blurple */
  --accent-hover: #6d79f4;
  --accent-soft:  rgba(88,101,242,0.15);

  --danger:  #f04747;
  --success: #66d98c;

  /* Agent palette (Theme.swift agentColors) */
  --agent-jen:    #f5b545;
  --agent-jenni:  #66d98c;
  --agent-jane:   #c773f2;
  --agent-jarvis: #57c7f2;
  --agent-voice:  #f2739e;
  --agent-multi:  #8c919c;

  --font-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  --radius: 8px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  font-family: var(--font-base);
  background: var(--bg-deep);
  color: var(--text);
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
  /* iOS standalone PWA: respect notch / home-indicator */
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

.app {
  display: grid;
  grid-template-columns: 280px 1fr;
  height: 100vh;
  height: 100dvh;
}

/* ── Sidebar — ChannelSidebar.swift ─────────────────────────────────────── */

.sidebar {
  background: var(--bg-mid);
  border-right: 1px solid rgba(0,0,0,0.4);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: var(--bg-deep);
  border-bottom: 1px solid rgba(0,0,0,0.4);
}

.brand-mark {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  flex-shrink: 0;
}

.brand-name {
  font-weight: 600;
  color: var(--text-bright);
  font-size: 17px;
  line-height: 1.2;
}

.brand-sub {
  font-size: 10px;
  font-family: var(--font-mono);
  color: var(--text-dim);
  line-height: 1.4;
}

/* Search field — white 4% fill, radius 6 (ChannelSidebar search bar) */
.channel-search {
  padding: 8px 10px 4px;
}

.channel-search input {
  width: 100%;
  padding: 7px 10px;
  font-size: 13px;
  font-family: inherit;
  background: rgba(255,255,255,0.04);
  color: var(--text-bright);
  border: none;
  border-radius: 6px;
  outline: none;
}
.channel-search input::placeholder { color: var(--text-muted); }
.channel-search input:focus {
  box-shadow: 0 0 0 1px rgba(88,101,242,0.55);
}

/* channel sort-mode toggle (A–Z vs custom drag order) */
.ch-sort-toggle {
  display: flex;
  gap: 2px;
  margin: 4px 10px 2px;
  background: rgba(255,255,255,0.04);
  border-radius: 6px;
  padding: 2px;
}
.ch-sort-toggle button {
  flex: 1;
  font-size: 11px;
  font-weight: 600;
  font-family: inherit;
  padding: 4px 0;
  background: transparent;
  color: var(--text-muted);
  border: none;
  border-radius: 5px;
  cursor: pointer;
}
.ch-sort-toggle button.active {
  background: var(--accent);
  color: #fff;
}

.channels {
  flex: 1;
  overflow-y: auto;
  padding: 4px 0 12px;
  position: relative; /* anchor for the drag drop-line */
}

/* drop indicator line shown while dragging a channel to reorder */
.ch-drop-line {
  position: absolute;
  left: 8px;
  right: 8px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
  pointer-events: none;
  z-index: 5;
  box-shadow: 0 0 4px var(--accent);
  margin-top: -1px;
}
.ch-drop-line::before {
  content: '';
  position: absolute;
  left: -3px;
  top: -2px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}
.channel.dragging { opacity: 0.45; }

/* Category headers — 12 bold, uppercase, blended back (textCategory) */
.channel-section-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  padding: 14px 12px 4px;
  user-select: none;
}

/* Channel rows — ChannelRow: # 20px muted, name 17px, selected = white 14% */
.channel {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px 8px 20px;
  margin: 1px 6px;
  border-radius: 6px;
  cursor: pointer;
  color: var(--ch-row-dim);
  font-size: 16px;
  user-select: none;
}

.channel:hover {
  background: var(--bg-hover);
  color: var(--ch-row);
}

.channel.active {
  background: var(--bg-active);
  color: var(--text-bright);
}

.channel .ch-hash {
  color: var(--text-muted);
  font-size: 19px;
  font-weight: 400;
  line-height: 1;
}

.channel .ch-name {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.channel.unread .ch-name {
  font-weight: 600;
  color: var(--text-bright);
}

/* Unread — JenChat shows a small agent-colored dot; we keep the count for a
   team chat but render it as a compact accent pill. */
.ch-unread-badge {
  margin-left: auto;
  background: var(--accent);
  color: white;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 9px;
  min-width: 16px;
  text-align: center;
}

.channels-empty {
  padding: 12px 16px;
  color: var(--text-muted);
  font-size: 12px;
  font-style: italic;
}

/* ── Mention popup ──────────────────────────────────────────────────────── */

.mention-popup {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: calc(100% + 4px);
  background: var(--bg-float);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 -4px 16px rgba(0,0,0,0.55);
  max-height: 240px;
  overflow-y: auto;
  z-index: 1200;
}
.mention-popup[hidden] { display: none !important; }

.mention-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  cursor: pointer;
  font-size: 13px;
}

.mention-item.active,
.mention-item:hover {
  background: var(--accent-soft);
}

.mention-item-avatar {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  background: var(--accent);
  color: white;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
  overflow: hidden;
}
.mention-item-avatar img { width: 100%; height: 100%; object-fit: cover; }

.mention-item-nick {
  color: var(--text-bright);
  font-weight: 500;
}

.mention-item-handle {
  color: var(--text-muted);
  font-size: 11px;
  margin-left: auto;
}

/* ── Composer — MessagesView inputBar ───────────────────────────────────── */

.composer {
  position: relative;
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 12px;
  /* Lift the input above the Android gesture bar / iOS home indicator so the
     system nav bar doesn't overlap the message box (reported 2026-07-06). */
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  background: var(--bg-chat);
  border-top: none;
}

/* plus.circle.fill attach button */
.composer-attach-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 44px;
  background: transparent;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 22px;
  padding: 0;
  flex-shrink: 0;
}
.composer-attach-btn svg { display: block; }
.composer-attach-btn:hover { color: var(--text-bright); }

.composer #composerInput {
  flex: 1;
  background: var(--bg-input);
  border: none;
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 16px;
  color: var(--text-bright);
  font-family: inherit;
  /* textarea: single-line by default, grows up to max-height, then scrolls.
     Height is managed in JS (autoResizeComposer). */
  resize: none;
  line-height: 1.4;
  max-height: 176px;
  overflow-y: auto;
}
.composer #composerInput::placeholder { color: var(--text-muted); }

.composer #composerInput:focus { outline: none; }

.composer #composerInput:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Send — blurple paperplane square, radius 8 (sendOrMicButton) */
.composer button[type="submit"] {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 44px;
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 8px;
  font-weight: 600;
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.12s;
}
.composer button[type="submit"] svg { display: block; }

.composer button[type="submit"]:hover:not(:disabled) {
  background: var(--accent-hover);
}

.composer button[type="submit"]:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Bot-lock toggle: when active, every message in the channel is routed to the
   bot (auto-@mention) until switched off. */
.composer .composer-botlock-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-input);
  color: var(--text-muted);
  border: none;
  border-radius: 8px;
  width: 44px;
  height: 44px;
  padding: 0;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
  flex-shrink: 0;
  transition: background 0.12s, opacity 0.12s, box-shadow 0.12s;
}
.composer .composer-botlock-btn svg { display: block; }
.composer .composer-botlock-btn:hover:not(:disabled) {
  opacity: 1;
}
.composer .composer-botlock-btn[aria-pressed="true"] {
  background: var(--accent);
  color: #fff;
  opacity: 1;
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.composer .composer-botlock-btn[hidden] { display: none !important; }

.composer-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 12px 0;
  background: var(--bg-chat);
}
.composer-attachments[hidden] { display: none !important; }

.pending-attachment {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 12px;
  color: var(--text);
}
.pending-attachment .pa-remove {
  background: none; border: none; color: var(--danger); cursor: pointer; padding: 0 2px;
  font-size: 13px;
}
/* Image attachments show a real thumbnail instead of an "image.png" chip. */
.pending-attachment.pending-image {
  position: relative;
  padding: 0;
  width: 56px;
  height: 56px;
  overflow: hidden;
}
.pending-attachment.pending-image .pa-thumb {
  width: 56px;
  height: 56px;
  object-fit: cover;
  display: block;
}
.pending-attachment.pending-image .pa-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(0,0,0,0.6);
  color: #fff;
  font-size: 11px;
}

/* ── Drop-to-attach overlay (MessagesView dropTargeted) ─────────────────── */

.drop-overlay {
  position: absolute;
  inset: 0;
  background: rgba(88,101,242,0.18);
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 800;
  pointer-events: none;
}
.drop-overlay[hidden] { display: none !important; }
.drop-overlay-inner {
  background: var(--bg-float);
  border: 1px solid var(--border);
  padding: 22px 34px;
  border-radius: 12px;
  font-size: 15px;
  color: var(--text-bright);
  font-weight: 600;
}

main.chat { position: relative; }

/* ── Attachments in messages (AttachmentGrid) ───────────────────────────── */

.attachment {
  margin-top: 6px;
  max-width: 420px;
}
.attachment video {
  max-width: 100%;
  border-radius: 8px;
  display: block;
  border: 1px solid rgba(255,255,255,0.06);
}
.attachment img {
  max-width: 100%;
  max-height: 300px;
  width: auto;
  border-radius: 8px;
  display: block;
  border: 1px solid rgba(255,255,255,0.06);
  cursor: pointer;
}
.attachment-file {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-decoration: none;
  color: var(--text-bright);
  font-size: 13px;
}
.attachment-file:hover { background: rgba(255,255,255,0.08); }

/* ── Typing indicator — TypingIndicator.swift ───────────────────────────── */

.jarvis-typing {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 8px 16px;
  margin: 2px 0;
  color: var(--text-muted);
  font-size: 12px;
  font-style: italic;
}

.typing-dot {
  width: 6px;
  height: 6px;
  background: var(--accent);
  border-radius: 50%;
  animation: typing-bounce 1.2s ease-in-out infinite;
}

.typing-dot:nth-child(2) { animation-delay: 0.15s; }
.typing-dot:nth-child(3) { animation-delay: 0.30s; }

.typing-label { margin-left: 5px; }

@keyframes typing-bounce {
  0%, 60%, 100% { opacity: 0.35; transform: translateY(0); }
  30%           { opacity: 1;    transform: translateY(-3px); }
}

/* ── Context menu ───────────────────────────────────────────────────────── */

.ctx-menu {
  position: fixed;
  z-index: 1500;
  background: var(--bg-float);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 0;
  min-width: 180px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.6);
  font-size: 13px;
  user-select: none;
}

.ctx-menu[hidden] { display: none; }

.ctx-menu-item {
  padding: 6px 14px;
  cursor: pointer;
  color: var(--text-bright);
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.ctx-menu-item:hover {
  background: var(--accent-soft);
  color: white;
}

.ctx-menu-item.danger { color: #f37b7d; }

.ctx-menu-item.danger:hover {
  background: rgba(240,71,71,0.15);
}

.ctx-menu-separator {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

.ctx-menu-hint {
  padding: 6px 14px;
  font-size: 11px;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}

/* ── Chat header buttons (header pills: white 4% fill, radius 5) ────────── */

.header-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

.translate-btn {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  background: rgba(255,255,255,0.04);
  color: var(--text-muted);
  border: none;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
}

.translate-btn:hover { background: rgba(255,255,255,0.08); }

.translate-btn.active {
  background: var(--accent-soft);
  color: var(--accent-hover);
}

.translate-icon { font-size: 13px; }

.notif-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px 8px;
  background: rgba(255,255,255,0.04);
  color: var(--text-muted);
  border: none;
  border-radius: 5px;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}

.notif-btn:hover { background: rgba(255,255,255,0.08); }

/* Unread count on the bell. Deliberately the SAME number as the tab title, so
   the header and "(3) MFChat" never disagree. Muted channels are excluded from
   both. (Zi 2026-08-30) */
.notif-btn { position: relative; }
.notif-count {
  position: absolute; top: -4px; right: -4px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 8px; background: #e5484d; color: #fff;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
  box-shadow: 0 0 0 2px rgba(0,0,0,.45);
  pointer-events: none;
}
.notif-count[hidden] { display: none; }
html.light .notif-count { box-shadow: 0 0 0 2px rgba(255,255,255,.9); }

.notif-btn.on {
  background: var(--accent-soft);
}

/* ── Translation chrome ─────────────────────────────────────────────────── */

.translated-meta {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 2px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.translated-badge {
  background: var(--accent-soft);
  color: var(--accent-hover);
  padding: 1px 6px;
  border-radius: 8px;
  font-size: 10px;
  font-weight: 600;
}

.translated-toggle {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 11px;
  padding: 0;
  text-decoration: underline dotted;
}

.translated-toggle:hover { color: var(--text-bright); }

.translation-pending {
  font-size: 11px;
  color: var(--text-muted);
  font-style: italic;
  margin-top: 2px;
}
/* Subtle "translated" marker sitting after the timestamp. Hover reveals the
   original (pre-translation) text in a small floating tooltip. */
.translated-tag {
  position: relative;
  font-size: 10px;
  color: var(--text-dim);
  opacity: 0.7;
  cursor: help;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}
.translated-tag:hover { opacity: 1; }
.orig-tooltip {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 4px;
  z-index: 50;
  width: max-content;
  max-width: 320px;
  white-space: pre-wrap;
  background: var(--bg-float);
  color: var(--text-bright);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 9px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.4;
  box-shadow: 0 4px 14px rgba(0,0,0,0.45);
  pointer-events: none;
}
.translated-tag:hover .orig-tooltip { display: block; }
/* Per-message on-demand "translate" link (sits where "translated" goes). */
.translate-link {
  font-size: 10px;
  color: var(--accent-hover);
  opacity: 0.85;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}
.translate-link:hover { opacity: 1; }
.translating-tag {
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  font-style: normal;
  background: linear-gradient(90deg, #3b82f6, #2563eb);
  padding: 2px 9px 2px 8px;
  border-radius: 11px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  animation: transPulse 1.15s ease-in-out infinite;
}
.translating-tag::before {
  content: '';
  width: 6px; height: 6px; border-radius: 50%;
  background: #fff;
  animation: transDot 1.15s ease-in-out infinite;
}
@keyframes transPulse { 0%,100% { filter: brightness(0.92); } 50% { filter: brightness(1.12); } }
@keyframes transDot { 0%,100% { transform: scale(0.6); opacity: 0.5; } 50% { transform: scale(1); opacity: 1; } }
/* the message body while its translation is in flight: dim + gentle shimmer so
   it's obvious work is happening (Zi 2026-07-28) */
.message-text.translating { opacity: 0.5; }
.message-text.translating { position: relative; }
.message-text.translating::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(59,130,246,0.14) 50%, transparent 70%);
  background-size: 200% 100%;
  animation: transShimmer 1.3s linear infinite;
  pointer-events: none; border-radius: 6px;
}
@keyframes transShimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* "Translate earlier messages" — sits at the top of the message list when
   auto-translation only covered the most recent few. */
.translate-earlier-bar {
  display: flex;
  justify-content: center;
  padding: 8px 0 12px;
  position: sticky;
  top: 0;
  z-index: 5;
  background: linear-gradient(var(--bg-chat) 65%, transparent);
}
.translate-earlier-btn {
  background: var(--bg-float);
  color: var(--accent-hover);
  border: 1px solid rgba(88,101,242,0.5);
  border-radius: 14px;
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.translate-earlier-btn:hover:not(:disabled) {
  background: var(--accent);
  color: #fff;
}
.translate-earlier-btn:disabled { opacity: 0.5; cursor: default; }

/* ── Language switcher / sidebar buttons ────────────────────────────────── */

.lang-switcher {
  display: flex;
  gap: 4px;
  padding: 4px 12px 8px;
  border-top: 1px solid var(--border);
}

.lang-btn {
  flex: 1;
  padding: 4px 6px;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}

.lang-btn:hover { background: rgba(255,255,255,0.04); }

.lang-btn.active {
  background: var(--accent-soft);
  color: var(--accent-hover);
  border-color: rgba(88,101,242,0.3);
}

.new-channel-btn {
  display: block;
  margin: 4px 10px 6px;
  padding: 6px 10px;
  background: var(--accent-soft);
  color: var(--accent-hover);
  border: none;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}

.new-channel-btn:hover { background: rgba(88,101,242,0.25); }

/* ── Modals ─────────────────────────────────────────────────────────────── */

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

.modal-backdrop[hidden] { display: none !important; }

.modal {
  background: var(--bg-float);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 24px;
  width: 100%;
  max-width: 420px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.6);
}

.modal h2 {
  margin: 0 0 16px;
  font-size: 18px;
  font-weight: 600;
  color: var(--text-bright);
}

.modal-field {
  display: block;
  margin-bottom: 16px;
}

.modal-field span {
  display: block;
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 6px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.modal-field input[type="text"],
.modal-field input[type="password"],
.modal-field select {
  width: 100%;
  padding: 9px 12px;
  font-size: 14px;
  font-family: inherit;
  background: var(--bg-input);
  color: var(--text-bright);
  /* Visible border so the field reads as an input — bg-input alone is nearly
     the same value as the modal background, which made the password boxes
     look invisible (reported 2026-07-04). */
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 6px;
  outline: none;
  box-sizing: border-box;
}

.modal-field input[type="text"]:focus,
.modal-field input[type="password"]:focus,
.modal-field select:focus {
  border-color: var(--accent);
}

.modal-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-bright);
  cursor: pointer;
  margin-bottom: 8px;
}
.modal-toggle input { accent-color: var(--accent); }

.modal-hint {
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 16px;
  padding: 8px 10px;
  background: var(--accent-soft);
  border-left: 2px solid var(--accent);
  border-radius: 4px;
}

.modal-hint code {
  background: rgba(0,0,0,0.3);
  padding: 1px 4px;
  border-radius: 3px;
  font-family: var(--font-mono);
  font-size: 10px;
}

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

.btn-primary, .btn-secondary {
  padding: 8px 16px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  border: 1px solid transparent;
}

.btn-primary {
  background: var(--accent);
  color: white;
}

.btn-primary:hover { background: var(--accent-hover); }

.btn-secondary {
  background: transparent;
  color: var(--text-bright);
  border-color: var(--border);
}

.btn-secondary:hover { background: rgba(255,255,255,0.05); }

.modal-error {
  margin-top: 12px;
  padding: 8px 12px;
  background: rgba(240,71,71,0.15);
  border: 1px solid rgba(240,71,71,0.3);
  border-radius: 6px;
  color: #f37b7d;
  font-size: 12px;
}

.admin-link {
  display: block;
  padding: 8px 16px;
  font-size: 12px;
  color: var(--accent-hover);
  text-decoration: none;
  border-top: 1px solid var(--border);
  background: rgba(88,101,242,0.04);
}

.admin-link:hover {
  background: var(--accent-soft);
  text-decoration: none;
}

.admin-link:visited { color: var(--accent-hover); }

/* ── Chat pane — MessagesView ───────────────────────────────────────────── */

.chat {
  display: flex;
  flex-direction: column;
  background: var(--bg-chat);
  overflow: hidden;
}

/* Header — # 24 muted, name 19 semibold, hairline bottom */
.chat-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(0,0,0,0.5);
  box-shadow: 0 1px 0 rgba(255,255,255,0.06);
  font-weight: 600;
  color: var(--text-bright);
  font-size: 19px;
  background: var(--bg-chat);
  flex-shrink: 0;
}

.chat-header .hash {
  color: var(--text-muted);
  font-size: 24px;
  font-weight: 400;
  line-height: 1;
  flex-shrink: 0;
}

/* Channel name truncates instead of wrapping (narrow screens) */
#chatTitle {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.messages {
  flex: 1;
  overflow-y: auto;
  padding: 14px 0;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* Message rows — MessageRow: avatar 36, author 16 semibold colored,
   ts 12 muted, body 15.5/1.55. No grouping (JenChat repeats every row). */
.message {
  display: flex;
  gap: 12px;
  padding: 12px 16px;
  align-items: flex-start;
}

.message:hover { background: rgba(255,255,255,0.02); }

/* Reveal animation — JenChat fades + lifts each new message (180ms) */
.message.msg-new {
  animation: msg-in 0.18s ease-out;
}
@keyframes msg-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.message-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--bg-input);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 13px;
  flex-shrink: 0;
  overflow: hidden;
}

.message-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* no circle crop — show the full image; the container's rounded square clips */
  border-radius: 0;
}

.message-body {
  flex: 1;
  min-width: 0;
}

.message-meta {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-bottom: 3px;
}

.message-author {
  font-weight: 600;
  color: var(--text-bright);
  font-size: 16px;
}

.message-ts {
  font-size: 12px;
  color: var(--text-muted);
}

.message-text {
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--text);
  word-wrap: break-word;
}

.message-text code {
  font-family: var(--font-mono);
  font-size: 13px;
  background: rgba(255,255,255,0.07);
  padding: 2px 5px;
  border-radius: 3px;
  color: var(--text-bright);
}

.message-text pre {
  /* A long code line used to widen the whole message, which is what let the
     chat screen slide left and right on a phone. Scroll inside the block
     instead. (Zi 2026-08-22) */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  font-family: var(--font-mono);
  font-size: 13px;
  background: #0f1217;
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  overflow-x: auto;
  margin: 6px 0;
}

.empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--text-dim);
  font-size: 14px;
}

.typing-indicator {
  padding: 8px 16px;
  font-size: 12px;
  color: var(--text-muted);
  font-style: italic;
}

/* ── Error banner ───────────────────────────────────────────────────────── */

.error-banner {
  position: fixed;
  top: 16px;
  right: 16px;
  background: var(--danger);
  color: white;
  padding: 10px 16px;
  border-radius: 8px;
  font-size: 13px;
  max-width: 320px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
  z-index: 1000;
}

/* ── Auth gate (login / register) ───────────────────────────────────────── */

.auth-gate {
  position: fixed;
  inset: 0;
  background: var(--bg-deep);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 999;
}

.auth-gate[hidden] { display: none; }

.auth-card {
  background: var(--bg-mid);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px 28px 28px;
  width: 100%;
  max-width: 380px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.6);
}

.auth-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
}
.auth-brand .brand-mark { width: 36px; height: 36px; font-size: 14px; }
.auth-brand .brand-name { font-size: 20px; }

.auth-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 18px;
  background: rgba(255,255,255,0.04);
  padding: 4px;
  border-radius: 8px;
}
.auth-tab {
  flex: 1;
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.auth-tab:hover { color: var(--text-bright); }
.auth-tab.active {
  background: var(--accent);
  color: white;
}

.auth-form { display: none; flex-direction: column; gap: 14px; }
.auth-form.active { display: flex; }

.auth-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.auth-form .hint {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-dim);
  font-size: 11px;
}
.auth-form input[type="text"],
.auth-form input[type="password"] {
  background: var(--bg-input);
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 14px;
  color: var(--text-bright);
  font-family: inherit;
}
.auth-form input[type="text"]:focus,
.auth-form input[type="password"]:focus {
  outline: none;
  border-color: var(--accent);
}
.auth-form button[type="submit"] {
  background: var(--accent);
  color: white;
  border: 0;
  border-radius: 8px;
  padding: 11px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  margin-top: 4px;
  transition: background 0.12s;
}
.auth-form button[type="submit"]:hover { background: var(--accent-hover); }
.auth-form button[type="submit"]:disabled { opacity: 0.5; cursor: wait; }

.auth-error {
  background: rgba(240,71,71,0.12);
  border: 1px solid rgba(240,71,71,0.4);
  color: #ffbaba;
  padding: 9px 12px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
}
.auth-error[hidden] { display: none; }

.avatar-picker { position: relative; }
.avatar-preview {
  width: 72px;
  height: 72px;
  border-radius: 10px;
  background: var(--bg-input);
  border: 1px dashed rgba(255,255,255,0.18);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  margin-top: 4px;
  overflow: hidden;
  position: relative;
}
.avatar-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.avatar-preview .avatar-fallback {
  font-size: 28px;
  font-weight: 700;
  color: var(--text-dim);
}
.avatar-picker input[type="file"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

/* ── User row in sidebar ────────────────────────────────────────────────── */

.user-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-top: 1px solid rgba(0,0,0,0.4);
  background: var(--bg-deep);
}
.user-row[hidden] { display: none; }
.user-avatar {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  background: var(--bg-input);
  object-fit: cover;
  flex-shrink: 0;
}
.user-meta {
  flex: 1;
  min-width: 0;
}
.user-nick {
  font-weight: 600;
  color: var(--text-bright);
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-name {
  font-size: 11px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.logout-btn {
  background: transparent;
  border: 0;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 16px;
  padding: 4px 8px;
  border-radius: 4px;
}
.logout-btn:hover {
  color: var(--danger);
  background: var(--bg-hover);
}

/* ── Responsive — sidebar visible wide (iPad landscape / desktop),
      off-canvas below 900px (iPad portrait / phone) ──────────────────────── */

.sidebar-toggle {
  display: none;
  background: transparent;
  border: none;
  color: var(--text-bright);
  font-size: 20px;
  line-height: 1;
  padding: 0 12px 0 0;
  cursor: pointer;
}
.sidebar-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  z-index: 90;
}
.sidebar-backdrop[hidden] { display: none; }

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  /* Sidebar becomes an off-canvas slide-in panel instead of vanishing. */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 82%;
    max-width: 320px;
    z-index: 100;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    box-shadow: 2px 0 16px rgba(0,0,0,0.5);
    padding-top: env(safe-area-inset-top);
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-toggle {
    display: inline-flex;
    align-items: center;
  }
  .message { padding: 10px 14px; }
  /* Push the chat header below the status bar on phones (installed PWA /
     edge-to-edge). The composer already pads for the bottom nav bar. */
  .chat-header { padding: calc(10px + env(safe-area-inset-top, 0px)) 14px 10px; }
}

/* ── Rich message renderer ──────────────────────────────────────────────── */
/* Ports the JenChat Swift MessageBodyView feature set: markdown, code blocks,
   callouts, custom ::: blocks (buttons, stat, pullquote, hero), tables. */

.md > * { margin: 6px 0; }
.md > *:first-child { margin-top: 0; }
.md > *:last-child  { margin-bottom: 0; }

/* Apple-style heading ramp (headingView): H1 hero, H2 section, H3 sub. */
.md h1 {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.5px;
  color: var(--text-bright);
  margin: 8px 0 4px;
  line-height: 1.2;
}
.md h2 {
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -0.3px;
  color: var(--text-bright);
  margin: 24px 0 2px;
  line-height: 1.25;
}
.md h3 {
  font-size: 17px;
  font-weight: 600;
  color: var(--text-bright);
  margin: 12px 0 2px;
  line-height: 1.3;
}
.md h4, .md h5, .md h6 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-bright);
  margin: 10px 0 2px;
}

.md p {
  margin: 4px 0;
  line-height: 1.55;
  color: var(--text);
}

.md strong { font-weight: 700; color: var(--text-bright); }
.md em     { font-style: italic; }
.md del    { text-decoration: line-through; opacity: 0.7; }
.md a      { color: var(--accent-hover); text-decoration: none; }
.md a:hover { text-decoration: underline; }

.md ul, .md ol { padding-left: 22px; margin: 4px 0; }
.md li         { margin: 2px 0; line-height: 1.55; }
.md li > p     { margin: 0; }
.md li::marker { color: var(--text-muted); }

.md blockquote {
  border-left: 3px solid rgba(133,138,148,0.6);
  padding: 2px 0 2px 12px;
  margin: 6px 0;
  color: var(--text);
}
.md blockquote p { margin: 4px 0; }

/* Inline code */
.md p code, .md li code, .md td code, .md th code, .md blockquote code {
  background: rgba(255,255,255,0.07);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 3px;
  padding: 1px 5px;
  font-family: var(--font-mono);
  font-size: 0.88em;
  color: var(--text-bright);
}

/* Tables — header tint, zebra rows, right-aligned numeric cols (tableView) */
.md table {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  margin: 8px 0;
  border: 1px solid rgba(133,138,148,0.25);
  border-radius: 6px;
  overflow: hidden;
  font-size: 13.5px;
}
.md table thead { background: var(--bg-input); }
.md table th {
  text-align: left;
  font-weight: 600;
  color: var(--text-bright);
  padding: 8px 10px;
  border-bottom: 1px solid rgba(133,138,148,0.18);
}
.md table td {
  padding: 6px 10px;
  color: var(--text);
  border-bottom: 1px solid rgba(133,138,148,0.12);
  vertical-align: top;
}
.md table tbody tr:nth-child(even) { background: rgba(255,255,255,0.04); }
.md table tbody tr:last-child td { border-bottom: none; }
/* Right-aligned cells get tabular-numeric monospace */
.md table th[align="right"], .md table td[align="right"] {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.md table th[align="center"], .md table td[align="center"] {
  text-align: center;
}

/* Code blocks — #0F1217 canvas, white 8% border, lang chip + copy button
   (codeBlockView + SyntaxTheme.chip) */
.code-wrap {
  position: relative;
  margin: 8px 0;
}
.code-wrap pre {
  background: #0f1217;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  padding: 14px;
  overflow-x: auto;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
}
.code-wrap pre code {
  background: transparent;
  border: none;
  padding: 0;
  color: #ebebf0;
  font-size: inherit;
}
.code-wrap .code-lang,
.code-wrap .code-copy {
  position: absolute;
  top: 8px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  background: #2e3038;
  color: var(--text-muted);
  border: none;
  padding: 3px 7px;
  border-radius: 4px;
}
.code-wrap .code-lang { right: 62px; text-transform: lowercase; }
.code-wrap .code-copy { right: 8px; cursor: pointer; }
.code-wrap .code-copy:hover { background: #3a3d47; color: var(--text-bright); }

/* Thematic break ornament — hairline + diamond + hairline */
.hr-ornament {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 16px 0;
}
.hr-ornament .hr-line {
  flex: 1;
  height: 1px;
  background: rgba(133,138,148,0.18);
}
.hr-ornament .hr-diamond {
  color: rgba(133,138,148,0.5);
  font-size: 6px;
}

/* GitHub-style callouts (calloutView): tinted bg 8%, 3px color bar, radius 6 */
.callout {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: 10px;
  padding: 14px;
  border-radius: 6px;
  margin: 8px 0;
  background: var(--callout-bg, rgba(87,140,242,0.08));
  border-left: 3px solid var(--callout-color, #578CF2);
}
.callout-head {
  grid-column: 1 / span 2;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--callout-color, #578CF2);
  margin-bottom: 2px;
}
.callout-icon {
  font-size: 14px;
  line-height: 1;
}
.callout-body {
  grid-column: 1 / span 2;
  font-size: 14.5px;
}
.callout-body > *:first-child { margin-top: 0; }
.callout-body > *:last-child  { margin-bottom: 0; }
.callout-note      { --callout-color: #578CF2; --callout-bg: rgba(87,140,242,0.08); }
.callout-tip       { --callout-color: #66D98C; --callout-bg: rgba(102,217,140,0.08); }
.callout-warning   { --callout-color: #F29E4C; --callout-bg: rgba(242,158,76,0.10); }
.callout-important { --callout-color: #C773F2; --callout-bg: rgba(199,115,242,0.10); }

/* Custom ::: blocks */

/* Buttons row — interactive pill buttons that send replies on click */
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0;
}
.btn-pill {
  display: inline-flex;
  align-items: center;
  font: 600 13px var(--font-base);
  color: white;
  background: linear-gradient(to bottom, var(--accent-hover), var(--accent));
  border: 1px solid rgba(255,255,255,0.15);
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: transform 0.05s, opacity 0.15s;
}
.btn-pill:hover  { transform: translateY(-1px); }
.btn-pill:active { transform: translateY(0); }
.btn-pill:disabled,
.btn-pill.sending {
  opacity: 0.55;
  cursor: default;
  transform: none;
}

/* Stat / KPI block — 46px heavy value, uppercase caption (statBlockView) */
.stat-block {
  padding: 8px 0;
  margin: 6px 0;
}
.stat-value {
  font-size: 46px;
  font-weight: 800;
  letter-spacing: -1px;
  color: var(--text-bright);
  line-height: 1.05;
}
.stat-caption {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-top: 4px;
}
.stat-block.tint-green  .stat-value { color: #B8E88C; }
.stat-block.tint-amber  .stat-value,
.stat-block.tint-warn   .stat-value { color: #F29E4C; }
.stat-block.tint-red    .stat-value { color: #F37272; }
.stat-block.tint-blue   .stat-value { color: #578CF2; }
.stat-block.tint-purple .stat-value { color: #C773F2; }

/* Pull quote — 19px italic medium, accent left bar (pullQuoteView) */
.pullquote {
  border-left: 3px solid var(--accent);
  padding: 6px 0 6px 14px;
  margin: 8px 0;
  font-size: 19px;
  font-weight: 500;
  font-style: italic;
  color: var(--text-bright);
  line-height: 1.45;
}

/* Hero block — banner + gradient overlay + title bottom-left (heroBlockView) */
.hero-block {
  position: relative;
  width: 100%;
  max-width: 600px;
  height: 240px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg-input);
  margin: 8px 0;
}
.hero-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hero-overlay {
  position: absolute;
  inset: auto 0 0 0;
  padding: 18px;
  background: linear-gradient(to top, rgba(0,0,0,0.75), rgba(0,0,0,0.15) 65%, transparent);
  color: white;
}
.hero-title {
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -0.4px;
  text-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.hero-sub {
  font-size: 13px;
  font-weight: 500;
  margin-top: 2px;
  color: rgba(255,255,255,0.9);
  text-shadow: 0 1px 2px rgba(0,0,0,0.3);
}

/* Unknown ::: kind — render as faint monospace placeholder */
.unknown-block {
  background: rgba(255,255,255,0.03);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 12px;
  padding: 8px 10px;
  border-radius: 4px;
  white-space: pre-wrap;
}

/* ── Scrollbars ──────────────────────────────────────────────────────────────
   Chrome/Windows render classic scrollbars (wide, light) which glare against
   the dark theme; macOS overlay scrollbars never showed the problem. Style
   them thin + dark everywhere, matching the JenChat feel. */
* {
  scrollbar-width: thin;            /* Firefox */
  scrollbar-color: #2e2e36 transparent;
}
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: #2e2e36;
  border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
  background: #3d3d47;
}
::-webkit-scrollbar-corner {
  background: transparent;
}

/* mention chips + readable message links (2026-07-02) */
.mention-chip{color:#7cb0ff;background:rgba(91,155,255,.14);border-radius:5px;padding:0 4px;font-weight:600}
.mention-chip.me{color:#fbbf24;background:rgba(251,191,36,.16)}
.message-text a{color:#7cb0ff;text-decoration-color:rgba(124,176,255,.5)}
.message-text a:visited{color:#7cb0ff}
.message-text a:hover{color:#a3c8ff}


/* ══════════════════ Slack dark retheme (2026-07-02) ══════════════════
   Overrides layered on top of the JenChat theme, per Zi's reference. */
:root {
  --bg-deep: #19171d; --bg-mid: #19171d; --bg-chat: #1a1d21;
  --bg-input: #222529; --bg-float: #222529;
  --border: rgba(255,255,255,0.09);
  --bg-hover: rgba(255,255,255,0.05); --bg-active: #1164a3;
  --text-bright: #ffffff; --text: #d1d2d3; --text-muted: #a3a6ab;
  --ch-row: #a3a6ab; --ch-row-dim: #7d8087;
  --accent: #1d9bd1; --accent-hover: #3fb2e3; --accent-soft: rgba(29,155,209,0.15);
}
body, .app { background: var(--bg-chat); }
.sidebar { background: var(--bg-deep); border-right: 1px solid rgba(0,0,0,.35); }
.brand { padding: 12px 16px; border-bottom: 1px solid rgba(255,255,255,.06); }
.brand .brand-name { font-size: 15.5px; font-weight: 900; color: #fff; }
.brand .brand-sub { color: var(--text-muted); }

/* channel rows — Slack rhythm */
.channel { padding: 4px 10px; border-radius: 6px; margin: 0 8px; color: var(--ch-row); font-size: 14px; gap: 8px; }
.channel:hover { background: rgba(255,255,255,.055); }
.channel.active { background: var(--bg-active); color: #fff; }
.channel.active .ch-hash, .channel.active .ch-name { color: #fff; }
.channel.unread .ch-name { color: #fff; font-weight: 700; }
.ch-unread-badge { background: #e01e5a; color: #fff; font-size: 10.5px; font-weight: 700; border-radius: 9px; padding: 1px 7px; }
.channel-section-title { color: var(--text-muted); font-size: 13px; font-weight: 500; text-transform: none; letter-spacing: 0; padding: 14px 18px 4px; }

/* presence dots on user DMs */
.ch-presence { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid #949494; flex: 0 0 auto; display: inline-block; }
.ch-presence.online { background: #2bac76; border-color: #2bac76; }

/* messages — tight Slack density, square avatars, white names */
.messages { background: var(--bg-chat); }
.message { padding: 3px 20px; border-radius: 0; }
.message:hover { background: rgba(255,255,255,.03); }
.message.grouped { margin-top: -2px; }
.message-avatar { width: 36px; height: 36px; border-radius: 6px; }
.message-avatar.spacer { background: transparent !important; height: 1px; }
.message-author { color: var(--text-bright) !important; font-weight: 800; font-size: 14.5px; }
.message-ts { color: var(--text-muted); font-size: 11.5px; }

/* date divider */
.day-divider { display: flex; align-items: center; text-align: center; margin: 14px 20px 8px; color: var(--text-muted); }
.day-divider::before, .day-divider::after { content: ''; flex: 1; border-top: 1px solid rgba(255,255,255,.09); }
.day-divider-label { font-size: 12.5px; font-weight: 700; color: #d1d2d3; padding: 3px 12px; border: 1px solid rgba(255,255,255,.12); border-radius: 999px; margin: 0 8px; background: var(--bg-chat); }

/* chat header */
.chat-header { background: var(--bg-chat); border-bottom: 1px solid rgba(255,255,255,.09); font-weight: 900; }
.chat-header .hash { color: var(--text-muted); }

/* composer — bordered rounded box like Slack */
.composer { margin: 4px 20px 18px; border: 1px solid #565856; border-radius: 8px; background: var(--bg-chat); padding: 6px 8px; }
.composer:focus-within { border-color: #a3a6ab; }
.composer textarea { background: transparent; border: none; }
.composer .composer-attach-btn { color: var(--text-muted); }

/* mention chips echo Slack's blue highlight */
.mention-chip { color: #1d9bd1; background: rgba(29,155,209,.16); }
.mention-chip.me { color: #f2c744; background: rgba(242,199,68,.18); }

/* grouped rows: no repeated name/time; tiny hover timestamp in the gutter */
.message.grouped .message-meta { display: none; }
.message.grouped .message-avatar.spacer { position: relative; height: auto; align-self: stretch; }
.message.grouped .message-avatar.spacer::after { content: attr(data-ts); position: absolute; right: 0; top: 2px; font-size: 10px; color: var(--text-muted); opacity: 0; white-space: nowrap; }
.message.grouped:hover .message-avatar.spacer::after { opacity: 1; }

/* emoji avatar presets (2026-07-03) */
.emoji-grid { display: grid; grid-template-columns: repeat(9, 1fr); gap: 6px; margin: 10px 0 4px; }
.emoji-grid.compact { grid-template-columns: repeat(9, 1fr); margin: 10px 0 0; }
.emoji-choice { font-size: 20px; line-height: 1; padding: 6px 0; background: var(--bg-input); border: 1px solid transparent; border-radius: 8px; cursor: pointer; }
.emoji-choice:hover { border-color: var(--border); background: var(--bg-hover); }
.emoji-choice.sel { border-color: var(--accent); background: var(--accent-soft); }
/* speech bubbles — both sides, shrink-to-fit (2026-07-03) */
.message-text {
  display: inline-block;
  width: fit-content;
  max-width: 68%;
  padding: 7px 12px;
  border-radius: 4px 14px 14px 14px;   /* received: notch top-left */
  background: #26292d;
  color: var(--text);
}
.message.agent .message-text { background: #2b2f36; }
.message-text pre,
.message-text img { max-width: 100%; }

/* own messages: right side, blue bubble */
.message.mine { flex-direction: row-reverse; }
.message.mine .message-body { display: flex; flex-direction: column; align-items: flex-end; }
.message.mine .message-meta { flex-direction: row-reverse; }
.message.mine .message-author { display: none; }
.message.mine .message-text {
  background: #1164a3;
  color: #fff;
  border-radius: 14px 4px 14px 14px;   /* mine: notch top-right */
}
/* grouped bubbles drop the notch so a stack reads as one column */
.message.grouped .message-text { border-radius: 14px; }
.message.mine .message-text a { color: #cfe3ff; }
.message-text code { background: rgba(0,0,0,.22); }
.message.mine .message-text code { background: rgba(0,0,0,.28); }
.message.mine .message-avatar.spacer::after { right: auto; left: 0; }
.message.mine .mention-chip { background: rgba(255,255,255,.2); color: #fff; }
@media (max-width: 700px) { .message-text { max-width: 82%; } }

/* tighter bubble rhythm (2026-07-03) */
.message { padding-top: 1px; padding-bottom: 1px; align-items: flex-start; }
.message.grouped { margin-top: 1px; }
.message-body { gap: 1px; }
.message-meta { margin-bottom: 1px; line-height: 1.1; }
.message-text { padding: 5px 11px; line-height: 1.34; }
/* consecutive bubbles from the same person hug each other */
.message.grouped .message-text { margin-top: 0; }

/* bubble internal padding correction (2026-07-03) */
.message { padding-top: 3px; padding-bottom: 3px; }   /* restore row rhythm */
.message.grouped { margin-top: 2px; }
.message-body { gap: 2px; }
.message-text { padding-top: 2px; padding-bottom: 2px; padding-left: 11px; padding-right: 11px; line-height: 1.3; }

/* bubble internal padding v2 — even tighter top/bottom (2026-07-03) */
.message-text { padding-top: 0px; padding-bottom: 1px; line-height: 1.28; }
.message-text p { margin: 0; }
.message-text p + p { margin-top: 4px; }

/* bubble padding split-difference (2026-07-03) */
.message-text { padding-top: 1px; padding-bottom: 2px; line-height: 1.3; }

/* both bubbles grey + roomier padding (2026-07-03) */
.message-text { background: #26292d; color: var(--text); padding: 6px 12px; line-height: 1.38; }
.message.mine .message-text { background: #26292d; color: var(--text); }
.message.agent .message-text { background: #2b2f36; }
.message.mine .message-text a { color: #7cb0ff; }
.message.mine .mention-chip { color: #1d9bd1; background: rgba(29,155,209,.16); }
.message.mine .message-text code { background: rgba(0,0,0,.22); }

/* image lightbox (2026-07-03) */
.lightbox { position: fixed; inset: 0; z-index: 3000; background: rgba(0,0,0,.9); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.lightbox img { max-width: 92vw; max-height: 92vh; user-select: none; transition: transform .04s linear; will-change: transform; }
/* archived channel rows read dimmed */
.channel.archived { opacity: .55; }
.channel.archived:hover { opacity: .8; }
/* show-archived toggle */
.show-archived-btn { display: block; width: calc(100% - 16px); margin: 2px 8px 6px; padding: 5px 10px; background: transparent; border: 1px solid var(--line); border-radius: 7px; color: var(--text-muted); font: inherit; font-size: 12px; cursor: pointer; text-align: left; }
.show-archived-btn:hover { background: var(--bg-hover); color: var(--text); }
.show-archived-btn.on { color: var(--accent); border-color: var(--accent); }

/* real icons in sidebar links (2026-07-03) */
.admin-link { display: flex; align-items: center; gap: 8px; }
.admin-link svg { flex: 0 0 auto; opacity: .85; }
.notif-icon svg, .translate-icon svg { display: block; }

/* ── Message search results (sidebar) ──────────────────────────────────────
   Populated by renderSearchResults() when the search box has a 2+ char query.
   Sits directly under the channel list; each row jumps to the message. */
.search-results {
  border-top: 1px solid var(--border);
  margin-top: 4px;
  padding: 6px 8px 10px;
  overflow-y: auto;
}
.search-results-head {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim);
  padding: 4px 6px 8px;
}
.search-result {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  padding: 7px 9px;
  margin-bottom: 2px;
  cursor: pointer;
  color: var(--text);
  font-family: var(--font-base);
}
.search-result:hover { background: var(--bg-hover); }
.search-result .sr-channel {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ch-row);
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.search-result .sr-line {
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--text-muted);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.search-result .sr-author { color: var(--text); font-weight: 600; }
.search-result mark {
  background: rgba(245,181,69,0.32);
  color: var(--text-bright);
  border-radius: 3px;
  padding: 0 1px;
}

/* Brief highlight on a message you jumped to from search results. */
@keyframes searchFlash {
  0%   { background: rgba(245,181,69,0.32); }
  100% { background: transparent; }
}
.message.search-flash {
  animation: searchFlash 2.2s ease-out;
  border-radius: var(--radius);
}
@media (prefers-reduced-motion: reduce) {
  .message.search-flash { animation: none; background: rgba(245,181,69,0.18); }
}

/* ── "Get the app" install section (profile modal) ───────────────────────── */
.install-section {
  margin-top: 6px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.install-app-btn {
  align-self: flex-start;
  cursor: pointer;
}
.install-hint {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-muted);
}
.install-hint strong { color: var(--text); font-weight: 600; }
.install-hint code {
  background: var(--bg-input);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text);
}

/* ── Press-and-hold language peek tabs (per message) ─────────────────────── */
.lang-peek-tabs {
  display: flex;
  gap: 4px;
  margin-top: 5px;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.message:hover .lang-peek-tabs { opacity: 1; }
.message.mine .lang-peek-tabs { justify-content: flex-end; }
.lang-peek-tab {
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.02em;
  padding: 3px 7px;
  border-radius: 5px;
  border: 1px solid var(--border);
  background: var(--bg-input);
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;         /* press-and-hold must not scroll the list on touch */
  font-family: var(--font-base);
}
.lang-peek-tab:hover { color: var(--text); border-color: rgba(255,255,255,0.18); }
.lang-peek-tab.active { background: var(--accent); color: #fff; border-color: var(--accent); }
.lang-peek-tab.loading { opacity: 0.55; }
/* Touch devices can't hover, so keep the tabs faintly visible for discovery. */
@media (hover: none) {
  .lang-peek-tabs { opacity: 0.5; }
}

/* Version line in the profile "Get the app" section (native APK + web build). */
.app-version-line {
  font-size: 11.5px;
  color: var(--text-muted);
  font-family: var(--font-mono);
  padding: 2px 0 4px;
}

/* ── Video attachments ──────────────────────────────────────────────────── */
.attachment-video {
  max-width: min(360px, 100%);
  max-height: 360px;
  border-radius: 8px;
  display: block;
  background: #000;
}
/* Video thumbnail in the composer pending row uses the same 56px chip as images. */
.pending-attachment.pending-image video.pa-thumb {
  object-fit: cover;
  background: #000;
}
.pending-attachment .pa-play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  font-size: 15px;
  text-shadow: 0 1px 3px rgba(0,0,0,0.75);
  pointer-events: none;
}

/* ── Video captions (CC) control ────────────────────────────────────────── */
.video-wrap { position: relative; display: inline-block; max-width: min(360px, 100%); }
.video-wrap .attachment-video { max-width: 100%; }
.cc-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  background: rgba(0,0,0,0.65);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.25);
  border-radius: 6px;
  font-size: 11px;
  font-weight: 700;
  padding: 3px 8px;
  cursor: pointer;
  font-family: var(--font-base);
}
.cc-btn.on { background: var(--accent); border-color: var(--accent); }
.cc-btn.busy { opacity: 0.7; }
.cc-menu {
  position: absolute;
  top: 34px;
  right: 8px;
  background: var(--bg-float);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px;
  z-index: 30;
  min-width: 130px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
}
.cc-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 5px;
  color: var(--text);
  font-size: 13px;
  padding: 7px 10px;
  cursor: pointer;
  font-family: var(--font-base);
}
.cc-item:hover { background: var(--bg-hover); }
.cc-note { font-size: 11.5px; color: var(--text-muted); padding: 6px 10px 4px; }
/* Caption cue readability */
.attachment-video::cue { background: rgba(0,0,0,0.75); font-size: 15px; }

/* ── Upload progress chip ───────────────────────────────────────────────── */
.pending-attachment.pa-uploading {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 220px;
  position: relative;
  overflow: hidden;
}
.pa-upname {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
}
.pa-pct { font-size: 11px; color: var(--text-muted); font-family: var(--font-mono); }
.pa-bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background: rgba(255,255,255,0.08);
}
.pa-bar-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  transition: width 0.15s linear;
}

/* ── Fullscreen video (wrapper-level, keeps CC controls usable) ─────────── */
.fs-btn { right: 54px; font-size: 13px; padding: 2px 8px; }
.video-wrap:fullscreen {
  max-width: none;
  width: 100%;
  height: 100%;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.video-wrap:fullscreen .attachment-video {
  max-width: 100%;
  max-height: 100%;
  width: 100%;
  height: 100%;
  border-radius: 0;
}
.video-wrap:fullscreen .cc-btn { top: 16px; right: 16px; font-size: 14px; padding: 6px 12px; }
.video-wrap:fullscreen .fs-btn { right: 92px; }
.video-wrap:fullscreen .cc-menu { top: 52px; right: 16px; min-width: 170px; }
.video-wrap:fullscreen .cc-item { font-size: 15px; padding: 9px 12px; }
/* Caption size: comfortable inline, notably larger in fullscreen. */
.attachment-video::cue { background: rgba(0,0,0,0.75); font-size: 16px; }
.video-wrap:fullscreen .attachment-video::cue { font-size: 30px; line-height: 1.35; }

/* One fullscreen button only: hide the native control (Chromium uses the
   controlsList attribute; WebKit/Safari needs this pseudo-element). Our ⛶
   wrapper-fullscreen button is the working one (keeps CC controls visible). */
.attachment-video::-webkit-media-controls-fullscreen-button { display: none !important; }

/* Caption-generation progress pill (bottom-center of the player) */
.cc-progress {
  position: absolute;
  left: 50%;
  bottom: 52px;
  transform: translateX(-50%);
  background: rgba(0,0,0,0.78);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 999px;
  font-size: 12px;
  padding: 6px 14px;
  pointer-events: none;
  white-space: nowrap;
  z-index: 25;
}
.video-wrap:fullscreen .cc-progress { font-size: 16px; bottom: 90px; }

/* ── Channel doc (shared editable notes per channel) ────────────────────── */
.doc-btn {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  background: rgba(255,255,255,0.04);
  color: var(--text-muted);
  border: none;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  font-family: var(--font-base);
}
.doc-btn:hover { color: var(--text-bright); background: rgba(255,255,255,0.08); }
.doc-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.55);
  z-index: 2000;
  display: flex;
  justify-content: flex-end;
}
.doc-grip {
  position: absolute; left: -3px; top: 0; width: 9px; height: 100%;
  cursor: col-resize; z-index: 5; touch-action: none;
}
.doc-grip:hover { background: linear-gradient(to right, transparent, var(--accent) 40%, transparent); opacity: .5; }
.doc-panel.fullscreen { width: 100% !important; max-width: none; border-left: none; }
.doc-panel.fullscreen .doc-grip { display: none; }
.doc-fs { background: transparent; border: none; color: var(--text-muted); cursor: pointer; font-size: 15px; padding: 2px 6px; }
.doc-fs:hover { color: var(--text-bright); }
.doc-panel {
  position: relative;
  min-width: 320px;
  width: min(560px, 100%);
  height: 100%;
  background: var(--bg-float);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  box-shadow: -8px 0 32px rgba(0,0,0,0.45);
}
.doc-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.doc-title { font-size: 15px; font-weight: 700; color: var(--text-bright);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.doc-head-btns { display: flex; gap: 8px; align-items: center; }
.doc-edit-btn { font-size: 12.5px; padding: 6px 14px; }
.doc-close {
  background: none; border: none; color: var(--text-muted); font-size: 17px;
  cursor: pointer; padding: 2px 6px;
}
.doc-close:hover { color: var(--text-bright); }
.doc-body { flex: 1; overflow-y: auto; padding: 16px 18px; }
.doc-body a { color: var(--accent-hover); }
.doc-find { display: flex; align-items: center; gap: 6px; padding: 8px 16px 0; }
.doc-find input { flex: 1; min-width: 0; background: var(--bg-input); color: var(--text-bright);
  border: 1px solid var(--border); border-radius: 6px; padding: 6px 9px; font: inherit; font-size: 13px; }
.doc-find input:focus { border-color: var(--accent); outline: none; }
.doc-find button { background: var(--bg-input); color: var(--text-muted); border: 1px solid var(--border);
  border-radius: 6px; width: 26px; height: 28px; cursor: pointer; line-height: 1; }
.doc-find button:hover { color: var(--text-bright); }
.doc-find-count { color: var(--text-muted); font-size: 12px; white-space: nowrap; min-width: 54px; text-align: right; }
mark.doc-hit { background: #f6d365; color: #1b1b1b; border-radius: 2px; }
mark.doc-hit.on { background: #f59e0b; box-shadow: 0 0 0 2px rgba(245,158,11,.45); }
/* Pasted images had no size rule, so a full-width screenshot overflowed the
   doc panel instead of fitting it. (Zi 2026-08-30) */
.doc-body img { max-width: 100%; height: auto; border-radius: 6px; display: block; margin: 8px 0; }
.doc-empty { color: var(--text-muted); font-size: 13.5px; padding: 22px 18px; line-height: 1.5; }
.doc-foot {
  padding: 10px 16px;
  border-top: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 11.5px;
  flex-shrink: 0;
}
.doc-textarea {
  flex: 1;
  margin: 12px 16px;
  background: var(--bg-input);
  color: var(--text-bright);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 13.5px;
  font-family: var(--font-mono);
  line-height: 1.55;
  resize: none;
  outline: none;
}
.doc-textarea:focus { border-color: var(--accent); }

/* Rich doc editor (Toast UI). The panel is a flex column, so the host needs an
   explicit min-height:0 or the editor grows past the panel instead of
   scrolling inside it. (Zi 2026-08-30) */
.doc-editor { flex: 1; min-height: 0; margin: 12px 16px; display: flex; }
.doc-editor > .toastui-editor-defaultUI { flex: 1; min-height: 0; border-radius: 8px; }
.doc-editor .doc-textarea { margin: 0; }
/* Toast UI underlines h1 (double rule) and h2 (single rule) by default. The doc
   VIEW does not, so the editor disagreed with the saved result and it looked
   like pasting had added horizontal lines. (Zi 2026-08-30) */
.doc-editor .toastui-editor-contents h1,
.doc-editor .toastui-editor-contents h2 { border-bottom: none; padding-bottom: 0; }
/* A pasted screenshot arrives at natural size — 2500px wide is common — and
   markdown carries no display size, so cap it to the editor instead of letting
   one image swallow the page. Matches what .doc-body already does on the view
   side. Height cap stops a tall screenshot pushing everything off screen.
   For a deliberate size, raw <img width="480"> still works. (Zi 2026-08-30) */
.doc-editor .toastui-editor-contents img,
.toastui-editor-contents img { max-width: 100%; height: auto; max-height: 70vh; }
.doc-body img { max-height: 70vh; cursor: zoom-in; }
/* Its default white chrome fights the dark app; the dark theme handles the rest. */
.toastui-editor-defaultUI { border-color: var(--border) !important; }
.toastui-editor-dark .toastui-editor-defaultUI,
.toastui-editor-dark .toastui-editor-md-container,
.toastui-editor-dark .toastui-editor-ww-container { background: var(--bg-input) !important; }
.toastui-editor-dark .toastui-editor-toolbar { background: var(--bg-float, #1b1e24) !important; }
@media (max-width: 900px) {
  .doc-panel { width: 100%; border-left: none; padding-top: env(safe-area-inset-top, 0px); }
  .doc-btn .doc-label { display: none; }
}

/* ── Download-apps popup ────────────────────────────────────────────────── */
.dl-modal { max-width: 460px; }
.dl-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 8px;
}
.dl-row.mine { border-color: var(--accent); background: var(--accent-soft); }
.dl-ic { font-size: 20px; flex-shrink: 0; }
.dl-tx { flex: 1; min-width: 0; }
.dl-nm { font-size: 13.5px; font-weight: 700; color: var(--text-bright); }
.dl-nt { font-size: 11.5px; color: var(--text-muted); line-height: 1.4; margin-top: 2px; }
.dl-go { font-size: 12px; padding: 7px 14px; text-decoration: none; white-space: nowrap; flex-shrink: 0; }
.dl-ic { display: flex; align-items: center; justify-content: center; width: 24px; color: var(--text); }

/* "Keep me signed in" — checkbox inline BESIDE its text (auth-form labels
   otherwise stack their contents vertically with uppercase styling). */
.auth-form label.remember-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  margin: 2px 0 12px;
  cursor: pointer;
}
.auth-form label.remember-row span {
  text-transform: none;
  letter-spacing: 0;
  font-size: 13px;
  font-weight: 400;
  color: var(--text);
  margin: 0;
}
.auth-form label.remember-row input[type="checkbox"] {
  width: auto;
  margin: 0;
  accent-color: var(--accent);
}

/* ── Inline message editing (no popup) ──────────────────────────────────── */
.inline-edit { margin-top: 4px; position: relative; }
.empty.loading { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; }
.msg-spinner { width: 30px; height: 30px; border-radius: 50%; border: 3px solid rgba(255,255,255,0.14); border-top-color: var(--accent, #5865f2); animation: msgspin 0.8s linear infinite; }
@keyframes msgspin { to { transform: rotate(360deg); } }
.mention-popup-fixed { z-index: 3500; box-shadow: 0 6px 20px rgba(0,0,0,0.6); }
.inline-edit-ta {
  width: 100%;
  max-width: 640px;
  background: var(--bg-input);
  color: var(--text-bright);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 15px;
  font-family: inherit;
  line-height: 1.4;
  resize: vertical;
  outline: none;
}
.inline-edit-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.inline-edit-btn { font-size: 12px; padding: 6px 14px; }
.inline-edit-hint { font-size: 11px; color: var(--text-dim); }

/* ── Translation language dropdown ──────────────────────────────────────── */
.tr-menu {
  position: fixed;
  background: var(--bg-float);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px;
  z-index: 2200;
  min-width: 180px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
}
.tr-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 5px;
  color: var(--text);
  font-size: 13px;
  padding: 8px 11px;
  cursor: pointer;
  font-family: var(--font-base);
}
.tr-item:hover { background: var(--bg-hover); }
.tr-item.active { color: var(--accent-hover); font-weight: 700; }

/* ============ LIGHT MODE (html.light) — user preference, 2026-07-15 ============ */
html.light {
  --bg-deep:#f6f6f8; --bg-mid:#f6f6f8; --bg-chat:#ffffff;
  --bg-input:#f0f0f3; --bg-float:#ffffff; --bg-panel:#f6f6f8;
  --bg-hover:rgba(0,0,0,0.05); --bg-active:#1164a3;
  --border:rgba(0,0,0,0.12);
  --text-bright:#1d1c1d; --text:#2b2b2e; --text-muted:#6b6f76; --text-dim:#9a9ea6;
  --ch-row:#4a4d55; --ch-row-dim:#8b8e95;
  --accent:#1d9bd1; --accent-hover:#1787b8; --accent-soft:rgba(29,155,209,0.12);
  color-scheme: light;
}
html.light .sidebar { border-right:1px solid rgba(0,0,0,.12); }
html.light .brand { border-bottom:1px solid rgba(0,0,0,.08); }
html.light .brand .brand-name { color:#1d1c1d; }
html.light .channel:hover { background:rgba(0,0,0,.05); }
html.light .channel.unread .ch-name { color:#1d1c1d; }
html.light .message:hover { background:rgba(0,0,0,.03); }
html.light .day-divider::before, html.light .day-divider::after { border-top-color:rgba(0,0,0,.10); }
html.light .day-divider-label { color:#6b6f76; border-color:rgba(0,0,0,.14); }
html.light .chat-header { border-bottom:1px solid rgba(0,0,0,.10); }
html.light .doc-btn, html.light .translate-btn, html.light .notif-btn { background:rgba(0,0,0,.04); }
html.light .doc-btn:hover, html.light .translate-btn:hover, html.light .notif-btn:hover,
html.light .attachment-file:hover { background:rgba(0,0,0,.07); }
html.light .btn-secondary:hover, html.light .lang-btn:hover { background:rgba(0,0,0,.04); }
html.light .md table tbody tr:nth-child(even) { background:rgba(0,0,0,.03); }
html.light .md code, html.light .md pre { background:rgba(0,0,0,.05); border-color:rgba(0,0,0,.10); }
html.light .hero-sub { color:rgba(0,0,0,.72); }
html.light .ch-presence { border-color:#9a9a9a; }
html.light .ch-sort-toggle button.active { color:#1d1c1d; }
html.light .tr-menu { box-shadow:0 8px 24px rgba(0,0,0,.16); }
html.light .message .msg-time { color:var(--text-dim); }

/* light mode: message bubbles + code + scrollbars (fix 2026-07-15, Zi report) */
html.light .message-text,
html.light .message.mine .message-text { background: #eef0f3; color: var(--text); }
html.light .message.agent .message-text { background: #e8edf3; }
html.light .message-text code,
html.light .message.mine .message-text code { background: rgba(0,0,0,.08); }
html.light .message.mine .message-text a { color: #1264a3; }
html.light .message-text pre,
html.light .code-wrap pre { background: #f4f5f7; border: 1px solid rgba(0,0,0,.10); color: #24292f; }
html.light * { scrollbar-color: #c3c6cc transparent; }
html.light ::-webkit-scrollbar-thumb { background: #c3c6cc; }

/* light mode: QC sweep fixes (2026-07-15) */
html.light .modal-field input[type="text"],
html.light .modal-field input[type="password"],
html.light .modal-field select { border-color: rgba(0,0,0,.20); }
html.light .chat-header { border-bottom: 1px solid rgba(0,0,0,.10); box-shadow: none; }
html.light .avatar-preview { border-color: rgba(0,0,0,.22); }
html.light .mention-chip { color: #1264a3; background: rgba(18,100,163,.10); }
html.light .mention-chip.me { color: #8a5a00; background: rgba(251,191,36,.22); }
html.light .message-text a, html.light .message-text a:visited { color: #1264a3; text-decoration-color: rgba(18,100,163,.4); }
html.light .md p code, html.light .md li code, html.light .md td code,
html.light .md th code, html.light .md blockquote code { background: rgba(0,0,0,.06); border-color: rgba(0,0,0,.08); }
html.light .ctx-menu, html.light .tr-menu, html.light .cc-menu, html.light .auth-card,
html.light .doc-panel { box-shadow: 0 8px 24px rgba(0,0,0,.16); }

/* emoji + meme picker (2026-07-15) */
.emoji-picker { position: fixed; z-index: 2500; background: var(--bg-float); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.5); display: flex; flex-direction: column;
  max-height: min(420px, 60vh); overflow: hidden; }
html.light .emoji-picker { box-shadow: 0 12px 32px rgba(0,0,0,.18); }
.ep-tabs { display: flex; gap: 2px; padding: 8px 8px 0; }
.ep-tabs button { flex: 1; background: transparent; border: none; color: var(--text-muted); font: 600 13px var(--font-base);
  padding: 7px 0; cursor: pointer; border-radius: 7px 7px 0 0; border-bottom: 2px solid transparent; }
.ep-tabs button.active { color: var(--text-bright); border-bottom-color: var(--accent); }
.ep-search { margin: 8px 10px 2px; padding: 7px 10px; background: var(--bg-input); border: 1px solid var(--border);
  border-radius: 7px; color: var(--text-bright); font: 13.5px var(--font-base); outline: none; }
.ep-body { overflow-y: auto; padding: 6px 10px 12px; }
.ep-cat { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); padding: 10px 2px 4px; }
.ep-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(36px, 1fr)); }
.ep-e { background: transparent; border: none; font-size: 22px; line-height: 1; padding: 6px 0; cursor: pointer; border-radius: 6px; }
.ep-e:hover { background: var(--bg-hover); }
.ep-loading { color: var(--text-muted); font-size: 13.5px; padding: 18px 6px; text-align: center; }
.meme-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding-top: 8px; }
.meme-card { background: var(--bg-input); border: 1px solid var(--border); border-radius: 8px; padding: 0 0 4px;
  cursor: pointer; overflow: hidden; display: flex; flex-direction: column; gap: 4px; }
.meme-card img { width: 100%; height: 92px; object-fit: cover; display: block; background: #202226; }
html.light .meme-card img { background: #e8eaee; }
.meme-card span { font-size: 11px; color: var(--text-muted); padding: 0 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.meme-card:hover { border-color: var(--accent); }

/* shell version line in the download popup (2026-07-15) */
.dl-shell-line { font-size: 12.5px; color: var(--text-muted); margin: -4px 0 10px; }
.dl-shell-line.dl-shell-old { color: #f0a742; font-weight: 600; }

/* sidebar version line (2026-07-15) */
.sidebar-version { font-size: 10.5px; color: var(--text-dim); padding: 6px 18px calc(env(safe-area-inset-bottom, 0px) + 8px); flex: none; }
.sidebar-version.sv-old { color: #f0a742; font-weight: 700; }

/* light mode: context-menu hover kept white text on a pale hover bg (2026-07-15) */
html.light .ctx-menu-item:hover { color: var(--text-bright); }
html.light .ctx-menu-item.danger { color: #c53030; }
html.light .ctx-menu-item.danger:hover { background: rgba(197,48,48,0.10); }

/* outdated-shell banner (2026-07-15) */
.shell-update-banner { position: fixed; top: 0; left: 0; right: 0; z-index: 4000; background: #b3261e; color: #fff;
  display: flex; align-items: center; justify-content: center; gap: 14px; flex-wrap: wrap;
  padding: 9px 16px; font-size: 13.5px; font-weight: 600; }
.shell-update-link { color: #fff; background: rgba(255,255,255,.18); padding: 4px 14px; border-radius: 6px;
  text-decoration: none; font-weight: 700; }
.shell-update-link:hover { background: rgba(255,255,255,.3); }
.shell-update-how { font-weight: 400; opacity: .85; font-size: 12.5px; }

/* tighter composer buttons (Zi 2026-07-16): emoji + attach share a compact cluster */
.composer-attach-btn { width: 28px; }
#emojiBtn { margin-right: -6px; }

/* image annotation (2026-07-16) */
.lb-btn { background: rgba(255,255,255,.14); color: #fff; border: none; border-radius: 8px;
  padding: 8px 16px; font: 600 13.5px var(--font-base); cursor: pointer; }
.lb-btn:hover { background: rgba(255,255,255,.24); }
.lb-btn.active { background: var(--accent); }
.lb-btn:disabled { opacity: .5; }
.lb-edit { position: absolute; top: 16px; right: 66px; }
.lb-close { position: absolute; top: 14px; right: 14px; width: 42px; height: 42px; padding: 0; font-size: 20px; line-height: 1; display: flex; align-items: center; justify-content: center; border-radius: 50%; z-index: 2; }
.ann-wrap { max-width: 92vw; max-height: 80vh; display: flex; align-items: center; justify-content: center; }
.ann-canvas { max-width: 92vw; max-height: 80vh; touch-action: none; cursor: crosshair;
  border-radius: 6px; box-shadow: 0 8px 40px rgba(0,0,0,.5); }
.ann-bar { position: absolute; bottom: calc(env(safe-area-inset-bottom, 0px) + 16px); left: 50%;
  transform: translateX(-50%); display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  justify-content: center; background: rgba(20,20,24,.92); padding: 10px 14px; border-radius: 12px;
  max-width: 94vw; }
.ann-swatches { display: flex; gap: 6px; padding: 0 4px; }
.ann-swatch { width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; padding: 0; }
.ann-swatch.active { border-color: #fff; box-shadow: 0 0 0 2px rgba(255,255,255,.35); }
.ann-size { min-width: 40px; }
.ann-save { background: #2f9e44; }
.ann-save:hover { background: #37b24d; }
.ann-textinput { position: fixed; z-index: 3100; background: rgba(0,0,0,.55); border: 1.5px dashed rgba(255,255,255,.6);
  border-radius: 6px; padding: 4px 8px; font-weight: 700; outline: none; min-width: 160px; }

/* long menus scroll (ping picker has 27 entries) */
.tr-menu { max-height: min(62vh, 560px); overflow-y: auto; }

/* doc attachments (2026-07-17) */
.doc-att-title { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); padding: 14px 20px 6px; }
.doc-atts { display: flex; flex-wrap: wrap; gap: 10px; padding: 0 20px 10px; }
.doc-att { position: relative; }
.doc-att-img img { width: 108px; height: 82px; object-fit: cover; border-radius: 8px; cursor: zoom-in;
  border: 1px solid var(--border); display: block; }
.doc-att-file { display: flex; align-items: center; gap: 8px; background: var(--bg-input);
  border: 1px solid var(--border); border-radius: 8px; padding: 9px 12px; color: var(--text);
  font: 13px var(--font-base); cursor: pointer; max-width: 240px; }
.doc-att-file span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.doc-att-file:hover { border-color: var(--accent); }
.doc-att-rm { position: absolute; top: -7px; right: -7px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--danger); color: #fff; border: none; font-size: 11px; cursor: pointer; line-height: 1; }
.doc-att-add { background: transparent; border: 1.5px dashed var(--border); border-radius: 8px;
  color: var(--text-muted); padding: 9px 14px; font: 600 13px var(--font-base); cursor: pointer; }
.doc-att-add:hover { color: var(--accent); border-color: var(--accent); }
.doc-att-uploading { color: var(--text-muted); font-size: 12.5px; padding: 9px 4px; }
.pdf-overlay { position: fixed; inset: 0; z-index: 3200; background: rgba(0,0,0,.85);
  display: flex; align-items: center; justify-content: center; }
.pdf-overlay iframe { width: min(920px, 94vw); height: 92vh; border: none; border-radius: 8px; background: #fff; }
.pdf-close { position: absolute; top: 14px; right: 16px; }

/* Send button "pending" state — queued behind an in-flight upload (Zi 2026-07-27).
   A gentle pulse signals the message is waiting to send, not an error. */
#composerSend.pending { animation: sendPending 1s ease-in-out infinite; }
@keyframes sendPending { 0%,100% { opacity: .45; } 50% { opacity: 1; } }


/* Reply composer bar + in-message reply quote (Zi 2026-07-28) */
.composer-reply { display: flex; align-items: center; gap: 8px; padding: 7px 12px; margin: 0 0 6px; background: var(--bg-float, #12161c); border-left: 3px solid #3b82f6; border-radius: 6px; font-size: 13px; }
.composer-reply[hidden] { display: none !important; }
.composer-reply .cr-label { color: var(--text-dim, #8a8f98); flex: 0 0 auto; }
.composer-reply .cr-who { color: #3b82f6; font-weight: 600; }
.composer-reply .cr-text { color: var(--text-dim, #8a8f98); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.composer-reply .cr-x { flex: 0 0 auto; background: none; border: none; color: var(--text-dim, #8a8f98); cursor: pointer; font-size: 15px; padding: 2px 4px; }
.reply-quote { display: flex; gap: 6px; align-items: baseline; padding: 3px 8px; margin: 0 0 4px; border-left: 2px solid #3b82f6; background: rgba(59,130,246,0.07); border-radius: 4px; font-size: 12px; cursor: pointer; max-width: 100%; }
.reply-quote:hover { background: rgba(59,130,246,0.13); }
.reply-quote .rq-who { color: #3b82f6; font-weight: 600; flex: 0 0 auto; }
/* Was --text-dim, which is #52525c on a black chat background: 2.7:1, effectively
   unreadable at 12px. Note the fallback in the old rule was #8a8f98, so the intent was
   always a lighter grey and the variable quietly overrode it. --text is 14.5:1 and
   adapts to light mode on its own. The quote still reads as secondary: smaller type,
   blue rule down the side, tinted background, truncated. (Zi 2026-08-07) */
.reply-quote .rq-text { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── MOBILE HORIZONTAL PAN LOCK ─────────────────────────────────────────────
   The chat screen could be dragged left and right on a phone instead of
   sitting still. Two causes, both handled here: content that outgrows the
   viewport (a long URL, a wide code line, a table), and iOS's willingness to
   rubber-band horizontally when anything overflows even briefly.
   The off-canvas sidebar is position:fixed so it is unaffected by this.
   (Zi 2026-08-22) */
html, body {
  overflow-x: hidden;
  overscroll-behavior-x: none;
  max-width: 100%;
}
/* Long unbroken strings (URLs, hashes, paths) wrap instead of pushing width. */
.message-text, .md, .md p, .md li, .message-text a, .md a {
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* Tables are the other classic offender: let them scroll in place. */
.md table { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Pending-approval panel (Zi 2026-08-26). Shown INSTEAD of the sign-in and
   register forms, never alongside them. */
.auth-pending { text-align:center; padding:6px 2px 2px; }
.auth-pending .ap-icon { width:52px; height:52px; margin:4px auto 14px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(56,139,253,.14); color:#58a6ff; }
.auth-pending .ap-title { font-size:19px; font-weight:700; color:#e6edf3; }
.auth-pending .ap-title-cn { font-size:15px; font-weight:600; color:#c9d1d9; margin-top:2px; }
.auth-pending .ap-body { margin:14px auto 0; max-width:34ch; font-size:13.5px; line-height:1.55; color:#9aa4b2; }
.auth-pending .ap-body b { color:#e6edf3; }
.auth-pending .ap-body-cn { margin:7px auto 0; max-width:34ch; font-size:13.5px; line-height:1.6; color:#9aa4b2; }
.auth-pending .ap-body-cn b { color:#e6edf3; }
.auth-pending .ap-user { margin-top:16px; font-size:12.5px; color:#6e7681; word-break:break-all; }
.auth-pending .ap-alt { margin-top:18px; background:none; border:0; padding:6px;
  color:#58a6ff; font:inherit; font-size:12.5px; cursor:pointer; text-decoration:underline; }
.auth-pending .ap-alt:hover { color:#79c0ff; }

/* While waiting for approval the card shows ONE thing. */
.auth-card.pending .auth-tabs,
.auth-card.pending .auth-form { display: none !important; }


/* Long-press on a channel opens the admin menu. Without these, iOS also runs
   its own press gesture on the row: text selection and the callout bubble.
   (Zi 2026-08-29) */
.channel { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }


/* Bell flashes while anything is unread. Appended at the end of the file on
   purpose: .notif-btn.on sets its own colour at equal specificity, so this has
   to come later to win. Slow pulse, not a strobe, and it stops entirely for
   anyone who asked the OS to reduce motion. (Zi 2026-08-30) */
.notif-btn.has-unread { color: #e5484d; animation: bellPulse 1.6s ease-in-out infinite; }
@keyframes bellPulse {
  0%, 100% { color: #e5484d; }
  50%      { color: #ff9ea0; }
}
@media (prefers-reduced-motion: reduce) {
  .notif-btn.has-unread { animation: none; color: #e5484d; }
}


/* Update checker popped from the sidebar version line. */
.upd-check { position: fixed; left: 12px; bottom: 34px; z-index: 90; width: 260px;
  background: var(--bg-float); border: 1px solid var(--border); border-radius: 10px;
  padding: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.5); font-size: 13px; color: var(--text-normal); }
.upd-check .upd-title { font-weight: 700; margin-bottom: 6px; color: var(--text-bright); }
.upd-check .upd-dim { color: var(--text-muted); margin: 2px 0; }
.upd-check .upd-warn { color: #f0b429; margin: 4px 0; font-weight: 600; }
.upd-check .upd-btn { display: block; margin-top: 8px; text-align: center; text-decoration: none;
  background: var(--accent); color: #fff; border: none; border-radius: 7px; padding: 7px 10px;
  font: inherit; font-size: 12.5px; cursor: pointer; }
.upd-check .upd-btn:hover { filter: brightness(1.08); }


/* Drag handle for resizing an image in the doc editor. Sits in our own overlay
   layer above the editor, so ProseMirror never sees it. */
.doc-editor { position: relative; }
.img-resize-handle {
  position: absolute; width: 14px; height: 14px; z-index: 20;
  background: var(--accent); border: 2px solid #fff; border-radius: 3px;
  cursor: nwse-resize; box-shadow: 0 1px 4px rgba(0,0,0,.5); touch-action: none;
}
.img-resize-handle[hidden] { display: none; }
