:root {
  --bg: #f6f7fb;
  --panel: #ffffff;
  --ink: #1c2333;
  --muted: #7a8295;
  --accent: #5b6cff;
  --accent-ink: #ffffff;
  --bubble-me: #5b6cff;
  --bubble-them: #eef0f6;
  --radius: 18px;
  --border: #e7e9f0;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

button {
  font: inherit;
  cursor: pointer;
  border: none;
  border-radius: 999px;
  padding: 10px 18px;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  white-space: nowrap;
  line-height: 1.2;
}
button.secondary {
  background: var(--bubble-them);
  color: var(--ink);
}
button:disabled { opacity: 0.5; cursor: default; }

input, textarea {
  font: inherit;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  background: #fff;
  color: var(--ink);
  width: 100%;
}
input:focus, textarea:focus { outline: 2px solid var(--accent); border-color: transparent; }

/* ---- centered card layout (join / fallback) ---- */
.center {
  min-height: 100%;
  display: grid;
  place-items: center;
  padding: 24px;
}
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 24px;
  padding: 28px;
  width: 100%;
  max-width: 420px;
  box-shadow: 0 12px 40px rgba(20, 30, 80, 0.06);
}
.card h1 { margin: 0 0 6px; font-size: 24px; }
.card p { margin: 0 0 18px; color: var(--muted); }
.card .row { display: flex; gap: 10px; margin-top: 14px; }

/* ---- chat ---- */
.chat {
  display: flex;
  flex-direction: column;
  height: 100%;
  max-width: 720px;
  margin: 0 auto;
  background: var(--panel);
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  position: relative; /* anchors the drag-and-drop overlay */
}
/* Native shell (iOS/macOS) embeds only the message feed — the app draws its own
   title bar and composer. Drop the centered max-width column + side borders so the
   feed is full width, and hide the web header/composer. Gated on body.native-embed,
   which only chat.js sets when window.__lchatEmbed is injected; browsers are
   unaffected. */
.native-embed .chat {
  max-width: none;
  border-left: none;
  border-right: none;
}
.native-embed .chat header,
.native-embed .composer,
.native-embed .composer-reply,
.native-embed .composer-edit {
  display: none;
}
/* Keep the attachment preview visible: it's how a staged photo/file shows up just
   above the native composer (drag-drop or the native + button stage into it). The
   composer below is hidden, so add the bottom padding the composer would have
   provided. */
.native-embed .composer-preview { padding-bottom: 10px; }

.chat header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--panel);
}
.chat header .title {
  font-weight: 700;
  font-size: 17px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-right: 10px;
}

/* kebab settings menu */
.icon-btn {
  background: transparent;
  color: var(--ink);
  font-size: 22px;
  line-height: 1;
  padding: 4px 10px;
  border-radius: 10px;
}
.icon-btn:hover { background: var(--bubble-them); }
.menu-wrap { position: relative; flex: none; }
.menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(20, 30, 80, 0.14);
  min-width: 230px;
  padding: 6px;
  z-index: 20;
}
.menu-who {
  font-size: 12px;
  color: var(--muted);
  padding: 8px 12px 6px;
}
.menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  color: var(--ink);
  border-radius: 10px;
  padding: 10px 12px;
  font-weight: 500;
  white-space: normal;
}
.menu-item:hover { background: var(--bubble-them); }
.menu-item.danger { color: #c2410c; }
.menu-item.disabled,
.menu-item.disabled:hover { color: var(--muted); cursor: default; background: transparent; }

.feed-wrap {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
/* shown only if the initial history load/decrypt is slow (>500ms) */
.chat-loading {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--panel);
}
.spinner {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
#feed {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden; /* clip messages mid swipe-to-reply; no horizontal scrollbar */
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* push a few messages to the bottom (near the composer); scrolls normally when full */
#feed::before {
  content: "";
  margin-top: auto;
}
.msg {
  display: flex;
  flex-direction: column;
  max-width: 78%;
  margin-top: 10px;
  position: relative; /* anchors the swipe-to-reply icon */
  touch-action: pan-y; /* vertical scroll stays native; we handle horizontal swipes */
}
/* continuation of a same-sender, same-minute run — tighter gap (see refreshGrouping) */
.msg.cont { margin-top: 2px; }
/* swipe-to-reply (touch): reply arrow that fades in just left of the bubble */
.swipe-reply-icon {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translate(-130%, -50%);
  color: var(--accent);
  opacity: 0;
  pointer-events: none;
  display: inline-flex;
}
.swipe-reply-icon svg { width: 20px; height: 20px; }
.msg .name { font-size: 12px; color: var(--muted); margin: 0 6px 3px; }
.msg .bubble {
  padding: 9px 13px;
  border-radius: var(--radius);
  background: var(--bubble-them);
  line-height: 1.35;
  word-wrap: break-word;
  white-space: pre-wrap;
}
.msg.me { align-self: flex-end; align-items: flex-end; }
.msg.me .bubble { background: var(--bubble-me); color: #fff; border-bottom-right-radius: 6px; }
.msg.them .bubble { border-bottom-left-radius: 6px; }
.msg .bubble a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
/* a message of just a few emoji: large and bubble-less, no background or padding (see fillContent) */
.msg .bubble.jumbo-emoji,
.msg.me .bubble.jumbo-emoji { background: none; color: inherit; padding: 2px 0; font-size: 44px; line-height: 1.15; }

/* centered time separator that opens a burst (replaces per-message timestamps) */
.time-sep {
  align-self: center;
  margin: 16px 0 6px;
  font-size: 11px;
  color: var(--muted);
  text-align: center;
}
.time-sep strong { color: var(--ink); font-weight: 600; }

/* persistent "Edited" label under an edited bubble */
.edited-tag { font-size: 11px; color: var(--muted); margin: 1px 6px 0; }

/* exact per-message time, revealed on hover (desktop) just beyond the hover
   reply/edit icons so they don't overlap */
.msg-time {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
}
.msg.them .msg-time { left: 100%; margin-left: 34px; }
.msg.me .msg-time { right: 100%; margin-right: 62px; }
@media (hover: hover) {
  .msg:hover .msg-time { opacity: 1; }
}

/* desktop hover reply/edit icons — absolutely positioned just outside the bubble
   so they reveal on hover without shifting any content. They abut the bubble (no
   gap) so the pointer can travel from bubble to icon without losing the hover. */
.reply-hover,
.edit-hover {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  color: var(--muted);
  padding: 4px 6px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  line-height: 1;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
}
/* them: icon to the right of the bubble; me: to the left. Edit only appears on
   your own messages, sitting just beyond the reply icon. */
.reply-hover { right: -30px; }
.msg.me .reply-hover { right: auto; left: -30px; }
.msg.me .edit-hover { right: auto; left: -58px; }
.reply-hover svg,
.edit-hover svg { width: 18px; height: 18px; }
.reply-hover:hover,
.edit-hover:hover { background: var(--bubble-them); color: var(--accent); }
@media (hover: hover) {
  .msg:hover .reply-hover,
  .msg:hover .edit-hover { opacity: 1; pointer-events: auto; }
}

/* message content (text bubble + any attachments) */
.content {
  position: relative; /* anchors the absolute hover reply icon */
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-start;
  min-width: 0;
}
.msg.me .content { align-items: flex-end; }

/* inline attachments */
.msg-image-wrap { max-width: 240px; }
.msg-image {
  max-width: 100%;
  max-height: 320px;
  border-radius: var(--radius);
  display: block;
  background: var(--bubble-them);
  cursor: zoom-in;
}

/* full-screen image viewer */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(0, 0, 0, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.lightbox img { max-width: 100%; max-height: 100%; border-radius: 8px; }
.lightbox-close {
  position: fixed;
  top: 14px;
  right: 16px;
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.lightbox-close svg { width: 20px; height: 20px; }

/* drag-and-drop overlay */
.drop-overlay {
  position: absolute;
  inset: 0;
  z-index: 40;
  background: rgba(91, 108, 255, 0.12);
  border: 3px dashed var(--accent);
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 18px;
  color: var(--accent);
  pointer-events: none;
}
.file-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--bubble-them);
  color: var(--ink);
  padding: 10px 14px;
  border-radius: var(--radius);
  text-decoration: none;
  font-size: 14px;
  max-width: 260px;
  word-break: break-word;
}
.msg.me .file-chip { background: var(--bubble-me); color: #fff; }

/* link (OpenGraph) preview card */
.link-preview {
  display: flex;
  flex-direction: column;
  max-width: 280px;
  background: var(--bubble-them);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  text-decoration: none;
}
.lp-image { width: 100%; max-height: 150px; object-fit: cover; display: block; }
.lp-body { padding: 8px 11px; }
.lp-title { font-weight: 600; font-size: 14px; line-height: 1.3; }
.lp-desc {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.lp-host { font-size: 11px; color: var(--muted); margin-top: 5px; }

/* composer attachment preview */
.composer-preview { padding: 10px 14px 0; }
.preview-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--bubble-them);
  border-radius: 12px;
  padding: 6px 34px 6px 8px;
  max-width: 100%;
}
.preview-chip img { width: 40px; height: 40px; object-fit: cover; border-radius: 8px; }
.preview-file { font-size: 24px; }
.preview-name {
  font-size: 13px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}
.preview-remove {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  background: var(--ink);
  color: #fff;
  width: 22px;
  height: 22px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.preview-remove svg { width: 13px; height: 13px; }

/* reactions */
.bubble-row { display: flex; align-items: center; gap: 6px; max-width: 100%; min-width: 0; }
.msg.me .bubble-row { flex-direction: row-reverse; }
/* Text selection works everywhere now: desktop reacts with a stationary hold
   (drag-select cancels it) and touch reacts with a double-tap, so long-press is
   free for native selection/copy on mobile. */
.reactions { display: flex; flex-wrap: wrap; gap: 4px; margin: 3px 2px 0; }
.msg.me .reactions { justify-content: flex-end; }
.reactions:empty { display: none; }
.reaction-chip {
  background: var(--bubble-them);
  color: var(--ink);
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 2px 9px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.35;
}
.reaction-chip.mine { border-color: var(--accent); background: #e7eaff; }
.emoji-picker {
  position: fixed;
  display: flex;
  gap: 2px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 6px;
  box-shadow: 0 12px 40px rgba(20, 30, 80, 0.18);
  z-index: 60;
}
.emoji-opt {
  background: transparent;
  font-size: 22px;
  padding: 4px 6px;
  border-radius: 50%;
  line-height: 1;
}
.emoji-opt:hover { background: var(--bubble-them); }
/* the "Reply" action in the message menu, set off from the emoji row */
.picker-action {
  background: transparent;
  color: var(--accent);
  padding: 4px 8px;
  margin-left: 2px;
  border-radius: 50%;
  border-left: 1px solid var(--border);
  display: inline-flex;
  align-items: center;
  line-height: 1;
}
.picker-action svg { width: 22px; height: 22px; }
.picker-action:hover { background: var(--bubble-them); }

/* a reply: a tappable quote of the parent sits above the bubble (à la Messages),
   and the parent gets a "N Replies" tag below it. */
.reply-quote {
  align-self: stretch;
  text-align: left;
  max-width: 100%;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 6px 11px;
  margin-bottom: 1px;
  font-weight: 400;
  white-space: normal;
}
.msg.me .reply-quote { text-align: right; }
.reply-quote-name { font-size: 11px; color: var(--muted); margin-bottom: 1px; }
.reply-quote-text {
  font-size: 13px;
  color: var(--muted);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.msg.me .reply-quote-text { margin-left: auto; }
.reply-count {
  font-size: 11px;
  font-weight: 600;
  color: var(--accent);
  margin: 3px 6px 0;
  cursor: pointer;
}
.reply-count[hidden] { display: none; }
/* flash a message when you jump to it from a quote */
.msg.flash { animation: flash-msg 1.2s ease; border-radius: var(--radius); }
@keyframes flash-msg {
  0%, 100% { background: transparent; }
  25% { background: rgba(91, 108, 255, 0.14); }
}

/* composer "Replying to …" / "Editing message" banners, above the composer
   (and any attachment preview). They share the .reply-bar inner markup. */
.composer-reply,
.composer-edit {
  padding: 8px 14px;
  border-top: 1px solid var(--border);
  background: var(--panel);
}
.composer-reply.hidden,
.composer-edit.hidden { display: none; }
.reply-bar { display: flex; align-items: center; gap: 10px; }
.reply-bar-icon { flex: none; color: var(--accent); display: inline-flex; }
.reply-bar-icon svg { width: 18px; height: 18px; }
.reply-bar-body {
  flex: 1;
  min-width: 0;
  border-left: 2px solid var(--accent);
  padding-left: 10px;
}
.reply-bar-name { font-size: 12px; font-weight: 600; color: var(--ink); }
.reply-bar-text {
  font-size: 13px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.reply-bar-cancel {
  flex: none;
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.reply-bar-cancel svg { width: 15px; height: 15px; }
.reply-bar-cancel:hover { background: var(--bubble-them); }

/* Subtle "… is typing" line, just above the composer. Transient presence only. */
.typing {
  padding: 2px 16px 6px;
  font-size: 12px;
  font-style: italic;
  color: var(--muted);
  background: var(--panel);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.typing.hidden { display: none; }

.composer {
  display: flex;
  gap: 8px;
  padding: 14px;
  border-top: 1px solid var(--border);
  background: var(--panel);
  align-items: flex-end;
}
.composer-field {
  position: relative;
  flex: 1;
  display: flex;
}
.composer textarea {
  flex: 1;
  resize: none;
  max-height: 140px;
  /* 7+9 padding + 22 line + 2 border = 40px at rest, matching .attach-btn. The
     1px-heavier bottom optically centers the text (a baseline sits low in its
     line box); right padding leaves room for the inline send button. */
  padding: 7px 46px 9px 14px;
  line-height: 22px;
  min-height: 40px;
  border-radius: 20px;
  font-family: inherit;
  overflow: hidden;
}
/* circular up-arrow send button, tucked into the bottom-right of the field */
.send-btn {
  position: absolute;
  right: 4px;
  bottom: 3px;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: #fff;
}
.send-btn[hidden] { display: none; }
/* left-side attach (＋) button */
.attach-btn {
  flex: none;
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bubble-them);
  color: var(--ink);
  font-size: 24px;
  line-height: 1;
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(20, 30, 80, 0.45);
  overflow: auto;
}

/* invite QR (admin) — full-screen opaque takeover so nothing else is on screen */
.qr-screen {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: var(--bg);
  overflow: auto;
}
.qr-modal {
  margin: 8vh auto;
  max-width: 360px;
  text-align: center;
  border: none;
  box-shadow: none;
}
.qr-modal h2 { margin: 0 0 6px; font-size: 20px; }
.qr-wrap {
  display: flex;
  justify-content: center;
  margin: 18px 0;
}
.qr-wrap canvas {
  max-width: 100%;
  height: auto;
  image-rendering: pixelated; /* keep modules crisp when CSS scales the canvas down */
  border-radius: 8px;
}
.qr-modal .row { justify-content: center; }

/* input + button on one row (e.g. Create invite) */
.inline-form {
  display: flex;
  gap: 10px;
  align-items: stretch;
}
.inline-form input {
  flex: 1;
  min-width: 0;
}

.banner {
  text-align: center;
  font-size: 13px;
  color: var(--muted);
  padding: 6px;
}
.banner.warn { color: #b4530a; }

/* connection status as a floating pill so it never reflows the message list */
#banner {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  box-shadow: 0 6px 20px rgba(20, 30, 80, 0.18);
  pointer-events: none;
  white-space: nowrap;
}
#banner.warn { background: #b4530a; color: #fff; }

/* ---- admin ---- */
.admin { max-width: 760px; margin: 0 auto; padding: 24px; }
.admin h1 { margin: 0 0 4px; }
.admin .sub { color: var(--muted); margin: 0 0 24px; }
.admin section {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 18px;
  margin-bottom: 18px;
}
.admin section h2 { margin: 0 0 12px; font-size: 16px; }
.invite {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 0;
  border-top: 1px solid var(--border);
}
.invite:first-of-type { border-top: none; }
.invite .meta { flex: 1; min-width: 0; }
.invite .meta .label { font-weight: 600; }
.invite .meta .status { font-size: 12px; color: var(--muted); }
.invite .status.revoked { color: #c2410c; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.key-box {
  background: var(--bubble-them);
  border-radius: 12px;
  padding: 12px;
  word-break: break-all;
  margin: 10px 0;
}
.hidden { display: none !important; }
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  background: var(--ink); color: #fff; padding: 10px 16px; border-radius: 999px;
  font-size: 14px; opacity: 0; transition: opacity .2s; pointer-events: none;
  z-index: 100; /* above full-screen overlays (qr-screen) so it's never hidden */
}
.toast.show { opacity: 1; }

.header-actions { display: flex; gap: 8px; align-items: center; }
.notif {
  background: var(--bubble-them);
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  padding: 7px 12px;
  white-space: nowrap;
}

/* full-screen onboarding cards */
.card.onboard { text-align: center; }
.card.onboard .row { justify-content: center; }
.card.onboard p { margin-bottom: 14px; }
.onboard-icon { font-size: 46px; line-height: 1; margin-bottom: 10px; }
.steps {
  text-align: left;
  color: var(--muted);
  line-height: 1.6;
  padding-left: 20px;
  margin: 4px 0 18px;
}
.steps li { margin-bottom: 6px; }
.steps strong { color: var(--ink); }
