/* ===========================================================================
   Chat — stylesheet

   Layout is the one every chat app uses, on purpose: conversation list on the
   left, thread on the right, your own messages on the right in blue. Familiar
   beats clever here — nobody should have to learn this.

   Mobile-first. Two panes on desktop, one sliding pane on phones.
   Light and dark are both driven from the same token set.
   =========================================================================== */

/* ===========================================================================
   ####  THEME  —  EVERYTHING YOU WOULD EVER WANT TO RESTYLE IS IN HERE  ####

   Nothing below this block contains a colour, a radius or a font. Change a
   value here and it changes everywhere it is used, in both light and dark.

   To rebrand: edit the six BRAND values. That is usually the whole job.
   =========================================================================== */

:root {
  /* ---- BRAND ------------------------------------------------------------
     The handful most people actually want to change. */
  --brand:            #2563eb;   /* buttons, links, own bubbles, active rows */
  --brand-hover:      #1d55d1;   /* the same colour, a shade darker          */
  --brand-tint:       #e8f0ff;   /* pale wash behind selected rows           */
  --brand-on:         #ffffff;   /* text drawn ON the brand colour           */

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --radius:    10px;             /* buttons, inputs, cards                   */

  /* ---- STATUS COLOURS ---------------------------------------------------
     -soft is a pale background, plain is text on that background,
     -solid is a saturated fill with white text on it. */
  --ok:            #12784a;
  --ok-soft:       #e3f5ec;
  --ok-solid:      #12784a;

  --warn:          #8a5a08;
  --warn-soft:     #fdf0d8;
  --warn-solid:    #b45309;   /* --warn is tuned for text and reads muddy as a fill */

  --danger:        #c1352b;
  --danger-soft:   #fdeae8;
  --danger-solid:  #c1352b;

  /* ---- SURFACES AND TEXT ------------------------------------------------ */
  --bg:            #eef1f5;   /* the page behind everything     */
  --surface:       #ffffff;   /* sidebar, headers, composer     */
  --surface-2:     #f7f9fb;   /* inputs, insets                 */
  --surface-3:     #eceff3;   /* hover states, quiet buttons    */
  --border:        #e3e7ec;
  --border-strong: #c9d0d9;

  --text:          #0f1720;   /* body copy         */
  --text-2:        #5a6573;   /* secondary labels  */
  --text-3:        #8b95a1;   /* timestamps, hints */

  --bubble-in:     var(--surface);   /* messages from other people */
  --bubble-out:    var(--brand);     /* your own messages          */

  --overlay:       rgba(9, 12, 18, .5);          /* behind modals and sheets */
  --quote-wash:    rgba(127, 127, 127, .12);     /* quoted-reply background  */

  --shadow-1:  0 1px 2px rgba(16, 24, 40, .06);
  --shadow-2:  0 4px 14px rgba(16, 24, 40, .10);
  --shadow-3:  0 20px 52px rgba(16, 24, 40, .20);

  /* ---- SIZES ------------------------------------------------------------ */
  --radius-lg: 16px;
  --bubble-r:  17px;
  --sidebar-w: 336px;
  --header-h:  62px;
  --read-col:  900px;   /* max width of the message column on wide screens */

  --approval-tick-size: 20px;   /* the ✅✅✅ approval stamp */

  --ease: cubic-bezier(.22, .61, .36, 1);

  /* Tells the browser to draw native controls and scrollbars to match. */
  color-scheme: light;

  /* Derived — do not edit; kept so old names keep working. */
  --accent:       var(--brand);
  --accent-hover: var(--brand-hover);
  --accent-soft:  var(--brand-tint);
  --accent-text:  var(--brand-on);
}

/* ---------------------------------------------------------------------------
   DARK THEME

   Only the values that actually differ. app.js always resolves the theme and
   stamps data-theme="light" or "dark" on <html> — including when the setting
   is "match my system" — so this one block is the single dark definition.
   There is no duplicated media-query copy to keep in step.
   --------------------------------------------------------------------------- */
:root[data-theme="dark"] {
  --brand:       #4d87f7;
  --brand-hover: #5f94f9;
  --brand-tint:  #17243c;
  --brand-on:    #ffffff;

  --ok:          #4fce87;
  --ok-soft:     #12301f;
  --ok-solid:    #15803d;

  --warn:        #e0ab5c;
  --warn-soft:   #322612;
  --warn-solid:  #d97706;

  --danger:      #f2796d;
  --danger-soft: #341a17;
  --danger-solid:#b91c1c;

  --bg:            #0c0f14;
  --surface:       #151a21;
  --surface-2:     #1a2029;
  --surface-3:     #222933;
  --border:        #252c37;
  --border-strong: #3a434f;

  --text:          #e9ecf1;
  --text-2:        #98a2af;
  --text-3:        #6b7583;

  --bubble-in:     #1d242e;
  --bubble-out:    #2b5bb8;

  --overlay:       rgba(0, 0, 0, .62);
  --quote-wash:    rgba(255, 255, 255, .07);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .32);
  --shadow-2: 0 4px 14px rgba(0, 0, 0, .44);
  --shadow-3: 0 20px 52px rgba(0, 0, 0, .6);

  color-scheme: dark;
}

/* ---------- Reset -------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  -webkit-text-size-adjust: 100%;   /* no size jump when a phone rotates */
}

body {
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}

button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
h1, h2, h3, p { margin: 0; }

/* The HTML `hidden` attribute only works through the UA stylesheet's
   `display: none`, so ANY author rule setting `display` on the same element
   beats it. Almost everything this app shows and hides is a flex or grid
   container, so without this line the boot spinner, the modals and the reply
   preview would all be permanently visible. */
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 5px;
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--accent-soft); color: var(--text); }

/* Slim scrollbars — the default Windows ones are heavy next to this UI. */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 99px;
  border: 2.5px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-3); background-clip: content-box; }

/* ---------- Buttons ------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 16px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-size: 14px; font-weight: 550;
  transition: background .14s var(--ease), border-color .14s var(--ease), opacity .14s var(--ease), transform .1s var(--ease);
  white-space: nowrap;
}
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn:not(:disabled):active { transform: scale(.975); }

.btn-primary { background: var(--accent); color: var(--accent-text); }
.btn-primary:not(:disabled):hover { background: var(--accent-hover); }

.btn-quiet { background: var(--surface-3); color: var(--text-2); border-color: var(--border); }
.btn-quiet:not(:disabled):hover { background: var(--border); color: var(--text); }

.btn-danger { background: var(--danger-soft); color: var(--danger); }
.btn-danger:not(:disabled):hover { background: var(--danger-solid); color: var(--brand-on); }

.btn-block { width: 100%; }
.btn-sm { padding: 6px 12px; font-size: 13px; }

.icon-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border-radius: 9px;
  color: var(--text-2);
  transition: background .14s var(--ease), color .14s var(--ease);
  flex-shrink: 0;
}
.icon-btn:hover { background: var(--surface-3); color: var(--text); }
.icon-btn:active { background: var(--border); }
.icon-btn-sm { width: 28px; height: 28px; }

.text-btn {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 9px 10px;
  border-radius: var(--radius);
  font-size: 13.5px; color: var(--text-2);
  transition: background .14s var(--ease), color .14s var(--ease);
}
.text-btn:hover { background: var(--surface-3); color: var(--text); }

.link-btn { color: var(--accent); font-weight: 550; }
.link-btn:hover { text-decoration: underline; }

.mini-btn {
  padding: 4px 10px;
  border-radius: 7px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  font-size: 12px; font-weight: 550; color: var(--text-2);
  transition: background .14s var(--ease), color .14s var(--ease);
}
.mini-btn:hover { background: var(--border); color: var(--text); }
.mini-btn.is-approve { background: var(--ok-soft); color: var(--ok); border-color: transparent; }
.mini-btn.is-reject  { background: var(--danger-soft); color: var(--danger); border-color: transparent; }

.pill-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 15px;
  border-radius: 999px;
  background: var(--accent); color: var(--accent-text);
  font-size: 13px; font-weight: 550;
  box-shadow: var(--shadow-2);
  transition: transform .12s var(--ease);
}
.pill-btn:hover { transform: translateY(-1px); }

/* ---------- Forms -------------------------------------------------------- */
.field { display: block; margin-bottom: 15px; }
.field-label {
  display: block; margin-bottom: 6px;
  font-size: 13px; font-weight: 550; color: var(--text-2);
}
.field-hint { display: block; margin-top: 5px; font-size: 12px; color: var(--text-3); line-height: 1.45; }

.field input, .field select, .field textarea, .input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  /* 16px minimum: below this, iOS Safari zooms on focus and will not zoom out. */
  font-size: 16px;
  transition: border-color .14s var(--ease), box-shadow .14s var(--ease);
}
.field input:focus, .field select:focus, .field textarea:focus, .input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.form-error {
  margin-bottom: 13px;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: var(--danger-soft);
  color: var(--danger);
  font-size: 13.5px;
}

/* ===========================================================================
   Auth screen
   =========================================================================== */
.auth-body {
  display: flex; align-items: center; justify-content: center;
  min-height: 100dvh;
  padding: 24px 20px calc(24px + env(safe-area-inset-bottom));
}

.auth-card {
  width: 100%; max-width: 400px;
  padding: 32px 28px 26px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
}

.auth-head { text-align: center; margin-bottom: 26px; }
.auth-logo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 50px; height: 50px; margin-bottom: 14px;
  border-radius: 14px;
  background: var(--brand); color: var(--brand-on);
  box-shadow: var(--shadow-2);
}
.auth-head h1 { font-size: 23px; font-weight: 650; letter-spacing: -.015em; }
.auth-sub { margin-top: 5px; font-size: 14px; color: var(--text-2); }
.auth-switch { margin-top: 18px; text-align: center; font-size: 13.5px; color: var(--text-2); }

/* ===========================================================================
   App shell
   =========================================================================== */
.boot {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg);
  z-index: 60;
}
.spinner {
  width: 26px; height: 26px;
  border: 2.5px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  /* An implicit grid row is auto-sized, so a tall thread would stretch the row
     past the container and push the composer off the bottom of the screen.
     minmax(0, 1fr) pins the row to the viewport and lets the thread scroll. */
  grid-template-rows: minmax(0, 1fr);
  /* dvh, not vh: mobile browser chrome collapses as you scroll, and vh would
     leave the composer stranded under the address bar. */
  height: 100dvh;
  overflow: hidden;
  background: var(--bg);
}

/* ---------- Sidebar ------------------------------------------------------ */
.sidebar {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
}

.sidebar-head {
  display: flex; align-items: center; gap: 10px;
  height: var(--header-h);
  padding: 0 10px 0 14px;
  padding-top: env(safe-area-inset-top);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.sidebar-me { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; }
.sidebar-me strong {
  font-size: 14.5px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sidebar-actions { display: flex; gap: 2px; }
.avatar-btn { border-radius: 50%; flex-shrink: 0; transition: transform .12s var(--ease); }
.avatar-btn:hover { transform: scale(1.06); }

.role-tag {
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--accent-soft); color: var(--accent);
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; white-space: nowrap;
}
.role-tag.role-admin { background: var(--warn-soft); color: var(--warn); }

.sidebar-search { position: relative; padding: 11px 12px; flex-shrink: 0; }
.search-icon {
  position: absolute; left: 24px; top: 50%; transform: translateY(-50%);
  color: var(--text-3); pointer-events: none;
}
.sidebar-search input {
  width: 100%;
  padding: 9px 12px 9px 34px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--surface-3);
  font-size: 16px;
  -webkit-appearance: none;
  transition: background .14s var(--ease), border-color .14s var(--ease);
}
.sidebar-search input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface);
}

.conversation-list {
  flex: 1;
  overflow-y: auto;
  padding: 0 8px 8px;
  -webkit-overflow-scrolling: touch;
}

.conv {
  display: flex; align-items: center; gap: 11px;
  width: 100%;
  padding: 9px 10px;
  border-radius: 12px;
  text-align: left;
  transition: background .12s var(--ease);
}
.conv:hover { background: var(--surface-3); }
.conv.is-active { background: var(--accent-soft); }
.conv.is-active .conv-name { color: var(--accent); }

.conv-text { flex: 1; min-width: 0; }
.conv-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
/* display:block matters: these are spans, and overflow/text-overflow are
   ignored on inline boxes, so without it long names and previews run past the
   sidebar edge instead of ellipsising. */
.conv-name {
  display: block;
  font-size: 14.5px; font-weight: 570;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.conv-time { font-size: 11.5px; color: var(--text-3); flex-shrink: 0; }
.conv-preview {
  display: block;
  margin-top: 1px;
  font-size: 13px; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.conv.is-unread .conv-name { font-weight: 680; }
.conv.is-unread .conv-preview { color: var(--text); font-weight: 500; }

.conv-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }

.badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 19px; height: 19px; padding: 0 6px;
  border-radius: 999px;
  background: var(--accent); color: var(--accent-text);
  font-size: 11px; font-weight: 650; line-height: 1;
}
.badge-warn { background: var(--warn-solid); color: var(--brand-on); }

.icon-btn .badge {
  position: absolute; top: -1px; right: -1px;
  min-width: 17px; height: 17px; font-size: 10px;
  border: 2px solid var(--surface);
}

.sidebar-foot {
  padding: 8px;
  padding-bottom: calc(8px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

/* ---------- Avatars ------------------------------------------------------ */
.avatar {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: hsl(var(--hue, 210) 55% 50%);
  color: var(--brand-on);
  font-size: 14px; font-weight: 640;
  flex-shrink: 0;
  user-select: none;
}
.avatar.is-group { border-radius: 13px; }
.avatar-sm { width: 30px; height: 30px; font-size: 11.5px; }

.avatar.is-online::after {
  content: "";
  position: absolute; right: -1px; bottom: -1px;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--ok);
  border: 2.5px solid var(--surface);
}

/* Unread count sits on the sender's picture — the face is what you scan the
   list for, so the number belongs on it. It clears only once the messages
   have actually been scrolled into view, not merely by opening the chat. */
.avatar-count {
  position: absolute; top: -5px; right: -6px;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: 999px;
  background: var(--accent); color: var(--accent-text);
  border: 2px solid var(--surface);
  font-size: 11px; font-weight: 700; line-height: 1;
  letter-spacing: -.02em;
}

/* ---------- Chat pane ---------------------------------------------------- */
.chat {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
  background: var(--bg);
}
.chat-inner { display: flex; flex-direction: column; height: 100%; min-height: 0; }

.empty-state {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px;
  padding: 30px;
  text-align: center;
}
.empty-icon {
  display: flex; align-items: center; justify-content: center;
  width: 62px; height: 62px; margin-bottom: 6px;
  border-radius: 50%;
  background: var(--surface); color: var(--accent);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-1);
}
.empty-state h2 { font-size: 16.5px; font-weight: 620; color: var(--text); }
.empty-state p { font-size: 14px; max-width: 32ch; color: var(--text-2); }
.empty-state .btn { margin-top: 8px; }

.chat-head {
  display: flex; align-items: center; gap: 11px;
  min-height: var(--header-h);
  padding: 0 8px 0 14px;
  padding-top: env(safe-area-inset-top);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.chat-head-text { flex: 1; min-width: 0; }
.chat-head-text h2 {
  font-size: 15.5px; font-weight: 620;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-head-sub {
  display: block;
  font-size: 12.5px; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-head-actions { display: flex; gap: 2px; }
.back-btn { display: none; margin-left: -6px; }

/* ---------- Messages ----------------------------------------------------- */
.messages {
  flex: 1;
  /* Without min-height:0 a flex item refuses to shrink below its content, so
     the thread would push the composer off screen instead of scrolling. */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 18px 18px 10px;
  scrollbar-gutter: stable;
}

/* Cap the reading column. Full-width lines on a 27" monitor are miserable to
   read and make the thread feel like a spreadsheet. */
#messageList, .load-more-wrap { max-width: var(--read-col); margin-inline: auto; }

.load-more-wrap { display: flex; justify-content: center; padding-bottom: 16px; }

.day-divider {
  display: flex; align-items: center; justify-content: center;
  margin: 20px 0 16px;
}
.day-divider span {
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-2);
  font-size: 11.5px; font-weight: 600;
  box-shadow: var(--shadow-1);
}

.msg { display: flex; gap: 9px; margin-bottom: 2px; }
.msg.is-group-start { margin-top: 15px; }
.msg.is-mine { flex-direction: row-reverse; }

.msg-avatar-slot { width: 30px; flex-shrink: 0; }
.msg.is-mine .msg-avatar-slot { display: none; }

.msg-main { max-width: min(560px, 74%); min-width: 0; }
.msg.is-mine .msg-main { display: flex; flex-direction: column; align-items: flex-end; }

.msg-sender {
  margin: 0 0 4px 3px;
  font-size: 12.5px; font-weight: 620; color: var(--text-2);
  display: flex; align-items: center; gap: 6px;
}

.bubble-wrap { position: relative; }

.bubble {
  padding: 8px 13px;
  border-radius: var(--bubble-r);
  background: var(--bubble-in);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-1);
  /* These three stop a pasted URL or a 200-character word blowing out the
     layout on a narrow phone. */
  word-break: break-word;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.msg.is-group-start .bubble { border-top-left-radius: 6px; }
.msg.is-mine .bubble {
  background: var(--bubble-out);
  border-color: transparent;
  color: var(--brand-on);
}
.msg.is-mine.is-group-start .bubble {
  border-top-left-radius: var(--bubble-r);
  border-top-right-radius: 6px;
}

.bubble-body { font-size: 14.5px; }
.bubble a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* Waiting for an admin sign-off. The message is fully visible to everyone —
   this only marks that someone asked for it to be checked. */
.msg.is-awaiting .bubble { border-style: dashed; border-color: var(--warn); }
/* Signed off. A quiet green edge, with the tick marks carried in the footer. */
.msg.is-approved .bubble { border-color: var(--ok); }
.msg.is-sending .bubble { opacity: .6; }
.msg.is-failed .bubble { border-color: var(--danger); }

.msg.is-highlight .bubble { animation: flash 1.7s var(--ease); }
@keyframes flash {
  0%, 28% { box-shadow: 0 0 0 3px var(--accent); }
  100%    { box-shadow: var(--shadow-1); }
}

.reply-quote {
  display: block;
  margin: 1px 0 7px;
  padding: 5px 10px;
  border-left: 3px solid currentColor;
  border-radius: 6px;
  background: var(--quote-wash);
  font-size: 12.5px;
  opacity: .85;
  white-space: normal;
  cursor: pointer;
  transition: opacity .12s var(--ease);
}
.reply-quote:hover { opacity: 1; }
.reply-quote b { display: block; font-size: 11.5px; margin-bottom: 1px; }
.reply-quote span {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

.msg-foot {
  display: flex; align-items: center; gap: 6px;
  margin-top: 3px; padding: 0 4px;
  font-size: 11px; color: var(--text-3);
}
.msg.is-mine .msg-foot { justify-content: flex-end; }

.msg-status { display: inline-flex; align-items: center; }
.msg-status.is-read { color: var(--accent); }

/* Admin sign-off. Only the handful of messages that were put up for approval
   ever carry a marker, which is what makes the marker worth looking at. */
.approval-stamp {
  display: inline-flex; align-items: center;
  vertical-align: middle;
}
.approval-ticks {
  font-size: var(--approval-tick-size);
  line-height: 1;
  /* Emoji carry their own colour font, so they need no colour of their own —
     just a little breathing room from the timestamp beside them. */
  letter-spacing: 1px;
}

.approval-tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10.5px; font-weight: 650;
}
.approval-tag.is-awaiting { background: var(--warn-soft); color: var(--warn); }

/* The "edited" marker is a button — every previous version is kept. */
.link-quiet {
  color: inherit; font-size: inherit;
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-style: dotted;
  opacity: .85;
}
.link-quiet:hover { opacity: 1; color: var(--accent); }

/* ---------- Message actions: hover toolbar ------------------------------- */
.msg-tools {
  position: absolute;
  top: -14px; right: 6px;
  display: flex; gap: 1px;
  padding: 3px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  opacity: 0;
  transform: translateY(3px);
  pointer-events: none;
  transition: opacity .13s var(--ease), transform .13s var(--ease);
  z-index: 3;
}
.msg.is-mine .msg-tools { right: auto; left: 6px; }

.msg:hover .msg-tools,
.msg:focus-within .msg-tools {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Touch devices get the long-press sheet instead — a hover toolbar can never
   be reached, and permanent buttons under every message are clutter. */
@media (hover: none) {
  .msg-tools { display: none; }
}

.tool-btn {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  border-radius: 7px;
  color: var(--text-2);
  transition: background .12s var(--ease), color .12s var(--ease);
}
.tool-btn:hover { background: var(--surface-3); color: var(--text); }
.tool-btn.is-approve:hover { background: var(--ok-soft); color: var(--ok); }
.tool-btn.is-reject:hover  { background: var(--danger-soft); color: var(--danger); }

/* ---------- Loading skeleton --------------------------------------------- */
.skel-msg { display: flex; gap: 9px; margin-bottom: 14px; align-items: flex-end; }
.skel-msg.is-mine { flex-direction: row-reverse; }

.skel {
  background: linear-gradient(90deg, var(--surface-3) 25%, var(--surface-2) 50%, var(--surface-3) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s linear infinite;
  border-radius: var(--bubble-r);
}
.skel-avatar { width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; }
.skel-bubble { height: 38px; max-width: 76%; }

/* Conversation list placeholders, shown until the first sync lands. Claiming
   "no conversations yet" at someone who has plenty is worse than a wait. */
.conv-skeleton { display: flex; align-items: center; gap: 11px; padding: 11px 10px; }
.conv-skeleton .skel-avatar { width: 40px; height: 40px; }
.conv-skeleton-text { flex: 1; display: flex; flex-direction: column; gap: 7px; }
.skel-line { height: 10px; border-radius: 5px; width: 70%; }
.skel-line.is-short { width: 45%; }

@keyframes shimmer { to { background-position: -200% 0; } }

/* ---------- Reactions ----------------------------------------------------- */
.reactions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.msg.is-mine .reactions { justify-content: flex-end; }

.reaction {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: 12px; line-height: 1.6;
  transition: border-color .12s var(--ease), background .12s var(--ease);
}
.reaction:hover { border-color: var(--border-strong); }
.reaction.is-mine { border-color: var(--brand); background: var(--brand-tint); }
.reaction-emoji { font-size: 13px; }
.reaction-count { font-weight: 600; color: var(--text-2); }
.reaction.is-mine .reaction-count { color: var(--brand); }

.emoji-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}
.emoji-grid.is-wide { grid-template-columns: repeat(8, 1fr); }
.emoji-choice {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1;
  border-radius: 10px;
  font-size: 22px;
  transition: background .12s var(--ease), transform .1s var(--ease);
}
.emoji-choice:hover { background: var(--surface-3); transform: scale(1.12); }

/* ---------- Pinned bar ---------------------------------------------------- */
.pinned-bar {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 16px;
  background: var(--warn-soft);
  color: var(--warn);
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  flex-shrink: 0;
}
.pinned-icon { display: flex; flex-shrink: 0; }
.pinned-text {
  flex: 1; min-width: 0;
  text-align: left; color: inherit;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pinned-text:hover { text-decoration: underline; }
.pinned-count { flex-shrink: 0; opacity: .75; font-size: 11.5px; }
.pinned-jump { text-align: left; }

.msg.is-pinned .bubble { box-shadow: inset 3px 0 0 var(--warn), var(--shadow-1); }
.pin-mark { display: inline-flex; align-items: center; color: var(--warn); }
.mute-mark { display: inline-flex; align-items: center; color: var(--text-3); }

/* ---------- "New messages" divider ---------------------------------------- */
.unread-divider {
  display: flex; align-items: center; gap: 12px;
  margin: 18px 0 14px;
  color: var(--brand);
  font-size: 11.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
}
.unread-divider::before, .unread-divider::after {
  content: ""; flex: 1; height: 1px; background: currentColor; opacity: .45;
}

/* ---------- Typing indicator ---------------------------------------------- */
.typing-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 18px 8px;
  color: var(--text-2);
  font-size: 12.5px;
  flex-shrink: 0;
}
.typing-dots { display: inline-flex; gap: 3px; }
.typing-dots i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  opacity: .4;
  animation: typing-bounce 1.2s infinite;
}
.typing-dots i:nth-child(2) { animation-delay: .15s; }
.typing-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes typing-bounce {
  0%, 60%, 100% { opacity: .35; transform: translateY(0); }
  30%           { opacity: 1;   transform: translateY(-3px); }
}

.scroll-pin {
  position: relative; height: 0;
  display: flex; justify-content: center;
  z-index: 5;
}
.scroll-pin > button { position: absolute; bottom: 12px; }

/* ---------- Composer ----------------------------------------------------- */
.composer {
  position: relative;   /* anchors the @mention picker */
  padding: 10px 14px;
  padding-bottom: calc(10px + env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

.composer-note {
  margin-bottom: 8px;
  padding: 8px 12px;
  border-radius: var(--radius);
  background: var(--warn-soft); color: var(--warn);
  font-size: 12.5px;
}

.reply-preview {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px;
  padding: 8px 10px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-3);
}
.reply-preview-text { flex: 1; min-width: 0; font-size: 12.5px; }
.reply-preview-label { display: block; color: var(--accent); font-weight: 550; }
.reply-preview-body {
  display: block; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---------- Attachments --------------------------------------------------- */
.attach-tray {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-bottom: 9px;
}
.attach-chip {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  max-width: 260px;
  padding: 6px 6px 6px 11px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 12.5px;
  overflow: hidden;
}
.attach-chip.is-failed { border-color: var(--danger); color: var(--danger); }
.attach-name {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 150px;
}
.attach-meta { color: var(--text-3); flex-shrink: 0; }
.attach-progress {
  position: absolute; left: 0; bottom: 0;
  height: 2px; width: 100%;
  background: var(--border);
}
.attach-progress-fill { display: block; height: 100%; background: var(--brand); transition: width .15s linear; }

/* In a message bubble */
.attachments { display: flex; flex-direction: column; gap: 7px; margin-top: 7px; }
.bubble-body + .attachments { margin-top: 9px; }

.attach-image-wrap { position: relative; display: inline-block; line-height: 0; }
.attach-image-link { display: block; line-height: 0; }

/* Attachments are kept for a short window, so the countdown is real
   information — it tells you whether to save the file now. */
.attach-expiry {
  position: absolute; right: 7px; bottom: 7px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  font-size: 10.5px; font-weight: 550; line-height: 1.5;
  backdrop-filter: blur(3px);
}

/* The bytes are gone; the record is not. */
.attach-file.is-expired {
  opacity: .62;
  cursor: default;
  border: 1px dashed var(--border-strong);
  background: transparent;
}
.attach-file.is-expired:hover { opacity: .62; }
.attach-file.is-expired .attach-file-name { text-decoration: line-through; }
.attach-image {
  max-width: 100%; height: auto;
  max-height: 340px;
  border-radius: 11px;
  border: 1px solid var(--border);
  object-fit: cover;
}
.msg.is-mine .attach-image { border-color: transparent; }

.attach-file {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  border-radius: 11px;
  background: var(--quote-wash);
  color: inherit;
  text-decoration: none;
  transition: opacity .12s var(--ease);
}
.attach-file:hover { opacity: .8; }
.attach-file-icon { display: flex; flex-shrink: 0; opacity: .75; }
.attach-file-text { min-width: 0; }
.attach-file-name {
  display: block; font-size: 13.5px; font-weight: 550;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.attach-file-size { display: block; font-size: 11.5px; opacity: .7; }

/* Whole-pane drop target */
.chat.is-dropping { outline: 2px dashed var(--brand); outline-offset: -10px; }

/* ---------- @mentions ----------------------------------------------------- */
.mention {
  padding: 1px 4px;
  margin: 0 -1px;
  border-radius: 5px;
  background: var(--brand-tint);
  color: var(--brand);
  font-weight: 570;
}
/* Being named yourself should stand out from the rest of the thread. */
.mention.is-me { background: var(--warn-soft); color: var(--warn); }
.msg.is-mine .mention {
  background: rgba(255, 255, 255, .22);
  color: inherit;
}

.mention-picker {
  position: absolute;
  bottom: calc(100% + 6px); left: 12px; right: 12px;
  max-width: 320px;
  max-height: 260px;
  overflow-y: auto;
  padding: 5px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-3);
  z-index: 12;
}
.mention-option {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 7px 9px;
  border-radius: 9px;
  text-align: left;
}
.mention-option.is-active,
.mention-option:hover { background: var(--surface-3); }

.composer-row { display: flex; align-items: flex-end; gap: 9px; }

/* "Ask an admin to sign this one off" — off by default, because the vast
   majority of messages are ordinary ones. */
.composer-btn {
  display: flex; align-items: center; justify-content: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  color: var(--text-3);
  flex-shrink: 0;
  transition: background .14s var(--ease), color .14s var(--ease);
}
.composer-btn:hover { background: var(--surface-3); color: var(--text-2); }
.composer-btn.is-on { background: var(--warn-soft); color: var(--warn); }

.composer-row textarea {
  flex: 1;
  max-height: 148px;
  padding: 10px 15px;
  border: 1px solid var(--border-strong);
  border-radius: 21px;
  background: var(--surface-2);
  color: var(--text);
  font-size: 16px;   /* keeps iOS from zooming on focus */
  line-height: 1.45;
  resize: none;
  overflow-y: auto;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.composer-row textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--surface);
}

.send-btn {
  display: flex; align-items: center; justify-content: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  background: var(--accent); color: var(--accent-text);
  flex-shrink: 0;
  transition: background .14s var(--ease), opacity .14s var(--ease), transform .12s var(--ease);
}
.send-btn:disabled { opacity: .35; cursor: not-allowed; }
.send-btn:not(:disabled):hover { background: var(--accent-hover); }
.send-btn:not(:disabled):active { transform: scale(.92); }

/* ===========================================================================
   Modal
   =========================================================================== */
.modal-host {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  z-index: 50;
}
.modal-backdrop {
  position: absolute; inset: 0;
  background: var(--overlay);
  animation: fade-in .15s var(--ease);
}
@keyframes fade-in { from { opacity: 0; } }

.modal {
  position: relative;
  display: flex; flex-direction: column;
  width: 100%; max-width: 490px;
  max-height: min(86dvh, 720px);
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  animation: modal-in .18s var(--ease);
}
@keyframes modal-in { from { opacity: 0; transform: translateY(10px) scale(.99); } }

.modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 12px 16px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.modal-head h3 { font-size: 16px; font-weight: 630; }
.modal-body { padding: 18px 20px; overflow-y: auto; flex: 1; }
.modal-foot {
  display: flex; gap: 9px; justify-content: flex-end;
  padding: 14px 20px;
  padding-bottom: calc(14px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

/* ---------- Lists inside modals ------------------------------------------ */
.row-list { display: flex; flex-direction: column; gap: 2px; }

.row {
  display: flex; align-items: center; gap: 11px;
  width: 100%;
  padding: 8px 9px;
  border-radius: var(--radius);
  text-align: left;
  transition: background .12s var(--ease);
}
button.row:hover { background: var(--surface-3); }

.row-text { flex: 1; min-width: 0; }
.row-title {
  display: block;
  font-size: 14px; font-weight: 550;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row-sub {
  display: block;
  font-size: 12.5px; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row-actions { display: flex; align-items: center; gap: 5px; flex-shrink: 0; }

.section-label {
  margin: 20px 0 8px;
  font-size: 11.5px; font-weight: 650; color: var(--text-3);
  text-transform: uppercase; letter-spacing: .05em;
}
.section-label:first-child { margin-top: 0; }

.muted { color: var(--text-2); font-size: 13.5px; line-height: 1.55; }
.empty-note { padding: 26px 0; text-align: center; color: var(--text-3); font-size: 13.5px; }

.check-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 9px;
  border-radius: var(--radius);
  cursor: pointer;
}
.check-row:hover { background: var(--surface-3); }
.check-row input { width: 17px; height: 17px; accent-color: var(--accent); flex-shrink: 0; }

/* ---------- Radio option cards (appearance picker) ------------------------ */
.mode-option {
  display: flex; gap: 11px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 8px;
  cursor: pointer;
  transition: border-color .13s var(--ease), background .13s var(--ease);
}
.mode-option:hover { border-color: var(--border-strong); }
.mode-option input { margin-top: 3px; accent-color: var(--accent); flex-shrink: 0; }
.mode-option.is-selected { border-color: var(--accent); background: var(--accent-soft); }
.mode-option strong { display: block; font-size: 14px; font-weight: 580; margin-bottom: 2px; }
.mode-option small { color: var(--text-2); font-size: 12.5px; line-height: 1.45; }

/* ---------- Approval queue ------------------------------------------------ */
.queue-list { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }

.queue-item {
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.queue-head { display: flex; align-items: center; gap: 10px; margin-bottom: 9px; }
.queue-body {
  padding: 9px 12px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 14px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 160px;
  overflow-y: auto;
}
.queue-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }

/* ---------- Audit log ----------------------------------------------------- */
.audit-list { display: flex; flex-direction: column; }
.audit-row {
  display: flex; gap: 12px; align-items: baseline;
  padding: 9px 2px;
  border-bottom: 1px solid var(--border);
  font-size: 13.5px;
}
.audit-row:last-child { border-bottom: 0; }
.audit-when {
  flex-shrink: 0; width: 116px;
  color: var(--text-3); font-size: 12px;
}
.audit-what { min-width: 0; }
.audit-what small {
  display: block; margin-top: 2px;
  color: var(--text-3); font-size: 12px;
  overflow-wrap: anywhere;
}

.row-split { display: flex; gap: 12px; }
.row-split > * { flex: 1; }

/* ---------- Edit history -------------------------------------------------- */
.history-version {
  padding: 10px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 14px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.history-version.is-current { border-color: var(--accent); background: var(--accent-soft); }

/* ---------- Search results ----------------------------------------------- */
.search-result {
  display: block; width: 100%;
  padding: 11px;
  border-radius: var(--radius);
  text-align: left;
  border-bottom: 1px solid var(--border);
  transition: background .12s var(--ease);
}
.search-result:hover { background: var(--surface-3); }
.search-result:last-child { border-bottom: 0; }
.search-result-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 9px;
  margin-bottom: 3px;
}
.search-result-where { font-size: 12px; font-weight: 620; color: var(--accent); }
.search-result-when { font-size: 11.5px; color: var(--text-3); flex-shrink: 0; }
.search-result-body {
  margin-top: 3px;
  font-size: 13.5px; color: var(--text-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
.search-result-body mark {
  background: var(--warn-soft); color: var(--warn);
  border-radius: 3px; padding: 0 2px;
}

/* ===========================================================================
   Bottom sheet — the touch action menu
   =========================================================================== */
.sheet-host {
  position: fixed; inset: 0;
  display: flex; align-items: flex-end; justify-content: center;
  z-index: 65;
}
.sheet-backdrop {
  position: absolute; inset: 0;
  background: var(--overlay);
  animation: fade-in .16s var(--ease);
}
.sheet {
  position: relative;
  width: 100%; max-width: 480px;
  max-height: 80dvh;
  overflow-y: auto;
  padding: 8px 10px calc(12px + env(safe-area-inset-bottom));
  background: var(--surface);
  border-radius: 20px 20px 0 0;
  box-shadow: var(--shadow-3);
  animation: sheet-up .22s var(--ease);
}
@keyframes sheet-up { from { transform: translateY(100%); } }

.sheet-host.is-closing .sheet { animation: sheet-down .17s var(--ease) forwards; }
.sheet-host.is-closing .sheet-backdrop { animation: fade-out .17s var(--ease) forwards; }
@keyframes sheet-down { to { transform: translateY(100%); } }
@keyframes fade-out { to { opacity: 0; } }

.sheet-grip {
  display: block;
  width: 38px; height: 4px; margin: 2px auto 10px;
  border-radius: 99px;
  background: var(--border-strong);
}
.sheet-title {
  padding: 0 12px 10px;
  font-size: 12.5px; color: var(--text-3);
  text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.sheet-item {
  display: flex; align-items: center; gap: 14px;
  width: 100%;
  padding: 14px 14px;
  border-radius: 12px;
  font-size: 15.5px; font-weight: 500;
  color: var(--text);
  text-align: left;
}
.sheet-item:active { background: var(--surface-3); }
.sheet-item.is-danger { color: var(--danger); }
.sheet-item.is-cancel {
  justify-content: center;
  margin-top: 8px;
  background: var(--surface-3);
  color: var(--text-2);
  font-weight: 550;
}
.sheet-icon { display: flex; align-items: center; color: var(--text-2); }
.sheet-item.is-danger .sheet-icon { color: var(--danger); }

/* Desktop only ever sees this via keyboard — centre it like a normal dialog. */
@media (min-width: 781px) and (hover: hover) {
  .sheet-host { align-items: center; }
  .sheet { border-radius: var(--radius-lg); max-width: 340px; animation: modal-in .18s var(--ease); }
  .sheet-grip { display: none; }
  .sheet-item { padding: 11px 13px; font-size: 14.5px; }
}

/* ===========================================================================
   Toasts and connection bar
   =========================================================================== */
.toast-host {
  position: fixed;
  left: 50%; transform: translateX(-50%);
  bottom: calc(18px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  z-index: 70;
  pointer-events: none;
  width: min(420px, calc(100vw - 32px));
}
.toast {
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--text);
  color: var(--bg);
  font-size: 13.5px; font-weight: 500;
  box-shadow: var(--shadow-2);
  animation: toast-in .2s var(--ease);
}
.toast.is-error { background: var(--danger-solid); color: var(--brand-on); }
.toast.is-ok    { background: var(--ok-solid); color: var(--brand-on); }
@keyframes toast-in { from { opacity: 0; transform: translateY(12px); } }

/* Appears only when a request is genuinely slow — see UI.Progress, which waits
   300ms before showing anything so healthy requests never flash a bar. */
.progress-bar {
  position: fixed; top: 0; left: 0;
  height: 2.5px; width: 100%;
  z-index: 90;
  background: var(--accent);
  transform-origin: 0 50%;
  animation: progress-grow 12s cubic-bezier(.1, .8, .3, 1) forwards;
}
.progress-bar.is-done {
  animation: none;
  transform: scaleX(1);
  transition: transform .18s ease, opacity .22s ease .06s;
  opacity: 0;
}
@keyframes progress-grow {
  0%   { transform: scaleX(.02); }
  40%  { transform: scaleX(.55); }
  80%  { transform: scaleX(.82); }
  100% { transform: scaleX(.94); }
}

.offline-bar {
  position: fixed; top: 0; left: 0; right: 0;
  padding: 6px;
  padding-top: calc(6px + env(safe-area-inset-top));
  background: var(--warn-solid); color: var(--brand-on);
  font-size: 12.5px; font-weight: 550; text-align: center;
  z-index: 80;
}

/* ===========================================================================
   Responsive — single pane below 780px
   =========================================================================== */
@media (max-width: 780px) {
  .app { grid-template-columns: 1fr; }

  .sidebar, .chat { grid-column: 1; grid-row: 1; min-height: 0; }

  /* One pane at a time, chosen by body[data-view]. Both stay mounted so
     returning to the list keeps its scroll position. */
  body[data-view="list"] .chat    { display: none; }
  body[data-view="chat"] .sidebar { display: none; }

  .back-btn { display: inline-flex; }

  .msg-main { max-width: 82%; }
  .messages { padding: 14px 12px 8px; }

  /* Modals become bottom sheets on phones — reaching a centred dialog's close
     button one-handed is awkward. */
  .modal-host { padding: 0; align-items: flex-end; }
  .modal {
    max-width: none;
    max-height: 92dvh;
    border-radius: 20px 20px 0 0;
    animation: sheet-up .22s var(--ease);
  }
  .modal-foot { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }

  .toast-host { bottom: calc(80px + env(safe-area-inset-bottom)); }
}

@media (max-width: 420px) {
  .msg-main { max-width: 88%; }
  .auth-card { padding: 28px 20px 22px; border: 0; box-shadow: none; background: transparent; }
  .auth-body { background: var(--surface); }
}

/* ---------- Accessibility ------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

@media (prefers-contrast: more) {
  :root { --border: currentColor; --border-strong: currentColor; }
  :root { --text-2: var(--text); }
}

/* 44px is the accessible minimum for touch targets. */
@media (pointer: coarse) {
  .icon-btn { width: 42px; height: 42px; }
  .mini-btn { padding: 7px 13px; font-size: 13px; }
}
