:root {
  /* Tavily-inspired warm, airy palette */
  --bg: #f6f2e7; /* warm cream */
  --card: #fffdf8; /* assistant bubble / panels */
  --border: #e8e2d3; /* soft warm border */
  --text: #24231f; /* charcoal */
  --muted: #8f8a7c; /* warm gray */
  --sage: #6e8570; /* primary accent */
  --sage-strong: #566d5b; /* darker sage for links/text */
  --sage-soft: #e8eee2; /* sage tint (user bubble) */
  --cyan: #86d4df; /* pop accent */
  --charcoal: #2a2723; /* dark pill buttons */
  --charcoal-hover: #3a3630;
  --cream-on-dark: #f4efe0;

  /* Estedad is kept as a fallback in every language so Persian text always has
     a ZWNJ-aware face (Inter covers Latin, Estedad covers Arabic script).
     Vazirmatn sits behind it as a LOCAL fallback only — it is no longer
     fetched as a webfont, but it is commonly installed on Persian systems, so
     it is a better next step than a generic sans if Estedad fails to load. */
  --font-sans: "Inter", "Estedad", "Vazirmatn", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-display: "Space Grotesk", "Estedad", "Vazirmatn", var(--font-sans);
}

/* Persian uses Estedad for both body and display type — warmer letterforms and
   more stroke contrast than Vazirmatn, and it handles the half-space cleanly. */
html[lang="fa"] {
  --font-sans: "Estedad", "Vazirmatn", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Tahoma, sans-serif;
  --font-display: "Estedad", "Vazirmatn", "Space Grotesk", sans-serif;
}

/* Persian headings read better a touch tighter: the script already carries its
   own rhythm, and default tracking makes large sizes look loose. */
html[lang="fa"] h1,
html[lang="fa"] h2,
html[lang="fa"] .empty-state h2 {
  letter-spacing: -0.01em;
}

* {
  box-sizing: border-box;
}

/* Ensure the HTML `hidden` attribute always wins over display rules below. */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  height: 100%;
  /* Never let the browser/WebView auto-inflate text (Android text autosizing);
     the layout is already tuned per breakpoint. Pairs with the native
     setTextZoom(100) so Android matches the iOS sizing. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  color: var(--text);
  font-family: var(--font-sans);
  /* Fresh, faded nature landscape: bright center, soft green hills, a light
     winding path, and a gentle sun glow — all abstract CSS (no image asset). */
  background:
    radial-gradient(58% 46% at 50% 36%, rgba(255, 254, 247, 0.96), rgba(255, 254, 247, 0) 72%),
    radial-gradient(42% 30% at 50% 6%, rgba(255, 250, 224, 0.55), transparent 70%),
    linear-gradient(116deg, transparent 45%, rgba(230, 242, 226, 0.75) 50%, transparent 55%),
    radial-gradient(130% 72% at 18% 120%, rgba(92, 150, 102, 0.62), transparent 60%),
    radial-gradient(130% 72% at 86% 124%, rgba(126, 176, 126, 0.58), transparent 58%),
    radial-gradient(160% 82% at 50% 140%, rgba(150, 192, 142, 0.5), transparent 55%),
    linear-gradient(180deg, #eef4e6 0%, #e9f1e2 42%, #dfead8 100%),
    var(--bg);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

.layout {
  display: flex;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.app {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
}

.sidebar-backdrop {
  display: none;
}

/* Center the chat column within the main area */
.messages > *,
.empty-state,
.composer-inner {
  width: 100%;
  max-width: 760px;
  margin-inline: auto;
}

/* ---------- Top bar ---------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 22px;
  border-bottom: 1px solid var(--border);
  background: rgba(246, 242, 231, 0.72);
  backdrop-filter: blur(12px);
  position: sticky;
  top: 0;
  z-index: 5;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
}

.logo {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background: var(--charcoal);
  /* The mark is a spark — Hooshang struck a stone and discovered fire; هوش is
     "mind". An SVG spark of insight, set in the app's sage→cyan palette. */
}
.logo-mark { display: block; width: 60%; height: 60%; }

.brand h1 {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}

.model {
  margin: 1px 0 0;
  font-size: 11px;
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.ghost-btn {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 7px 16px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  transition: all 0.15s ease;
}

.ghost-btn:hover {
  border-color: var(--sage);
  color: var(--sage-strong);
  background: rgba(110, 133, 112, 0.06);
}

/* ---------- Messages ---------- */
.messages {
  flex: 1;
  overflow-y: auto;
  padding: 28px 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.empty-state {
  margin: auto;
  text-align: center;
  padding: 0 20px;
}
.empty-state h2 {
  font-family: var(--font-display);
  font-size: clamp(32px, 6vw, 52px);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 0;
  /* A soft, light green glow drifts gently across the words like a slow wave. */
  background: linear-gradient(
    100deg,
    var(--text) 0%,
    var(--text) 43%,
    #7fae90 47%,
    #bfe6cc 50%,
    #7fae90 53%,
    var(--text) 57%,
    var(--text) 100%
  );
  background-size: 320% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Rises in as part of the welcome sequence, THEN the green wave drifts across
     it. Two animations, so the RTL rule below flips only the shimmer. */
  animation: heading-in 0.55s var(--ease-out) 0.14s both,
             title-shimmer 9s ease-in-out 0.72s infinite;
}
@keyframes heading-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
/* LTR sweeps left→right; RTL (Persian) sweeps right→left. */
@keyframes title-shimmer {
  0% {
    background-position: 190% 0;
  }
  100% {
    background-position: -90% 0;
  }
}
html[dir="rtl"] .empty-state h2 {
  /* heading-in stays normal; only the shimmer sweeps the other way for RTL. */
  animation-direction: normal, reverse;
}
@media (prefers-reduced-motion: reduce) {
  .empty-state h2 {
    animation: none;
  }
}

.msg {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  max-width: 100%;
  animation: fade-in 0.22s ease;
}

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.msg .avatar {
  flex: 0 0 32px;
  height: 32px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 600;
}

.msg.user .avatar {
  background: var(--sage-soft);
  color: var(--sage-strong);
}

.msg.assistant .avatar {
  background: var(--sage);
  color: var(--cream-on-dark);
}

.msg .bubble {
  padding: 11px 15px;
  border-radius: 14px;
  line-height: 1.62;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  font-size: 15px;
  text-align: start; /* follows dir=auto (RTL for Persian, LTR for English) */
  min-width: 0;
}

.msg.user .bubble {
  background: var(--sage-soft);
  color: var(--text);
  white-space: pre-wrap; /* preserve the user's own line breaks */
}

.msg.assistant .bubble {
  flex: 1 1 auto;
  background: var(--card);
  border: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(40, 38, 30, 0.04), 0 8px 24px rgba(40, 38, 30, 0.05);
}

.bubble .cursor {
  display: inline-block;
  width: 7px;
  height: 15px;
  background: var(--sage);
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: blink 1s steps(2) infinite;
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

.error {
  color: #c0553f;
  font-size: 14px;
}

/* "Searching the web…" indicator */
.bubble .status {
  font-size: 13px;
  font-weight: 500;
  color: var(--sage-strong);
  margin-bottom: 8px;
  animation: pulse 1.2s ease-in-out infinite;
}

@keyframes pulse {
  50% {
    opacity: 0.5;
  }
}

/* ---------- Composer ---------- */
.composer {
  padding: 10px 22px 20px;
}

.composer-inner {
  background: rgba(255, 253, 248, 0.72);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: 22px;
  padding: 14px 16px 12px;
  box-shadow: 0 2px 6px rgba(40, 38, 30, 0.04), 0 12px 32px rgba(40, 38, 30, 0.06);
  transition: border-color 0.15s ease;
}

.composer-inner:focus-within {
  border-color: var(--sage);
}

#input,
#room-input {
  display: block;
  width: 100%;
  resize: none;
  border: none;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 15.5px;
  line-height: 1.5;
  max-height: 200px;
  outline: none;
}
#input::placeholder,
#room-input::placeholder {
  color: var(--muted);
}

.composer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
}

/* Web-search chip (Tavily-style: dark when active) */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 13px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s ease;
}
.chip:hover {
  color: var(--text);
  border-color: var(--sage);
}
.chip .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #c6bfad;
}
.chip.active {
  background: var(--charcoal);
  color: var(--cream-on-dark);
  border-color: var(--charcoal);
}
.chip.active .dot {
  background: var(--cyan);
  box-shadow: 0 0 8px rgba(134, 212, 223, 0.9);
}

.send-btn {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--charcoal);
  color: var(--cream-on-dark);
  border: none;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.15s ease, transform 0.1s ease;
}
.send-btn:hover {
  background: var(--charcoal-hover);
}
.send-btn:active {
  transform: scale(0.94);
}
.send-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.send-btn.stopping {
  background: #c0553f;
}
.send-btn.stopping:hover {
  background: #a94733;
}

/* Empty-state suggestion chips */
.suggest-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: 20px;
}
.suggest-chip {
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.6);
  border-radius: 999px;
  padding: 8px 15px;
  font: inherit;
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
  transition: all 0.15s ease;
}
.suggest-chip:hover {
  border-color: var(--sage);
  color: var(--sage-strong);
  background: var(--card);
}

.hint {
  margin: 10px 4px 0;
  text-align: center;
  font-size: 11.5px;
  color: var(--muted);
}

/* ---------- Markdown rendering ---------- */
.bubble > :first-child {
  margin-top: 0;
}
.bubble > :last-child {
  margin-bottom: 0;
}
.content > :first-child {
  margin-top: 0;
}
.content > :last-child {
  margin-bottom: 0;
}

.bubble p {
  margin: 0 0 10px;
}

.bubble h1,
.bubble h2,
.bubble h3,
.bubble h4 {
  font-family: var(--font-display);
  margin: 16px 0 8px;
  line-height: 1.25;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.bubble h1 {
  font-size: 1.4em;
}
.bubble h2 {
  font-size: 1.25em;
}
.bubble h3 {
  font-size: 1.1em;
}
.bubble h4 {
  font-size: 1em;
}

.bubble strong {
  font-weight: 650;
  color: var(--text);
}
.bubble em {
  font-style: italic;
}

.bubble ul,
.bubble ol {
  margin: 0 0 10px;
  padding-inline-start: 1.5em;
}
.bubble li {
  margin: 3px 0;
}
.bubble li > p {
  margin: 0;
}
.bubble li::marker {
  color: var(--sage);
}

.bubble a {
  color: var(--sage-strong);
  text-decoration: none;
  border-bottom: 1px solid rgba(86, 109, 91, 0.35);
}
.bubble a:hover {
  border-bottom-color: var(--sage-strong);
}

.bubble blockquote {
  margin: 0 0 10px;
  padding: 2px 14px;
  border-inline-start: 3px solid var(--sage);
  color: var(--muted);
}

.bubble hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 14px 0;
}

/* Code */
.bubble code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
  background: rgba(40, 38, 30, 0.06);
  padding: 1px 6px;
  border-radius: 6px;
  direction: ltr;
  unicode-bidi: embed;
}
.bubble pre {
  position: relative;
  margin: 0 0 10px;
  padding: 13px 15px;
  background: #f4f0e3;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow-x: auto;
  direction: ltr;
  text-align: left;
}
.bubble pre code {
  background: none;
  padding: 0;
  font-size: 0.85em;
  line-height: 1.5;
}
.bubble pre code.hljs {
  padding: 0;
  background: none;
}

/* Tables */
.bubble table {
  border-collapse: collapse;
  margin: 4px 0 12px;
  width: 100%;
  font-size: 0.92em;
  display: block;
  overflow-x: auto;
}
.bubble th,
.bubble td {
  border: 1px solid var(--border);
  padding: 7px 12px;
  text-align: start;
}
.bubble thead th {
  background: var(--sage-soft);
  font-weight: 600;
}
.bubble tbody tr:nth-child(even) {
  background: rgba(40, 38, 30, 0.02);
}

/* ---------- Copy buttons ---------- */
.copy-code {
  position: absolute;
  top: 6px;
  right: 6px;
  background: var(--card);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 3px 10px;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.bubble pre:hover .copy-code {
  opacity: 1;
}
.copy-code:hover {
  color: var(--sage-strong);
  border-color: var(--sage);
}
.copy-code.copied {
  opacity: 1;
  color: var(--sage-strong);
  border-color: var(--sage);
}

/* Per-message copy action, on its own line under the bubble */
.msg-actions {
  flex-basis: 100%;
  margin-inline-start: 44px;
  margin-top: 2px;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.msg:hover .msg-actions {
  opacity: 1;
}
.copy-msg {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.copy-msg:hover {
  color: var(--sage-strong);
  border-color: var(--sage);
}
.copy-msg.copied {
  color: var(--sage-strong);
  border-color: var(--sage);
}

/* ---------- Sidebar ---------- */
.sidebar {
  /* Width lives in --sidebar-w (see "Resizable sidebar" below) — don't set a
     fixed width here, or a future edit will appear to do nothing. */
  display: flex;
  flex-direction: column;
  border-inline-end: 1px solid var(--border);
  background: rgba(246, 242, 231, 0.6);
  backdrop-filter: blur(10px);
}
.sidebar-head {
  padding: 16px 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.sidebar .brand {
  padding: 0 4px;
}
.new-chat-btn {
  background: var(--charcoal);
  color: var(--cream-on-dark);
  border: none;
  border-radius: 12px;
  padding: 10px 14px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  text-align: start;
  transition: background 0.15s ease;
}
.new-chat-btn:hover {
  background: var(--charcoal-hover);
}
.conversation-list {
  flex: 1;
  overflow-y: auto;
  padding: 6px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.convo-empty {
  color: var(--muted);
  font-size: 13px;
  padding: 10px 8px;
}
.convo-item {
  display: flex;
  align-items: center;
  gap: 4px;
  border-radius: 10px;
  padding-inline: 10px 4px;
  transition: background 0.12s ease;
}
.convo-item:hover {
  background: rgba(40, 38, 30, 0.05);
}
.convo-item.active {
  background: var(--sage-soft);
}
.convo-title-btn {
  flex: 1;
  min-width: 0;
  background: none;
  border: none;
  text-align: start;
  cursor: pointer;
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
  padding: 9px 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.convo-del {
  flex: 0 0 auto;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 12px;
  opacity: 0;
  padding: 4px 6px;
  border-radius: 8px;
  transition: opacity 0.12s ease;
}
.convo-item:hover .convo-del {
  opacity: 0.55;
}
.convo-del:hover {
  opacity: 1;
  background: rgba(192, 85, 63, 0.12);
}
.convo-item.confirming {
  background: rgba(192, 85, 63, 0.08);
  padding: 5px 8px;
  gap: 6px;
}
.convo-confirm-q {
  flex: 1;
  font-size: 12.5px;
  color: var(--muted);
}
.convo-confirm-yes {
  background: #c0553f;
  color: #fff;
  border: none;
  border-radius: 7px;
  padding: 4px 9px;
  font-size: 12px;
  cursor: pointer;
}
.convo-confirm-no {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 4px 9px;
  font-size: 12px;
  cursor: pointer;
  color: var(--text);
}
.sidebar-foot {
  border-top: 1px solid var(--border);
  padding: 10px;
}
.user-chip {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  background: transparent;
  border: none;
  border-radius: 12px;
  padding: 8px;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s ease;
}
.user-chip:hover {
  background: rgba(40, 38, 30, 0.05);
}
.user-avatar {
  flex: 0 0 34px;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--sage);
  color: var(--cream-on-dark);
  font-size: 13px;
  font-weight: 600;
}
.user-meta {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.user-name {
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-sub {
  font-size: 11px;
  color: var(--muted);
}

/* ---------- Topbar (main area) ---------- */
.topbar {
  justify-content: flex-start;
  gap: 12px;
}
.icon-btn {
  background: transparent;
  border: none;
  font-size: 18px;
  cursor: pointer;
  color: var(--text);
  padding: 6px 8px;
  border-radius: 9px;
  line-height: 1;
}
.icon-btn:hover {
  background: rgba(40, 38, 30, 0.06);
}
#menu-btn {
  display: none;
}
.topbar-title {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.topbar-title #convo-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60vw;
}
.chat-actions {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}
.chat-confirm-q {
  font-size: 12.5px;
  color: var(--muted);
}

/* ---------- Auth page ---------- */
.auth-body {
  display: grid;
  place-items: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 20px;
}
.auth-card {
  width: 100%;
  max-width: 400px;
  background: rgba(255, 253, 248, 0.82);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: 24px;
  padding: 34px 30px;
  box-shadow: 0 2px 8px rgba(40, 38, 30, 0.05), 0 20px 50px rgba(40, 38, 30, 0.08);
}
.auth-brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
.auth-brand h1 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  margin: 0;
}
.auth-tagline {
  color: var(--muted);
  margin: 10px 0 22px;
  font-size: 14px;
}
.auth-tabs {
  display: flex;
  gap: 6px;
  background: rgba(40, 38, 30, 0.05);
  border-radius: 12px;
  padding: 4px;
  margin-bottom: 20px;
}
.auth-tab {
  flex: 1;
  background: transparent;
  border: none;
  border-radius: 9px;
  padding: 9px;
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  color: var(--muted);
}
.auth-tab.active {
  background: var(--card);
  color: var(--text);
  box-shadow: 0 1px 2px rgba(40, 38, 30, 0.06);
}
.auth-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.field span {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
.field input {
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 11px 13px;
  font: inherit;
  font-size: 15px;
  background: var(--card);
  color: var(--text);
  outline: none;
  transition: border-color 0.15s ease;
}
.field input:focus {
  border-color: var(--sage);
}
.auth-error {
  color: #c0553f;
  font-size: 13px;
  margin: 0;
}
.auth-submit {
  margin-top: 4px;
  background: var(--charcoal);
  color: var(--cream-on-dark);
  border: none;
  border-radius: 12px;
  padding: 12px;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease;
}
.auth-submit:hover {
  background: var(--charcoal-hover);
}
.auth-submit:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.auth-hint {
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  margin: 18px 0 0;
}
.auth-hint a {
  color: var(--sage-strong);
  font-weight: 500;
  text-decoration: none;
}
.auth-hint a:hover {
  text-decoration: underline;
}

/* ---------- Profile / usage modal ---------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(40, 38, 30, 0.35);
  backdrop-filter: blur(3px);
  display: grid;
  place-items: center;
  padding: 20px;
  z-index: 50;
}
.modal-overlay[hidden] {
  display: none;
}
/* When the on-screen keyboard is open, an autofocused dialog must not hide
   behind it. On iOS the fixed layout keeps full height and the keyboard is drawn
   over the bottom, so `inset:0` centres the dialog partly off-screen. --vvh (set
   by the viewport tracker) is the height actually visible above the keyboard —
   clamp the overlay to it so the dialog re-centres in view. On Android
   (resizes-content) --vvh is unset and 100% already tracks the shrunk layout. */
html[data-kb="1"] .modal-overlay {
  bottom: auto;
  height: var(--vvh, 100%);
}
.modal {
  width: 100%;
  max-width: 520px;
  /* min(...100%) so that when the overlay is clamped to the visible area above
     the keyboard, the dialog fits it and scrolls internally instead of spilling
     behind the keyboard. */
  max-height: min(90vh, 100%);
  overflow-y: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 22px;
  padding: 24px;
  box-shadow: 0 20px 60px rgba(40, 38, 30, 0.2);
}
.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}
.modal-head h2 {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  margin: 0;
}
.modal-tabs {
  display: flex;
  gap: 4px;
  background: rgba(40, 38, 30, 0.05);
  border-radius: 10px;
  padding: 4px;
  margin-bottom: 18px;
}
.modal-tab {
  flex: 1;
  border: none;
  background: transparent;
  border-radius: 8px;
  padding: 8px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.modal-tab.active {
  background: var(--card);
  color: var(--text);
  box-shadow: 0 1px 2px rgba(40, 38, 30, 0.06);
}
.ptab-panel {
  display: none;
}
.ptab-panel.active {
  display: block;
}
.profile-account {
  display: flex;
  gap: 16px;
  margin-bottom: 18px;
}
.profile-avatar {
  flex: 0 0 56px;
  width: 56px;
  height: 56px;
  border-radius: 16px;
  display: grid;
  place-items: center;
  background: var(--sage);
  color: var(--cream-on-dark);
  font-size: 20px;
  font-weight: 600;
}
.field.inline {
  margin-bottom: 6px;
}
.profile-email {
  margin: 2px 0 0;
  color: var(--text);
  font-size: 14px;
}
.profile-since {
  margin: 2px 0 0;
  color: var(--muted);
  font-size: 12px;
}
.switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-bottom: 20px;
  font-size: 14px;
}
.switch-row small {
  color: var(--muted);
  font-size: 11.5px;
}
.switch-row input {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  accent-color: var(--sage);
  cursor: pointer;
}
.usage-h {
  font-family: var(--font-display);
  font-size: 15px;
  margin: 0 0 12px;
}
.usage-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 16px;
}
.usage-card {
  background: var(--sage-soft);
  border-radius: 14px;
  padding: 14px 10px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.usage-num {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--text);
}
.usage-lbl {
  font-size: 11px;
  color: var(--muted);
}
.usage-chart {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 80px;
  padding: 8px 0 0;
  border-top: 1px solid var(--border);
}
.chart-bar {
  flex: 1;
  background: linear-gradient(var(--sage), #9cc0a6);
  border-radius: 5px 5px 0 0;
  min-height: 4px;
}
.usage-empty {
  color: var(--muted);
  font-size: 13px;
}
.modal-foot {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-top: 22px;
}
.pill-primary {
  background: var(--charcoal);
  color: var(--cream-on-dark);
  border: none;
  border-radius: 11px;
  padding: 10px 18px;
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
}
.pill-primary:hover {
  background: var(--charcoal-hover);
}
.pill-primary:disabled {
  opacity: 0.5;
}
.pill-ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 10px 18px;
  font: inherit;
  font-weight: 500;
  font-size: 14px;
  cursor: pointer;
}
.pill-ghost:hover {
  border-color: #c0553f;
  color: #c0553f;
}

/* ---------- Language switcher ---------- */
.lang-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  font-size: 14px;
}
.lang-switch {
  display: inline-flex;
  gap: 4px;
  background: rgba(40, 38, 30, 0.05);
  border-radius: 999px;
  padding: 3px;
}
.auth-card .lang-switch {
  display: flex;
  width: max-content;
  margin: 16px auto 0;
}
.lang-switch button {
  border: none;
  background: transparent;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  padding: 5px 13px;
  border-radius: 999px;
  color: var(--muted);
  transition: all 0.12s ease;
}
.lang-switch button.active {
  background: var(--card);
  color: var(--text);
  box-shadow: 0 1px 2px rgba(40, 38, 30, 0.08);
}
.tone-select {
  font: inherit;
  font-size: 13px;
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 6px 10px;
  background: var(--card);
  color: var(--text);
  cursor: pointer;
}

/* ---------- Background themes ---------- */
/* "nature" is the default body background defined above. */
html[data-bg="cream"] body {
  background: radial-gradient(60% 45% at 50% 32%, rgba(255, 254, 247, 0.9), transparent 72%),
    linear-gradient(180deg, #f8f4ea 0%, #f1e9d8 100%), var(--bg);
  background-attachment: fixed;
}
html[data-bg="dawn"] body {
  background: radial-gradient(1100px 480px at 50% -8%, rgba(255, 199, 205, 0.5), transparent 62%),
    radial-gradient(820px 460px at 96% 2%, rgba(150, 214, 205, 0.42), transparent 58%),
    radial-gradient(760px 460px at 4% 6%, rgba(190, 210, 255, 0.4), transparent 56%), #f7f3ea;
  background-attachment: fixed;
}
html[data-bg="sky"] body {
  background: radial-gradient(60% 45% at 50% 34%, rgba(255, 255, 255, 0.82), transparent 72%),
    radial-gradient(120% 80% at 50% 120%, rgba(150, 190, 235, 0.5), transparent 60%),
    linear-gradient(180deg, #eaf3ff 0%, #dceafc 100%), var(--bg);
  background-attachment: fixed;
}

/* Picture backgrounds: a soft cream wash fades the photo (Telegram-style). */
html[data-bg="bg1"] body,
html[data-bg="bg2"] body,
html[data-bg="bg3"] body {
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  background-attachment: fixed;
}
html[data-bg="bg1"] body {
  background-image: radial-gradient(58% 44% at 50% 38%, rgba(255, 255, 250, 0.34), transparent 72%),
    linear-gradient(rgba(247, 244, 234, 0.42), rgba(247, 244, 234, 0.42)), url("backgrounds/bg1.jpg");
}
html[data-bg="bg2"] body {
  background-image: radial-gradient(58% 44% at 50% 38%, rgba(255, 255, 250, 0.34), transparent 72%),
    linear-gradient(rgba(247, 244, 234, 0.42), rgba(247, 244, 234, 0.42)), url("backgrounds/bg2.jpg");
}
html[data-bg="bg3"] body {
  background-image: radial-gradient(58% 44% at 50% 38%, rgba(255, 255, 250, 0.34), transparent 72%),
    linear-gradient(rgba(247, 244, 234, 0.42), rgba(247, 244, 234, 0.42)), url("backgrounds/bg3.jpg");
}

/* ---------- Background picker (profile modal) ---------- */
.bg-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: 10px;
  margin-bottom: 20px;
}
.bg-swatch {
  aspect-ratio: 1 / 1;
  border-radius: 12px;
  border: 2px solid transparent;
  outline: 1px solid var(--border);
  outline-offset: -1px;
  cursor: pointer;
  padding: 0;
  background-size: cover;
  background-position: center;
  position: relative;
  transition: transform 0.12s ease, border-color 0.12s ease;
}
.bg-swatch:hover {
  transform: translateY(-2px);
}
.bg-swatch.active {
  border-color: var(--sage);
  outline-color: var(--sage);
}
.bg-swatch.active::after {
  content: "✓";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.bg-swatch[data-bg="nature"] {
  background: linear-gradient(160deg, #eef4e6 0%, #9cc0a6 100%);
}
.bg-swatch[data-bg="cream"] {
  background: linear-gradient(160deg, #f8f4ea 0%, #e6d9bd 100%);
}
.bg-swatch[data-bg="dawn"] {
  background: linear-gradient(160deg, #ffd9df 0%, #cdeae0 55%, #cdd9ff 100%);
}
.bg-swatch[data-bg="sky"] {
  background: linear-gradient(160deg, #dbeafe 0%, #9cc2f0 100%);
}
.bg-swatch[data-bg="bg1"] {
  background-image: linear-gradient(rgba(247, 244, 234, 0.32), rgba(247, 244, 234, 0.32)),
    url("backgrounds/bg1-thumb.jpg");
}
.bg-swatch[data-bg="bg2"] {
  background-image: linear-gradient(rgba(247, 244, 234, 0.32), rgba(247, 244, 234, 0.32)),
    url("backgrounds/bg2-thumb.jpg");
}
.bg-swatch[data-bg="bg3"] {
  background-image: linear-gradient(rgba(247, 244, 234, 0.32), rgba(247, 244, 234, 0.32)),
    url("backgrounds/bg3-thumb.jpg");
}

/* ---------- Messenger ---------- */
.layout[data-mode="ai"] .mode-rooms-only,
.layout[data-mode="ai"] .mode-calls-only,
.layout[data-mode="rooms"] .mode-ai-only,
.layout[data-mode="rooms"] .mode-calls-only,
.layout[data-mode="calls"] .mode-ai-only,
.layout[data-mode="calls"] .mode-rooms-only {
  display: none !important;
}

.mode-switch {
  display: flex;
  gap: 4px;
  background: rgba(40, 38, 30, 0.05);
  border-radius: 10px;
  padding: 3px;
}
.mode-switch button {
  flex: 1;
  border: none;
  background: transparent;
  border-radius: 8px;
  padding: 7px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  position: relative;
}
.mode-switch button.active {
  background: var(--card);
  color: var(--text);
  box-shadow: 0 1px 2px rgba(40, 38, 30, 0.06);
}
.mode-switch button.has-badge::after {
  content: "";
  position: absolute;
  top: 5px;
  inset-inline-end: 8px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #c0553f;
}

.rooms-actions {
  display: flex;
  gap: 8px;
}
.rooms-actions .new-chat-btn {
  flex: 1;
}

.rooms-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.invites-list {
  padding: 4px 8px 0;
}
.invites-h {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 6px;
}
.invite-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: 10px;
  margin-bottom: 6px;
  background: rgba(255, 255, 255, 0.45);
}
.invite-label {
  flex: 1;
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Room top bar */
.room-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex: 1;
  min-width: 0;
}
.room-head-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.shared-note {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--sage-soft);
  color: var(--sage-strong);
  border-radius: 999px;
  padding: 4px 11px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  cursor: default;
}
.shared-note.private {
  background: rgba(40, 38, 30, 0.06);
  color: var(--muted);
}
.room-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}
.ai-mode {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
}
.ai-mode select {
  font: inherit;
  font-size: 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 6px;
  background: var(--card);
  color: var(--text);
  cursor: pointer;
}
#room-sub {
  font-family: var(--font-sans);
  max-width: 46vw;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Room messages */
.rmsg {
  display: flex;
  gap: 10px;
  max-width: 100%;
  align-items: flex-start;
  animation: fade-in 0.2s ease;
}
.rmsg.own {
  flex-direction: row-reverse;
}
.ravatar {
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 600;
  background: var(--sage-soft);
  color: var(--sage-strong);
}
.rmsg.bot .ravatar {
  background: var(--sage);
  color: var(--cream-on-dark);
}
.rmsg.own .ravatar {
  background: var(--charcoal);
  color: var(--cream-on-dark);
}
.rbody {
  min-width: 0;
  max-width: 78%;
  display: flex;
  flex-direction: column;
}
.rmsg.own .rbody {
  align-items: flex-end;
}
.rname {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--sage-strong);
  margin: 0 2px 3px;
}
/* Collapse consecutive same-sender messages */
.rmsg.grouped {
  margin-top: -10px;
}
.rmsg.grouped .ravatar {
  visibility: hidden;
}
.rtime {
  font-size: 10.5px;
  color: var(--muted);
  margin: 2px 4px 0;
}
/* Optimistic (queued/offline) message — dim until the server confirms it. */
.rmsg.pending .rbubble { opacity: .55; }
.rmsg.pending .rtime::after { content: " ⏳"; }

/* Quiet connection-status pill (reconnecting / offline). */
.conn-banner {
  position: fixed;
  bottom: calc(78px + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  padding: 6px 15px;
  border-radius: 999px;
  background: rgba(40, 38, 30, 0.9);
  color: #f4efe0;
  font-size: 12.5px;
  font-weight: 600;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
  pointer-events: none;
  animation: conn-in 0.2s ease;
}
@keyframes conn-in { from { opacity: 0; transform: translate(-50%, 6px); } to { opacity: 1; transform: translateX(-50%); } }
.rbubble {
  padding: 8px 12px;
  border-radius: 14px;
  line-height: 1.55;
  font-size: 14.5px;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  text-align: start;
  background: var(--card);
  border: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(40, 38, 30, 0.04);
}
.rmsg.own .rbubble,
.rmsg.other .rbubble {
  white-space: pre-wrap;
}
.rmsg.own .rbubble {
  background: var(--sage-soft);
  border-color: transparent;
}
.rsys {
  text-align: center;
  color: var(--muted);
  font-size: 12px;
  margin: 6px 0;
}
.rbubble {
  position: relative;
}
.rmsg.own .rtext,
.rmsg.other .rtext {
  display: inline;
}
.redited {
  color: var(--muted);
  font-size: 11px;
}
.rmsg.own .redited {
  color: rgba(40, 38, 30, 0.45);
}
.msg-edit {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  font-size: 12px;
  padding: 0 4px;
  margin-inline-start: 4px;
  opacity: 0;
  vertical-align: middle;
}
.rmsg.own:hover .msg-edit {
  opacity: 0.6;
}
.msg-edit:hover {
  opacity: 1;
  color: var(--sage-strong);
}
.msg-editor {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 220px;
}
.msg-editor textarea {
  width: 100%;
  resize: vertical;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 9px;
  font: inherit;
  font-size: 14px;
  background: var(--card);
  color: var(--text);
  outline: none;
}
.me-actions {
  display: flex;
  gap: 6px;
}
.me-save,
.me-cancel {
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  border-radius: 8px;
  padding: 4px 12px;
  cursor: pointer;
  border: 1px solid var(--border);
}
.me-save {
  background: var(--charcoal);
  color: var(--cream-on-dark);
  border-color: transparent;
}
.me-cancel {
  background: transparent;
  color: var(--text);
}

/* Edit affordance on your own AI-tab prompts */
.utext {
  display: inline;
}
.msg.user .msg-edit {
  display: none;
}
.msg.user[data-mid] .msg-edit,
.msg.user[data-mid] .msg-del {
  display: inline;
}
.msg.user .msg-del {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 12px;
  padding: 0 2px;
  margin-inline-start: 2px;
  opacity: 0;
  vertical-align: middle;
}
.msg.user:hover .msg-edit,
.msg.user:hover .msg-del {
  opacity: 0.6;
}
.msg.user .msg-edit:hover,
.msg.user .msg-del:hover {
  opacity: 1;
}

/* Inline delete confirm bar under a message */
.msg-confirm {
  flex-basis: 100%;
  margin-inline-start: 44px;
  margin-top: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.msg-confirm-q {
  font-size: 12.5px;
  color: var(--muted);
}
.typing-indicator {
  flex: 1;
  font-size: 12px;
  color: var(--sage-strong);
  font-style: italic;
  min-height: 1em;
  align-self: center;
}

.modal-sm {
  max-width: 420px;
}
.modal-sm .field {
  margin-bottom: 12px;
}

/* Profile: bio, privacy block */
#profile-bio {
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 9px 12px;
  font: inherit;
  font-size: 14px;
  background: var(--card);
  color: var(--text);
  resize: vertical;
  outline: none;
}
#profile-bio:focus,
#profile-username:focus {
  border-color: var(--sage);
}
.privacy-block {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 6px 12px;
  margin-bottom: 16px;
}
.privacy-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
  padding: 8px 0 2px;
}
.switch-row.compact {
  padding: 8px 0;
  border: none;
  margin: 0;
  border-radius: 0;
  border-top: 1px solid var(--border);
  font-size: 13.5px;
}

/* View-profile modal */
.vp-body {
  text-align: center;
  padding: 6px 0 4px;
}
.vp-avatar {
  width: 64px;
  height: 64px;
  border-radius: 18px;
  background: var(--sage);
  color: var(--cream-on-dark);
  display: grid;
  place-items: center;
  font-size: 24px;
  font-weight: 600;
  margin: 0 auto 12px;
}
.vp-name {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
}
.vp-username {
  color: var(--sage-strong);
  font-size: 14px;
  margin-top: 2px;
}
.vp-bio {
  margin: 12px auto 0;
  max-width: 320px;
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
}
.vp-meta {
  margin-top: 10px;
  color: var(--muted);
  font-size: 12.5px;
}

/* Clickable sender name -> profile */
.rname.clickable {
  cursor: pointer;
}
.rname.clickable:hover {
  text-decoration: underline;
}

/* Quota line + admin table */
.ai-quota {
  margin: 12px 0 0;
  font-size: 12.5px;
  color: var(--muted);
  text-align: start;
}
.modal-foot {
  flex-wrap: wrap;
}
.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}
.admin-table th {
  text-align: start;
  color: var(--muted);
  font-weight: 600;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
}
.admin-table td {
  padding: 8px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.admin-name {
  font-weight: 600;
}
.admin-email {
  font-size: 11.5px;
  color: var(--muted);
}
.admin-role {
  font: inherit;
  font-size: 13px;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 5px 8px;
  background: var(--card);
  color: var(--text);
  cursor: pointer;
}
.admin-today {
  color: var(--muted);
  white-space: nowrap;
}

/* ---------- Lite-mode offer banner ---------- */
.lite-banner {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 16px;
  background: var(--charcoal);
  color: var(--cream-on-dark);
  font-size: 13.5px;
  box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.18);
}
.lite-banner button {
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  border-radius: 999px;
  padding: 6px 14px;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.3);
}
.lite-banner .lite-load {
  background: var(--cream-on-dark);
  color: var(--charcoal);
  border-color: transparent;
}
.lite-banner .lite-stay {
  background: transparent;
  color: var(--cream-on-dark);
}

/* ---------- Responsive ---------- */
@media (max-width: 760px) {
  .sidebar {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(84vw, 300px);
    z-index: 45;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
  }
  html[dir="rtl"] .sidebar {
    transform: translateX(100%);
  }
  .layout.sidebar-open .sidebar {
    transform: none;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.25);
  }
  .layout.sidebar-open .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(40, 38, 30, 0.4);
  }
  /* While a finger is dragging the drawer, kill the settle transition so it
     tracks 1:1, and show the backdrop at the drag's inline opacity. */
  .layout.dragging .sidebar { transition: none !important; will-change: transform; }
  .layout.dragging .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(40, 38, 30, 0.4);
    transition: none !important;
  }
  #menu-btn {
    display: inline-flex;
  }
  .messages {
    padding: 16px 12px;
    gap: 14px;
  }
  .topbar {
    padding: 11px 12px;
  }
  .topbar-title #convo-title {
    max-width: 64vw;
  }
  .shared-note {
    display: none !important;
  }
  #room-sub {
    max-width: 40vw;
  }
  .composer {
    padding: 8px 12px 14px;
  }
  .composer-inner {
    border-radius: 18px;
    padding: 11px 12px;
  }
  .msg .bubble {
    font-size: 14.5px;
  }
  .modal {
    padding: 18px;
    border-radius: 18px;
  }
  .usage-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ---------- Scrollbar ---------- */
.messages::-webkit-scrollbar,
.conversation-list::-webkit-scrollbar {
  width: 10px;
}
.messages::-webkit-scrollbar-thumb {
  background: rgba(40, 38, 30, 0.14);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: padding-box;
}
.messages::-webkit-scrollbar-thumb:hover {
  background: rgba(40, 38, 30, 0.24);
  background-clip: padding-box;
}

/* ------------------------------ Replies -------------------------------- */
/* Quoted parent shown at the top of a bubble. The inline-start border is the
   RTL-safe equivalent of border-left — it flips with the text direction. */
.reply-quote {
  display: block;
  border-inline-start: 3px solid var(--sage, #5c7360);
  background: rgba(0, 0, 0, 0.04);
  border-radius: 6px;
  padding: 5px 9px;
  margin-bottom: 6px;
  font-size: 12.5px;
  line-height: 1.45;
  opacity: 0.85;
}
.reply-quote.is-linked { cursor: pointer; }
.reply-quote.is-linked:hover { opacity: 1; }
.reply-quote-label {
  display: block;
  font-weight: 700;
  font-size: 11.5px;
  color: var(--sage, #5c7360);
  margin-bottom: 1px;
}
.reply-quote-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Banner above the composer while you're composing a reply. */
.reply-banner {
  display: flex;
  align-items: baseline;
  gap: 7px;
  border-inline-start: 3px solid var(--sage, #5c7360);
  background: rgba(0, 0, 0, 0.04);
  border-radius: 6px;
  padding: 6px 9px;
  margin-bottom: 7px;
  font-size: 12.5px;
}
.reply-banner[hidden] { display: none; }
.reply-banner-label { font-weight: 700; color: var(--sage, #5c7360); white-space: nowrap; }
.reply-banner-text { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: 0.8; }
.reply-cancel {
  border: none; background: none; cursor: pointer;
  font-size: 13px; line-height: 1; padding: 2px 4px; color: inherit; opacity: 0.55;
}
.reply-cancel:hover { opacity: 1; }

/* Reply affordance on room bubbles, mirroring .msg-edit. */

/* Brief highlight when you jump to a quoted message. */
.flash { animation: reply-flash 1.2s ease-out; }
@keyframes reply-flash {
  0%   { background: rgba(92, 115, 96, 0.28); }
  100% { background: transparent; }
}

/* ------------------------------- Clock --------------------------------- */
.clock {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
  padding-inline-end: 12px;
  margin-inline-end: 4px;
  border-inline-end: 1px solid var(--border, #e2ddce);
  white-space: nowrap;
  cursor: default;
}
.clock-time { font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
.clock-date { font-size: 10.5px; opacity: 0.65; }
@media (max-width: 640px) {
  .clock-date { display: none; }
  .clock { padding-inline-end: 8px; }
}

/* ------------------------------ Contacts ------------------------------- */
.contacts-block { border-bottom: 1px solid var(--border, #e2ddce); padding-bottom: 6px; margin-bottom: 6px; }
.contacts-head {
  display: flex; align-items: center; gap: 7px; width: 100%;
  background: none; border: none; cursor: pointer;
  padding: 8px 12px; font: inherit; font-size: 12px; font-weight: 700;
  letter-spacing: .02em; text-transform: uppercase; opacity: .7; color: inherit;
}
.contacts-head:hover { opacity: 1; }
.contacts-caret { font-size: 10px; width: 10px; }
.contacts-count { margin-inline-start: auto; font-weight: 600; opacity: .6; text-transform: none; }
/* Dot marking "someone added you" while the section is collapsed. */
.contacts-head.has-badge .contacts-count::after {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--sage, #5c7360); margin-inline-start: 6px; vertical-align: middle;
}
.contacts-body { padding: 0 8px 4px; }
.contact-search {
  width: 100%; border: 1px solid var(--border, #e2ddce); border-radius: 9px;
  padding: 7px 10px; font: inherit; font-size: 13px; outline: none; background: transparent; color: inherit;
}
.contact-search:focus { border-color: var(--sage, #5c7360); }
.contact-results { margin-top: 5px; border: 1px dashed var(--border, #e2ddce); border-radius: 9px; padding: 3px; }
.contact-results[hidden] { display: none; }
.contact-pending:not(:empty) { margin-top: 6px; }
.contact-list { margin-top: 4px; }

.contact-row { display: flex; align-items: center; gap: 8px; padding: 5px 4px; border-radius: 8px; }
.contact-row:hover { background: rgba(0, 0, 0, .04); }
.contact-avatar { flex: 0 0 auto; }
.contact-meta {
  flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start;
  background: none; border: none; cursor: pointer; font: inherit; text-align: start; padding: 0; color: inherit;
}
.contact-name { font-size: 13.5px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-sub { font-size: 11px; opacity: .6; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-add {
  border: 1px solid var(--sage, #5c7360); background: none; color: var(--sage, #5c7360);
  border-radius: 8px; padding: 3px 9px; font: inherit; font-size: 11.5px; cursor: pointer; white-space: nowrap;
}
.contact-add:hover { background: var(--sagebg, #e6ece0); }
.contact-add:disabled { opacity: .5; cursor: default; }
.contact-del {
  border: none; background: none; cursor: pointer; font-size: 12px;
  padding: 2px 5px; color: inherit; opacity: 0; transition: opacity .12s;
}
.contact-row:hover .contact-del { opacity: .5; }
.contact-del:hover { opacity: 1; }

/* --------------------------- Unread badges ----------------------------- */
.unread-badge {
  margin-inline-start: auto;
  min-width: 18px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--sage, #5c7360);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
  text-align: center;
  flex: 0 0 auto;
}
.convo-item.has-unread .convo-title-btn { font-weight: 700; }

/* ------------------------------- Search -------------------------------- */
.search-block { padding: 8px 12px 4px; }
.search-results {
  margin-top: 6px; max-height: 46vh; overflow-y: auto;
  border: 1px dashed var(--border, #e2ddce); border-radius: 10px; padding: 4px;
}
.search-results[hidden] { display: none; }
.search-row {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  width: 100%; text-align: start; background: none; border: none; cursor: pointer;
  font: inherit; color: inherit; padding: 7px 8px; border-radius: 8px;
}
.search-row:hover { background: rgba(0, 0, 0, .05); }
.search-row-title { font-size: 12.5px; font-weight: 700; }
.search-row-snippet {
  font-size: 12px; opacity: .75; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.search-row-sub { font-size: 10.5px; opacity: .5; }

/* -------------------------------- Notes -------------------------------- */
.notes-panel {
  position: absolute; inset-block: 56px 0; inset-inline-end: 0; width: min(380px, 92vw);
  z-index: 20; display: flex; flex-direction: column;
  background: #fff; border-inline-start: 1px solid var(--border, #e2ddce);
  box-shadow: 0 6px 28px rgba(0,0,0,.12);
}
.notes-panel[hidden] { display: none; }
.notes-head {
  display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border-bottom: 1px solid var(--border, #e2ddce);
}
.notes-head b { flex: 1; font-size: 14px; }
.notes-body { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 9px; }
.note-card {
  border: 1px solid var(--border, #e2ddce); border-radius: 11px; padding: 10px 11px;
  background: rgba(0,0,0,.015);
}
.note-card.is-summary { border-inline-start: 3px solid var(--sage, #5c7360); }
.note-head { display: flex; align-items: baseline; gap: 8px; }
.note-head b { flex: 1; font-size: 12.5px; }
.note-del { border: none; background: none; cursor: pointer; opacity: .4; font-size: 12px; color: inherit; }
.note-del:hover { opacity: 1; }
.note-content { font-size: 13px; line-height: 1.6; margin-top: 5px; overflow-wrap: anywhere; }
.note-content p:first-child { margin-top: 0; }
.note-content p:last-child { margin-bottom: 0; }
.note-foot { font-size: 10.5px; opacity: .5; margin-top: 6px; }

/* ----------------------------- Attachments ----------------------------- */
.attach-preview {
  display: flex; align-items: center; gap: 8px;
  border: 1px dashed var(--border, #e2ddce); border-radius: 9px;
  padding: 6px 9px; margin-bottom: 7px; font-size: 12.5px;
}
.attach-preview[hidden] { display: none; }
.attach-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: .8; }
.attachment { margin-bottom: 5px; }
.attachment img {
  max-width: min(320px, 68vw); max-height: 320px;
  border-radius: 10px; display: block; object-fit: cover;
}
.attachment-file {
  display: inline-block; padding: 7px 10px; border-radius: 9px;
  background: rgba(0,0,0,.05); font-size: 12.5px; text-decoration: none; color: inherit;
  overflow-wrap: anywhere;
}
.attachment-file:hover { background: rgba(0,0,0,.09); }

/* ------------------------- Mobile / standalone -------------------------- */
/* Respect the notch when installed to a home screen. */
@supports (padding: env(safe-area-inset-bottom)) {
  .composer { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
  .sidebar { padding-top: env(safe-area-inset-top); }
  .topbar { padding-top: env(safe-area-inset-top); }
}

@media (max-width: 640px) {
  /* Touch targets: 44px is the smallest reliably hittable size. */
  .icon-btn, .send-btn, .ghost-btn, .chip { min-height: 40px; min-width: 40px; }
  .contact-row { padding: 8px 4px; }
  .contact-add, .contact-del { min-height: 34px; }
  .msg-edit { opacity: .45; }  /* no hover on touch */
  .notes-panel { width: 100vw; inset-inline-end: 0; }
  .search-results { max-height: 40vh; }
  /* iOS zooms any input under 16px on focus. */
  textarea, input[type="text"], input[type="search"], input[type="password"], input[type="email"] {
    font-size: 16px;
  }
}

/* ------------------------------ Autolinks ------------------------------ */
.autolink { color: var(--sage, #5c7360); text-decoration: underline; overflow-wrap: anywhere; }
.autolink:hover { opacity: .8; }
/* System lines carry multi-line invite output, so keep the newlines. */
.rsys { white-space: pre-wrap; overflow-wrap: anywhere; }

/* ------------------------------ Dashboard ------------------------------ */
.empty-state.dash {
  display: flex; flex-direction: column; gap: 22px;
  width: 100%; max-width: 720px; margin: 0 auto; padding: 26px 18px 40px;
  text-align: start;
}
.empty-state.dash h2 { text-align: center; margin: 0; }
.dash-section h3 {
  font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  opacity: .55; margin: 0 0 10px;
}

/* Stat tiles: value is the figure, label is plain ink beneath it. */
.dash-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.stat-tile {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  border: 1px solid var(--border, #e2ddce); border-radius: 12px;
  padding: 12px 13px; background: rgba(255,255,255,.55);
}
.stat-value {
  font-size: 26px; font-weight: 600; line-height: 1.1;
  /* Proportional figures on purpose: tabular-nums looks loose at this size. */
}
.stat-label { font-size: 11px; opacity: .6; line-height: 1.35; }
.stat-tile.is-active { border-color: var(--sage, #5c7360); }
.stat-tile.is-active .stat-value { color: var(--sage, #5c7360); }

.dash-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.dash-action {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--border, #e2ddce); background: rgba(255,255,255,.55);
  border-radius: 999px; padding: 8px 15px; font: inherit; font-size: 13px;
  cursor: pointer; color: inherit;
}
.dash-action:hover { border-color: var(--sage, #5c7360); }
.dash-action-icon { font-size: 14px; }

.dash-recent { display: flex; flex-direction: column; gap: 6px; }
.dash-recent-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  border: 1px solid var(--border, #e2ddce); background: rgba(255,255,255,.5);
  border-radius: 11px; padding: 10px 12px; font: inherit; cursor: pointer;
  color: inherit; text-align: start;
}
.dash-recent-item:hover { border-color: var(--sage, #5c7360); }
.dash-recent-name { font-size: 13.5px; font-weight: 600; white-space: nowrap; }
.dash-recent-last {
  flex: 1; min-width: 0; font-size: 12px; opacity: .6;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.dash-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.dash-card {
  border: 1px solid var(--border, #e2ddce); border-radius: 12px;
  padding: 13px 14px; background: rgba(255,255,255,.45);
}
.dash-card-h { font-size: 13.5px; font-weight: 700; margin-bottom: 4px; }
.dash-card p { margin: 0; font-size: 12.5px; line-height: 1.65; opacity: .7; }

@media (max-width: 640px) {
  .dash-stats { grid-template-columns: repeat(2, 1fr); }
  .dash-cards { grid-template-columns: 1fr; }
  .empty-state.dash { padding: 18px 12px 32px; gap: 18px; }
}

/* ============================ UX pass ================================== */

/* --- Focus visibility ---------------------------------------------------
   Several inputs set `outline: none` with nothing in its place, so keyboard
   users had no idea where focus was. :focus-visible only shows for keyboard
   navigation, so mouse users see no change. */
:focus-visible {
  outline: 2px solid var(--sage, #5c7360);
  outline-offset: 2px;
  border-radius: 6px;
}
textarea:focus-visible,
input:focus-visible {
  outline: 2px solid var(--sage, #5c7360);
  outline-offset: 1px;
}

/* --- Loading skeletons --------------------------------------------------
   Every list previously showed nothing at all until its fetch resolved, which
   on a slow connection is indistinguishable from a broken screen. */
.skeleton { display: flex; flex-direction: column; gap: 7px; padding: 6px 2px; }
.skeleton-row {
  height: 34px; border-radius: 9px;
  background: linear-gradient(90deg, rgba(0,0,0,.05) 25%, rgba(0,0,0,.09) 37%, rgba(0,0,0,.05) 63%);
  background-size: 400% 100%;
  animation: skeleton-sweep 1.3s ease-in-out infinite;
}
.skeleton-row:nth-child(2) { width: 86%; }
.skeleton-row:nth-child(3) { width: 72%; }
@keyframes skeleton-sweep {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* --- Jump to latest -----------------------------------------------------
   Auto-scrolling on every incoming message dragged people out of the history
   they were reading. Now it only follows when you are already at the bottom,
   and offers this when you are not. */
.jump-latest {
  position: absolute; inset-inline-end: 18px; bottom: 14px; z-index: 15;
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--border, #e2ddce); background: #fff; color: inherit;
  border-radius: 999px; padding: 7px 13px; font: inherit; font-size: 12.5px;
  cursor: pointer; box-shadow: 0 3px 14px rgba(0,0,0,.13);
}
.jump-latest[hidden] { display: none; }
.jump-latest .n {
  background: var(--sage, #5c7360); color: #fff; border-radius: 999px;
  padding: 0 6px; font-size: 11px; font-weight: 700;
}
.messages { position: relative; }

/* --- Pending actions ----------------------------------------------------
   A button that is working should say so rather than looking inert. */
.is-busy { opacity: .6; pointer-events: none; }

/* --- Respect reduced motion --------------------------------------------
   26 transitions and animations previously ignored the preference. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Keyboard hint on the search box ------------------------------------ */
.search-block { position: relative; }
.kbd-hint {
  position: absolute; inset-inline-end: 20px; top: 16px;
  font-size: 10px; opacity: .38; pointer-events: none;
  border: 1px solid currentColor; border-radius: 4px; padding: 0 4px;
}
@media (max-width: 640px) { .kbd-hint { display: none; } }

/* Profile affordances in the contact list. */
.contact-avatar.is-clickable { border: none; cursor: pointer; padding: 0; font: inherit; }
.contact-avatar.is-clickable:hover { filter: brightness(.94); }
.contact-sub.is-clickable { cursor: pointer; }
.contact-sub.is-clickable:hover { text-decoration: underline; opacity: .9; }

/* Deleted-message tombstone and destructive controls. */
.rtext.is-deleted { opacity: .5; font-style: italic; }
.ghost-btn.danger { color: #c0553f; border-color: rgba(192,85,63,.35); }
.ghost-btn.danger:hover { background: rgba(192,85,63,.08); }

/* --------------------- Presence & read receipts ------------------------- */
/* The dot is a hollow ring when offline and filled when online, so the state
   survives greyscale and colour-blindness — and every dot carries a title. */
.presence-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  border: 1.5px solid var(--muted, #8a857a); background: transparent;
  margin-inline-end: 2px;
}
.presence-dot.is-online { background: var(--sage, #5c7360); border-color: var(--sage, #5c7360); }

.receipt {
  display: block; margin-top: 3px; font-size: 10.5px;
  opacity: .55; white-space: nowrap; text-align: end;
}
.receipt.is-seen { opacity: .8; color: var(--sage, #5c7360); }

/* ===================== Sidebar: professional pass ====================== */
/* The panel sat at 60% opacity over a photo background, so every label in it
   was competing with flowers. Solid enough to read, still tinted. */
.sidebar {
  background: rgba(249, 246, 238, 0.94);
  backdrop-filter: blur(14px) saturate(115%);
}

/* Conversation rows are <button>s, and nothing reset the native button chrome
   — they were rendering as grey system buttons. */
.convo-item,
.room-item {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  width: 100%;
  text-align: start;
}

.room-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 11px;
  margin-bottom: 1px;
}
.room-item:hover { background: rgba(40, 38, 30, 0.055); }
.room-item.active { background: var(--sage-soft, #e6ece0); }

.room-avatar {
  flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--sage-soft, #e6ece0);
  color: var(--sage, #5c7360);
  font-size: 12px; font-weight: 700; letter-spacing: .01em;
}
.room-avatar.is-group { background: rgba(40, 38, 30, 0.07); color: var(--muted, #8a857a); font-size: 15px; }

.room-col { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.room-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.room-name {
  flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.room-time { flex: 0 0 auto; font-size: 10.5px; opacity: .45; }
.room-last {
  flex: 1; min-width: 0; font-size: 12px; opacity: .58;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.room-item.has-unread .room-name { font-weight: 700; }
.room-item.has-unread .room-last { opacity: .78; }
.room-line .unread-badge { margin-inline-start: auto; }

/* Section headings: one consistent treatment instead of three. */
.contacts-head,
.invites-h,
.dash-section h3 {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  opacity: .45;
}
.contacts-head { padding: 10px 12px 6px; }
.contacts-count {
  margin-inline-start: auto; font-size: 11px; letter-spacing: 0;
  text-transform: none; opacity: .8;
}

/* Contact rows: align with the room rows rather than being their own thing. */
.contact-row { padding: 6px 8px; border-radius: 10px; gap: 9px; }
.contact-avatar {
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--sage-soft, #e6ece0); color: var(--sage, #5c7360);
  font-size: 11px; font-weight: 700; flex: 0 0 auto;
}
.contact-name { font-size: 13px; font-weight: 600; }
.contact-sub { font-size: 11px; }

/* The lists need room to breathe between blocks. */
.rooms-panel { display: flex; flex-direction: column; gap: 2px; }
.conversation-list, #room-list { padding: 4px 8px 10px; }

/* ------------------------------- Avatars -------------------------------- */
/* Generated faces are background images, so any element that shows one needs
   the text hidden and the circle preserved. */
.has-avatar { color: transparent !important; background-color: transparent; overflow: hidden; }
.ravatar, .room-avatar, .contact-avatar, .user-avatar, .profile-avatar, .vp-avatar {
  background-repeat: no-repeat; background-position: center; background-size: cover;
}
.profile-avatar-wrap { display: flex; flex-direction: column; align-items: center; gap: 9px; }
.avatar-actions { display: flex; gap: 7px; }
.avatar-hint { margin: 0; font-size: 11px; opacity: .5; text-align: center; max-width: 240px; line-height: 1.5; }

/* --------------------------- Resizable sidebar -------------------------- */
/* SCOPED to desktop on purpose. These rules live near the end of the file, so
   an unscoped `.sidebar` here would override the mobile `position: fixed` in
   the Responsive block above it — which put the overlay back into normal flow,
   squeezed the app into a sliver and left a wide empty band. Never restyle
   .sidebar unconditionally below that media query. */
@media (min-width: 761px) {
  .sidebar {
    position: relative;
    flex: 0 0 var(--sidebar-w, 272px);
    width: var(--sidebar-w, 272px);
    /* No width transition, or every drag frame would lag behind the pointer. */
  }
}

/* A wide invisible grab strip with a thin visible line, so the target is
   comfortable to hit without drawing a heavy border. */
.sidebar-resizer {
  position: absolute;
  inset-block: 0;
  inset-inline-end: -3px;
  width: 7px;
  cursor: col-resize;
  z-index: 30;
  touch-action: none;              /* let the pointer handler own the gesture */
  background: transparent;
}
.sidebar-resizer::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-end: 3px;
  width: 1px;
  background: var(--sage, #5c7360);
  opacity: 0;
  transition: opacity .14s ease;
}
.sidebar-resizer:hover::after,
.sidebar-resizer:focus-visible::after,
.layout.is-resizing .sidebar-resizer::after { opacity: .55; }
.sidebar-resizer:focus-visible { outline: none; }

/* While dragging, stop the pointer selecting text or landing on an iframe. */
.layout.is-resizing { user-select: none; cursor: col-resize; }
.layout.is-resizing * { pointer-events: none; }
.layout.is-resizing .sidebar-resizer { pointer-events: auto; }

@media (max-width: 760px) {
  /* The overlay's geometry is owned entirely by the Responsive block above;
     only the handle needs hiding here. */
  .sidebar-resizer { display: none; }
}

/* ------------------------------ Reactions ------------------------------- */
.reactions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; position: relative; }
.reaction {
  display: inline-flex; align-items: center; gap: 3px;
  border: 1px solid var(--border, #e2ddce); background: rgba(255,255,255,.7);
  border-radius: 999px; padding: 2px 8px; font: inherit; font-size: 12px;
  line-height: 1.6; cursor: pointer; color: inherit;
}
.reaction:hover { border-color: var(--sage, #5c7360); }
/* Your own reaction is tinted AND outlined, so it doesn't rely on colour alone. */
.reaction.is-mine { background: var(--sage-soft, #e6ece0); border-color: var(--sage, #5c7360); font-weight: 600; }
.reaction-add { opacity: 0; transition: opacity .12s; }
.rmsg:hover .reaction-add, .reactions:hover .reaction-add { opacity: .6; }
.reaction-add:hover { opacity: 1; }
@media (hover: none) { .reaction-add { opacity: .5; } }

.emoji-pop {
  position: absolute; bottom: calc(100% + 6px); inset-inline-start: 0; z-index: 25;
  display: flex; gap: 2px; padding: 5px;
  background: #fff; border: 1px solid var(--border, #e2ddce);
  border-radius: 12px; box-shadow: 0 6px 22px rgba(0,0,0,.14);
}
.emoji-pop button {
  border: none; background: none; cursor: pointer; font-size: 17px;
  line-height: 1; padding: 4px 5px; border-radius: 8px;
}
.emoji-pop button:hover { background: rgba(0,0,0,.06); }

/* ------------------------------- Rename --------------------------------- */
#room-title.is-renamable { cursor: text; border-radius: 6px; padding-inline: 3px; }
#room-title.is-renamable:hover { background: rgba(0,0,0,.05); }
.room-rename {
  font: inherit; font-size: inherit; font-weight: inherit; color: inherit;
  background: #fff; border: 1px solid var(--sage, #5c7360);
  border-radius: 7px; padding: 2px 7px; min-width: 160px; outline: none;
}

/* ---------------------------- Danger zone ------------------------------- */
.danger-zone {
  margin-top: 12px; padding: 12px; border-radius: 12px;
  border: 1px solid rgba(192, 85, 63, .35); background: rgba(192, 85, 63, .05);
  display: flex; flex-direction: column; gap: 9px;
}
.danger-msg { margin: 0; font-size: 12.5px; line-height: 1.6; opacity: .85; }
.danger-zone input {
  border: 1px solid var(--border, #e2ddce); border-radius: 9px;
  padding: 9px 11px; font: inherit; font-size: 16px; outline: none;
}
.danger-actions { display: flex; gap: 7px; }
.pill-primary.danger { background: #c0553f; color: #fff; }
.pill-primary.danger:hover { background: #a94733; }
.pill-ghost.danger { color: #c0553f; border-color: rgba(192,85,63,.35); }

/* ------------------------------- Members -------------------------------- */
.member-row { display: flex; align-items: center; gap: 9px; padding: 7px 4px; border-radius: 10px; }
.member-row:hover { background: rgba(0, 0, 0, .04); }
.member-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.member-meta.is-clickable { cursor: pointer; }
.member-meta.is-clickable:hover .member-name { text-decoration: underline; }
.member-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.member-sub { font-size: 11px; opacity: .55; }
.member-row .contact-del { opacity: .4; }
.member-row:hover .contact-del { opacity: .7; }
.member-confirm { margin-bottom: 8px; }
/* The subtitle is the way into the members list, so it should look reachable. */
#room-sub { cursor: pointer; }
#room-sub:hover { text-decoration: underline; }

/* --------------------------- Invite link list --------------------------- */
.invite-links { margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--border, #e2ddce); }
.invite-link-row { display: flex; align-items: center; gap: 7px; padding: 5px 2px; }
.invite-link-meta { flex: 1; min-width: 0; font-size: 11.5px; opacity: .6; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --------------------------- Admin usage -------------------------------- */
.admin-usage { margin-bottom: 18px; }
.admin-usage h3, .admin-sub {
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  opacity: .45; margin: 0 0 10px;
}
.admin-sub { margin-top: 20px; }
.admin-usage .dash-stats { margin-bottom: 14px; }
.stat-hint { font-size: 10px; opacity: .45; margin-top: 2px; }

.au-block { margin-bottom: 14px; }
.au-head {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 11.5px; opacity: .6; margin-bottom: 6px;
}
.au-legend { font-variant-numeric: tabular-nums; }

.au-top { display: flex; flex-direction: column; gap: 6px; }
.au-row { display: flex; align-items: center; gap: 9px; }
.au-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.au-name { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* One series, so magnitude is length in a single hue — rank is never a colour. */
.au-bar { display: block; height: 6px; border-radius: 999px; background: rgba(0,0,0,.07); overflow: hidden; }
.au-fill { display: block; height: 100%; background: var(--sage, #5c7360); border-radius: 999px; }
/* Numbers align in a column, so tabular figures are correct here. */
.au-num { flex: 0 0 auto; font-size: 11.5px; opacity: .65; font-variant-numeric: tabular-nums; }

@media (max-width: 640px) { .admin-usage .dash-stats { grid-template-columns: repeat(2, 1fr); } }

/* ----------------------------- Suspension ------------------------------- */
.admin-suspended { font-size: 11px; color: #c0553f; margin-top: 2px; line-height: 1.4; }
.admin-actions { white-space: nowrap; }

/* ------------------------- Retry / saved answers ------------------------ */
.retry-row { margin-top: 8px; }
#saved-panel .note-content { max-height: 340px; overflow-y: auto; }

/* -------------------------------- Install -------------------------------- */
.install-btn {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  width: 100%; margin-bottom: 8px; padding: 9px 12px;
  border: 1px solid var(--sage, #5c7360); background: var(--sage-soft, #e6ece0);
  color: var(--sage, #5c7360); border-radius: 10px;
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.install-btn[hidden] { display: none; }
.install-btn:hover { filter: brightness(.97); }
.install-hint {
  font-size: 11px; opacity: .6; line-height: 1.5;
  padding: 8px 10px; margin-bottom: 8px;
  border: 1px dashed var(--border, #e2ddce); border-radius: 10px; text-align: center;
}
.install-hint[hidden] { display: none; }

/* ---------------------------- Profile view ------------------------------ */
.vp-avatar-wrap { position: relative; width: 88px; height: 88px; margin: 0 auto 12px; }
.vp-avatar {
  width: 88px; height: 88px; border-radius: 50%;
  display: grid; place-items: center; font-size: 30px;
  background: var(--sage-soft, #e6ece0); color: var(--sage, #5c7360);
  box-shadow: 0 2px 14px rgba(0,0,0,.08);
}
/* Presence as a ring on the avatar: a filled dot when online, hollow when not,
   so it survives greyscale — and it always carries a title. */
.vp-presence {
  position: absolute; inset-block-end: 4px; inset-inline-end: 4px;
  width: 15px; height: 15px; border-radius: 50%;
  border: 2.5px solid #fff; background: var(--muted, #8a857a);
}
.vp-presence.is-online { background: var(--sage, #5c7360); }
.vp-presence[hidden] { display: none; }

.vp-badges { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; margin: 8px 0 2px; }
.vp-badge {
  font-size: 11px; padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--border, #e2ddce); opacity: .85;
}
.vp-badge.is-contact { border-color: var(--sage, #5c7360); color: var(--sage, #5c7360); }
.vp-badge.is-blocked { border-color: rgba(192,85,63,.4); color: #c0553f; }
.vp-badge.is-bot { border-color: var(--sage, #5c7360); color: var(--sage, #5c7360); }

.vp-bio { font-size: 13px; line-height: 1.7; opacity: .8; margin-top: 8px; text-align: center; }
.vp-bio:empty { display: none; }

.vp-rooms {
  display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border, #e2ddce);
}
.vp-rooms[hidden] { display: none; }
.vp-rooms-h { flex: 0 0 100%; font-size: 11px; opacity: .5; text-align: center; margin-bottom: 2px; }
.vp-room {
  border: 1px solid var(--border, #e2ddce); background: none; color: inherit;
  border-radius: 999px; padding: 4px 11px; font: inherit; font-size: 12px; cursor: pointer;
}
.vp-room:hover { border-color: var(--sage, #5c7360); }

/* Four actions need to wrap gracefully; Block recedes rather than competing. */
.vp-foot { display: flex; flex-wrap: wrap; gap: 7px; justify-content: center; }
.pill-ghost.subtle { opacity: .65; }
.pill-ghost.subtle:hover { opacity: 1; }

/* ----------------------------- Pagination ------------------------------- */
.load-earlier {
  display: block; margin: 6px auto 12px; padding: 6px 16px;
  border: 1px solid var(--border, #e2ddce); background: rgba(255,255,255,.6);
  border-radius: 999px; font: inherit; font-size: 12.5px; cursor: pointer; color: inherit;
}
.load-earlier:hover { border-color: var(--sage, #5c7360); }
.load-earlier:disabled { opacity: .6; cursor: default; }

/* --------------------------- Admin statistics --------------------------- */
.as-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 4px 18px; margin-top: 4px; }
.as-row {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 12px; padding: 4px 0; border-bottom: 1px dotted var(--border, #e2ddce);
}
.as-row b { font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .as-grid { grid-template-columns: 1fr; } }

/* ====================== Room topbar: overflow control ==================== */
/* The title and the controls were laid out as two flex children with nothing
   stopping either from overflowing, so on a phone they were painted on top of
   one another. Both sides now have an explicit shrink rule. */
.room-topbar { flex-wrap: wrap; }
.room-head-left { flex: 1 1 auto; min-width: 0; overflow: hidden; }
.room-topbar .topbar-title {
  min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start;
}
#room-title, #room-sub {
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Controls keep their size on desktop rather than being squeezed into the
   title; they move to their own row when there isn't space. */
.room-controls { flex: 0 0 auto; }

@media (max-width: 760px) {
  /* Own row, scrolled horizontally rather than wrapped: five controls stacked
     would push the conversation off the screen. */
  .room-topbar { flex-direction: column; align-items: stretch; gap: 6px; }
  .room-controls {
    width: 100%;
    overflow-x: auto;
    flex-wrap: nowrap;
    gap: 7px;
    padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .room-controls::-webkit-scrollbar { display: none; }
  .room-controls > * { flex: 0 0 auto; }
  /* The select's options already name the mode, so the label is redundant
     where space is scarce. */
  .ai-mode > span { display: none; }
  .topbar { padding: 10px 12px; gap: 8px; flex-wrap: wrap; }
  #room-title { font-size: 15px; }
  #room-sub { font-size: 11px; }
}

/* Narrow phones: the clock competes with the title for the only row that
   matters. The time is available everywhere else on the device. */
@media (max-width: 460px) {
  .clock { display: none; }
}

/* ============================ Composer + menu ============================ */
/* The active chip used to be a filled charcoal pill — the loudest thing on a
   calm screen, for a setting that is merely on. It now reads as a quiet state
   badge, and the control itself moved into the + menu. */
.chip.active {
  background: var(--sage-soft, #e6ece0);
  color: var(--sage, #5c7360);
  border-color: var(--sage, #5c7360);
  font-weight: 500;
}
.chip.active .dot { background: var(--sage, #5c7360); box-shadow: none; }

.plus-wrap { position: relative; display: inline-flex; }
.plus-btn {
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--border, #e2ddce); background: transparent;
  color: var(--muted, #8a857a); font-size: 20px; line-height: 1;
  display: grid; place-items: center; cursor: pointer;
  transition: color .12s, border-color .12s;
}
.plus-btn:hover { color: var(--text); border-color: var(--sage, #5c7360); }
.plus-btn[aria-expanded="true"] { color: var(--sage, #5c7360); border-color: var(--sage, #5c7360); }

.plus-menu {
  position: absolute; bottom: calc(100% + 8px); inset-inline-start: 0;
  z-index: 40; min-width: 210px; padding: 6px;
  background: #fff; border: 1px solid var(--border, #e2ddce);
  border-radius: 14px; box-shadow: 0 10px 34px rgba(0, 0, 0, .16);
}
.plus-menu[hidden] { display: none; }
.plus-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border: none; background: none; border-radius: 9px;
  font: inherit; font-size: 13.5px; color: inherit; cursor: pointer; text-align: start;
}
.plus-item:hover:not(.is-disabled) { background: rgba(0, 0, 0, .05); }
.plus-item.is-disabled { opacity: .38; cursor: default; }
.plus-icon { font-size: 15px; width: 20px; text-align: center; flex: 0 0 auto; }
.plus-label { flex: 1; min-width: 0; }
.plus-check { color: var(--sage, #5c7360); font-weight: 700; }

/* Send stays at the far end; the + leads, as in the reference. */
.composer-row { display: flex; align-items: center; gap: 8px; }
.composer-row .send-btn { margin-inline-start: auto; }

/* ========================= Message context menu ========================== */
/* Replaces the per-message toolbar. Those buttons had to be permanently
   visible on touch, which put four icons inside every bubble and pushed the
   text around; and the empty reaction bar added a row under every message. */
.msgmenu {
  position: fixed; z-index: 60; min-width: 200px; padding: 6px;
  background: #fff; border: 1px solid var(--border, #e2ddce);
  border-radius: 14px; box-shadow: 0 12px 40px rgba(0, 0, 0, .2);
}
.msgmenu-emoji {
  display: flex; gap: 2px; padding: 3px 2px 7px;
  border-bottom: 1px solid var(--border, #e2ddce); margin-bottom: 5px;
}
.msgmenu-emoji button {
  flex: 1; border: none; background: none; cursor: pointer;
  font-size: 19px; line-height: 1; padding: 5px 2px; border-radius: 8px;
}
.msgmenu-emoji button:hover { background: rgba(0, 0, 0, .06); }
.msgmenu-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border: none; background: none; border-radius: 9px;
  font: inherit; font-size: 13.5px; color: inherit; cursor: pointer; text-align: start;
}
.msgmenu-item:hover { background: rgba(0, 0, 0, .05); }
.msgmenu-item.is-danger { color: #c0553f; }
.msgmenu-icon { width: 18px; text-align: center; flex: 0 0 auto; }

/* A held message dims slightly, so the gesture is acknowledged before the
   menu appears. */
.rmsg.is-pressed .rbubble { filter: brightness(.96); }
.rmsg { -webkit-touch-callout: none; }        /* no iOS text-selection popup */
.rbubble { -webkit-user-select: none; user-select: none; }
/* Links and inputs inside a bubble stay selectable and tappable. */
.rbubble a, .rbubble input, .rbubble textarea { user-select: text; }

/* Tighter rhythm now that nothing extra sits under each message. */
.rmsg { margin-bottom: 2px; }
.reactions { margin-top: 3px; }

/* --------------------------- Brand mark --------------------------------- */
/* Anywhere the «ه» can appear, it must be set in the Persian face even when
   the interface language is English. Estedad carries Latin too, so avatars
   showing initials are unaffected. */
.logo,
.ravatar,
.vp-avatar,
.room-avatar,
.contact-avatar {
  font-family: "Estedad", "Vazirmatn", var(--font-sans);
}

/* A flex child only scrolls internally if it may shrink below its content;
   without this the list can grow past its box and the page scrolls instead,
   which makes every "am I at the bottom" measurement meaningless. */
.messages { min-height: 0; }

/* --------------------------- Image analysis ----------------------------- */
#image-preview img {
  width: 34px; height: 34px; border-radius: 7px; object-fit: cover; flex: 0 0 auto;
}
.msg-image { display: block; margin-bottom: 7px; }
.msg-image img {
  max-width: min(300px, 62vw); max-height: 300px;
  border-radius: 10px; display: block; object-fit: cover;
}

/* ==================== Shared content on a profile ======================= */
/* Photos, videos, files, links, notes and groups a person has shared into
   rooms you are also in.

   NOTE: this file keeps its responsive rules in the MIDDLE (from ~line 1922),
   so anything down here wins at every width. Every size-dependent rule below
   is therefore inside its own media query rather than relying on position. */

.vp-shared {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border, #e2ddce);
}
.vp-shared[hidden] { display: none; }

/* The tab strip scrolls rather than wraps: seven tabs stacked into three rows
   pushes the content itself off the screen on a phone. */
.vp-tabs {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 8px;
}
.vp-tabs::-webkit-scrollbar { display: none; }
.vp-tab {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--border, #e2ddce); background: none; color: inherit;
  border-radius: 999px; padding: 5px 11px; font: inherit; font-size: 12px;
  cursor: pointer; opacity: .75;
}
.vp-tab:hover { border-color: var(--sage, #5c7360); opacity: 1; }
.vp-tab.is-active {
  opacity: 1;
  border-color: var(--sage, #5c7360);
  background: var(--sage-soft, #e6ece0);
  color: var(--sage, #5c7360);
}
.vp-tab-icon { font-size: 13px; line-height: 1; }
.vp-tab-n { font-size: 11px; opacity: .65; font-variant-numeric: tabular-nums; }

/* A bounded, scrollable panel: a profile with 200 photos must not turn the
   modal into an endless page with the action buttons stranded below it. */
.vp-tabpanel { max-height: 260px; overflow-y: auto; }
.vp-empty { font-size: 12.5px; opacity: .55; text-align: center; padding: 18px 0; margin: 0; }

.vp-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.vp-cell {
  position: relative; aspect-ratio: 1; border-radius: 8px; overflow: hidden;
  background: var(--sage-soft, #e6ece0); display: block;
}
.vp-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vp-cell.is-video {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; padding: 6px; text-decoration: none; color: inherit;
}
.vp-cell-icon { font-size: 17px; }
.vp-cell-name {
  font-size: 9.5px; opacity: .7; text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}

.vp-list { display: flex; flex-direction: column; gap: 2px; }
.vp-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 8px; border-radius: 9px; border: 0; background: none;
  color: inherit; font: inherit; text-align: start; cursor: pointer;
  text-decoration: none;
}
.vp-item:hover { background: var(--sage-soft, #e6ece0); }
.vp-item-icon { flex: 0 0 auto; font-size: 15px; opacity: .8; }
/* min-width:0 is what actually lets the ellipsis happen inside a flex child. */
.vp-item-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.vp-item-title {
  font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vp-item-sub {
  font-size: 11px; opacity: .55; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* A URL is not Persian; forcing LTR keeps it from being reordered in an RTL
     page, which turns a readable link into nonsense. */
  direction: ltr; text-align: start;
}
.vp-item-room {
  flex: 0 0 auto; font-size: 10.5px; opacity: .45; max-width: 33%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* A name is only obviously clickable if it says so. */
.rname.clickable, .roomsub-name.clickable, .note-foot .clickable, .reply-quote-label.clickable {
  cursor: pointer;
}
.rname.clickable:hover, .roomsub-name.clickable:hover,
.note-foot .clickable:hover, .reply-quote-label.clickable:hover {
  text-decoration: underline;
}
.ravatar.clickable, .room-avatar.clickable { cursor: pointer; }
.clickable:focus-visible { outline: 2px solid var(--sage, #5c7360); outline-offset: 2px; border-radius: 4px; }

@media (max-width: 640px) {
  .vp-grid { grid-template-columns: repeat(3, 1fr); }
  .vp-tabpanel { max-height: 210px; }
}

/* The guide modal reuses the feature cards that used to sit permanently on the
   empty Rooms screen. Bounded and scrollable so six cards cannot push the
   close button off a phone. */
.guide-body { max-height: 62vh; overflow-y: auto; padding: 2px; }
@media (max-width: 640px) { .guide-body { max-height: 68vh; } }

/* ======================= Touch & mobile polish ==========================
   Everything below is scoped: this file keeps its responsive rules in the
   MIDDLE (from ~1922), so an unscoped rule down here would win at every
   width. Nothing here is allowed to change the desktop layout.

   The changes are the ones that decide whether a web app feels native on a
   phone or feels like a website: no zoom on focus, no dead taps, sheets
   instead of centre-screen dialogs, and a composer the keyboard cannot
   cover. */

/* ---- 1. The blue flash ------------------------------------------------ */
/* iOS/Android paint a translucent rectangle over any tapped element. It is
   the single most "this is a web page" tell. Removed globally and replaced
   with real press states below, so feedback is designed rather than default. */
* { -webkit-tap-highlight-color: transparent; }

/* ---- 2. Scroll containment ------------------------------------------- */
/* Without this, hitting the end of the message list scrolls the page behind
   it and the whole app rubber-bands. */
.messages,
.modal,
.conversation-list,
.vp-tabpanel,
.guide-body,
.notes-body {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* ---- 3. Press feedback where :hover never fires ----------------------- */
@media (hover: none) {
  /* A finger gets no hover, so every :hover-only affordance in this file is
     invisible on a phone. These give the same information on contact. */
  .icon-btn:active,
  .pill-ghost:active,
  .pill-primary:active,
  .vp-tab:active,
  .vp-item:active,
  .action-btn:active,
  .room-row:active,
  .contact-row:active,
  .convo-row:active {
    transform: scale(0.97);
    opacity: 0.85;
  }
  .icon-btn,
  .pill-ghost,
  .pill-primary,
  .vp-tab,
  .vp-item,
  .action-btn {
    transition: transform 0.09s ease, opacity 0.09s ease;
  }

  /* Controls revealed by hover must not be permanently invisible on touch. */
  .contact-row .contact-del { opacity: 0.45; }
}

/* ---- 4. Hit slop ------------------------------------------------------ */
/* Small icons stay visually small but become reachable. A pseudo-element
   grows the TOUCH area without touching layout, which padding cannot do
   without moving everything around it. */
@media (pointer: coarse) {
  .icon-btn,
  .contact-del,
  .modal-x {
    position: relative;
  }
  .icon-btn::after,
  .contact-del::after,
  .modal-x::after {
    content: "";
    position: absolute;
    top: 50%;
    inset-inline-start: 50%;
    width: 44px;
    height: 44px;
    /* -50% centres it on the button. Written as two axes rather than `inset`
       so it lands correctly in RTL as well as LTR. */
    transform: translate(-50%, -50%);
    /* Purely a target: it never paints. */
  }
  html[dir="rtl"] .icon-btn::after,
  html[dir="rtl"] .contact-del::after,
  html[dir="rtl"] .modal-x::after {
    transform: translate(50%, -50%);
  }
}

/* ---- 5. Phone ---------------------------------------------------------- */
@media (max-width: 640px) {
  /* iOS zooms the entire page when a focused field is under 16px, and never
     zooms back. Every input in the app was 13–15.5px. */
  #input,
  #room-input,
  .field input,
  .contact-search,
  .modal input,
  .modal textarea,
  .modal select {
    font-size: 16px;
  }

  /* Modals become bottom sheets. A centre-screen dialog on a phone is a
     desktop pattern: it lands under the thumb badly, and the keyboard
     shoves it off-centre the moment a field is focused. */
  .modal-overlay {
    place-items: end stretch;
    padding: 0;
  }
  .modal {
    max-width: none;
    max-height: 88dvh;
    border-radius: 20px 20px 0 0;
    border-bottom: 0;
    padding: 8px 18px calc(18px + env(safe-area-inset-bottom));
    animation: sheet-up 0.24s cubic-bezier(0.32, 0.72, 0, 1);
  }
  /* The header IS the right thing to pin. Scrolling down a tall sheet took
     the close button away with it, leaving no way out but scrolling back up.
     One row, always reachable — unlike the five-button footer, which is why
     that one stays in the flow. */
  .modal-head {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--card);
    margin-bottom: 12px;
    padding-bottom: 10px;
  }

  /* The grabber: says "this is a sheet" before anyone touches it. */
  .modal::before {
    content: "";
    display: block;
    width: 38px;
    height: 4px;
    border-radius: 999px;
    background: var(--border, #e2ddce);
    margin: 6px auto 12px;
  }
  .modal-sm { max-width: none; }

  /* Footer actions as an even two-column grid.
     NOT sticky: `justify-content: space-between` with wrapping scatters five
     buttons across three ragged rows, and pinning that to the bottom of the
     sheet buried the form behind it — tried, screenshotted, reverted. */
  .modal-foot {
    justify-content: stretch;
    gap: 8px;
  }
  .modal-foot > button {
    flex: 1 1 calc(50% - 4px);
    min-width: 0;
    padding-top: 11px;
    padding-bottom: 11px;
  }
  /* The primary action earns the full width above the rest. */
  .modal-foot > .pill-primary { flex-basis: 100%; }

  /* Keyboard shortcuts are not a thing on a phone, and this one cost two
     lines directly above the composer. */
  .hint { display: none; }

  /* Room and conversation rows: comfortable rather than dense. */
  .room-row, .convo-row { padding-top: 10px; padding-bottom: 10px; }
  .contact-row { padding-top: 8px; padding-bottom: 8px; }

  /* Bubbles get room to breathe; a phone has none to spare sideways. */
  .msg .bubble { line-height: 1.65; }
}

@keyframes sheet-up {
  from { transform: translateY(14px); opacity: 0.6; }
  to   { transform: translateY(0);    opacity: 1; }
}

/* ---- 6. The keyboard --------------------------------------------------- */
/* --vvh is written by app.js from visualViewport. 100dvh does NOT shrink for
   the on-screen keyboard on iOS Safari, so the composer ends up underneath
   it and you type blind. Falls back to dvh wherever the API is missing. */
@media (max-width: 760px) {
  .layout, .app { height: var(--vvh, 100dvh); }
}

/* ---- 7. Motion --------------------------------------------------------- */
/* Everything above that moves is opt-out, in one place. */
@media (prefers-reduced-motion: reduce) {
  .modal { animation: none; }
  .msg { animation: none; }
  @media (hover: none) {
    .icon-btn:active, .pill-ghost:active, .pill-primary:active,
    .vp-tab:active, .vp-item:active, .action-btn:active,
    .room-row:active, .contact-row:active, .convo-row:active {
      transform: none;
    }
  }
}

/* ============================ Phone tab bar =============================
   Switching between Hooshang and the rooms meant opening the drawer every
   single time — a lot of friction for the two halves of the app.

   It is a flex child of .app, not position:fixed, so it occupies real space
   and nothing else needs padding to avoid it. Hidden entirely above 760px,
   where the sidebar's own switch is already visible. */

.tabbar { display: none; }

@media (max-width: 760px) {
  .tabbar {
    display: flex;
    flex: 0 0 auto;
    gap: 4px;
    padding: 6px 10px calc(6px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border, #e2ddce);
    background: rgba(255, 253, 248, 0.92);
    backdrop-filter: blur(12px);
  }

  .tab {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 7px 4px 5px;
    border: 0;
    border-radius: 12px;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.15s ease, background-color 0.15s ease;
  }
  .tab.active {
    opacity: 1;
    background: var(--sagebg, #e6ece0);
    color: var(--sage, #5c7360);
  }
  .tab:active { transform: none; } /* a nav tab bouncing reads as a mis-tap */

  .tab-icon { font-size: 17px; line-height: 1.1; }
  .tab-label { font-size: 11px; font-weight: 600; }

  /* Count, not a dot: sitting in the AI tab, this is the only thing telling
     you something is waiting on the other side. */
  .tab-badge {
    position: absolute;
    top: 2px;
    inset-inline-end: max(12px, 22%);
    min-width: 17px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--sage, #5c7360);
    color: #fff;
    font-size: 10.5px;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
  }
  .tab-badge[hidden] { display: none; }

  /* With the keyboard up, vertical space is the scarcest thing on screen and
     you are typing, not navigating. app.js sets data-kb on <html> from
     visualViewport. */
  html[data-kb="1"] .tabbar { display: none; }
}

/* ===================== Admin content moderation ========================= */
/* Reading other people's conversations, so it looks deliberately more serious
   than the rest of the panel — a warning band, and the messages verbatim in a
   bounded reader. */
.admin-mod { margin-top: 22px; }
.mod-warn {
  font-size: 12.5px; line-height: 1.6;
  color: #8a5a3c;
  background: rgba(192, 133, 63, 0.1);
  border: 1px solid rgba(192, 133, 63, 0.3);
  border-radius: 10px; padding: 9px 12px; margin: 6px 0 12px;
}
#mod-search { margin-bottom: 8px; }

.mod-list { display: flex; flex-direction: column; gap: 2px; max-height: 230px; overflow-y: auto; }
.mod-row {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px; border: 0; border-radius: 9px; background: none; color: inherit;
  font: inherit; text-align: start; cursor: pointer;
}
.mod-row:hover { background: var(--sagebg, #e6ece0); }
.mod-row-kind { flex: 0 0 auto; font-size: 14px; opacity: .8; }
.mod-row-main { flex: 1 1 auto; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mod-row-meta { flex: 0 0 auto; font-size: 11px; opacity: .5; font-variant-numeric: tabular-nums; }

.mod-reader {
  margin-top: 12px; border: 1px solid var(--border, #e2ddce); border-radius: 12px;
  padding: 10px 12px; max-height: 360px; overflow-y: auto; background: var(--card, #fffdf8);
}
.mod-reader[hidden] { display: none; }
.mod-reader-head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  position: sticky; top: -10px; background: var(--card, #fffdf8);
  padding: 2px 0 8px; margin: -2px 0 8px; border-bottom: 1px solid var(--border, #e2ddce);
}
.mod-msg { margin-bottom: 10px; }
.mod-msg.is-bot { padding-inline-start: 10px; border-inline-start: 2px solid var(--sage, #5c7360); }
.mod-msg-meta { font-size: 10.5px; opacity: .55; margin-bottom: 2px; }
/* Message text is shown verbatim; pre-wrap keeps its own line breaks without
   letting a long token blow out the width. */
.mod-msg-body { font-size: 13px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.mod-msg-body.is-deleted { opacity: .5; font-style: italic; }

.mod-log-wrap { margin-top: 14px; }
.mod-log-wrap summary { font-size: 12.5px; cursor: pointer; opacity: .75; padding: 4px 0; }
.mod-log-wrap summary:hover { opacity: 1; }
.mod-log { margin-top: 6px; display: flex; flex-direction: column; gap: 1px; max-height: 200px; overflow-y: auto; }
.mod-log-row {
  display: flex; align-items: baseline; gap: 8px; font-size: 11.5px;
  padding: 4px 2px; border-bottom: 1px dotted var(--border, #e2ddce);
}
.mod-log-who { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mod-log-what { flex: 0 0 auto; opacity: .7; }
.mod-log-when { flex: 0 0 auto; opacity: .45; font-variant-numeric: tabular-nums; }
.guide-mod-note {
  margin-top: 14px; font-size: 12px; line-height: 1.6; color: var(--muted, #8a857a);
  border-top: 1px solid var(--border, #e2ddce); padding-top: 12px;
}
.guide-mod-note[hidden] { display: none; }

/* ------------------------- Share conversation ------------------------- */
.share-intro { color: var(--muted); font-size: 13px; line-height: 1.6; margin: 4px 0 16px; }
.share-make { display: flex; flex-direction: column; gap: 10px; }
.share-opt {
  display: flex; flex-direction: column; gap: 3px; text-align: start;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 14px;
  background: var(--card); cursor: pointer; transition: border-color .15s, background .15s;
}
.share-opt:hover { border-color: var(--sage); background: var(--sage-soft); }
.share-opt:disabled { opacity: .6; cursor: default; }
.share-opt-t { font-weight: 600; font-size: 14px; color: var(--text); }
.share-opt-h { font-size: 12px; color: var(--muted); line-height: 1.5; }

.share-links { margin-top: 20px; }
.share-links-h { font-size: 12px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 10px; }
.share-empty { font-size: 13px; color: var(--muted); margin: 0; }
.share-link-row {
  border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px;
  margin-bottom: 10px; background: var(--card);
}
.share-link-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.share-badge {
  font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 999px;
}
.share-badge.is-live { background: #fde8e0; color: #b5502a; }
.share-badge.is-snap { background: var(--sage-soft); color: var(--sage-strong); }
.share-url {
  width: 100%; font-size: 12px; padding: 8px 10px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; direction: ltr; text-align: left;
}
.share-link-acts { display: flex; gap: 8px; margin-top: 8px; }
.share-link-acts .pill-ghost { font-size: 13px; padding: 6px 14px; }
.share-revoke { color: #b5502a; }

/* ======================================================================
   Motion & polish — one cohesive system, not scattered effects.
   Everything here is neutralised by the prefers-reduced-motion guard above.
   ====================================================================== */
:root {
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);   /* springy settle for entrances */
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);     /* calm for interactions */
  --dur-fast: 130ms;
  --dur: 220ms;
}

/* --- Signature: a message arriving feels alive ---------------------------
   The one place motion is bold. Bubbles rise and settle with a spring; the
   assistant's own bubble breathes its shadow in as it lands. */
.msg {
  animation: msg-in 0.42s var(--ease-out) both;
}
@keyframes msg-in {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
.msg.user { animation-name: msg-in-user; }
@keyframes msg-in-user {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

/* The streaming cursor: a soft breathing bar rather than a hard blink. */
.bubble .cursor {
  border-radius: 2px;
  animation: cursor-breathe 1.15s var(--ease-soft) infinite;
}
@keyframes cursor-breathe {
  0%, 100% { opacity: 1; transform: scaleY(1); }
  50%      { opacity: 0.25; transform: scaleY(0.82); }
}

/* --- Interactive micro-interactions: quiet, consistent, everywhere ------- */
.icon-btn { transition: background var(--dur-fast) ease, color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out); }
.icon-btn:hover { transform: translateY(-1px); }
.icon-btn:active { transform: scale(0.9); }

.pill-primary, .pill-ghost {
  transition: background var(--dur-fast) ease, color var(--dur-fast) ease,
              border-color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur) var(--ease-out);
}
.pill-primary:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(40, 38, 30, 0.14); }
.pill-ghost:hover { transform: translateY(-1px); }
.pill-primary:active:not(:disabled), .pill-ghost:active { transform: translateY(0) scale(0.98); box-shadow: none; }

.chip { transition: background var(--dur-fast) ease, border-color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out); }
.chip:active { transform: scale(0.96); }

/* The + opening its menu: the mark turns toward an ×, so the affordance is
   visible rather than implied. */
.plus-btn { transition: color var(--dur) var(--ease-soft), border-color var(--dur) var(--ease-soft), transform var(--dur) var(--ease-out); }
.plus-btn[aria-expanded="true"] { transform: rotate(45deg); }

/* Conversation rows glide slightly toward their content on hover, and the
   active one grows a sage marker on its leading edge. */
.convo-item { position: relative; transition: background var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out); }
.convo-item:hover { transform: translateX(2px); }
.convo-item.active::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 50%;
  height: 58%;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--sage);
  transform: translateY(-50%);
  animation: marker-in 0.32s var(--ease-out) both;
}
@keyframes marker-in {
  from { transform: translateY(-50%) scaleY(0); opacity: 0; }
  to   { transform: translateY(-50%) scaleY(1); opacity: 1; }
}

/* While an answer generates, the Stop button wears a soft pulsing ring — a
   quiet "still working" signal. */
.send-btn.stopping { position: relative; }
.send-btn.stopping::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid #c0553f;
  animation: ring-pulse 1.5s var(--ease-soft) infinite;
}
@keyframes ring-pulse {
  0%   { opacity: 0.55; transform: scale(1); }
  70%  { opacity: 0;    transform: scale(1.35); }
  100% { opacity: 0;    transform: scale(1.35); }
}

/* --- Modals arrive, not appear ------------------------------------------- */
.modal-overlay:not([hidden]) { animation: overlay-in var(--dur) ease both; }
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }
.modal-overlay:not([hidden]) .modal { animation: modal-pop 0.34s var(--ease-out) both; }
@keyframes modal-pop {
  from { opacity: 0; transform: translateY(10px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

/* --- Accessibility polish: a clear, on-brand focus ring ------------------ */
button:focus-visible, a:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--sage);
  outline-offset: 2px;
}

/* --- Welcome screen: an orchestrated arrival ----------------------------
   The empty AI screen is the app's front door, so it earns a small sequence:
   a soft sage aura settles, the Hooshang mark drops in and then breathes, the
   heading rises (its shimmer follows), and the suggestion chips cascade. The
   whole thing replays each time you start a new chat, because show/hide
   restarts CSS animations. */
.empty-state { position: relative; }

/* Ambient aura behind the mark — a slow, living glow, kept low and quiet. */
.empty-state::before {
  content: "";
  position: absolute;
  left: 50%;
  top: -30px;
  width: min(460px, 80vw);
  height: 320px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(126, 174, 144, 0.22), transparent 72%);
  filter: blur(14px);
  z-index: -1;
  pointer-events: none;
  animation: aura-breathe 7s var(--ease-soft) infinite;
}
@keyframes aura-breathe {
  0%, 100% { opacity: 0.55; transform: translateX(-50%) scale(1); }
  50%      { opacity: 1;    transform: translateX(-50%) scale(1.09); }
}

/* The Hooshang mark: drops in, then floats and haloes gently. */
.welcome-emblem {
  position: relative;
  width: 74px;
  height: 74px;
  margin: 0 auto 22px;
  border-radius: 22px;
  background: var(--charcoal);
  color: var(--cream-on-dark);
  display: grid;
  place-items: center;
  box-shadow: 0 12px 30px rgba(40, 38, 30, 0.18);
  animation: emblem-in 0.6s var(--ease-out) both,
             emblem-float 5.5s var(--ease-soft) 0.9s infinite;
}
/* The spark twinkles: a slow lean-and-swell, independent of the tile's float. */
.welcome-emblem .logo-mark {
  width: 56%;
  height: 56%;
  transform-origin: 50% 56%;
  animation: spark-twinkle 4.5s var(--ease-soft) 1s infinite;
}
@keyframes spark-twinkle {
  0%, 100% { transform: rotate(0deg) scale(1); }
  50%      { transform: rotate(7deg) scale(1.07); }
}
@keyframes emblem-in {
  from { opacity: 0; transform: translateY(16px) scale(0.8) rotate(-8deg); }
  to   { opacity: 1; transform: none; }
}
@keyframes emblem-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-7px); }
}
.welcome-emblem::before {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 26px;
  border: 2px solid rgba(110, 133, 112, 0.45);
  animation: emblem-halo 2.8s var(--ease-soft) 1.2s infinite;
}
@keyframes emblem-halo {
  0%   { opacity: 0.5; transform: scale(1); }
  70%  { opacity: 0;   transform: scale(1.32); }
  100% { opacity: 0;   transform: scale(1.32); }
}

/* Suggestion chips cascade in after the heading, then feel tactile. */
.empty-state .suggest-chip {
  animation: chip-in 0.5s var(--ease-out) both;
}
.empty-state .suggest-chip:nth-child(1) { animation-delay: 0.40s; }
.empty-state .suggest-chip:nth-child(2) { animation-delay: 0.48s; }
.empty-state .suggest-chip:nth-child(3) { animation-delay: 0.56s; }
.empty-state .suggest-chip:nth-child(4) { animation-delay: 0.64s; }
@keyframes chip-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.suggest-chip:hover { transform: translateY(-1px); }
.suggest-chip:active { transform: scale(0.96); }

/* --- Minimal footer actions (theme toggle, feedback) --------------------- */
.foot-actions { display: flex; gap: 8px; margin-bottom: 10px; }
.foot-icon {
  width: 36px; height: 36px; flex: 0 0 auto;
  display: grid; place-items: center;
  background: transparent; border: 1px solid var(--border); border-radius: 10px;
  font-size: 16px; line-height: 1; cursor: pointer; color: var(--muted);
  transition: border-color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out), background var(--dur-fast) ease;
}
.foot-icon:hover { border-color: var(--sage); transform: translateY(-1px); }
.foot-icon:active { transform: scale(0.92); }
.feedback-text {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg);
  color: var(--text);
  padding: 12px 14px;
  font: inherit;
  font-size: 14px;
  line-height: 1.6;
  resize: vertical;
  min-height: 110px;
}
.feedback-text:focus { outline: 2px solid var(--sage); outline-offset: 1px; border-color: var(--sage); }
.feedback-ok { color: var(--sage-strong); font-weight: 600; font-size: 14px; margin: 10px 0 0; }
.feedback-ok[hidden] { display: none; }

/* ========================================================================
   DARK THEME
   Activated by html[data-theme="dark"] (set pre-paint from localStorage or the
   OS). Everything driven by the palette vars flips for free; the block below
   also re-skins the handful of surfaces that hardcode a light colour, plus the
   body background (which otherwise stays cream under any data-bg preset).
   ======================================================================== */
html[data-theme="dark"] {
  --bg: #1b1916;
  --card: #262320;
  --border: #3a352e;
  --text: #f3eee4;
  --muted: #a99f8f;
  --sage: #8fbf9c;
  --sage-strong: #a9d4b4;
  --sage-soft: #2b3a30;
  --cyan: #86d4df;
  --charcoal: #33302b;        /* elevated surface for dark pills */
  --charcoal-hover: #403b34;
  --cream-on-dark: #f4efe0;
}

/* Abstract presets (nature/cream/dawn/sky) become one calm dark background —
   their light colour washes don't translate to dark. The photo backgrounds,
   below, DO carry over (a "night" version of the same picture). */
html[data-theme="dark"] body {
  background:
    radial-gradient(1000px 460px at 80% -10%, rgba(134, 212, 223, .07), transparent 60%),
    radial-gradient(900px 440px at 3% 2%, rgba(143, 191, 156, .07), transparent 58%),
    linear-gradient(180deg, #1f1c18 0%, #1a1714 100%),
    var(--bg) !important;
  background-attachment: fixed !important;
  background-repeat: no-repeat !important;
}

/* Photo backgrounds in dark mode: keep the picture, but under a heavy dark wash
   so it sits behind the dark UI instead of glowing. More specific than the rule
   above (extra [data-bg] attribute), so it wins. */
html[data-theme="dark"][data-bg="bg1"] body,
html[data-theme="dark"][data-bg="bg2"] body,
html[data-theme="dark"][data-bg="bg3"] body {
  background-repeat: no-repeat !important;
  background-position: center !important;
  background-size: cover !important;
  background-attachment: fixed !important;
}
html[data-theme="dark"][data-bg="bg1"] body {
  background-image: linear-gradient(rgba(15, 13, 11, .68), rgba(15, 13, 11, .74)), url("backgrounds/bg1.jpg") !important;
}
html[data-theme="dark"][data-bg="bg2"] body {
  background-image: linear-gradient(rgba(15, 13, 11, .68), rgba(15, 13, 11, .74)), url("backgrounds/bg2.jpg") !important;
}
html[data-theme="dark"][data-bg="bg3"] body {
  background-image: linear-gradient(rgba(15, 13, 11, .68), rgba(15, 13, 11, .74)), url("backgrounds/bg3.jpg") !important;
}

/* Translucent chrome */
html[data-theme="dark"] .topbar { background: rgba(27, 25, 22, .74); }
html[data-theme="dark"] .sidebar { background: rgba(23, 21, 18, .55); }
html[data-theme="dark"] .composer-inner { background: rgba(38, 35, 32, .78); }
html[data-theme="dark"] .tabbar { background: rgba(23, 21, 18, .94); }
html[data-theme="dark"] .auth-card { background: rgba(38, 35, 32, .92); }

/* Panels & pop-overs that hardcode #fff / near-white */
html[data-theme="dark"] .notes-panel,
html[data-theme="dark"] .emoji-pop,
html[data-theme="dark"] .room-rename,
html[data-theme="dark"] .plus-menu,
html[data-theme="dark"] .msgmenu,
html[data-theme="dark"] .jump-latest,
html[data-theme="dark"] .dash-card { background: var(--card); }

/* Faint white fills → faint light-on-dark fills */
html[data-theme="dark"] .suggest-chip,
html[data-theme="dark"] .invite-row,
html[data-theme="dark"] .stat-tile,
html[data-theme="dark"] .dash-action,
html[data-theme="dark"] .dash-recent-item,
html[data-theme="dark"] .reaction,
html[data-theme="dark"] .load-earlier { background: rgba(255, 255, 255, .045); }

/* Hover tints that used dark ink on light must become light on dark */
html[data-theme="dark"] .icon-btn:hover,
html[data-theme="dark"] .convo-item:hover,
html[data-theme="dark"] .plus-item:hover,
html[data-theme="dark"] .suggest-chip:hover { background: rgba(255, 255, 255, .07); }

/* Inputs: legible fields on dark */
html[data-theme="dark"] input,
html[data-theme="dark"] textarea,
html[data-theme="dark"] select { color: var(--text); }
html[data-theme="dark"] .contact-search,
html[data-theme="dark"] #global-search,
html[data-theme="dark"] .msearch,
html[data-theme="dark"] #input,
html[data-theme="dark"] #room-input,
html[data-theme="dark"] .modal input,
html[data-theme="dark"] .modal textarea { background: rgba(255, 255, 255, .04); border-color: var(--border); }
html[data-theme="dark"] ::placeholder { color: var(--muted); opacity: .7; }

/* Primary actions: on dark the charcoal pill vanishes, so lead with sage. */
html[data-theme="dark"] .pill-primary,
html[data-theme="dark"] .send-btn,
html[data-theme="dark"] .new-chat-btn,
html[data-theme="dark"] .new-room-btn { background: var(--sage); color: #16221a; }
html[data-theme="dark"] .pill-primary:hover:not(:disabled),
html[data-theme="dark"] .send-btn:hover,
html[data-theme="dark"] .new-chat-btn:hover { background: #a3ceb0; }

/* The logo tile stays genuinely dark so the spark pops (decoupled from pills). */
html[data-theme="dark"] .logo,
html[data-theme="dark"] .welcome-emblem { background: #131110; }

/* Keep code blocks on a light card so the (light-theme) syntax colours stay
   readable — a common, deliberate choice in dark UIs. */
html[data-theme="dark"] .bubble pre { background: #f4f1e8; border-color: #e4dccb; }
html[data-theme="dark"] .bubble pre code { color: #24231f; }

/* Skeleton shimmer on dark */
html[data-theme="dark"] .skeleton-row,
html[data-theme="dark"] .skeleton { background: rgba(255, 255, 255, .05); }


/* --------------------- Profile & usage modal polish --------------------- */
.profile-foot {
  display: flex; flex-direction: column; gap: 14px;
  margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border);
}
.profile-foot #save-profile { width: 100%; padding: 12px; font-size: 15px; border-radius: 12px; }
.foot-links { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 6px 10px; }
.fl-group { display: inline-flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.foot-link {
  background: transparent; border: none; color: var(--muted);
  font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
  padding: 6px 10px; border-radius: 8px;
  transition: color var(--dur-fast) ease, background var(--dur-fast) ease;
}
.foot-link:hover { color: var(--sage-strong); background: var(--sage-soft); }
.foot-link.danger { color: #c0553f; }
.foot-link.danger:hover { color: #c0553f; background: rgba(192, 85, 63, .1); }
html[data-theme="dark"] .foot-link.danger { color: var(--danger, #e08769); }

/* A calmer account header: bigger avatar, identity grouped and left-aligned. */
.profile-account { align-items: center; gap: 18px; }
.profile-avatar { flex: 0 0 64px; width: 64px; height: 64px; font-size: 24px; box-shadow: 0 6px 16px rgba(40, 38, 30, .12); }
.profile-email { font-weight: 500; }

/* Usage cards: crisper, with a hairline and a bigger figure. */
.usage-card {
  background: var(--card); border: 1px solid var(--border);
  padding: 15px 10px; transition: transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast);
}
.usage-card:hover { transform: translateY(-2px); border-color: var(--sage); }
.usage-num { font-size: 23px; letter-spacing: -.02em; }
.usage-lbl { font-weight: 500; }
html[data-theme="dark"] .usage-card { background: rgba(255, 255, 255, .035); }

/* ----------------------- Settings tab: one calm list -------------------- */
.set-list {
  border: 1px solid var(--border); border-radius: 14px;
  overflow: hidden; margin-bottom: 20px; background: var(--card);
}
html[data-theme="dark"] .set-list { background: rgba(255, 255, 255, .025); }
/* Rows share one look: label (with optional sub) on one side, control on the
   other, divided by hairlines instead of each sitting in its own box. */
.set-list .set-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 14px 16px; margin: 0; border: none; border-radius: 0;
  border-bottom: 1px solid var(--border); font-size: 14px;
}
.set-list .set-row:last-child { border-bottom: none; }
.set-list .switch-row.set-row > span:first-child { display: flex; flex-direction: column; gap: 3px; }
.set-list .switch-row.set-row small { color: var(--muted); font-size: 12px; line-height: 1.5; }
.set-h { margin-top: 4px; }

/* Checkboxes in the profile modal become tidy toggle switches. */
#profile-modal input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; margin: 0; flex: 0 0 auto;
  width: 42px; height: 24px; border-radius: 999px; background: var(--border);
  position: relative; cursor: pointer; transition: background .2s var(--ease-out);
}
#profile-modal input[type="checkbox"]::after {
  content: ""; position: absolute; top: 3px; inset-inline-start: 3px;
  width: 18px; height: 18px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25); transition: transform .2s var(--ease-out);
}
#profile-modal input[type="checkbox"]:checked { background: var(--sage); }
#profile-modal input[type="checkbox"]:checked::after { transform: translateX(18px); }
html[dir="rtl"] #profile-modal input[type="checkbox"]:checked::after { transform: translateX(-18px); }

/* The language pill needs a visible track on dark. */
html[data-theme="dark"] .lang-switch { background: rgba(255, 255, 255, .06); }

/* Background swatches: a touch smaller and tidier. */
.bg-picker { grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: 9px; }
.bg-swatch { border-radius: 11px; transition: transform var(--dur-fast) var(--ease-out); }
.bg-swatch:hover { transform: translateY(-2px); }

/* ---------------- New robot mark (logo + welcome emblem) ---------------- */
/* The robot SVG carries its own circular background, so drop the old dark tile
   and let it fill the badge in every theme. */
.logo { background: transparent !important; padding: 0 !important; }
.logo .logo-mark { width: 100%; height: 100%; }
.welcome-emblem { background: transparent !important; box-shadow: none !important; }
.welcome-emblem .logo-mark { width: 100%; height: 100%; animation: none; transform: none; }
.welcome-emblem::before { border-radius: 50%; inset: -7px; }  /* circular halo to match the face */
html[data-theme="dark"] .logo,
html[data-theme="dark"] .welcome-emblem { background: transparent !important; }

/* The AI avatar is the robot face SVG (no tinted square behind it). */
.msg.assistant .avatar { background: transparent; overflow: hidden; }
.msg.assistant .avatar svg { width: 100%; height: 100%; display: block; }
#vp-avatar svg, .profile-avatar svg { width: 100%; height: 100%; display: block; }

/* --------------------------- Notification bell -------------------------- */
.notif-wrap { position: relative; flex: 0 0 auto; }
.notif-count {
  position: absolute; top: 0; inset-inline-end: 0;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 9px;
  background: #c0553f; color: #fff; font-size: 10px; font-weight: 700;
  display: grid; place-items: center; line-height: 1; pointer-events: none;
}
.notif-count[hidden] { display: none; }
.notif-panel {
  position: absolute; top: calc(100% + 8px); inset-inline-start: 0;
  width: 330px; max-width: 88vw; max-height: 70vh; overflow-y: auto;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 14px 44px rgba(40, 38, 30, .16); z-index: 40; padding: 8px;
  animation: modal-pop .26s var(--ease-out) both;
}
.notif-panel[hidden] { display: none; }
.notif-head { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); padding: 8px 10px 10px; }
.notif-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px; border-radius: 10px; background: transparent; border: none;
  cursor: pointer; text-align: start; font: inherit; color: var(--text);
  transition: background var(--dur-fast) ease;
}
.notif-item:hover { background: var(--sage-soft); }
.notif-item .ni-av { width: 34px; height: 34px; border-radius: 9px; flex: 0 0 auto; display: grid; place-items: center; background: var(--sage-soft); color: var(--sage-strong); font-weight: 700; font-size: 13px; overflow: hidden; }
.notif-item .ni-av svg { width: 100%; height: 100%; }
.notif-item .ni-body { flex: 1; min-width: 0; }
.notif-item .ni-title { font-weight: 600; font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.notif-item .ni-sub { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.notif-item .ni-badge { flex: 0 0 auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--sage); color: #fff; font-size: 11px; font-weight: 700; display: grid; place-items: center; }
.notif-empty { padding: 22px 10px; text-align: center; color: var(--muted); font-size: 13px; }
@media (max-width: 640px) {
  .notif-panel { position: fixed; inset-inline: 8px; width: auto; max-width: none; top: 56px; }
}

/* ------------- Profile header: tidy vertical layout (mobile-safe) -------- */
/* The old side-by-side avatar + name row cramped badly on phones. Stack it:
   avatar centred on top, compact photo buttons, then the fields full-width. */
.profile-account {
  flex-direction: column;
  align-items: stretch;
  gap: 16px;
  text-align: start;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.profile-avatar-wrap { align-items: center; gap: 11px; text-align: center; width: 100%; }
.profile-avatar { margin: 0 auto; }
.avatar-actions { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.avatar-actions .pill-ghost { font-size: 13px; padding: 7px 15px; white-space: nowrap; border-radius: 10px; }
.avatar-hint { max-width: 300px; margin: 2px auto 0; }
.profile-account > div:last-child { width: 100%; }
.profile-account .field.inline { margin-bottom: 0; }
.profile-email { margin-top: 8px; }
.profile-since { margin-top: 3px; }

/* Bigger profile picture in the header. */
.profile-avatar { flex: 0 0 104px; width: 104px; height: 104px; font-size: 38px; border-radius: 26px; }

/* Profile modal: one fixed canvas. Switching tabs changes the content, not the
   window size — the active tab scrolls inside a set height instead. */
#profile-modal .modal {
  height: min(88vh, 680px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#profile-modal .modal-head,
#profile-modal .modal-tabs,
#profile-modal .profile-foot { flex: 0 0 auto; }
#profile-modal .ptab-panel { min-height: 0; }
#profile-modal .ptab-panel.active { flex: 1 1 auto; overflow-y: auto; padding-inline: 2px; }

/* Force the fixed profile canvas even against the mobile bottom-sheet rules. */
#profile-modal .modal { height: min(88vh, 680px) !important; max-height: 88vh !important; display: flex !important; flex-direction: column; overflow: hidden !important; }
#profile-modal .ptab-panel.active { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* ======================= Rooms dashboard (main canvas) =================== */
.rooms-dash {
  width: 100%; max-width: 760px; margin: 0 auto;
  padding: 26px 22px 48px; display: flex; flex-direction: column;
  animation: fade-in .22s ease;
}
.rd-head { display: flex; align-items: center; justify-content: space-between; gap: 12px 16px; margin-bottom: 20px; flex-wrap: wrap; }
.rd-head h2 { font-family: var(--font-display); font-size: 26px; font-weight: 700; letter-spacing: -.02em; margin: 0; }
.rd-head .dash-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* Shortcuts: compact pills, not big cards. */
.rd-head .dash-action {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 13px; border-radius: 11px; border: 1px solid var(--border);
  background: var(--card); font: inherit; font-size: 13px; font-weight: 600;
  color: var(--text); cursor: pointer; white-space: nowrap;
  transition: transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast);
}
.rd-head .dash-action:hover { transform: translateY(-1px); border-color: var(--sage); }
html[data-theme="dark"] .rd-head .dash-action { background: rgba(255,255,255,.04); }

/* Invites: highlighted cards at the top. */
.rd-invites:empty { display: none; }
.rd-invites { margin-bottom: 16px; display: flex; flex-direction: column; gap: 8px; }
.rd-invites .invites-h { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 0 2px 2px; }
.rd-invites .invite-row {
  display: flex; align-items: center; gap: 10px; padding: 12px 14px;
  border: 1px solid var(--sage); border-radius: 13px; background: var(--sage-soft);
}
.rd-invites .invite-label { flex: 1; font-weight: 600; min-width: 0; }

/* Filter segmented control. */
.rd-filters { display: inline-flex; gap: 3px; background: var(--card); border: 1px solid var(--border); border-radius: 12px; padding: 4px; margin-bottom: 14px; width: fit-content; }
html[data-theme="dark"] .rd-filters { background: rgba(255,255,255,.03); }
.rd-filters button { background: none; border: none; font: inherit; font-weight: 600; font-size: 13px; color: var(--muted); padding: 7px 16px; border-radius: 9px; cursor: pointer; transition: color .15s, background .15s; }
.rd-filters button:hover { color: var(--text); }
.rd-filters button.active { color: var(--sage-strong); background: var(--sage-soft); }

/* The chat list — roomier rows than the old sidebar list. */
.rd-list { display: flex; flex-direction: column; gap: 4px; }
.rd-list .convo-empty { padding: 34px 10px; text-align: center; color: var(--muted); font-size: 14px; }
.rd-list .room-item { width: 100%; padding: 12px 14px; border-radius: 14px; gap: 12px; transition: background var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out); }
.rd-list .room-item:hover { background: var(--sage-soft); transform: translateX(2px); }
.rd-list .room-item.active { background: var(--sage-soft); }
/* Roomier, more legible list rows: bigger faces + names, calmer preview. */
.rd-list .room-avatar { width: 42px; height: 42px; font-size: 15px; }
.rd-list .room-avatar.is-group { font-size: 16px; font-weight: 700; }
.rd-list .room-col { gap: 3px; }
.rd-list .room-name { font-size: 15px; }
.rd-list .room-last { font-size: 13px; opacity: .62; }
.rd-list .room-time { font-size: 11px; }

/* Back chevron in the room header. */
.room-back { font-size: 26px; line-height: 1; padding: 2px 10px; }
html[dir="rtl"] .room-back { transform: scaleX(-1); }

/* Rooms sidebar is contacts-only now — the new-room/DM actions live in the main
   canvas shortcuts, so hide the redundant sidebar copy (kept in the DOM so the
   shortcuts can still trigger them). */
.rooms-actions { display: none !important; }

/* ============================= Room sheets =============================== */
.sheet-new { width: 100%; margin-bottom: 12px; }
.sheet-list { display: flex; flex-direction: column; gap: 6px; }
.sheet-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: start;
  padding: 11px 13px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--card); font: inherit; color: var(--text); cursor: pointer;
  transition: border-color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out);
}
.sheet-item:hover { border-color: var(--sage); transform: translateX(2px); }
.sheet-item-ic { color: var(--sage-strong); font-size: 16px; flex: 0 0 auto; }
.sheet-item-name { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Editor modal — wider than a normal dialog, grid scrolls inside it. */
.sheet-modal { max-width: 720px; width: 96vw; display: flex; flex-direction: column; }
.sheet-title { flex: 1; font: inherit; font-size: 17px; font-weight: 700; font-family: var(--font-display); background: transparent; border: none; color: var(--text); padding: 4px 0; }
.sheet-title:focus { outline: none; }
.sheet-toolbar { display: flex; align-items: center; gap: 8px; margin: 4px 0 12px; flex-wrap: wrap; }
.sheet-toolbar .pill-ghost { padding: 6px 12px; font-size: 13px; }
.sheet-saved { font-size: 12px; color: var(--muted); margin-inline-start: auto; }
.sheet-del { }
.sheet-grid-wrap { overflow: auto; max-height: 58vh; border: 1px solid var(--border); border-radius: 12px; }
.sheet-grid { border-collapse: collapse; width: 100%; }
.sheet-grid th, .sheet-grid td { border: 1px solid var(--border); padding: 0; position: relative; min-width: 96px; }
.sheet-grid th { background: var(--sage-soft); }
.sheet-grid input { width: 100%; border: none; background: transparent; font: inherit; font-size: 14px; padding: 9px 10px; color: var(--text); }
.sheet-grid input:focus { outline: 2px solid var(--sage); outline-offset: -2px; }
.sheet-colname { font-weight: 700; }
.sheet-coldel, .sheet-rowdel {
  position: absolute; border: none; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 15px; line-height: 1; padding: 2px 5px; opacity: 0; transition: opacity .12s;
}
.sheet-coldel { top: 2px; inset-inline-end: 2px; }
.sheet-grid th:hover .sheet-coldel, .sheet-grid tr:hover .sheet-rowdel { opacity: .7; }
.sheet-coldel:hover, .sheet-rowdel:hover { color: #c0553f; opacity: 1; }
.sheet-rowdel-cell { min-width: 30px; width: 30px; border: none; background: transparent; }
.sheet-rowdel { position: static; opacity: .5; }
.sheet-grid tfoot td { background: var(--sage-soft); font-weight: 700; font-size: 13px; color: var(--sage-strong); padding: 8px 10px; text-align: start; }
.sheet-hint { font-size: 12px; color: var(--muted); margin: 10px 2px 0; }
html[data-theme="dark"] .sheet-grid th, html[data-theme="dark"] .sheet-grid tfoot td { background: rgba(143,191,156,.12); }

/* ------------------- Room header: ⋯ options menu ----------------------- */
.room-menu-wrap { position: relative; flex: 0 0 auto; }
.room-menu-btn { font-size: 22px; line-height: 1; padding: 0 10px; }
.room-controls {
  position: absolute; top: calc(100% + 8px); inset-inline-end: 0;
  display: flex !important; flex-direction: column !important; align-items: stretch; gap: 2px;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 14px 44px rgba(40, 38, 30, .16); padding: 8px; width: 230px; max-width: 82vw;
  z-index: 40; animation: modal-pop .24s var(--ease-out) both;
}
.room-controls[hidden] { display: none !important; }
.room-controls .ghost-btn {
  text-align: start; border: none; background: transparent; border-radius: 9px;
  padding: 10px 12px; font-size: 14px; width: 100%; color: var(--text);
}
.room-controls .ghost-btn:hover { background: var(--sage-soft); }
.room-controls .ghost-btn.danger { color: #c0553f; }
.room-controls .ghost-btn.danger:hover { background: rgba(192, 85, 63, .1); }
.room-controls .ai-mode {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 12px; font-size: 13.5px; border-bottom: 1px solid var(--border); margin-bottom: 4px;
}
.room-controls .ai-mode select { font: inherit; font-size: 13px; border: 1px solid var(--border); border-radius: 8px; padding: 5px 7px; background: var(--card); color: var(--text); }

/* ------------------- Room message bubbles: clearer own vs others -------- */
.rmsg.own .rbubble {
  background: linear-gradient(180deg, var(--sage) 0%, var(--sage-strong) 140%);
  color: #fff; border-color: transparent;
  box-shadow: 0 1px 2px rgba(40, 38, 30, .08), 0 6px 16px rgba(86, 109, 91, .18);
}
.rmsg.own .rbubble a { color: #eafff0; text-decoration: underline; }
.rmsg.other .rbubble { box-shadow: 0 1px 2px rgba(40, 38, 30, .05), 0 6px 16px rgba(40, 38, 30, .05); }
html[data-theme="dark"] .rmsg.other .rbubble { box-shadow: none; }

/* ==================== Composer: clean single-row input =================== */
.composer { padding: 10px 16px calc(12px + env(safe-area-inset-bottom)); }
.composer-inner {
  display: flex; flex-direction: column; gap: 5px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 24px; padding: 4px 6px; backdrop-filter: none;
  box-shadow: 0 2px 10px rgba(40, 38, 30, .05);
  transition: border-color .15s ease;
}
.composer-inner:focus-within { border-color: var(--sage); }
html[data-theme="dark"] .composer-inner { background: rgba(255, 255, 255, .05); }
.composer-row { display: flex; align-items: flex-end; gap: 4px; }
#input, #room-input {
  flex: 1 1 auto; min-width: 0; width: auto; max-width: none;
  border: none !important; background: transparent !important; box-shadow: none !important;
  resize: none; margin: 0; padding: 9px 8px;
  font-size: 16px; line-height: 1.45; max-height: 40vh; color: var(--text);
}
#input:focus, #room-input:focus { outline: none !important; }
#input::placeholder, #room-input::placeholder { color: var(--muted); }
.composer-row .plus-wrap, .composer-row .plus-btn, .composer-row .send-btn,
.composer-row .chip { flex: 0 0 auto; align-self: flex-end; }
.composer-row .plus-btn { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; font-size: 20px; }
.composer-row .send-btn { margin-inline-start: 2px; }
.composer-row .send-btn.stopping::after { inset: -3px; }
.web-chip { padding: 0 !important; width: 34px; height: 34px; border-radius: 50% !important; display: grid; place-items: center; }
.web-chip .dot { margin: 0 !important; }
#attach-btn.chip { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; padding: 0; font-size: 17px; }
/* contextual rows stack above the input, not inside it */
.composer-inner .reply-banner, .composer-inner .attach-preview { margin: 4px 8px 0; }
.typing-indicator:not(:empty) { padding: 2px 12px; font-size: 12px; color: var(--muted); }

/* ---- Composer alignment fix: field vertically centred, never cropped ---- */
.composer-row { align-items: flex-end; }
#input, #room-input { min-height: 42px; box-sizing: border-box; padding: 10px 12px; line-height: 1.4; }
.composer-row .plus-btn, .composer-row .send-btn,
.composer-row .web-chip, .composer-row #attach-btn.chip { width: 42px; height: 42px; flex: 0 0 auto; align-self: flex-end; }

/* ---------------- Minimal bottom tab bar (iOS-style) -------------------- */
@media (max-width: 760px) {
  #tabbar.tabbar { gap: 0; padding: 5px 10px calc(5px + env(safe-area-inset-bottom)); }
  #tabbar .tab {
    opacity: 1; background: none !important; color: var(--muted);
    padding: 7px 4px 5px; gap: 3px; border-radius: 12px;
  }
  #tabbar .tab.active { color: var(--sage-strong); background: none !important; }
  /* a small indicator bar rides the top edge of the active tab */
  #tabbar .tab.active::before {
    content: ""; position: absolute; top: 0; inset-inline: 34%;
    height: 3px; border-radius: 0 0 3px 3px; background: var(--sage);
  }
  #tabbar .tab-icon { font-size: 22px; line-height: 1; display: grid; place-items: center; height: 24px; }
  #tabbar .tab-icon svg { width: 23px; height: 23px; display: block; }
  #tabbar .tab.active .tab-icon svg { filter: none; }
  #tabbar .tab:not(.active) .tab-icon svg { opacity: .8; }
  #tabbar .tab-label { font-size: 10.5px; font-weight: 600; letter-spacing: .01em; }
}
html[data-theme="dark"] #tabbar .tab { color: var(--muted); }
html[data-theme="dark"] #tabbar .tab.active { color: var(--sage); }

/* --- Web-search indicator: a calm globe instead of the old bare dot --- */
.web-chip .globe {
  width: 20px;
  height: 20px;
  stroke: var(--sage-strong, #3f5a45);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.web-chip {
  background: color-mix(in srgb, var(--sage, #5c7360) 16%, transparent) !important;
  border: 1px solid color-mix(in srgb, var(--sage, #5c7360) 42%, transparent) !important;
}
.web-chip .dot { display: none; }
html[data-theme="dark"] .web-chip .globe { stroke: var(--sage, #8fae94); }

/* --- Streaming reply: each new block fades up as it appears (line reveal),
       replacing the jittery per-token typewriter. No page scroll involved. --- */
.bubble .content > .stream-in {
  animation: line-fade .34s cubic-bezier(.22, .61, .36, 1) both;
}
@keyframes line-fade {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .bubble .content > .stream-in { animation: none; }
}

/* ---------- Glassy edges: content fades under the header & footer ----------
   The message column tucks a little under the top bar and composer, and a soft
   mask fades its top and bottom edges to transparent. Text dissolves into the
   frosted, blurred bars instead of being sliced by a hard line. */
:root { --edge-fade: 28px; }

.app > .messages {
  /* Pull the scroll viewport under the bars by the fade distance… */
  margin-top: calc(-1 * var(--edge-fade));
  margin-bottom: calc(-1 * var(--edge-fade));
  /* …then pad the content back so nothing is hidden on first paint. */
  padding-top: calc(28px + var(--edge-fade));
  padding-bottom: calc(20px + var(--edge-fade));
  -webkit-mask-image: linear-gradient(to bottom, transparent 0,
    #000 var(--edge-fade), #000 calc(100% - var(--edge-fade)), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0,
    #000 var(--edge-fade), #000 calc(100% - var(--edge-fade)), transparent 100%);
  position: relative;
  z-index: 1;
}

/* The bars ride above the fading content as a pane of frosted glass: a milky
   translucent body, a bright specular line along the top edge, and a soft
   top-to-bottom sheen — like Apple's Liquid Glass, not a clear window. */
.app > .topbar {
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.14)),
    rgba(247, 243, 233, 0.6);
  -webkit-backdrop-filter: blur(26px) saturate(185%);
  backdrop-filter: blur(26px) saturate(185%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1px 0 rgba(255, 255, 255, 0.18),
    0 8px 26px -16px rgba(40, 38, 30, 0.35);
  z-index: 6;
}
.app > .composer {
  position: relative;
  z-index: 6;
}

html[data-theme="dark"] .app > .topbar {
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.02)),
    rgba(30, 28, 25, 0.6);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 -1px 0 rgba(255, 255, 255, 0.04),
    0 8px 26px -16px rgba(0, 0, 0, 0.6);
}

/* The composer pill gets the same glass treatment — a rounded shard with a
   glossy sheen, a rim highlight and a lifted shadow. */
.app > .composer .composer-inner {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.2)),
    rgba(255, 253, 248, 0.5);
  -webkit-backdrop-filter: blur(26px) saturate(185%);
  backdrop-filter: blur(26px) saturate(185%);
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 2px 6px rgba(40, 38, 30, 0.05),
    0 16px 36px -14px rgba(40, 38, 30, 0.16);
}
html[data-theme="dark"] .app > .composer .composer-inner {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.02)),
    rgba(42, 39, 35, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.13);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 16px 36px -14px rgba(0, 0, 0, 0.5);
}

@media (max-width: 760px) {
  .app > .messages {
    padding-top: calc(9px + var(--edge-fade));
    padding-bottom: calc(14px + var(--edge-fade));
  }
}

/* =================== Screen efficiency (mobile) ====================
   The header was wrapping onto two rows — the AI action icons dropped below
   the title, and the Rooms ⋯ menu stacked under the title — eating a tall band
   of vertical space. Force a single compact header row in both modes and trim
   the paddings so the conversation gets the most of the screen. */
@media (max-width: 760px) {
  .app > .topbar {
    flex-wrap: nowrap;
    padding: 6px 10px;
    gap: 6px;
    min-height: 0;
  }
  .topbar .icon-btn { padding: 5px 6px; font-size: 17px; flex: 0 0 auto; }
  .topbar #menu-btn, .topbar .notif-wrap, .topbar .chat-menu-wrap { flex: 0 0 auto; }
  /* The conversation title takes priority for space and truncates; the action
     menu button keeps its size instead of collapsing the title to nothing. */
  .topbar > .topbar-title { flex: 1 1 auto; min-width: 0; }
  .topbar-title #convo-title { max-width: none; }

  /* Rooms header on ONE row: the ⋯ opens the controls as a dropdown, so it
     belongs inline beside the title, not stacked beneath it. */
  .topbar .room-topbar {
    flex-direction: row;
    align-items: center;
    flex-wrap: nowrap;
    gap: 8px;
  }
  .topbar .room-head-left { flex: 1 1 auto; min-width: 0; }
  .topbar .room-menu-wrap { flex: 0 0 auto; }

  /* Trim the top/bottom chrome a touch more. */
  .app > .composer { padding: 6px 12px 10px; }
  #tabbar.tabbar { padding: 4px 10px calc(4px + env(safe-area-inset-bottom)); }
  #tabbar .tab { padding: 5px 4px 4px; }
}

/* AI chat actions: inline icons on desktop, folded into a ⋯ overflow menu on
   mobile so the conversation title stays prominent in a single-row header. */
.chat-menu-wrap { position: relative; display: flex; align-items: center; margin-inline-start: auto; }
.chat-menu-wrap > .chat-actions { margin-inline-start: 0; }
#chat-menu-btn { display: none; }

@media (max-width: 760px) {
  #chat-menu-btn { display: inline-flex; }
  .chat-menu-wrap > .chat-actions {
    position: absolute;
    top: calc(100% + 8px);
    inset-inline-end: 0;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 6px;
    min-width: 168px;
    background: var(--surface, #fff);
    border: 1px solid var(--border);
    border-radius: 14px;
    box-shadow: 0 14px 36px -8px rgba(40, 38, 30, 0.28);
    z-index: 40;
  }
  .chat-menu-wrap.open > .chat-actions { display: flex; }
  .chat-menu-wrap > .chat-actions .icon-btn {
    font-size: 17px;
    padding: 9px 12px;
    text-align: start;
    border-radius: 9px;
  }
}
html[data-theme="dark"] .chat-menu-wrap > .chat-actions { background: rgba(38, 35, 32, 0.98); }

/* ============== Floating mode toggle (Hooshang / Rooms) ==============
   Was a full-width bottom panel taking its own row. Now a small centered
   segmented pill floating over the content, just above the composer — an
   iOS-style glass switch, not a separate bar. */
@media (max-width: 760px) {
  /* The toggle IS the title: it sits centered in the header band, in place of
     the conversation / room name. */
  .topbar > .topbar-title,
  .room-topbar .topbar-title { visibility: hidden; }
  #tabbar.tabbar {
    position: fixed;
    /* Centre with auto margins rather than translateX(-50%): a transformed /
       backdrop-filtered ancestor can become the containing block and skew a
       translate, which cropped the pill in the mobile browser. Margins + a
       frame guard stay centred and on-screen everywhere. */
    left: auto;
    right: auto;
    /* Centre the pill in the space that ISN'T taken by the topbar icon cluster
       (menu + bell, always on the inline-start side), so on a narrow screen it
       can never crowd or overlap the bell. */
    inset-inline-start: 96px;
    inset-inline-end: 0;
    transform: none;
    margin-inline: auto;
    top: calc(4px + env(safe-area-inset-top));
    bottom: auto;
    width: fit-content;
    max-width: calc(100vw - 108px);
    display: flex;
    gap: 2px;
    padding: 3px;
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 999px;
    background:
      linear-gradient(180deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.24)),
      rgba(247, 243, 233, 0.6);
    -webkit-backdrop-filter: blur(22px) saturate(185%);
    backdrop-filter: blur(22px) saturate(185%);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.9),
      0 10px 28px -10px rgba(40, 38, 30, 0.4);
    z-index: 30;
  }
  #tabbar .tab {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    gap: 5px;
    padding: 4px 13px;
    border-radius: 999px;
    opacity: 1;
    background: none !important;
    color: var(--muted);
  }
  #tabbar .tab.active {
    background: #fff !important;
    color: var(--sage-strong, #3f5a45);
    box-shadow: 0 2px 6px rgba(40, 38, 30, 0.14);
  }
  #tabbar .tab.active::before { display: none; } /* drop the old top indicator */
  #tabbar .tab-icon { font-size: 16px; height: auto; }
  #tabbar .tab-icon svg { width: 18px; height: 18px; }
  #tabbar .tab-label { font-size: 12px; font-weight: 600; letter-spacing: 0; }
  #tabbar .tab-badge { top: -4px; inset-inline-end: -2px; }
  /* Keep the pill compact so it never reaches the topbar icons (the bell): only
     the ACTIVE tab shows its label; the others are icon-only. With three tabs a
     full-label pill grew wide enough to overlap the header. */
  #tabbar .tab .tab-label { display: none; }
  #tabbar .tab.active .tab-label { display: inline; }
  #tabbar .tab.active { gap: 6px; }
}
html[data-theme="dark"] #tabbar.tabbar {
  border-color: rgba(255, 255, 255, 0.12);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.02)),
    rgba(30, 28, 25, 0.62);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 10px 28px -10px rgba(0, 0, 0, 0.6);
}
html[data-theme="dark"] #tabbar .tab { color: var(--muted); }
html[data-theme="dark"] #tabbar .tab.active {
  background: rgba(255, 255, 255, 0.16) !important;
  color: #fff;
  box-shadow: none;
}

/* The room composer reserved a blank line above the input for the typing
   indicator even when nobody was typing, making it taller than the AI
   composer. Collapse it when empty so both composers are the same thin height. */
.typing-indicator:empty { display: none; }

/* ================= Rooms dashboard tidy-up (mobile) ================= */
@media (max-width: 760px) {
  /* The header toggle already names the mode — drop the duplicate big heading,
     and trim the tall empty band above the list. */
  .rooms-dash { padding-top: 6px; }
  .rooms-dash .rd-head h2 { display: none; }
  .rooms-dash .rd-head { margin-bottom: 8px; }
  .rooms-dash .rd-filters button { padding: 7px 12px; }

  /* Action shortcuts as one neat scrollable row instead of a ragged wrap. */
  .rooms-dash .rd-head .dash-actions {
    flex-wrap: nowrap;
    overflow-x: auto;
    width: 100%;
    padding-bottom: 2px;
    scrollbar-width: none;
  }
  .rooms-dash .rd-head .dash-actions::-webkit-scrollbar { display: none; }
  .rooms-dash .rd-head .dash-action { flex: 0 0 auto; }

  /* Give each chat row a readable frosted card so the list is clean and legible
     over the wallpaper, instead of text floating directly on the photo. */
  .rd-list { gap: 7px; }
  .rd-list .room-item {
    background: rgba(255, 255, 255, 0.72);
    -webkit-backdrop-filter: blur(10px) saturate(150%);
    backdrop-filter: blur(10px) saturate(150%);
    border: 1px solid rgba(255, 255, 255, 0.5);
    border-radius: 16px;
    padding: 10px 13px;
    box-shadow: 0 4px 14px -8px rgba(40, 38, 30, 0.25);
  }
  .rd-list .room-item:hover,
  .rd-list .room-item.active { transform: none; }
}
html[data-theme="dark"] .rd-list .room-item {
  background: rgba(30, 28, 25, 0.55);
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow: 0 4px 14px -8px rgba(0, 0, 0, 0.5);
}

/* ================= Sidebar tidy-up ================= */
/* Footer on a single line: the profile chip stretches, the theme + feedback
   icons sit beside it, and the install button (when shown) takes a full row
   above them. Frees vertical space for the conversation list. */
.sidebar-foot {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 10px;
}
.sidebar-foot .install-btn,
.sidebar-foot .install-hint { flex: 1 1 100%; order: 0; margin: 0; }
.sidebar-foot .user-chip {
  flex: 1 1 auto;
  width: auto;
  order: 1;
  min-width: 0;
  padding: 6px 8px;
  text-align: start;
}
.sidebar-foot .foot-actions { order: 2; margin: 0; flex: 0 0 auto; gap: 6px; }
.foot-icon { width: 38px; height: 38px; }

@media (max-width: 760px) {
  /* The header now carries the Hooshang/Rooms toggle, so the drawer's copy is
     redundant — reclaim the space and give the list room. */
  .sidebar .mode-switch { display: none; }
  .sidebar-head { padding: 12px 12px 8px; gap: 9px; }
  .sidebar .brand { padding: 0 2px; }
  .new-chat-btn { padding: 9px 13px; }
  .search-block { padding: 6px 12px 2px; }
}

/* ============= Softer drawer + edge grab handle (mobile) ============= */
.drawer-handle { display: none; }
/* The Calls page has no sidebar content worth opening, so the pull-tab does
   nothing there — hide it in calls mode (web and native alike). */
.layout[data-mode="calls"] .drawer-handle { display: none !important; }
@media (max-width: 760px) {
  /* Round the drawer's inner edge so it reads as a soft card sliding in. */
  .sidebar {
    border-start-end-radius: 22px;
    border-end-end-radius: 22px;
    border-inline-end: none;
  }
  .layout.sidebar-open .sidebar {
    box-shadow: 0 0 48px rgba(0, 0, 0, 0.28);
  }

  /* A little pull-tab on the leading edge (right in RTL, left in LTR): a rounded
     tab flush to the screen edge with a chevron, that gently nudges inward to
     say "drag or tap me to open the menu". */
  .drawer-handle {
    display: grid;
    place-items: center;
    position: fixed;
    inset-inline-start: 0;
    top: calc(50% - 28px);
    z-index: 44;
    width: 30px;
    height: 56px;
    padding: 0;
    border: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    /* Rounded on the inner edge, flush to the screen edge. */
    border-start-start-radius: 0;
    border-end-start-radius: 0;
    border-start-end-radius: 16px;
    border-end-end-radius: 16px;
    background: linear-gradient(180deg,
      var(--sage, #5c7360),
      color-mix(in srgb, var(--sage, #5c7360) 78%, #000 8%));
    box-shadow: 2px 2px 14px rgba(40, 38, 30, 0.3);
  }
  .drawer-handle svg {
    width: 18px;
    height: 18px;
    margin-inline-end: 3px; /* nudge the chevron toward the rounded side */
    fill: none;
    stroke: var(--cream-on-dark, #fff);
    stroke-width: 2.4;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  html[dir="ltr"] .drawer-handle svg { transform: scaleX(-1); }
  .drawer-handle:active { filter: brightness(1.08); }
  /* Out of the way while the drawer is open or being pulled. */
  .layout.sidebar-open .drawer-handle,
  .layout.dragging .drawer-handle {
    opacity: 0;
    pointer-events: none;
  }
  /* The Calls tab is a self-contained list — the drawer pull-tab isn't needed
     there and just clutters the edge. */
  .layout[data-mode="calls"] .drawer-handle { display: none; }
  html[dir="rtl"] .drawer-handle { --nudge: -4px; }
  html[dir="ltr"] .drawer-handle { --nudge: 4px; }
  @media (prefers-reduced-motion: no-preference) {
    .drawer-handle { animation: handle-nudge 3.2s ease-in-out infinite; }
    @keyframes handle-nudge {
      0%, 82%, 100% { transform: translateX(0); }
      88% { transform: translateX(var(--nudge, -4px)); }
      94% { transform: translateX(0); }
    }
  }
}
html[data-theme="dark"] .drawer-handle {
  background: linear-gradient(180deg, var(--sage, #8fae94),
    color-mix(in srgb, var(--sage, #8fae94) 74%, #000 22%));
  box-shadow: 2px 2px 16px rgba(0, 0, 0, 0.5);
}

/* ============================ Voice calls ============================ */
.room-call-btn svg { width: 20px; height: 20px; fill: currentColor; display: block; }
.room-call-btn { color: var(--sage-strong); }

.call-ui {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(20, 18, 15, 0.55);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.call-ui[hidden] { display: none; }
.call-card {
  width: min(92vw, 340px);
  padding: 30px 24px 24px;
  border-radius: 26px;
  text-align: center;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.16)),
    rgba(247, 243, 233, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85), 0 24px 60px -18px rgba(0, 0, 0, 0.45);
}
html[data-theme="dark"] .call-card {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)),
    rgba(32, 30, 27, 0.82);
  border-color: rgba(255, 255, 255, 0.12);
}
.call-avatar {
  width: 96px; height: 96px; margin: 0 auto 16px;
  border-radius: 50%; display: grid; place-items: center;
  font-size: 40px; font-weight: 700; color: var(--cream-on-dark);
  background: var(--sage);
}
.call-card[data-state="ringing"] .call-avatar,
.call-card[data-state="calling"] .call-avatar { animation: call-pulse 1.6s ease-in-out infinite; }
@keyframes call-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--sage) 50%, transparent); }
  50%      { box-shadow: 0 0 0 16px color-mix(in srgb, var(--sage) 0%, transparent); }
}
.call-name { font-family: var(--font-display); font-size: 22px; font-weight: 700; }
.call-status {
  margin-top: 6px; color: var(--muted); font-size: 14px;
  font-variant-numeric: tabular-nums; min-height: 20px;
}
.call-actions { display: flex; justify-content: center; gap: 18px; margin-top: 26px; }
.call-btn {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  border: none; background: none; font: inherit; cursor: pointer; color: var(--text);
}
.call-btn::before {
  content: ""; width: 60px; height: 60px; border-radius: 50%;
  display: grid; place-items: center; transition: transform var(--dur-fast) var(--ease-out);
}
.call-btn:active::before { transform: scale(0.92); }
.call-btn span { font-size: 12px; color: var(--muted); }
.call-btn.accept::before  { background: #2e9e5b; box-shadow: 0 8px 20px -6px rgba(46,158,91,.6); }
.call-btn.decline::before { background: #d64848; box-shadow: 0 8px 20px -6px rgba(214,72,72,.6); }
.call-btn.mute::before    { background: rgba(120,120,120,.22); }
.call-btn.mute.on::before { background: var(--sage); }
/* Little glyphs on the round buttons. */
.call-btn.accept::before  { content: "📞"; font-size: 24px; }
.call-btn.decline::before { content: "📵"; font-size: 22px; }
.call-btn.mute::before    { content: "🎙"; font-size: 22px; }
.call-btn.mute.on::before { content: "🔇"; font-size: 22px; }

/* ---- Video calls ---- */
.call-video {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #0c0b0a;
  overflow: hidden;
}
.call-video[hidden] { display: none; }
#call-remote-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #0c0b0a;
}
#call-local-video {
  position: absolute;
  inset-block-start: 14px;
  inset-inline-end: 14px;
  width: 30vw;
  max-width: 132px;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: 14px;
  border: 2px solid rgba(255, 255, 255, 0.6);
  box-shadow: 0 8px 24px -8px rgba(0, 0, 0, 0.6);
  transform: scaleX(-1); /* mirror your own preview */
  background: #1a1714;
}
/* In a video call the card floats ABOVE the video. While connected it becomes a
   translucent bottom control bar; before that it's a centered scrim card. */
.call-ui[data-media="video"] .call-card { position: relative; z-index: 2; }
.call-ui[data-media="video"]:not([data-state="connected"]) .call-card {
  background: rgba(20, 18, 15, 0.55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #fff;
}
.call-ui[data-media="video"]:not([data-state="connected"]) .call-name { color: #fff; }
.call-ui[data-media="video"][data-state="connected"] {
  place-items: end center;
  padding: 0;
}
.call-ui[data-media="video"][data-state="connected"] .call-card {
  width: 100%;
  max-width: none;
  padding: 16px 16px calc(20px + env(safe-area-inset-bottom));
  border: none;
  border-radius: 0;
  box-shadow: none;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.55));
}
.call-ui[data-media="video"][data-state="connected"] .call-avatar { display: none; }
.call-ui[data-media="video"][data-state="connected"] .call-name {
  color: #fff;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
}
.call-ui[data-media="video"][data-state="connected"] .call-status { color: rgba(255, 255, 255, 0.85); }
.call-ui[data-media="video"][data-state="connected"] .call-actions { margin-top: 14px; }

/* camera toggle button */
.call-btn.cam::before { content: "📹"; font-size: 22px; background: rgba(120, 120, 120, 0.22); }
.call-btn.cam.off::before { content: "🚫"; font-size: 22px; background: #d64848; }
.call-ui[data-media="video"][data-state="connected"] .call-btn span { color: rgba(255, 255, 255, 0.85); }

/* ---- Voice/Video chooser ---- */
.call-choose {
  position: fixed; inset: 0; z-index: 101;
  display: grid; place-items: center; padding: 24px;
  background: rgba(20, 18, 15, 0.5);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
.call-choose[hidden] { display: none; }
.call-choose-card {
  width: min(88vw, 320px); padding: 22px 20px 16px; border-radius: 22px; text-align: center;
  background:
    linear-gradient(180deg, rgba(255,255,255,.55), rgba(255,255,255,.16)),
    rgba(247,243,233,.75);
  border: 1px solid rgba(255,255,255,.5);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.85), 0 24px 60px -18px rgba(0,0,0,.45);
}
html[data-theme="dark"] .call-choose-card {
  background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(255,255,255,.02)), rgba(32,30,27,.86);
  border-color: rgba(255,255,255,.12);
}
.call-choose-title { font-family: var(--font-display); font-weight: 700; font-size: 17px; margin-bottom: 16px; }
.call-choose-actions { display: flex; gap: 14px; justify-content: center; }
.call-choose-btn {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 16px 10px; border-radius: 16px; border: 1px solid var(--border);
  background: var(--card); color: var(--text); font: inherit; font-weight: 600; font-size: 13px; cursor: pointer;
  transition: border-color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out);
}
html[data-theme="dark"] .call-choose-btn { background: rgba(255,255,255,.05); }
.call-choose-btn:hover { border-color: var(--sage); transform: translateY(-1px); }
.call-choose-btn .cc-ic { font-size: 26px; }
.call-choose-cancel {
  margin-top: 14px; background: none; border: none; color: var(--muted);
  font: inherit; font-size: 14px; cursor: pointer; padding: 6px 10px;
}

/* flip-camera button */
.call-btn.flip::before { content: "🔄"; font-size: 21px; background: rgba(120,120,120,.22); }

/* in-call data-saver toggle */
.call-btn.ds::before { content: "🌿"; font-size: 20px; background: rgba(120, 120, 120, 0.22); }
.call-btn.ds.on::before { background: var(--sage); }

/* In a specific room/DM: show its name in the header, hide the mode toggle so
   you always know where you are (the back button returns you to the list). */
@media (max-width: 760px) {
  .layout.in-room #tabbar.tabbar { display: none; }
  .layout.in-room .room-topbar .topbar-title { visibility: visible; }
  .layout.in-room #room-title { font-size: 16px; font-weight: 700; }
}

/* ============ Professional call controls (icons, not emoji) ============ */
.call-btn::before { content: none !important; } /* retire the old emoji discs */
.call-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; gap: 14px; margin-top: 26px; }
.call-btn {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  border: none; background: none; font: inherit; cursor: pointer; color: var(--text);
  -webkit-tap-highlight-color: transparent;
}
.call-btn .cb-ic {
  width: 54px; height: 54px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(120, 120, 120, 0.22);
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-fast) ease;
}
.call-btn .cb-ic svg { width: 25px; height: 25px; fill: #fff; display: block; }
.call-btn:active .cb-ic { transform: scale(0.92); }
.call-btn .cb-l { font-size: 12px; color: var(--muted); max-width: 72px; text-align: center; }
/* engaged toggles glow sage */
.call-btn.on .cb-ic { background: var(--sage); }
/* accept = green upright handset, decline/hang-up = red down handset */
.call-btn.accept .cb-ic { background: #2e9e5b; box-shadow: 0 8px 20px -6px rgba(46, 158, 91, .55); }
.call-btn.decline .cb-ic { background: #d64848; box-shadow: 0 8px 20px -6px rgba(214, 72, 72, .55); }
.call-btn.decline .cb-ic svg { transform: rotate(134deg); }

/* In the video bottom bar: icon-only, one tidy row */
.call-ui[data-media="video"][data-state="connected"] .call-btn .cb-l { display: none; }
.call-ui[data-media="video"][data-state="connected"] .call-actions { gap: 12px; margin-top: 12px; flex-wrap: nowrap; }
.call-ui[data-media="video"][data-state="connected"] .call-btn .cb-ic { width: 46px; height: 46px; }
.call-ui[data-media="video"][data-state="connected"] .call-btn .cb-ic svg { width: 22px; height: 22px; }

/* Peer name pinned in the corner of the video */
.call-peer-tag {
  position: absolute; top: 14px; inset-inline-start: 14px; z-index: 2;
  max-width: 55%; padding: 6px 13px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.45);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  color: #fff; font-weight: 600; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.call-peer-tag[hidden] { display: none; }

/* ===================== Group (mesh) call ===================== */
.gcall-ui { padding: 0 !important; place-items: stretch; display: flex; flex-direction: column; }
.gcall-ui[hidden] { display: none; }
.gcall-grid {
  flex: 1; display: grid; gap: 6px; padding: 6px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  grid-auto-rows: 1fr; align-content: stretch;
}
.gtile {
  position: relative; background: #14120f; border-radius: 14px; overflow: hidden;
  min-height: 130px; display: flex; align-items: center; justify-content: center;
}
.gtile video { width: 100%; height: 100%; object-fit: cover; display: block; }
.gtile.no-video video { display: none; }
.gtile-av {
  width: 66px; height: 66px; border-radius: 50%;
  background: var(--sage) center/cover no-repeat;
  display: grid; place-items: center; color: #fff; font-size: 27px; font-weight: 700;
}
.gtile:not(.no-video) .gtile-av { display: none; }
.gtile-name {
  position: absolute; bottom: 8px; inset-inline-start: 8px;
  background: rgba(0, 0, 0, 0.5); color: #fff; font-size: 12px; font-weight: 600;
  padding: 3px 10px; border-radius: 999px; max-width: 82%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gcall-bottom {
  padding: 10px 12px calc(14px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.55));
  text-align: center;
}
.gcall-title {
  color: #fff; font-weight: 700; font-family: var(--font-display); font-size: 16px;
  margin-bottom: 4px; text-shadow: 0 1px 6px rgba(0, 0, 0, 0.6);
}
.gcall-ui .call-actions { margin-top: 6px; flex-wrap: nowrap; gap: 12px; }
.gcall-ui .call-btn .cb-l { display: none; }
.gcall-ui .call-btn .cb-ic { width: 48px; height: 48px; }
.gcall-ui .call-btn .cb-ic svg { width: 22px; height: 22px; }

/* In-room "call in progress — Join" banner */
.gcall-banner {
  position: fixed; z-index: 60; left: 50%; transform: translateX(-50%);
  bottom: calc(86px + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: 10px;
  padding: 7px 7px 7px 15px; border-radius: 999px;
  background: var(--sage-strong, #3f5a45); color: #fff;
  box-shadow: 0 12px 30px -8px rgba(0, 0, 0, 0.45);
  font-size: 13.5px; font-weight: 600; max-width: 92vw;
}
.gcall-banner[hidden] { display: none; }
.gcall-banner-dot { width: 9px; height: 9px; border-radius: 50%; background: #6ee7a0; animation: gpulse 1.4s infinite; flex: 0 0 auto; }
@keyframes gpulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
.gcall-banner-join {
  background: #fff; color: var(--sage-strong, #3f5a45); border: none; border-radius: 999px;
  padding: 6px 16px; font: inherit; font-weight: 700; cursor: pointer; flex: 0 0 auto;
}

/* Fit call controls on narrow phones (Android): wrap instead of overflowing,
   and shrink the discs a touch on small widths. iPhone Pro Max had the room;
   360-dp Androids did not. */
.call-ui[data-media="video"][data-state="connected"] .call-actions,
.gcall-ui .call-actions { flex-wrap: wrap !important; row-gap: 12px; }
@media (max-width: 400px) {
  .call-actions { gap: 10px; }
  .call-ui[data-media="video"][data-state="connected"] .call-btn .cb-ic,
  .gcall-ui .call-btn .cb-ic { width: 44px; height: 44px; }
  .call-ui[data-media="video"][data-state="connected"] .call-btn .cb-ic svg,
  .gcall-ui .call-btn .cb-ic svg { width: 20px; height: 20px; }
  .call-btn .cb-l { font-size: 11px; max-width: 62px; }
  .call-card { padding: 22px 14px 16px; }
  .call-avatar { width: 82px; height: 82px; }
}
@media (max-width: 340px) {
  .call-ui[data-media="video"][data-state="connected"] .call-btn .cb-ic,
  .gcall-ui .call-btn .cb-ic { width: 40px; height: 40px; }
  .call-actions { gap: 8px; }
}

/* ---- Mic waveform (in-call) + self-preview + standalone mic tester ---- */
.call-wave { display: block; width: min(72%, 220px); height: 44px; margin: 16px auto 2px; }
.call-wave[hidden] { display: none; }
.call-selfcam {
  width: 132px; height: 132px; margin: 16px auto 2px; border-radius: 22px; overflow: hidden;
  background: #0c0b0a; border: 2px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 12px 28px -12px rgba(0, 0, 0, 0.55);
}
.call-selfcam[hidden] { display: none; }
.call-selfcam video { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }

.mic-test-btn {
  flex: 0 0 auto; border: 1px solid color-mix(in srgb, var(--text) 16%, transparent);
  background: transparent; color: var(--text); border-radius: 999px;
  padding: 7px 16px; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.mic-test-btn:hover { transform: translateY(-1px); background: color-mix(in srgb, var(--text) 6%, transparent); }
.mic-test-btn.on { background: var(--sage); color: var(--cream-on-dark); border-color: var(--sage); }
.mic-test-wave { display: block; width: 100%; height: 40px; margin: 2px 0 10px; }
.mic-test-wave[hidden] { display: none; }

/* ---- Call log ---- */
#calls-btn { position: relative; }
.foot-badge {
  position: absolute; top: 1px; inset-inline-end: 1px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px; background: #d64848; color: #fff; font: 700 10px/16px system-ui, sans-serif;
  text-align: center; box-shadow: 0 0 0 2px var(--surface);
}
.foot-badge[hidden] { display: none; }
.calls-list { margin: 4px 0 8px; display: flex; flex-direction: column; gap: 2px; }
/* A small red count on the sidebar's Calls tab (mobile uses the .tab-badge). */
.mode-badge {
  display: inline-grid; place-items: center; min-width: 16px; height: 16px; padding: 0 4px;
  margin-inline-start: 6px; border-radius: 999px; background: #d64848; color: #fff;
  font: 700 10px/1 system-ui, sans-serif; vertical-align: middle;
}
.mode-badge[hidden] { display: none; }
.calls-empty { text-align: center; color: var(--muted); padding: 30px 0; font-size: 14px; }
.call-row {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: start;
  border: none; background: none; font: inherit; color: var(--text); cursor: pointer;
  padding: 9px 8px; border-radius: 12px; transition: background var(--dur-fast) var(--ease-out);
}
.call-row:hover { background: color-mix(in srgb, var(--text) 6%, transparent); }
.call-av {
  width: 40px; height: 40px; flex: 0 0 auto; border-radius: 50%; object-fit: cover;
  display: grid; place-items: center; font-weight: 700; color: #fff; background: var(--sage);
}
.call-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.call-name { font-weight: 600; font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.call-name.missed { color: #d64848; }
.call-sub { font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 4px; }
.call-arrow { font-weight: 700; }
.call-arrow.missed { color: #d64848; }
.call-arrow.ok { color: var(--sage); }
.call-back { flex: 0 0 auto; font-size: 18px; opacity: .5; }
.call-row:hover .call-back { opacity: 1; }

/* ---- Contact picker (New DM / New room) ---- */
.picker { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.picker-search {
  width: 100%; border: 1px solid var(--border); border-radius: 12px; padding: 11px 14px;
  font: inherit; background: transparent; color: inherit; outline: none;
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.picker-search:focus { border-color: var(--sage); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sage) 20%, transparent); }
.picker-list { max-height: 44vh; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.pick-row {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: start;
  border: none; background: none; font: inherit; color: var(--text); cursor: pointer;
  padding: 6px 8px; border-radius: 10px; transition: background var(--dur-fast) var(--ease-out);
}
.pick-row:hover { background: color-mix(in srgb, var(--text) 6%, transparent); }
.pick-row.on { background: color-mix(in srgb, var(--sage) 15%, transparent); }
.pick-av { width: 34px; height: 34px; flex: 0 0 auto; font-size: 14px; }
.pick-meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.pick-name { font-weight: 600; font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pick-sub { font-size: 12.5px; color: var(--muted); }
.pick-check {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  border: 1.5px solid var(--border); color: transparent; font-size: 12px; font-weight: 800;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.pick-row.on .pick-check { background: var(--sage); border-color: var(--sage); color: #fff; }
.picker-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.picker-chips[hidden] { display: none; }
.pick-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px;
  background: color-mix(in srgb, var(--sage) 16%, transparent); color: var(--text);
  border-radius: 999px; font-size: 13px; font-weight: 600;
}
.pick-chip-x { border: none; background: none; cursor: pointer; color: var(--muted); font-size: 12px; line-height: 1; padding: 2px; }
.pick-chip-x:hover { color: var(--text); }

/* Picker modals must fit any height: the header, name field, search box and the
   action button stay put; only the contact LIST scrolls. This is what keeps the
   New-room / New-DM dialog usable when the on-screen keyboard leaves little room
   above it. min-height:0 lets the list shrink so the button is never clipped. */
.modal-picker { display: flex; flex-direction: column; overflow: hidden; }
.modal-picker .picker { flex: 1 1 auto; min-height: 0; }
/* A HARD cap (not just flex) so the contact list always scrolls and never grows
   tall enough to push the Create button behind the keyboard — flex still lets it
   shrink further when the dialog is squeezed above the keyboard. */
.modal-picker .picker-list { flex: 1 1 auto; min-height: 0; max-height: 42vh; overflow-y: auto; }
@media (max-width: 760px) {
  .modal-picker { padding: 16px; }
  .modal-picker .picker-list { max-height: 38vh; }
}

/* In-chat call event — a centered summary chip, tap to call back */
.rmsg.call-event { justify-content: center; margin: 10px 0; }
.call-event-chip {
  display: inline-flex; align-items: center; gap: 8px; border: 1px solid var(--border);
  background: color-mix(in srgb, var(--sage) 9%, transparent); color: var(--text);
  border-radius: 999px; padding: 6px 14px; font: inherit; font-size: 13px; cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.call-event-chip:hover { background: color-mix(in srgb, var(--sage) 18%, transparent); }
.call-event-chip:active { transform: scale(.98); }
.call-event-chip.missed {
  color: #d64848; border-color: color-mix(in srgb, #d64848 32%, transparent);
  background: color-mix(in srgb, #d64848 9%, transparent);
}
.ce-icon { font-size: 15px; }
.ce-time { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.call-event-chip.missed .ce-time { color: color-mix(in srgb, #d64848 65%, var(--muted)); }

/* ---- Rooms dashboard header: + (new room) and ⋯ overflow menu ---- */
.rd-actions { display: flex; align-items: center; gap: 8px; }
.rd-menu-wrap { position: relative; }
.rd-icon-btn {
  width: 40px; height: 40px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--card); color: var(--text); font-size: 20px; line-height: 1; cursor: pointer;
  display: grid; place-items: center;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.rd-icon-btn:hover { border-color: var(--sage); transform: translateY(-1px); }
.rd-icon-btn.primary { background: var(--sage); border-color: var(--sage); color: #fff; font-weight: 600; }
.rd-icon-btn.primary:hover { box-shadow: 0 8px 18px -6px color-mix(in srgb, var(--sage) 65%, transparent); }
.rd-menu {
  position: absolute; inset-inline-end: 0; top: calc(100% + 6px); z-index: 30; min-width: 190px;
  background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 6px;
  box-shadow: 0 20px 44px -18px rgba(0,0,0,.4); display: flex; flex-direction: column; gap: 2px;
}
.rd-menu[hidden] { display: none; }
.rd-menu-item {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: start;
  border: none; background: none; font: inherit; font-size: 14px; color: var(--text);
  padding: 10px 11px; border-radius: 10px; cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}
.rd-menu-item:hover { background: color-mix(in srgb, var(--text) 6%, transparent); }
.rd-menu-ic { font-size: 16px; width: 20px; text-align: center; flex: 0 0 auto; }

/* ---- AI usage bars (Profile → Usage) ---- */
.usage-bars { display: flex; flex-direction: column; gap: 16px; margin: 4px 0 8px; }
.ubar-top { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 7px; }
.ubar-label { font-size: 14px; font-weight: 600; color: var(--text); }
.ubar-val { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.ubar-track { height: 10px; border-radius: 999px; background: color-mix(in srgb, var(--text) 9%, transparent); overflow: hidden; }
.ubar-fill {
  height: 100%; border-radius: 999px; background: var(--sage);
  transition: width .4s var(--ease-out), background .3s;
}
.ubar-fill.mid { background: #d99a41; }
.ubar-fill.high { background: #d64848; }
.ubar.unlimited .ubar-fill { background: linear-gradient(90deg, var(--sage), color-mix(in srgb, var(--sage) 55%, transparent)); }
.ubar.unlimited .ubar-val { color: var(--sage); font-weight: 700; }
.usage-role { margin: 4px 2px 0; font-size: 12.5px; color: var(--muted); }
#usage-detail { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border); }

/* ---- Announcements channel ---- */
.room-avatar.is-channel { background: color-mix(in srgb, var(--sage) 24%, transparent); color: var(--sage-strong, #3f5a45); font-size: 18px; }
.rd-list .room-avatar.is-channel { font-size: 20px; }
.channel-note {
  flex: 0 0 auto; text-align: center; color: var(--muted); font-size: 13px;
  padding: 14px 16px calc(14px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  background: color-mix(in srgb, var(--sage) 7%, transparent);
}
.channel-note[hidden] { display: none; }
