.kp-select{display:inline-flex;min-width:0;max-width:100%;vertical-align:middle}.kp-select .kp-select-trigger{display:flex;align-items:center;justify-content:space-between;gap:14px;min-width:0;width:100%;padding:9px 12px;border:1px solid var(--line);border-radius:10px;background:var(--bg-0);color:var(--text);font:inherit;text-align:left;cursor:pointer;transition:border-color .16s,background .16s,box-shadow .16s}.kp-select-trigger>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kp-select-trigger>i{font-size:10px;color:var(--dim);transition:transform .18s}.kp-select-trigger[aria-expanded=true]>i{transform:rotate(180deg)}.kp-select-trigger:hover{background:var(--hover)}.kp-select-trigger:focus-visible,.kp-select-trigger[aria-expanded=true]{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 28%,transparent)}.kp-select-trigger:disabled{opacity:.45;cursor:default}.kp-select-menu{position:fixed;z-index:100100;overflow:auto;box-sizing:border-box;padding:6px;background:var(--bg-2);color:var(--text);border:1px solid color-mix(in srgb,var(--accent) 35%,var(--line));border-radius:12px;box-shadow:0 12px 40px #0005,0 2px 6px #0003;font-size:13px;overscroll-behavior:contain;animation:kp-select-enter .14s ease-out}.kp-select-menu.is-closing{opacity:0;transform:translateY(-3px);transition:opacity .12s,transform .12s;pointer-events:none}.kp-select-option{display:flex;align-items:center;gap:12px;justify-content:space-between;padding:10px 11px;min-height:36px;box-sizing:border-box;border-radius:7px;cursor:pointer;transition:background .1s;overflow-wrap:anywhere}.kp-select-option>span{min-width:0}.kp-select-option.is-active{background:var(--hover)}.kp-select-option[aria-selected=true]{color:var(--text);background:color-mix(in srgb,var(--accent) 20%,transparent)}.kp-select-option>i{color:var(--accent);font-size:11px;flex-shrink:0}.kp-select-option[aria-disabled=true]{opacity:.4;cursor:default}.kp-select-group{font-size:10px;letter-spacing:.05em;font-weight:700;color:var(--dim);padding:12px 11px 6px;overflow-wrap:anywhere}.dd-workspace-bar .kp-select{flex:1;max-width:520px}.ds-panel label>.kp-select{width:100%}.dd-head>.kp-select.dd-depot-sel{padding:0;border:0;background:transparent}@keyframes kp-select-enter{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.kp-select-menu{animation:none}.kp-select-menu.is-closing,.kp-select .kp-select-trigger,.kp-select-trigger>i,.kp-select-option{transition:none}}

/* Select popups may be portalled outside their app surface. */
.kp-select-trigger,.kp-select-menu{-webkit-user-select:none;user-select:none}
/* Design tokens. The one scale every stylesheet draws from: spacing, radius,
   type, elevation, stacking and motion, plus the semantic colours that themes
   do not set themselves. Themes (themes.css, custom themes) only provide the
   surface/text/accent palette; whether a theme is light or dark is told by
   data-scheme on <html> (set in theme.ts). Loaded before every other sheet. */
:root {
  /* Spacing */
  --sp-0: 2px; --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px; --sp-7: 48px;
  /* Corner radius */
  --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-full: 999px;
  /* Type: sizes, weights, line heights */
  --fs-xs: 11px; --fs-sm: 12px; --fs-md: 14px; --fs-lg: 16px; --fs-xl: 20px;
  --fw-regular: 400; --fw-semibold: 600; --fw-bold: 700;
  --lh-tight: 1.25; --lh-body: 1.5;
  /* Control sizes: compact controls, standard controls, touch targets */
  --control-sm: 28px; --control-md: 36px; --control-touch: 44px;
  /* Elevation */
  --shadow-color: rgb(0 0 0 / 0.36);
  --shadow-1: 0 1px 3px var(--shadow-color);
  --shadow-2: 0 8px 24px var(--shadow-color);
  --shadow-3: 0 24px 64px var(--shadow-color);
  /* Stacking layers, lowest to highest */
  --z-raised: 1; --z-sticky: 10; --z-drawer-backdrop: 110; --z-drawer: 120;
  --z-popover: 1000; --z-scrim: 4000; --z-menu: 4001; --z-safe-area: 5000; --z-toast: 10000;
  /* Motion */
  --dur-fast: 120ms; --dur-base: 200ms; --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  /* Endless loops (pulses, blinks) breathe evenly instead of rushing and stalling each cycle. */
  --ease-loop: ease-in-out;

  /* Semantic colours, dark schemes */
  color-scheme: dark;
  --danger: #ed4245; --success: #3ba55d; --warning: #f0b232;
  --online: #3ba55d; --idle: #f0b232; --dnd: #ed4245; --offline: #80848e;
  --on-accent: var(--bg-0);
  --on-danger: #fff; /* text on a red fill (mention badges and pills, Live): white in every theme */
  --overlay: rgb(4 6 10 / 0.6);
  /* Controls drawn over photos and banners: the same in every theme. */
  --on-media: #fff; --media-chip: rgb(16 24 32 / 0.7); --media-chip-hover: rgb(16 24 32 / 0.9);
  --scrim-blur: 4px;

  /* Names other stylesheets used before tokens existed. */
  --red: var(--danger); --text-1: var(--text); --text-2: var(--dim); --text-dim: var(--dim);
  --accent-dim: color-mix(in srgb, var(--accent) 22%, transparent); --bg-hover: var(--hover);
}
[data-scheme='light'] {
  color-scheme: light;
  --shadow-color: rgb(16 24 40 / 0.14);
  --danger: #c62f32; --success: #23864a; --warning: #a86b00;
  --online: #23a55a; --idle: #d79a15; --dnd: #d83a3d; --offline: #8a919c;
  --overlay: rgb(20 26 36 / 0.32);
}
@media (prefers-reduced-motion: reduce) {
  :root { --dur-fast: 0ms; --dur-base: 0ms; }
  /* Nothing keeps moving: every animation (spinners, typing dots, flashes, pulses) settles at
     once on its end state, and there are no transitions (0s, not a tiny duration: even a 0.01ms
     transition paints its starting frame, e.g. a menu flashing at its first position). No code
     waits for animation or transition events, so this is safe app-wide. A busy indicator that truly
     needs motion can only opt out with a more specific !important (none does today). */
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; animation-delay: 0s !important; transition-duration: 0s !important; transition-delay: 0s !important; scroll-behavior: auto !important; }
}
/* Shared controls used across Kelp Pup (chat, Emoji Studio, Drydock). */

/* Switch: <button role="switch" class="switch" aria-checked> with an optional label span and a .switch-track. */
.switch { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: var(--control-sm); padding: var(--sp-1) 0 var(--sp-1) var(--sp-1); background: transparent; color: var(--dim); font: inherit; font-size: var(--fs-xs); white-space: nowrap; }
.switch:hover { color: var(--text); }
.switch:focus-visible { outline: 2px solid var(--accent); outline-offset: var(--sp-1); border-radius: var(--radius-sm); }
.switch-track { display: inline-flex; align-items: center; width: 32px; height: 20px; padding: var(--sp-0); border-radius: var(--radius-full); background: var(--bg-0); box-shadow: inset 0 0 0 1px var(--line); transition: background-color var(--dur-fast) var(--ease); }
.switch-track > span { width: 16px; height: 16px; border-radius: 50%; background: var(--dim); transition: transform var(--dur-base) var(--ease), background-color var(--dur-fast) var(--ease); }
.switch[aria-checked='true'] .switch-track { background: var(--accent); }
.switch[aria-checked='true'] .switch-track > span { background: var(--bg-0); transform: translateX(12px); }
:root {
  --teal: #159a8a;
  --green: #5bc88a;
  --blue: #2f80ed;
  /* Primary-action / selected-highlight color. Change THIS ONE value to
     restyle every primary button (Join voice, Create channel, Save, etc.) and
     every blue "selected/active" highlight app-wide. */
  --accent: #5db23b;
  --orange: #f2683c;
  --purple: #9b6dff;
  --yellow: #f0b232;

  --bg-0: #0f1216;
  --bg-1: #161a20;
  --bg-2: #1c2128;
  --bg-3: #232a33;
  --hover: #272e38;
  --active: #2e3742;
  --line: #2a313b;
  --text: #e7ebf0;
  --dim: #98a2b0;
  --faint: #6b7480;

  /* Surface gradients (one set per theme; see themes.css for the variants).
     --sidebar-bg: side columns, dark at top → lighter blue at the bottom.
     --panel-bg:   the bottom-left "me" panel, a subtle golden circular glow.
     --main-bg:    the central chat column, a flat darker surface (no gradient). */
  --sidebar-bg: linear-gradient(180deg, #0f131b 0%, #16203a 60%, #1d2c4e 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(241,185,67,0.17), rgba(241,185,67,0.05) 44%, rgba(0,0,0,0) 72%), #0d1117;
  --main-bg: #0e1116;
  /* Full-screen image viewer backdrop — dark by default; each theme tints it
     to match (medium gray on the light theme; see themes.css). */
  --lb-backdrop: rgba(8, 10, 14, 0.95);

  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body, #root { height: 100%; }
body { font-family: var(--sans); background: var(--bg-0); color: var(--text); font-size: 14px; -webkit-font-smoothing: antialiased; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
input, select { font-family: inherit; }
a { color: var(--blue); cursor: pointer; }
/* Scrollbars follow the theme: thumb derived from the theme's text/background
   mix so it adapts to every preset AND custom themes. */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--text) 20%, var(--bg-0)); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--text) 32%, var(--bg-0)); }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }

.splash { display: grid; place-items: center; height: 100%; color: var(--dim); }

/* ---------------- auth + setup ---------------- */
.auth-wrap { display: grid; place-items: center; height: 100%; background: radial-gradient(circle at 50% 0%, #16242a, var(--bg-0) 60%); padding: 20px; }
.auth-card { width: 360px; background: var(--bg-1); border: 1px solid var(--line); border-radius: 16px; padding: 32px 28px; display: flex; flex-direction: column; }
.auth-card.wide { width: 440px; }
.auth-logo { width: 64px; height: 64px; align-self: center; margin-bottom: 8px; }
.auth-card h1 { text-align: center; font-size: 24px; letter-spacing: -0.02em; }
.auth-sub { text-align: center; color: var(--dim); margin-bottom: 20px; }
.auth-card label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--dim); margin: 12px 0 6px; }
.auth-card input, .settings-form input, .settings-form select {
  background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 11px 13px; color: var(--text); font-size: 14px; outline: none;
}
.auth-card input:focus { border-color: var(--accent); }
.auth-error { margin-top: 12px; color: #ff8a8a; font-size: 13px; }
.hint { font-size: 12px; color: var(--faint); margin-top: 8px; }
.btn-primary { background: var(--accent); color: #fff; font-weight: 600; border-radius: 8px; padding: 10px 16px; font-size: 14px; }
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 86%, #000); }
.btn-primary:disabled { opacity: 0.5; cursor: default; }
.btn-ghost { background: var(--bg-3); color: var(--dim); border-radius: 8px; padding: 10px 16px; font-weight: 600; }
.btn-ghost:hover { background: var(--hover); color: var(--text); }
.auth-toggle { text-align: center; margin-top: 16px; color: var(--dim); font-size: 13px; }

.wiz-dots { display: flex; gap: 6px; justify-content: center; margin-bottom: 18px; }
.wiz-dot { width: 28px; height: 4px; border-radius: 3px; background: var(--hover); }
.wiz-dot.on { background: var(--accent); }
.wiz-h { font-size: 16px; font-weight: 700; margin-bottom: 4px; }
.wiz-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 22px; }
.radio-row { display: flex; gap: 10px; }
.radio-card { flex: 1; border: 1px solid var(--line); border-radius: 9px; padding: 12px; cursor: pointer; }
.radio-card.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.radio-card .rc-t { font-weight: 700; font-size: 13px; }
.radio-card .rc-d { font-size: 12px; color: var(--dim); margin-top: 3px; }

/* ---------------- bubbles (top tab bar) + app shell ---------------- */
.app-shell { height: 100%; display: flex; flex-direction: column; min-height: 0; }
.app-shell > .app { flex: 1; min-height: 0; height: auto; }

.bubble-bar {
  flex: 0 0 auto; display: flex; align-items: center; gap: 6px;
  padding: 6px 10px; background: var(--sidebar-bg); border-bottom: 1px solid var(--line);
  overflow-x: auto; scrollbar-width: none;
  user-select: none; -webkit-user-select: none;
}
.bubble-bar::-webkit-scrollbar { display: none; }
.bubble {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  padding: 6px 14px; border-radius: 999px; border: 1px solid transparent;
  background: var(--bg-3); color: var(--dim); font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.bubble:hover { color: var(--text); background: var(--hover); }
.bubble.active { background: var(--accent); color: #fff; border-color: transparent; }
.bubble .dd-off-chip { margin-left: 2px; }

/* On a tool bubble the tool fills the width. Use FLEX (not the grid with
   0-width side columns): display:none-ing grid items makes .main reflow into
   the first 0-width column and collapse — flex just drops the hidden panels. */
.app.on-tool { display: flex !important; }
.app.on-tool .sidebar { display: none; }
.app.on-tool .main { flex: 1 1 auto; min-width: 0; }

/* Keep-alive tool/chat panes: only the active one shows; the rest stay mounted.
   `display:contents` makes the visible wrapper layout-transparent, so each tool
   lays out exactly as if it were a direct child of .main (its original context);
   hidden panes are pulled out of layout entirely but stay mounted. */
.tab-pane { display: contents; }
.tab-pane.tab-hidden { display: none; }

/* ---------------- app shell (three panes) ---------------- */
.app { display: grid; grid-template-columns: 240px 1fr; height: 100%; }

.sidebar { background: var(--sidebar-bg); border-right: 1px solid var(--line); display: flex; flex-direction: column; min-height: 0; }

.user-panel { border-top: 1px solid var(--line); background: var(--panel-bg); display: flex; align-items: center; gap: 9px; padding: 8px 10px; }
.user-panel .meta { flex: 1; min-width: 0; }
.user-panel .name { font-size: 13px; font-weight: 700; display: flex; align-items: center; gap: 6px; white-space: nowrap; overflow: hidden; }
.user-panel .status { font-size: 11px; color: var(--dim); display: flex; align-items: center; gap: 5px; }
.dot { width: 8px; height: 8px; border-radius: 50%; }
.logout { color: var(--dim); font-size: 17px; padding: 6px; border-radius: 6px; }
.logout:hover { background: var(--hover); color: var(--text); }

/* ---------------- main ---------------- */
.main { background: var(--main-bg); display: flex; flex-direction: column; min-width: 0; }
/* Extra breathing room before a new author's block; consecutive messages from
   the same person (grouped) stay tight. */

.voice-placeholder { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--dim); }
.voice-placeholder img { width: 56px; height: 56px; opacity: 0.8; }
.voice-placeholder h3 { color: var(--text); }

/* ---------------- role tags ---------------- */
.role-tag { font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.03em; padding: 1px 5px; border-radius: 4px; }
.t-owner { background: rgba(240, 178, 50, 0.18); color: var(--yellow); }
.t-admin { background: rgba(155, 109, 255, 0.18); color: var(--purple); }
.t-member { background: rgba(47, 128, 237, 0.16); color: #8fb4ff; }
.t-guest { background: rgba(120, 130, 145, 0.18); color: #9aa3af; }

/* ---------------- settings modal ---------------- */
.overlay { position: fixed; inset: 0; background: rgba(8, 9, 11, 0.72); display: flex; align-items: center; justify-content: center; padding: 24px; z-index: 50; }
.modal { background: var(--bg-2); border: 1px solid var(--line); border-radius: 14px; width: 100%; max-width: 640px; max-height: 84vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5); }
.modal-head { display: flex; align-items: center; padding: 18px 22px; border-bottom: 1px solid var(--line); }
.modal-head h3 { font-size: 17px; }
.modal-close { margin-left: auto; width: 30px; height: 30px; border-radius: 7px; color: var(--dim); font-size: 16px; }
.modal-close:hover { background: var(--hover); color: var(--text); }
.tabs { display: flex; gap: 4px; padding: 0 22px; border-bottom: 1px solid var(--line); }
.tab { padding: 12px 14px; font-size: 13px; font-weight: 600; color: var(--dim); border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tab.active { color: #fff; border-color: var(--accent); }
.tab:hover { color: var(--text); }
.modal-body { padding: 20px 22px; overflow-y: auto; }
.settings-form { display: flex; flex-direction: column; max-width: 320px; }
.settings-form label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--dim); margin: 14px 0 6px; }
.settings-form .btn-primary { margin-top: 20px; align-self: flex-start; }
/* Space between the last field (or error) and the Log in / Create account
   button — the glass glow otherwise touches the password input. */
.auth-card .btn-primary { margin-top: 20px; }

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th { text-align: left; color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; padding: 8px 10px; border-bottom: 1px solid var(--line); }
td { padding: 9px 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
td select { background: var(--bg-0); border: 1px solid var(--line); border-radius: 6px; padding: 5px 8px; color: var(--text); }
.muted { color: var(--faint); }
.pill { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 10px; }
.pill.on { background: rgba(91, 200, 138, 0.16); color: var(--green); }
.pill.off { background: rgba(120, 130, 145, 0.16); color: var(--dim); }
.mini { font-size: 12px; color: var(--dim); padding: 4px 9px; border-radius: 6px; border: 1px solid var(--line); }
.mini:hover { background: var(--hover); color: var(--text); }
.invite-create { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; }
.invite-create select, .invite-create input { background: var(--bg-0); border: 1px solid var(--line); border-radius: 7px; padding: 8px 10px; color: var(--text); outline: none; }

@media (max-width: 1100px) { .app { grid-template-columns: 220px 1fr; } }
@media (max-width: 640px) { .app { grid-template-columns: 1fr; } .sidebar { display: none; }  }
/* Attachments + upload UI (M2) */

/* Image/media attachments line up with the message text column — i.e. the
   image's left edge starts exactly where text begins (under the username), with
   no extra indent. align-items: flex-start so the wrappers (and the image
   inside) shrink-wrap to the photo's real width instead of stretching to the
   full message width — otherwise a portrait photo gets letterboxed/centered
   (object-fit: contain) inside an over-wide element and looks indented. */
.attachments { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin-top: 4px; }

/* No frame — the photo sits in the message at its true aspect ratio, with just
   softly rounded corners (no border, no background fill). */
.att-image {
  max-width: 420px; max-height: 320px; width: auto; height: auto; border-radius: 8px;
  cursor: pointer; display: block; object-fit: contain; background: transparent;
}
.att-video { max-width: 480px; max-height: 340px; border-radius: 8px; border: 1px solid var(--line); background: #000; }
.att-audio { width: 360px; max-width: 100%; }

.att-file {
  display: flex; align-items: center; gap: 12px; max-width: 360px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 13px; text-decoration: none; color: var(--text);
}
.att-file:hover { border-color: var(--accent); }
.att-file .fi { width: 36px; height: 36px; border-radius: 7px; background: color-mix(in srgb, var(--accent) 18%, transparent); display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
.att-file .fn { font-weight: 600; font-size: 13px; color: #cdd9ff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-file .fs { font-size: 11px; color: var(--faint); }

.att-processing {
  display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--dim);
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px;
}
.att-processing .spin { width: 12px; height: 12px; border: 2px solid var(--faint); border-top-color: var(--accent); border-radius: 50%; animation: kp-spin 0.8s linear infinite; }
@keyframes kp-spin { to { transform: rotate(360deg); } }

/* composer upload chips */
.upload-chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 16px 8px; }
.chip {
  display: flex; align-items: center; gap: 8px; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 8px; padding: 7px 10px; max-width: 240px; font-size: 12px;
}
.chip .cn { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 120px; }
.chip .bar { width: 60px; height: 4px; background: #3a4049; border-radius: 3px; overflow: hidden; }
.chip .bar > i { display: block; height: 100%; background: var(--accent); border-radius: 3px; transition: width 0.15s; }
.chip .x { color: var(--faint); cursor: pointer; font-size: 14px; }
.chip .x:hover { color: var(--text); }
.chip.err { border-color: var(--orange); color: #ffb39a; }
.chip .ok { color: var(--green); }

/* Inline links + Discord-style unfurl preview cards. */

.link-card {
  display: block; max-width: 440px; margin-top: 6px; padding: 10px 12px;
  border-left: 4px solid var(--accent); background: var(--bg-2);
  border-radius: 4px 8px 8px 4px; text-decoration: none; overflow: hidden;
}
.link-card:hover { background: var(--bg-3); }
.lc-body { min-width: 0; }
.lc-site { color: var(--dim); font-size: 12px; margin-bottom: 3px; }
.lc-title { color: var(--accent); font-weight: 700; font-size: 15px; line-height: 1.3; word-break: break-word; }
.lc-desc {
  color: var(--dim); font-size: 13px; margin-top: 4px; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.lc-thumb {
  position: relative; margin-top: 10px; border-radius: 8px;
  width: 100%; aspect-ratio: 16 / 9; max-height: 300px;
  background-size: cover; background-position: center; background-color: var(--bg-0);
}
/* Portrait thumbnails (e.g. TikTok 9:16) are letterboxed, not cropped, and kept
   to a sensible height so the card doesn't dominate the message list. */
.lc-thumb.portrait {
  aspect-ratio: auto; height: 320px; max-width: 240px;
  background-size: contain; background-repeat: no-repeat;
}
.lc-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.lc-play i {
  width: 56px; height: 56px; border-radius: 50%; background: rgba(0, 0, 0, 0.55); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 20px; padding-left: 3px;
}
.link-card:hover .lc-play i { background: rgba(0, 0, 0, 0.72); }

/* ---- Inline 3D model viewer ---- */
.mv-wrap {
  position: relative; width: min(520px, 100%); border-radius: 12px; overflow: hidden;
  background: radial-gradient(120% 130% at 50% 20%, #1c2230, #0b0e14 75%);
  border: 1px solid var(--line);
}
/* Works for both native fullscreen and the iOS CSS fallback: fixed+inset
   pins the viewer over the app; dvh tracks the collapsing browser chrome. */
.mv-wrap.fs { position: fixed; inset: 0; width: 100vw; height: 100dvh; z-index: 2000; border-radius: 0; background: var(--bg-2); }
.mv-canvas { width: 100%; height: 300px; cursor: grab; }
.mv-wrap.fs .mv-canvas { height: calc(100% - 40px); }
.mv-canvas:active { cursor: grabbing; }
.mv-canvas canvas { display: block; }
.mv-status {
  position: absolute; inset: 0 0 40px; display: flex; align-items: center; justify-content: center; gap: 10px;
  color: #8fa0b5; font-size: 13px; pointer-events: none;
}
.mv-status.err { color: #e8a0a2; }
.mv-bar {
  display: flex; align-items: center; gap: 8px; height: 40px; padding: 0 10px;
  background: rgba(8, 10, 14, 0.75); border-top: 1px solid var(--line);
}
.mv-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; color: #c8d2de; display: flex; gap: 8px; align-items: center; }
.mv-actions { display: flex; gap: 4px; }
.mv-actions button, .mv-actions a {
  width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 7px; color: #9fb0c3; font-size: 12.5px; cursor: pointer; background: transparent;
}
.mv-actions button:hover, .mv-actions a:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }
.mv-actions button.on { background: var(--accent); color: #fff; }
.mv-mats {
  position: absolute; right: 10px; bottom: 48px; width: 290px; z-index: 5;
  max-width: calc(100% - 20px);
  /* Never taller than the viewer: cap to the wrap and scroll the slot list
     inside — otherwise long slot lists clip against the viewer's edges. */
  max-height: calc(100% - 58px);
  display: flex; flex-direction: column;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5); padding: 12px;
}
.mv-mats-head, .mv-mats-foot, .mv-mats-empty { flex: 0 0 auto; }
.mv-mats-head { font-size: 12.5px; font-weight: 700; margin-bottom: 10px; }
.mv-mats-head .muted { display: block; font-weight: 400; font-size: 11px; margin-top: 2px; }
.mv-mat-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.mv-mat-label { width: 92px; flex: none; font-size: 12px; color: var(--dim); }
.mv-mat-row select {
  flex: 1; min-width: 0; background: var(--bg-3); color: var(--text); border: 1px solid var(--line);
  border-radius: 7px; padding: 5px 8px; font-size: 12px; outline: none;
}
.mv-mats-foot { display: flex; gap: 6px; margin-top: 10px; align-items: center; flex-wrap: wrap; }
.mv-mats-foot button { white-space: nowrap; }
@media (max-width: 760px) { .mv-canvas { height: 240px; } }
.mv-mats-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.mv-slot { padding: 6px 0; }
.mv-slot + .mv-slot { border-top: 1px solid var(--line); }
.mv-slot-name { font-size: 12px; font-weight: 700; color: var(--text); margin-bottom: 6px; display: flex; align-items: center; gap: 7px; }
.mv-slot-name i { color: var(--accent); font-size: 11px; }
.mv-mats-empty { font-size: 12px; color: var(--text-dim); line-height: 1.5; padding: 8px 10px; background: color-mix(in srgb, var(--accent) 8%, transparent); border: 1px dashed var(--line); border-radius: 8px; margin: 6px 0; }
.mv-mats-empty b { color: var(--text); font-weight: 600; }
.mv-wrap.droptex { outline: 2px dashed var(--accent); outline-offset: -2px; }
.mv-wrap.droptex::after { content: 'Drop textures to add them to this model'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--bg-2) 72%, transparent); color: var(--text); font-weight: 700; font-size: 14px; z-index: 6; pointer-events: none; border-radius: inherit; }

/* Inline YouTube player (click-to-load facade → iframe). */
.link-card.yt-card { max-width: 480px; padding: 10px 12px 12px; }
.yt-embed, .yt-facade {
  position: relative; display: block; width: 100%; aspect-ratio: 16 / 9;
  margin-top: 8px; padding: 0; border: none; border-radius: 10px; overflow: hidden;
  background-color: #000; background-position: center; background-size: cover; background-repeat: no-repeat;
  cursor: pointer;
}
.yt-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.yt-play { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.yt-play i { font-size: 52px; color: #ff0000; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.5)); transition: transform .12s ease; }
.yt-facade:hover .yt-play i { transform: scale(1.08); }
/* Voice room (M3) */
.voice-join {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: var(--dim);
}
.voice-join img { width: 56px; height: 56px; }
.voice-join h3 { color: var(--text); }
.voice-join .btn-primary { margin-top: 8px; }

.voice-room { flex: 1; display: flex; flex-direction: column; min-height: 0; background: #14161b; }
.voice-stage { flex: 1; }
/* ---- Video stage: only live video gets a tile ----
   VoiceStage sizes every tile to the same 16:9 width (--vr-tile) so the set
   fills the stage, and sets --vr-gap once: it is the gap between tiles on both
   axes, the stage padding and the roster spacing. Insets inside a tile are
   10px everywhere (label, hand, kick, live badge). The stage stays dark in
   every theme, so its text colors are fixed light values. */
.vr-stage {
  flex: 1; min-height: 0; display: flex; flex-direction: column; gap: var(--vr-gap); padding: var(--vr-gap);
  background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 62%);
}
.vr-grid { flex: 1; min-height: 0; display: flex; overflow: auto; }
.vr-grid-inner { margin: auto; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--vr-gap); }
.vr-tile {
  position: relative; flex: none; width: var(--vr-tile); aspect-ratio: 16 / 9; overflow: hidden; isolation: isolate;
  border-radius: 16px; background: #0b0c10; container-type: inline-size;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}
/* Speaking ring drawn inside the tile, so it never changes the layout. */
.vr-tile::after {
  content: ''; position: absolute; inset: 0; z-index: 3; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 2px var(--green, #3ba55d), inset 0 0 26px color-mix(in srgb, var(--green, #3ba55d) 35%, transparent);
  opacity: 0; transition: opacity var(--dur-fast) var(--ease);
}
.vr-tile.speaking::after { opacity: 1; }
.vr-tile video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.vr-tile .kp-hand { top: 10px; left: 10px; }
.vr-label, .vr-live, .vr-kick {
  position: absolute; z-index: 2; border-radius: 999px; color: #fff;
  background: rgba(12, 12, 16, 0.5); -webkit-backdrop-filter: blur(14px) saturate(1.4); backdrop-filter: blur(14px) saturate(1.4);
}
.vr-label {
  left: 10px; bottom: 10px; max-width: calc(100% - 20px); display: flex; align-items: center; gap: 6px;
  padding: 5px 10px; font-size: 12px; font-weight: 600;
}
.vr-label span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The stage's labels and chips are fixed dark glass, so their marks are a fixed white
   that pairs with the name (elsewhere marks are --dim). Live stays the one red pill. */
:is(.vr-label, .vr-chip) .vc-state { color: rgba(255, 255, 255, 0.72); }
.vr-label .vc-state { font-size: 11px; }
/* Moderator disconnect: out of sight until you hover or tab to the tile. */
.vr-kick {
  top: 10px; right: 10px; width: 30px; height: 30px; border: 1px solid rgba(255, 255, 255, 0.14); font-size: 12px; cursor: pointer;
  opacity: 0; transform: scale(0.9); transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.vr-tile:hover .vr-kick, .vr-kick:focus-visible { opacity: 1; transform: none; }
.vr-kick:hover { background: rgba(220, 60, 62, 0.85); }

/* A shared screen: live preview, Watch on hover or focus. */
.vr-share {
  display: block; padding: 0; border: none; font: inherit; color: #fff; cursor: pointer;
  background: radial-gradient(90% 120% at 50% 0%, color-mix(in srgb, var(--accent) 30%, #101016), #0b0c10 70%);
  transition: transform var(--dur-base) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.vr-share video { object-fit: contain; background: #000; }
.vr-share:hover { transform: translateY(-2px); box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45), inset 0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent); }
.vr-share:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vr-live {
  top: 10px; left: 10px; display: flex; align-items: center; gap: 6px; padding: 4px 9px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
}
/* A shared screen's badge: the same red Live pill as a person's mark, with a beating dot. */
.vr-share .vr-live { background: var(--danger); -webkit-backdrop-filter: none; backdrop-filter: none; }
.vr-live i { width: 7px; height: 7px; border-radius: 50%; background: #fff; animation: vr-live 1.8s var(--ease-loop) infinite; }
@keyframes vr-live { 0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.55); } 70%, 100% { box-shadow: 0 0 0 7px rgba(255, 255, 255, 0); } }
.vr-share-watch {
  position: absolute; left: 50%; top: 50%; z-index: 2; transform: translate(-50%, -50%) scale(0.92); opacity: 0;
  display: flex; align-items: center; gap: 7px; padding: 8px 16px; border-radius: 999px;
  background: var(--accent); font-size: 13px; font-weight: 700;
  box-shadow: 0 6px 18px color-mix(in srgb, var(--accent) 40%, transparent);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.vr-share:hover .vr-share-watch, .vr-share:focus-visible .vr-share-watch { opacity: 1; transform: translate(-50%, -50%); }
.vr-share-watch i { font-size: 11px; }
.vr-label-icon { color: #fff !important; opacity: 0.8; }

/* Everyone without a camera, while others are on video. */
.vr-roster { flex: none; display: flex; gap: var(--vr-gap); justify-content: safe center; overflow-x: auto; scrollbar-width: none; }
.vr-chip {
  flex: none; display: flex; align-items: center; gap: 8px; height: 40px; padding: 4px 14px 4px 4px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.05); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
  color: #e8ebf1; font-size: 13px; font-weight: 600; transition: background var(--dur-fast) var(--ease);
}
.vr-chip:hover { background: rgba(255, 255, 255, 0.08); }
.vr-chip-av { box-shadow: 0 0 0 2px transparent; transition: box-shadow var(--dur-fast) var(--ease); }
/* The ring stays inside the chip's 4px padding; the chip outline picks up the green too. */
.vr-chip.speaking { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--online) 60%, transparent); }
.vr-chip.speaking .vr-chip-av { box-shadow: 0 0 0 2px var(--online); }
.vr-chip-name { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vr-chip-hand { color: #f0c040; font-size: 12px; }
@media (prefers-reduced-motion: reduce) {
  .vr-live i { animation: none; }
  .vr-share, .vr-kick, .vr-share-watch { transition: none; }
}

.voice-bar {
  flex-shrink: 0; border-top: 1px solid rgba(255, 255, 255, 0.06);
  display: flex; align-items: center; padding: 8px 12px; gap: 12px;
}
.vb-info { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.vb-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.vb-text b { color: #e8ebf1; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vb-text small { color: rgba(232, 235, 241, 0.55); font-size: 12px; }
.vb-controls {
  display: flex; gap: 8px; padding: 6px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.04); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
}
.vb-controls .vctrl { width: 44px; height: 44px; }
.vb-controls .vctrl.leave { width: 60px; }
.vb-spacer { flex: 1; }
.q { width: 9px; height: 9px; border-radius: 50%; background: #5a6270; display: inline-block; }
.q-excellent { background: var(--green); } .q-good { background: var(--green); }
.q-poor { background: var(--yellow); } .q-lost { background: var(--orange); }
.vctrl {
  width: 46px; height: 46px; border-radius: 50%; background: var(--bg-3); color: var(--text);
  display: flex; align-items: center; justify-content: center; font-size: 18px;
}
.vctrl:hover { background: var(--hover); }
.vctrl.on { background: #fff; color: #15171b; }
.vctrl.off { background: var(--bg-3); color: var(--orange); }
.vctrl.leave { background: var(--orange); color: #fff; }
.vctrl.leave:hover { background: #d9542c; }

/* sidebar voice participants */
.vc-members { padding: 0 0 var(--sp-1); }
/* Who's in a voice channel: a 28px sub-list under its row, faces lined up with the
   channel's name (row inset + icon column + gap). Each opens that person's voice menu. */
.vc-member { display: flex; align-items: center; gap: var(--sp-2); box-sizing: border-box; width: 100%; min-height: 28px; padding: 0 var(--sp-2) 0 calc(var(--sp-2) * 2 + 24px); border: 0; border-radius: var(--radius-md); background: none; color: var(--dim); font: inherit; font-size: var(--fs-sm); text-align: left; cursor: pointer; }
.vc-member:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.vc-member .va {
  width: 18px; height: 18px; border-radius: 50%; background: linear-gradient(135deg, var(--teal), var(--blue));
  color: #fff; font-size: 9px; font-weight: 700; display: flex; align-items: center; justify-content: center;
}
/* Real-time speaking highlight in the sidebar call list — green ring on the
   avatar + brighter name, matching the call tiles/pucks. */
.vc-member .avatar { box-shadow: 0 0 0 0 transparent; transition: box-shadow var(--dur-fast) var(--ease); }
.vc-member.speaking .avatar { box-shadow: 0 0 0 2px var(--online); }
.vc-member.speaking { color: var(--text); }
/* Live / muted / deafened marks, right-aligned after the name. */
.vc-member .vc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vc-state { flex: none; display: inline-flex; align-items: center; gap: 6px; color: var(--dim); font-size: 12px; }
.vc-live {
  padding: 1px 6px; border-radius: 999px; background: var(--danger); color: var(--on-danger);
  font-size: 10px; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase;
}

/* Raise-hand badge on a puck/tile; the hand waves briefly every few seconds. */
.kp-hand {
  position: absolute; top: 6px; left: 6px; z-index: 4;
  width: 28px; height: 28px; border-radius: 50%;
  background: rgba(240, 192, 64, 0.96); color: #3b2a00;
  display: flex; align-items: center; justify-content: center; font-size: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}
.kp-hand i { transform-origin: 65% 80%; animation: kp-wave 3.2s var(--ease-loop) infinite; }
@keyframes kp-wave {
  0%, 68%, 100% { transform: rotate(0deg); }
  72% { transform: rotate(-16deg); }
  77% { transform: rotate(13deg); }
  82% { transform: rotate(-11deg); }
  87% { transform: rotate(9deg); }
  92% { transform: rotate(0deg); }
}

/* ---- Watching shared screens: switch between them, or side by side ---- */
.tb-streams { display: flex; gap: 8px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.tb-stream {
  display: flex; align-items: center; gap: 7px; padding: 7px 12px; border-radius: 999px; white-space: nowrap; cursor: pointer;
  border: 1px solid var(--line); background: transparent; color: var(--dim); font-size: 12.5px; font-weight: 650;
}
.tb-stream:hover { color: var(--text); }
.tb-stream[aria-selected='true'], .tb-stream[aria-pressed='true'] {
  color: var(--text); background: color-mix(in srgb, var(--accent) 16%, transparent); border-color: color-mix(in srgb, var(--accent) 60%, var(--line));
}
.tb-stream:focus-visible, .theater-split-cell:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theater-split { position: absolute; inset: 0; display: grid; grid-template-columns: repeat(var(--split-cols, 2), minmax(0, 1fr)); grid-auto-rows: minmax(0, 1fr); gap: 8px; padding: 8px; background: #000; }
.theater-split-cell { position: relative; padding: 0; border: 0; border-radius: 12px; overflow: hidden; background: #0b0c10; cursor: zoom-in; }
.theater-split-cell .theater-video { position: absolute; inset: 0; }
.theater-split-cell:hover { box-shadow: inset 0 0 0 2px var(--accent); }
/* M4 collaboration polish: reactions, replies, mentions, pins, typing, search, DMs */

/* Settings → Emojis tab */
.emj-tab { display: flex; flex-direction: column; gap: 12px; }
.emj-add { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.emj-naming { display: flex; align-items: center; gap: 6px; }
.emj-naming input { background: var(--bg-2); border: 1px solid var(--line); border-radius: 8px; color: var(--text); padding: 6px 10px; font-family: ui-monospace, monospace; font-size: 13px; width: 220px; }
.emj-preview { width: 32px; height: 32px; object-fit: contain; }
.emj-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; max-height: 46vh; overflow-y: auto; }
.emj-cell { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 6px; border: 1px solid var(--line); border-radius: 10px; }
.emj-cell:hover { background: var(--hover); }
.emj-img { width: 32px; height: 32px; object-fit: contain; }
.emj-name { font-size: 11px; color: var(--dim); font-family: ui-monospace, monospace; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.emj-del { position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border-radius: 6px; color: var(--dim); opacity: 0; }
.emj-cell:hover .emj-del { opacity: 1; }
.emj-del:hover { color: #ed4245; background: var(--hover); }

/* Discord-style "who reacted" tooltip on hover */

.emoji-pop {
  position: absolute; z-index: 30; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 9px; padding: 6px; display: flex; gap: 4px; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}
.emoji-pop button { font-size: 18px; padding: 3px 5px; border-radius: 6px; }
.emoji-pop button:hover { background: var(--hover); }

.reply-bar {
  padding: 6px 18px; font-size: 12px; color: var(--dim); display: flex; align-items: center; gap: 8px;
}
.reply-bar { background: var(--bg-3); border-top: 1px solid var(--line); }
.reply-bar .x { margin-left: auto; cursor: pointer; color: var(--faint); }
.reply-bar .x:hover { color: var(--text); }

/* search + pins panels (reuse .overlay/.modal from styles.css) */
.search-box { display: flex; gap: 8px; margin-bottom: 14px; }
.search-box input { flex: 1; background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 10px 13px; color: var(--text); outline: none; }
.search-box input:focus { border-color: var(--accent); }
.result { padding: 10px 8px; border-bottom: 1px solid var(--line); cursor: pointer; border-radius: 6px; }
.result:hover { background: #1e242c; }
.result .rh { display: flex; gap: 8px; align-items: baseline; font-size: 12px; }
.result .rh b { color: #fff; }
.result .rh .where { color: var(--faint); }
.result .rc { color: #dce0e6; margin-top: 2px; }

.icon-btn { width: 32px; height: 32px; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: var(--dim); }
.icon-btn:hover { background: var(--hover); color: var(--text); }
/* M4b: read-only composer + notification menu */

.notif-wrap { position: relative; }
.notif-menu {
  position: absolute; right: 0; top: 38px; z-index: 30; width: 200px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 9px; padding: 6px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}
.notif-menu .item { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 6px; font-size: 13px; cursor: pointer; width: 100%; text-align: left; }
.notif-menu .item:hover { background: var(--hover); }
.notif-menu .item.sel { color: #fff; }
.notif-menu .item.sel::after { content: '✓'; margin-left: auto; color: var(--accent); }
.notif-menu .sep { height: 1px; background: var(--line); margin: 5px 2px; }
.icon-btn.has-menu.on { color: #fff; }
/* Layout robustness: the "chrome" (headers, composer, user panel) must always
   stay visible; only the scroll regions flex. Fixes elements getting clipped
   when the window is resized. The crucial bit is min-height:0 on the flex
   columns so a tall message list scrolls instead of pushing the composer off. */

.app { min-height: 0; }
.sidebar, .main { min-height: 0; min-width: 0; }

.user-panel,
.reply-bar,
.upload-chips,
.voice-bar {
  flex-shrink: 0;
}

.voice-stage {
  min-height: 0;
}

.user-panel .meta { min-width: 0; }
.user-panel .name { text-overflow: ellipsis; }

/* Brand: bigger Dogfish Games badge on the login screen. */
.auth-logo { width: 96px; height: 96px; }
/* Avatars as images */

/* Context menu (right-click) */
.ctx-menu {
  position: fixed; z-index: 200; min-width: 210px; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 10px; padding: 5px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
}
.ctx-item {
  position: relative; display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 7px;
  font-size: 13px; color: var(--text); cursor: pointer; user-select: none;
}
.ctx-item:hover { background: var(--accent); color: #fff; }
.ctx-item.danger { color: #ff8a8a; }
.ctx-item.danger:hover { background: var(--red, #ed4245); color: #fff; }
.ctx-item.disabled { opacity: 0.4; cursor: default; }
.ctx-item.disabled:hover { background: transparent; color: var(--text); }
.ctx-item .ci { width: 18px; text-align: center; }
.ctx-item .cl { flex: 1; }
/* A checked item's ✓ keeps clear of its label, in the trailing column. */
.ctx-item .cl + .cc { padding-left: 24px; }
.ctx-item .ca { color: var(--dim); }

/* Voice user menu (right-click a person in a call) */
.vum-head {
  display: flex; align-items: center; gap: 9px; padding: 8px 9px 9px; margin-bottom: 3px;
  border-bottom: 1px solid var(--line);
}
.vum-name { font-weight: 700; font-size: 13.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vum-vol { padding: 8px 10px 10px; }
.vum-vol-top { display: flex; align-items: center; justify-content: space-between; font-size: 12.5px; color: var(--dim); margin-bottom: 7px; }
.vum-vol-top .fa-solid { margin-right: 6px; }
.vum-pct { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.vum-vol input[type="range"] { display: block; }
.vum-sub { padding-left: 24px; }
.vum-sub .ci { color: var(--dim); }
.ctx-item:hover .ca { color: #fff; }
.ctx-item .ck { color: var(--accent); }
.ctx-item:hover .ck { color: #fff; }
.ctx-item.on { color: #fff; }
.ctx-sep { height: 1px; background: var(--line); margin: 5px 4px; }
.ctx-submenu {
  position: absolute; left: 100%; top: -6px; min-width: 190px; background: var(--bg-3); border: 1px solid var(--line);
  border-radius: 10px; padding: 5px; box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
}
/* Flip the submenu when it would run off the viewport edge. */
.ctx-submenu.up { top: auto; bottom: -6px; }
.ctx-submenu.left { left: auto; right: 100%; }

/* Create-channel modal */
.create-modal { max-width: 480px; }
.ctype { display: flex; gap: 10px; margin-bottom: 16px; }
.ctype-opt { flex: 1; display: flex; align-items: center; gap: 10px; text-align: left; border: 1px solid var(--line); border-radius: 10px; padding: 12px; color: var(--text); }
.ctype-opt.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 9%, transparent); }
.ctype-opt .ct-ic { width: 34px; height: 34px; border-radius: 8px; background: var(--bg-0); display: flex; align-items: center; justify-content: center; font-size: 17px; color: var(--dim); }
.create-modal label, .profile-modal label { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--dim); margin: 12px 0 6px; }
.create-modal input, .create-modal select, .profile-modal input, .profile-modal textarea {
  width: 100%; background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; color: var(--text); font-size: 14px; outline: none; font-family: inherit;
}
.create-modal input:focus, .profile-modal input:focus, .profile-modal textarea:focus { border-color: var(--accent); }
.name-row { display: flex; gap: 8px; }
.emoji-btn { width: 44px; flex-shrink: 0; background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; font-size: 18px; }
.emoji-btn:hover { border-color: var(--accent); }
.emoji-grid { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
.emoji-grid .eg { width: 32px; height: 32px; border-radius: 7px; font-size: 17px; }
.emoji-grid .eg:hover { background: var(--hover); }
.emoji-grid .eg.sel { background: color-mix(in srgb, var(--accent) 20%, transparent); }

/* Profile modal */
.profile-modal { max-width: 460px; }
.profile-view { text-align: center; }
.profile-view h2 { font-size: 22px; }
.pf-status { margin-top: 8px; font-size: 14px; }
.pf-bio { margin-top: 12px; color: var(--dim); white-space: pre-wrap; }
.pf-row { margin-top: 10px; font-size: 13px; }
.pf-avatar-row { display: flex; align-items: center; gap: 16px; margin-bottom: 8px; }

/* drag-reorder */
.user-panel .name { cursor: pointer; }
.user-panel .name:hover { text-decoration: underline; }

.toast {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 250;
  background: var(--bg-3); border: 1px solid var(--line); color: var(--text);
  padding: 9px 16px; border-radius: 10px; font-size: 13px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}
/* Keep logos at their natural aspect ratio inside fixed boxes. */
.voice-join img, .voice-room img { object-fit: contain; }

/* ---- Themed confirm dialog (replaces window.confirm) ---- */
.confirm-overlay {
  position: fixed; inset: 0; z-index: 3000;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(6, 8, 11, 0.6);
}
.confirm-box {
  width: 100%; max-width: 380px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 14px;
  padding: 22px 22px 18px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}
.confirm-title { font-size: 16px; font-weight: 700; margin-bottom: 8px; }
.confirm-msg { font-size: 14px; line-height: 1.5; color: var(--dim); white-space: pre-wrap; }
.confirm-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }
.confirm-actions button { padding: 9px 18px; border-radius: 8px; font-size: 14px; font-weight: 600; }
.btn-danger { background: #dc3c3e; color: #fff; border-radius: 8px; }
.btn-danger:hover { background: #e4494b; }

/* ---- "View as" preview (owner only) ---- */
.preview-wrap { position: relative; margin-left: auto; }
.preview-eye { padding: 0 12px; }
.preview-eye.on { background: var(--yellow); color: #1a1200; border-color: var(--yellow); }
.preview-scrim { position: fixed; inset: 0; z-index: 3000; }
.preview-menu {
  /* Fixed + portalled to <body>: the bubble bar's overflow-x would otherwise
     clip it, and no z-index can escape an ancestor that clips. */
  position: fixed; z-index: 3001; transform: translateX(-100%);
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px;
  padding: 8px; min-width: 170px; box-shadow: 0 10px 30px rgba(0,0,0,.45);
  display: flex; flex-direction: column; gap: 2px;
}
.preview-menu p { margin: 2px 6px 6px; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
.preview-menu button {
  text-align: left; padding: 7px 10px; border-radius: 7px;
  background: transparent; color: var(--text); font-size: 13px; cursor: pointer;
}
.preview-menu button:hover { background: var(--hover); }

.preview-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 16px; font-size: 13px;
  background: var(--yellow); color: #1a1200; font-weight: 600;
}
.preview-bar i { opacity: .8; }
.preview-bar .mini {
  margin-left: auto; background: rgba(0,0,0,.22); color: #1a1200;
  border: none; font-weight: 700;
}
.preview-bar .mini:hover { background: rgba(0,0,0,.34); }
/* Color schemes. Dark is the default (defined in styles.css :root). Each theme
   also defines its own surface gradients: --sidebar-bg (side columns, dark top →
   lighter/bluer bottom), --panel-bg (bottom-left "me" panel, a subtle golden
   circular glow) and --main-bg (flat central chat surface). */

[data-theme='light'] {
  --bg-0: #ffffff; --bg-1: #f3f5f8; --bg-2: #ffffff; --bg-3: #eef1f5;
  --hover: #e7edf3; --active: #dbe4ee; --line: #e1e6ec;
  --text: #1b2330; --dim: #5c6573; --faint: #8b94a1;
  --sidebar-bg: linear-gradient(180deg, #eef1f6 0%, #e6edf8 58%, #d9e7fc 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(240,184,64,0.22), rgba(240,184,64,0.06) 45%, rgba(255,255,255,0) 72%), #eef1f5;
  --main-bg: #ffffff;
  /* Light theme keeps the viewer readable with a medium gray (not near-black). */
  --lb-backdrop: rgba(82, 88, 97, 0.96);
}

[data-theme='gray'] {
  --bg-0: #1f2123; --bg-1: #292c2f; --bg-2: #303336; --bg-3: #393d41;
  --hover: #41464c; --active: #4b5158; --line: #3c4147;
  --text: #e6e8ea; --dim: #a3a8af; --faint: #777d85;
  --sidebar-bg: linear-gradient(180deg, #232527 0%, #29313f 58%, #2e3a52 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(240,184,64,0.16), rgba(240,184,64,0.045) 44%, rgba(0,0,0,0) 72%), #202224;
  --main-bg: #1a1c1e;
}

[data-theme='retro'] {
  --bg-0: #1a1410; --bg-1: #221a13; --bg-2: #2a2017; --bg-3: #34281d;
  --hover: #3d3022; --active: #4a3a28; --line: #3a2d1f;
  --text: #f0d9b5; --dim: #c2a47c; --faint: #8a7050;
  --blue: #e0a13e; --green: #a7c957; --teal: #c98b2e;
  /* Warm variant: top dark amber → lighter toasted amber at the bottom. */
  --sidebar-bg: linear-gradient(180deg, #1c150e 0%, #2a1f14 55%, #3a2c1a 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(224,161,62,0.24), rgba(224,161,62,0.07) 46%, rgba(0,0,0,0) 72%), #1a130c;
  --main-bg: #17110b;
}

[data-theme='sea'] {
  --bg-0: #061a2b; --bg-1: #0b2436; --bg-2: #0e2c42; --bg-3: #123851;
  --hover: #164460; --active: #1c5272; --line: #15415d;
  --text: #e0f3fb; --dim: #8fc1da; --faint: #5e93ad;
  --blue: #22b8c4; --teal: #1fb6a8; --green: #4fd1a6;
  /* Deep navy → brighter teal at the bottom. */
  --sidebar-bg: linear-gradient(180deg, #061a2b 0%, #0b2f48 55%, #114f60 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(240,184,64,0.18), rgba(240,184,64,0.05) 45%, rgba(0,0,0,0) 72%), #07202f;
  --main-bg: #051420;
}

/* Light theme readability: several elements hardcode white text that assumed a
   dark background. On the light theme those backgrounds are pale, so switch the
   text to the theme's dark --text (or accent) to keep them readable. */
[data-theme='light'] .tab.active,
[data-theme='sakura'] .tab.active,
[data-theme='light'] .icon-btn.has-menu.on,
[data-theme='sakura'] .icon-btn.has-menu.on,
[data-theme='light'] .ctx-item.on,
[data-theme='sakura'] .ctx-item.on,
[data-theme='light'] .notif-menu .item.sel, [data-theme='sakura'] .notif-menu .item.sel { color: var(--accent); }
[data-theme='light'] .result .rh b, [data-theme='sakura'] .result .rh b { color: var(--text); }

/* =====================================================================
   Desktop (Electron) custom title bar. Each theme sets --titlebar to the
   same color as the TOP of its --sidebar-bg gradient, so the window chrome
   reads as one continuous surface (like Discord). --titlebar-text drives
   both our label and the native min/max/close symbols (via IPC). */
:root { --titlebar: #0f131b; --titlebar-text: #e7ebf0; }
[data-theme='light'] { --titlebar: #eef1f6; --titlebar-text: #1b2330; }
[data-theme='gray'] { --titlebar: #232527; --titlebar-text: #e6e8ea; }
[data-theme='retro'] { --titlebar: #1c150e; --titlebar-text: #f0d9b5; }
[data-theme='sea'] { --titlebar: #061a2b; --titlebar-text: #e0f3fb; }
[data-theme='midnight'] { --titlebar: #0a0a14; --titlebar-text: #e6e4f5; }
[data-theme='forest'] { --titlebar: #0d1710; --titlebar-text: #e3f0e6; }
[data-theme='sakura'] { --titlebar: #fdeef3; --titlebar-text: #3a2a33; }
[data-theme='sunset'] { --titlebar: #1a0f18; --titlebar-text: #f5e3dc; }
[data-theme='nord'] { --titlebar: #2b303b; --titlebar-text: #eceff4; }
[data-theme='terminal'] { --titlebar: #030503; --titlebar-text: #c8facc; }



/* ---- Six additional themes ---- */

[data-theme='midnight'] {
  --bg-0: #0a0a12; --bg-1: #10101c; --bg-2: #151525; --bg-3: #1c1c30;
  --hover: #24243c; --active: #2d2d4a; --line: #202036;
  --text: #e6e4f5; --dim: #a29ec4; --faint: #6d6a92;
  --accent: #7c5cff; --blue: #7c5cff; --teal: #5cb3ff;
  --sidebar-bg: linear-gradient(180deg, #0a0a14 0%, #131332 58%, #1b1b48 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(124,92,255,0.20), rgba(124,92,255,0.06) 45%, rgba(0,0,0,0) 72%), #0a0a12;
  --main-bg: #07070d;
}

[data-theme='forest'] {
  --bg-0: #0f1a12; --bg-1: #14211a; --bg-2: #182920; --bg-3: #1f3428;
  --hover: #274031; --active: #2f4d3b; --line: #23392c;
  --text: #e3f0e6; --dim: #9fc0a9; --faint: #6b8f77;
  --accent: #4caf6e; --green: #4caf6e; --teal: #3d9c82;
  --sidebar-bg: linear-gradient(180deg, #0d1710 0%, #14291c 55%, #1b3a26 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(76,175,110,0.18), rgba(76,175,110,0.05) 45%, rgba(0,0,0,0) 72%), #0e1811;
  --main-bg: #0b140d;
}

[data-theme='sakura'] {
  --bg-0: #fff7f9; --bg-1: #fbeef2; --bg-2: #ffffff; --bg-3: #f7e4ea;
  --hover: #f3d9e2; --active: #eccbd8; --line: #eed7de;
  --text: #3a2a33; --dim: #8a6a78; --faint: #b394a2;
  --accent: #e0559a;
  --sidebar-bg: linear-gradient(180deg, #fdeef3 0%, #fbdce8 58%, #f7cbdd 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(224,85,154,0.16), rgba(224,85,154,0.05) 45%, rgba(255,255,255,0) 72%), #fbeef2;
  --main-bg: #ffffff;
  --lb-backdrop: rgba(97, 78, 88, 0.96);
}

[data-theme='sunset'] {
  --bg-0: #1a1016; --bg-1: #221520; --bg-2: #2a1a26; --bg-3: #35202e;
  --hover: #422939; --active: #4f3143; --line: #3a2433;
  --text: #f5e3dc; --dim: #c9a49c; --faint: #90716c;
  --accent: #ff7849; --blue: #ff9f68; --teal: #ff6d8a;
  --sidebar-bg: linear-gradient(180deg, #1a0f18 0%, #3a1b33 55%, #5a2440 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(255,120,73,0.20), rgba(255,120,73,0.06) 45%, rgba(0,0,0,0) 72%), #190f15;
  --main-bg: #150c12;
}

[data-theme='nord'] {
  --bg-0: #2e3440; --bg-1: #333a48; --bg-2: #3b4252; --bg-3: #434c5e;
  --hover: #4c566a; --active: #566078; --line: #454e60;
  --text: #eceff4; --dim: #aeb6c5; --faint: #7d8697;
  --accent: #88c0d0; --blue: #81a1c1; --green: #a3be8c; --teal: #8fbcbb;
  --sidebar-bg: linear-gradient(180deg, #2b303b 0%, #333a48 58%, #3b4557 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(136,192,208,0.16), rgba(136,192,208,0.05) 45%, rgba(0,0,0,0) 72%), #2c313d;
  --main-bg: #292e39;
}

[data-theme='terminal'] {
  --bg-0: #050805; --bg-1: #081008; --bg-2: #0a150c; --bg-3: #0e1e10;
  --hover: #132916; --active: #18341c; --line: #122815;
  --text: #c8facc; --dim: #7fbf88; --faint: #4d7d55;
  --accent: #33ff66; --green: #33ff66; --blue: #37d9a0; --teal: #2bd482;
  --sidebar-bg: linear-gradient(180deg, #030503 0%, #07140a 55%, #0a1f0e 100%);
  --panel-bg: radial-gradient(130% 150% at 26% 50%, rgba(51,255,102,0.14), rgba(51,255,102,0.04) 45%, rgba(0,0,0,0) 72%), #040704;
  --main-bg: #030503;
}
[data-theme='terminal'] .btn-primary { color: #04140a; }

/* ---- Under the Sea: ambient effects (bubbles + drifting fish) ----
   Rendered by SeaEffects.tsx inside both side columns; invisible on every
   other theme, and fully disabled for reduced-motion users. */
.sea-fx { display: none; }
/* overflow keeps fish/bubbles clipped inside the bars. position: relative is
   desktop-only: on mobile the bars are position:fixed drawers, and this
   higher-specificity rule must NOT override that (it collapsed the whole
   phone layout when it did — the drawers fell back into the grid flow). */
[data-theme='sea'] .sidebar { overflow: hidden; }
@media (min-width: 761px) {
  [data-theme='sea'] .sidebar { position: relative; }
}
[data-theme='sea'] .sea-fx { display: block; position: absolute; inset: 0; pointer-events: none; z-index: 0; }

.sea-bubble {
  position: absolute; bottom: -14px; border-radius: 50%;
  background: rgba(180, 230, 255, 0.14);
  box-shadow: inset 0 0 4px rgba(220, 245, 255, 0.4);
  animation: sea-rise linear infinite;
}
@keyframes sea-rise {
  0%   { transform: translate(0, 0); opacity: 0; }
  8%   { opacity: 0.75; }
  30%  { transform: translate(6px, -30vh); }
  55%  { transform: translate(-5px, -55vh); }
  80%  { transform: translate(7px, -80vh); opacity: 0.45; }
  100% { transform: translate(0, -104vh); opacity: 0; }
}

.sea-fish { position: absolute; left: 0; animation: sea-swim linear infinite; opacity: 0.55; }
.sea-fish img { display: block; animation: sea-bob 5.5s ease-in-out infinite alternate; }
.sea-fish.rev { animation-name: sea-swim-rev; }
.sea-fish.rev img { transform: scaleX(-1); }
@keyframes sea-swim { from { translate: -70px 0; } to { translate: 380px 0; } }
@keyframes sea-swim-rev { from { translate: 380px 0; } to { translate: -70px 0; } }
@keyframes sea-bob { from { margin-top: -5px; rotate: -2deg; } to { margin-top: 6px; rotate: 2.5deg; } }

@media (prefers-reduced-motion: reduce) { .sea-fx { display: none !important; } }

/* ---- Custom theme editor ---- */
.th-fields { display: flex; flex-direction: column; gap: 8px; }
.th-field {
  display: flex; align-items: center; gap: 12px; padding: 8px 10px;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: 10px; cursor: pointer;
}
.th-field input[type='color'] {
  width: 40px; height: 30px; border: none; background: none; padding: 0; cursor: pointer;
}
.th-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.th-label { font-size: 14px; font-weight: 600; }
.th-hint { font-size: 11px; color: var(--faint); }
.th-hex { font-family: var(--mono); font-size: 12px; color: var(--dim); }


/* ---- Theme-change transition: bouncy circle reveal ----
   The new theme's snapshot pops out of the last click point (--vt-x/--vt-y,
   set by theme.ts), overshoots with a springy scale wobble, and settles.
   Only runs when theme.ts calls document.startViewTransition. */
::view-transition-old(root),
::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-old(root) { z-index: 1; }
::view-transition-new(root) {
  z-index: 2;
  animation: kp-theme-pop 640ms cubic-bezier(0.34, 1.4, 0.64, 1) both;
  transform-origin: var(--vt-x, 50%) var(--vt-y, 50%);
}
@keyframes kp-theme-pop {
  0%   { clip-path: circle(0px at var(--vt-x, 50%) var(--vt-y, 50%)); transform: scale(0.96); }
  55%  { clip-path: circle(145% at var(--vt-x, 50%) var(--vt-y, 50%)); transform: scale(1.014); }
  74%  { transform: scale(0.995); }
  88%  { transform: scale(1.004); }
  100% { clip-path: circle(150% at var(--vt-x, 50%) var(--vt-y, 50%)); transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; }
}

/* Studio palette refresh. Keep existing IDs so saved preferences survive. */
[data-theme='sea'] {
  --accent: #53d8cc; --blue: #53d8cc; --dim: #a6cbd8; --faint: #7aa6b8;
  --sidebar-bg: radial-gradient(ellipse at 100% 0%, #166075 0%, transparent 60%), linear-gradient(155deg, #071d30 10%, #10344c 55%, #12605b);
  --main-bg: linear-gradient(155deg, #081a29, #081820 75%, #0b262c);
  --panel-bg: linear-gradient(120deg,#0d3545,#10443f); --titlebar: #0b293c;
}
[data-theme='sea'] .sea-fx { opacity: .55; }
[data-theme='sunset'] {
  --accent: #ffac86; --blue: #ffac86; --dim: #d7b5bd; --faint: #b18a97;
  --sidebar-bg: radial-gradient(ellipse at 100% 100%, #ad593a 0%, transparent 65%), linear-gradient(155deg,#251831,#58304c 58%,#7d3d46);
  --main-bg: linear-gradient(150deg,#1c1420,#21151f 70%,#302027);
  --panel-bg: linear-gradient(110deg,#44243a,#6a393e); --titlebar: #251831;
}
[data-theme='midnight'] { --accent: #b39aff; --blue: #b39aff; --sidebar-bg: radial-gradient(ellipse at 0% 100%,#44327a,transparent 75%),linear-gradient(150deg,#111329,#242248); --main-bg: linear-gradient(150deg,#10101d,#171529); }
[data-theme='forest'] { --accent: #8aceab; --sidebar-bg: radial-gradient(ellipse at 100% 100%,#526844,transparent 75%),linear-gradient(150deg,#13291e,#254539); --main-bg: linear-gradient(150deg,#101c17,#162820); }
[data-theme='retro'] { --accent: #e9bb7c; --sidebar-bg: linear-gradient(145deg,#30271f,#645040 70%,#846549); --panel-bg: #362c23; }
[data-theme='gray'] { --accent: #b7c5d5; --sidebar-bg: linear-gradient(145deg,#252a30,#414954); --panel-bg: #2a3038; }
[data-theme='nord'] { --sidebar-bg: linear-gradient(145deg,#303b50,#495d73 65%,#527d85); --main-bg: linear-gradient(155deg,#292f3b,#303a47); }
[data-theme='light'] { --accent: #365fb0; --blue: #365fb0; --sidebar-bg: linear-gradient(145deg,#edf0fa,#dfebf5 55%,#d4e7e4); --panel-bg: #e5edf3; --faint: #697788; }
[data-theme='sakura'] { --accent: #a83971; --dim: #755263; --faint: #866477; --sidebar-bg: linear-gradient(145deg,#f9e4ed,#e9dff4 58%,#f4d9d3); --panel-bg: #eedee8; }
[data-theme='terminal'] { --accent: #81dfa4; --sidebar-bg: linear-gradient(145deg,#061710,#12382b); --panel-bg: #0c241b; }

[data-theme='aurora'] {
  --bg-0:#101c23; --bg-1:#14252d; --bg-2:#1b303a; --bg-3:#243e47;
  --hover:#2d4b54; --active:#365660; --line:#34515a; --text:#e5f5f3; --dim:#a7c9c8; --faint:#80a7aa;
  --accent:#86ddce; --blue:#86ddce; --teal:#a5b3ed;
  --sidebar-bg: linear-gradient(145deg,#29264c,#225763 55%,#407966);
  --main-bg:linear-gradient(150deg,#111f2a,#152e32); --panel-bg:#233d46; --titlebar:#29264c; --titlebar-text:#e5f5f3;
}
[data-theme='lagoon'] {
  --bg-0:#0c1b2c; --bg-1:#10253a; --bg-2:#173149; --bg-3:#203e56;
  --hover:#294c64; --active:#325972; --line:#2c4b62; --text:#e8f4ff; --dim:#abc5dd; --faint:#83a7c4;
  --accent:#78ccef; --blue:#78ccef; --teal:#73d4bc;
  --sidebar-bg:linear-gradient(140deg,#182b67,#165b78 60%,#258d86);
  --main-bg:linear-gradient(155deg,#0d1b30,#112c3b); --panel-bg:#153e55; --titlebar:#182b67; --titlebar-text:#e8f4ff;
}
[data-theme='ember'] {
  --bg-0:#25191a; --bg-1:#2e2020; --bg-2:#3a2927; --bg-3:#47332e;
  --hover:#563f36; --active:#65493d; --line:#594036; --text:#f7ece2; --dim:#d3b8a4; --faint:#b79781;
  --accent:#efbf7b; --blue:#efbf7b; --teal:#e89f95;
  --sidebar-bg:linear-gradient(145deg,#382330,#744735 58%,#a47b3e);
  --main-bg:linear-gradient(155deg,#241a20,#30211c); --panel-bg:#4a3028; --titlebar:#382330; --titlebar-text:#f7ece2;
}
[data-theme='dusk'] {
  --bg-0:#211b30; --bg-1:#2a233b; --bg-2:#352d48; --bg-3:#423853;
  --hover:#514461; --active:#5d4e70; --line:#53465f; --text:#f3edfb; --dim:#c8b9dc; --faint:#ac98c4;
  --accent:#d8aff4; --blue:#d8aff4; --teal:#9fc9e8;
  --sidebar-bg:linear-gradient(145deg,#313269,#62517e 60%,#986a88);
  --main-bg:linear-gradient(150deg,#211d30,#30243a); --panel-bg:#42334f; --titlebar:#313269; --titlebar-text:#f3edfb;
}
/* Custom tags */
.utag { display: inline-flex; align-items: center; height: 16px; padding: 0 6px; border-radius: 8px; font-size: 10px; font-weight: 700; color: #fff; letter-spacing: .2px; white-space: nowrap; text-shadow: 0 1px 1px rgba(0,0,0,.25); }
.row-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }

/* ---- Theme-aware text colors (audit). ---- */
.result .rh b { color: var(--text); }
.result .rc { color: var(--dim); }
.att-file .fn { color: var(--text); }
[data-theme='light'] .tab.active,
[data-theme='sakura'] .tab.active,
[data-theme='light'] .ctx-item.on,
[data-theme='sakura'] .ctx-item.on,
[data-theme='light'] .notif-menu .item.sel,
[data-theme='sakura'] .notif-menu .item.sel,
[data-theme='light'] .icon-btn.has-menu.on, [data-theme='sakura'] .icon-btn.has-menu.on { color: var(--accent); }

/* Suspended members */
tr.row-suspended td { opacity: .6; }

/* Attachment expiry note */
.att-wrap { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 3px; max-width: 100%; }
.att-expiry { font-size: 11px; color: var(--faint); display: flex; align-items: center; gap: 4px; }

/* ---- Resizable, wider sidebar (drag the right edge: -10% to +20%). ---- */
.app { grid-template-columns: var(--col-l, var(--sidebar-w, 280px)) 1fr; }
.sidebar { position: relative; }
.sidebar-grip { position: absolute; top: 0; right: -3px; width: 7px; height: 100%; cursor: col-resize; z-index: 40; }
.sidebar-grip:hover { background: linear-gradient(90deg, transparent, rgba(59,130,246,.6)); }
@media (max-width: 760px) { .sidebar-grip { display: none; } }

/* ---- Sidebar "On Voice" panel (Discord-style); only while in a voice channel. ---- */
.voice-status { margin: 8px; padding: 8px; border-radius: 10px; background: var(--bg-2); border: 1px solid var(--line); display: flex; flex-direction: column; gap: 8px; }
.vs-top { display: flex; align-items: center; gap: 8px; }
.vs-info { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 1px; background: transparent; border: none; cursor: pointer; padding: 2px 3px; border-radius: 6px; text-align: left; }
.vs-info:hover { background: var(--hover); }
.vs-on { display: flex; align-items: center; gap: 6px; color: var(--online); font-weight: 800; font-size: 13px; line-height: 1.2; }
.vs-wave { width: 9px; height: 9px; border-radius: 50%; background: var(--online); }
.vs-wave.live { animation: vs-pulse 1.7s ease-out infinite; }
@keyframes vs-pulse { 0% { box-shadow: 0 0 0 0 rgba(59,165,93,.5); } 70% { box-shadow: 0 0 0 6px rgba(59,165,93,0); } 100% { box-shadow: 0 0 0 0 rgba(59,165,93,0); } }
.vs-chan { color: var(--dim); font-size: 12px; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-info:hover .vs-chan { color: var(--text); }
.vs-hang { width: 36px; height: 36px; border-radius: 8px; background: var(--bg-3); color: #ed4245; border: none; cursor: pointer; font-size: 15px; flex-shrink: 0; }
.vs-hang:hover { background: #ed4245; color: #fff; }
.vs-ctrls { display: flex; gap: 6px; }
.vs-btn { flex: 1; height: 32px; border-radius: 8px; background: var(--bg-3); color: var(--text); border: none; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; }
.vs-btn:hover { background: var(--hover); }
.vs-btn.on { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.vs-btn.off { background: rgba(237,66,69,.18); color: #ed4245; }
.vs-btn:disabled { opacity: .5; cursor: default; }

/* Voice-only call (no cameras): centered circular avatars that scale with the
   frame, with a green speaking ring — Discord's voice-call look. Uses container
   query units so avatars grow/shrink as the panel is resized, staying centered. */
.voice-stage.audio-only { display: flex; flex-wrap: wrap; align-content: center; justify-content: center; gap: 30px; padding: 24px; container-type: size; overflow: auto; }
.voice-puck { display: flex; flex-direction: column; align-items: center; gap: 12px; }
/* No overflow:hidden here, so overlay badges (raised hand, kick) sit OVER the
   circle's edge instead of being clipped inside it. The Avatar rounds itself. */
.puck-av { --puck: clamp(48px, 22cqmin, 168px); position: relative; width: var(--puck); height: var(--puck); border-radius: 50%; }
.puck-av > .avatar { --av: var(--puck); }
.voice-puck.speaking .puck-av { box-shadow: 0 0 0 3px var(--online), 0 0 0 7px color-mix(in srgb, var(--online) 28%, transparent); }
.puck-name { display: flex; align-items: center; gap: 6px; color: var(--dim); font-size: 13px; font-weight: 600; max-width: 180px; }
.puck-name > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.puck-kick { position: absolute; top: 6%; right: 6%; background: rgba(0,0,0,.6); color: #fff; border: none; border-radius: 50%; width: 24px; height: 24px; cursor: pointer; font-size: 12px; line-height: 1; }
.puck-kick:hover { background: var(--red, #ed4245); }

/* Theater (maximized stream) */
.voice-theater { display: flex; flex-direction: column; height: 100%; background: #000; }
.theater-stage { position: relative; flex: 1; min-height: 0; background: #000; }
.theater-video { width: 100%; height: 100%; object-fit: contain; background: #000; display: block; }
.theater-fs { position: absolute; top: 10px; right: 10px; background: rgba(0,0,0,.55); color: #fff; border: none; width: 32px; height: 32px; border-radius: 8px; cursor: pointer; font-size: 16px; pointer-events: auto; }
.theater-fs:hover { background: rgba(0,0,0,.8); }
.theater-bar { display: flex; align-items: center; gap: 10px; padding: 8px 14px; background: var(--bg-1); border-top: 1px solid var(--line); }
.theater-bar .tb-title { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.theater-bar .tb-controls { margin-left: auto; display: flex; gap: 8px; }

/* Popped-out screen share: floating draggable mini-player over the whole app. */
.kp-floater {
  position: fixed; z-index: 2147483000; background: #000;
  border: 1px solid var(--line); border-radius: 10px; overflow: hidden;
  box-shadow: 0 18px 50px rgba(0,0,0,.6); user-select: none;
}
.kpf-head {
  display: flex; align-items: center; gap: 8px; padding: 6px 8px; cursor: move;
  background: var(--bg-1); border-bottom: 1px solid var(--line); font-size: 12px; color: var(--text-1);
}
.kpf-head > .fa-display { opacity: .7; }
.kpf-title { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
.kpf-btn {
  background: transparent; border: none; color: var(--text-2); cursor: pointer;
  width: 24px; height: 24px; border-radius: 6px; font-size: 13px; display: grid; place-items: center;
}
.kpf-btn:hover { background: rgba(255,255,255,.08); color: var(--text-1); }
.kpf-video { width: 100%; background: #000; }
.kpf-video .theater-video { width: 100%; height: 100%; }
.kpf-resize {
  position: absolute; right: 0; bottom: 0; width: 16px; height: 16px; cursor: nwse-resize;
  background: linear-gradient(135deg, transparent 50%, var(--text-2) 50%, var(--text-2) 60%, transparent 60%, transparent 72%, var(--text-2) 72%, var(--text-2) 82%, transparent 82%);
  opacity: .5;
}
.kpf-resize:hover { opacity: .9; }

/* Theater layout: grow the voice panel (resizable), dock the chat. */
body.kp-theater .voice-dock.expanded { max-height: none; height: 60vh; }

/* Drag-to-resize grip at the bottom of the voice dock. */
/* Drag-to-resize grip at the bottom of the voice dock. It sits above the
   floating composer (.composer-dock, z-index 6), which docks to the bottom of
   <main> and would otherwise sit on top of an 8px transparent strip and eat
   every pointer event aimed at it. The pill is always faintly visible so the
   handle is findable without hunting for a dead zone. */
.voice-resize {
  height: 11px; flex: 0 0 11px; cursor: ns-resize; background: transparent; touch-action: none;
  position: relative; z-index: 7;
  display: flex; align-items: center; justify-content: center;
}
.voice-resize::before {
  content: ''; width: 46px; height: 3px; border-radius: 999px;
  background: var(--line); opacity: .8; transition: background .12s ease, width .12s ease, opacity .12s ease;
}
.voice-resize:hover::before { background: var(--blue); width: 78px; opacity: 1; }

/* Minimized voice room: keep the audio alive but render nothing here — the
   sidebar "On Voice" panel is the control surface. */
.voice-dock.mini { position: absolute; width: 0; height: 0; overflow: hidden; pointer-events: none; }
.voice-bg { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Shared drawing overlay + tools + cursors */
.draw-wrap { position: absolute; inset: 0; pointer-events: none; }
.draw-canvas { position: absolute; inset: 0; pointer-events: none; }
.draw-canvas.active { pointer-events: auto; cursor: crosshair; touch-action: none; }
.draw-canvas.erasing { cursor: cell; }
.draw-cursors { position: absolute; inset: 0; pointer-events: none; }
.draw-cursor { position: absolute; transform: translate(-3px, -3px); display: flex; align-items: center; gap: 4px; }
.dc-dot { width: 10px; height: 10px; border-radius: 50%; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0,0,0,.5); flex-shrink: 0; }
.dc-name { color: #fff; font-size: 11px; font-weight: 700; padding: 1px 6px; border-radius: 6px; white-space: nowrap; text-shadow: 0 1px 1px rgba(0,0,0,.45); }
.draw-tools { position: absolute; top: 10px; left: 10px; display: flex; align-items: center; gap: 6px; background: rgba(0,0,0,.55); border-radius: 999px; padding: 5px 8px; pointer-events: auto; }
.draw-tools .dt { background: transparent; color: #fff; font-size: 15px; padding: 2px 6px; border-radius: 6px; cursor: pointer; }
.draw-tools .dt.on { background: var(--accent); }
.draw-tools .dt-color { width: 18px; height: 18px; border-radius: 50%; border: 2px solid rgba(255,255,255,.5); cursor: pointer; }
.draw-tools .dt-color.sel { border-color: #fff; transform: scale(1.12); }
.draw-tools .dt-size { width: 84px; accent-color: var(--accent); cursor: pointer; }
.draw-tools .dt-labelled { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 650; padding: 4px 10px; }
.draw-tools .dt-labelled i { font-size: 13px; }
.draw-tools .dt-done { background: var(--accent); margin-left: 2px; }
.draw-tools .dt-sep { width: 1px; height: 18px; background: rgba(255,255,255,.2); }
.draw-tools .dt:focus-visible, .draw-tools .dt-color:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Persistent voice dock */
.voice-dock.expanded { display: flex; flex-direction: column; max-height: 46vh; min-height: 200px; overflow: hidden; border-bottom: 1px solid var(--line); }
.voice-dock.expanded .voice-room { flex: 1; min-height: 0; }
.voice-cta { display: flex; align-items: center; gap: 14px; padding: 14px 18px; border-bottom: 1px solid var(--line); background: var(--bg-1); }
.voice-cta img { width: 40px; height: 40px; opacity: .9; }
.voice-cta .vcta-text { display: flex; flex-direction: column; min-width: 0; }
.voice-cta .vcta-text b { font-size: 15px; }
.voice-cta .vcta-text span { color: var(--dim); font-size: 13px; }
.voice-cta .btn-primary { margin-left: auto; flex-shrink: 0; }

/* New-DM member picker */
.dm-search { width: 100%; background: var(--bg-3); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; color: var(--text); outline: none; font-size: 14px; }
.dm-search:focus { border-color: var(--accent); }
.dm-pick-list { margin-top: 12px; max-height: 52vh; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.dm-pick-row { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: 8px; cursor: pointer; }
.dm-pick-row:hover { background: var(--hover); }
.dpr-meta { min-width: 0; }
.dpr-name { font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.dpr-user { font-size: 12px; color: var(--dim); }
.dm-pick-row.picked { background: var(--active); }
.dm-pick-row.picked .dpr-user { color: inherit; opacity: 0.75; }
.dpr-check { margin-left: auto; color: var(--accent); }
.dm-pick-row.picked .dpr-check { color: inherit; }

/* Multi-select "To:" chips (group DMs) */
.dm-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 10px; }
.dm-chips-to { color: var(--dim); font-size: 13px; margin-right: 2px; }
.dm-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--bg-3); border: 1px solid var(--line); border-radius: 999px; padding: 3px 10px; font-size: 13px; }
.dm-chip .x { cursor: pointer; color: var(--dim); display: inline-flex; }
.dm-chip .x:hover { color: var(--text); }

/* GIF (Giphy) picker + emoji board */
.emoji-btn { background: transparent; font-size: 18px; padding: 0 6px; line-height: 1; }
.emoji-backdrop { position: fixed; inset: 0; z-index: 200; }
.emoji-popover { position: absolute; bottom: calc(100% + 10px); right: 8px; z-index: 201; box-shadow: 0 16px 44px rgba(0,0,0,.5); border-radius: 10px; }
.giphy-modal { max-width: 560px; }
.giphy-attr { margin-left: 10px; font-size: 10px; color: var(--faint); letter-spacing: 1.5px; align-self: center; }
.giphy-grid { columns: 3; column-gap: 8px; margin-top: 12px; max-height: 52vh; overflow-y: auto; }
.giphy-cell { display: block; width: 100%; margin: 0 0 8px; padding: 0; border: none; background: var(--bg-1); border-radius: 8px; overflow: hidden; cursor: pointer; break-inside: avoid; }
.giphy-cell img { width: 100%; display: block; }
.giphy-cell:hover { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Profile banner editor */
.pf-banner-preview { height: 100px; border-radius: 10px; background-size: cover; background-position: center; display: flex; align-items: flex-end; justify-content: center; margin-bottom: 32px; }
.banner-tabs { display: flex; align-items: center; gap: 8px; margin: 6px 0 10px; flex-wrap: wrap; }
.seg { border: 1px solid var(--line); background: transparent; color: var(--text); padding: 5px 12px; border-radius: 8px; font-size: 13px; cursor: pointer; }
.seg.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.banner-colors { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.bc-row { display: flex; align-items: center; gap: 10px; }
.bc-label { width: 60px; font-size: 12px; color: var(--dim); }
.crop-stage.banner { width: 320px; height: 120px; border-radius: 10px; }

/* Settings */
.row-actions { white-space: nowrap; }
.row-actions .mini { margin-left: 4px; }
.mini.danger { color: var(--red, #ed4245); border-color: var(--red, #ed4245); }
.tag-picker { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 0; }
.tag-toggle { border: 1px solid var(--line); background: transparent; color: var(--text); border-radius: 12px; padding: 3px 10px; font-size: 12px; cursor: pointer; }
.tag-toggle.on { color: #fff; }
.tag-create { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.swatches { display: flex; gap: 5px; flex-wrap: wrap; }
.swatch { width: 22px; height: 22px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; }
.swatch.sel { border-color: var(--text); }
.tag-list { display: flex; flex-direction: column; gap: 8px; }
.tag-row { display: flex; align-items: center; gap: 10px; }
.audit-list { display: flex; flex-direction: column; gap: 6px; }
.audit-row { display: flex; gap: 10px; align-items: baseline; padding: 6px 8px; border-radius: 6px; background: var(--bg-1); font-size: 13px; }
.audit-when { color: var(--faint); font-size: 11px; white-space: nowrap; min-width: 130px; }
.audit-text { color: var(--dim); }
.audit-text b { color: var(--text); }

/* GIF framing stage (banner-ratio window, drag/zoom the animated GIF). */
.crop-stage.gif-stage { width: 320px; height: 110px; border-radius: 12px; background-color: #000; }

/* ---- Two-factor section (Edit Profile) ---- */
.tfa { background: var(--bg-3); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }
.tfa-row { display: flex; align-items: center; gap: 10px; }
.tfa-row .muted { flex: 1; font-size: 13px; }
.tfa-on { flex: 1; color: var(--green, #3ba55d); font-size: 13px; display: flex; align-items: center; gap: 8px; }
.tfa-setup { display: flex; gap: 14px; align-items: flex-start; }
.tfa-qr { width: 132px; height: 132px; border-radius: 10px; background: #fff; padding: 6px; flex: none; }
.tfa-steps { display: flex; flex-direction: column; gap: 8px; font-size: 13px; min-width: 0; }
.tfa-steps code { font-family: var(--mono); font-size: 11px; word-break: break-all; background: var(--bg-0); padding: 2px 6px; border-radius: 5px; }
.tfa-confirm { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.tfa-confirm input { width: 110px; font-family: var(--mono); letter-spacing: 3px; }

/* ---- "New version available" banner (versionCheck.ts). Theme-driven. ---- */
.kp-upd {
  position: fixed;
  /* Clear the mobile status bar / notch — it also swallowed taps before. */
  top: calc(12px + env(safe-area-inset-top, 0px));
  left: 50%; transform: translateX(-50%);
  z-index: 2147483646;
  display: flex; align-items: center; gap: 10px;
  width: max-content; max-width: min(94vw, 480px);
  padding: 8px 10px 8px 16px; border-radius: 16px;
  background: var(--bg-2); color: var(--text);
  border: 1px solid var(--line);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  font-size: 13.5px; font-weight: 500;
  -webkit-app-region: no-drag;
}
/* Electron: the 40px custom titlebar is above everything and draggable —
   sit below it or the banner is clipped and unclickable. */
.kp-upd.desktop { top: 52px; }
.kp-upd-msg { flex: 1 1 auto; min-width: 0; }
.kp-upd .btn-primary { white-space: nowrap; flex: 0 0 auto; }
.kp-upd-x {
  background: transparent; border: none; color: var(--text-dim, var(--text));
  cursor: pointer; font-size: 15px; line-height: 1; padding: 6px 8px; flex: 0 0 auto;
}
.kp-upd-x:hover { color: var(--text); }


/* ---- Focused-workspace layout (big tools auto-collapse the side panels) ---- */
@media (min-width: 761px) {
  .app.tool-focus { transition: grid-template-columns .18s ease; }
  .app.tool-focus .sidebar { overflow: hidden; }
  .app.tool-left-collapsed { --col-l: 0px; }
}
/* Small edge tabs to collapse/expand each panel while in a tool. */
.tool-edge {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 30;
  width: 20px; height: 48px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-2); color: var(--dim);
  border: 1px solid var(--line); cursor: pointer;
  opacity: 0.65; transition: opacity .12s ease, background .12s ease, color .12s ease;
  font-size: 12px;
}
.tool-edge:hover { opacity: 1; color: var(--text); background: var(--bg-3); }
.tool-edge.left { left: 0; border-left: none; border-radius: 0 8px 8px 0; }
/* Right panel is hidden below 1100px anyway; drop its tab there. Both tabs go
   on phones, where tools already use the full width. */
@media (max-width: 760px) { .tool-edge { display: none; } }
/* ---- Whiteboards ---- */

/* Sidebar entry (pinned above the channel list). */
.wb-nav-btn {
  display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: transparent; color: var(--text); border: none; cursor: pointer;
  padding: 7px 10px; border-radius: 8px; font-size: 14px; font-weight: 600; margin-bottom: 4px;
}
.wb-nav-btn:hover { background: var(--hover); }
.wb-nav-btn.active { background: var(--active, var(--hover)); color: var(--accent); }
.wb-nav-btn .npi { font-size: 15px; }

/* Sidebar: collapsible live list of boards under the Whiteboards entry. */
.wb-nav { margin-bottom: 4px; }
.wb-nav .wb-nav-btn { margin-bottom: 2px; }
.wb-nav-toggle { margin-left: auto; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 5px; opacity: .55; font-size: 11px; }
.wb-nav-toggle:hover { opacity: 1; background: rgba(255,255,255,.1); }
.wb-nav-list { display: flex; flex-direction: column; margin: 0 0 4px 12px; padding-left: 8px; border-left: 1px solid var(--line); }
.wb-nav-note { font-size: 12px; color: var(--text-2); padding: 4px 8px; }
.wb-nav-sub { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-2); padding: 6px 8px 2px; }
.wb-nav-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; background: transparent; border: none; color: var(--text); cursor: pointer; padding: 4px 8px; border-radius: 6px; font-size: 13px; min-width: 0; }
.wb-nav-item:hover { background: var(--hover); }
.wb-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-nav-item.is-active .wb-item-name { font-weight: 600; }
.wb-item-count { flex: none; font-size: 11px; color: var(--text-2); background: rgba(255,255,255,.09); border-radius: 9px; padding: 0 6px; line-height: 16px; }
.wb-live { flex: none; width: 7px; height: 7px; border-radius: 50%; background: #10b981; animation: wb-live-pulse 2s infinite; }
@keyframes wb-live-pulse { 0% { box-shadow: 0 0 0 0 rgba(16,185,129,.5); } 70% { box-shadow: 0 0 0 5px rgba(16,185,129,0); } 100% { box-shadow: 0 0 0 0 rgba(16,185,129,0); } }
.wb-item-dot { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--text-2); opacity: .35; }
/* Tiny board cover in the sidebar list; a green ring marks an active board. */
.wb-item-cover { flex: none; width: 18px; height: 18px; border-radius: 4px; background-size: cover; background-position: center; background-color: var(--bg-2); }
.wb-item-cover.live { box-shadow: 0 0 0 1px var(--bg-1), 0 0 0 2px #10b981; }

/* Launcher */
.wb-launcher { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--bg-2); }
.wb-head { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--line); }
.wb-crumbs { display: flex; align-items: center; gap: 4px; flex: 1; min-width: 0; flex-wrap: wrap; }
.wb-crumb-wrap { display: inline-flex; align-items: center; gap: 4px; }
.wb-crumb { background: transparent; border: none; color: var(--text); font-size: 15px; font-weight: 700; cursor: pointer; padding: 2px 4px; border-radius: 6px; }
.wb-crumb:hover { background: var(--hover); }
.wb-sep { color: var(--faint); }
.wb-actions { display: flex; gap: 6px; flex-shrink: 0; }
.btn-ghost.sm, .btn-primary.sm { padding: 6px 12px; font-size: 13px; border-radius: 8px; }

.wb-grid { flex: 1; overflow: auto; padding: 16px; display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); align-content: start; }
.wb-card {
  display: flex; flex-direction: column; padding: 0; border: 1px solid var(--line); border-radius: 12px;
  overflow: hidden; background: var(--bg-1); cursor: pointer; text-align: left; transition: border-color .12s, transform .08s;
}
.wb-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.wb-thumb { height: 110px; display: flex; align-items: center; justify-content: center; font-size: 34px; color: rgba(255,255,255,.55); }
/* Board cover image: cropped to fill the tile, consistent across all boards. */
.wb-cover { background-size: cover; background-position: center; background-repeat: no-repeat; }
.wb-folder-thumb { background: linear-gradient(160deg, #2a2f37, #1b1e24); color: #cdd3dc; }
/* Department-colored folder cards (color set inline via --dept). */
.wb-folder { border-color: color-mix(in srgb, var(--dept, var(--line)) 40%, var(--line)); }
.wb-card-foot { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-top: 1px solid var(--line); }
.wb-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wb-dots { color: var(--dim); padding: 0 4px; border-radius: 6px; font-weight: 700; }
.wb-dots:hover { background: var(--hover); color: var(--text); }

.wb-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; color: var(--dim); }

/* Board view */
.wb-board { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--bg-2); }
.wb-bar { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--line); }
.wb-back { background: var(--bg-3); border: none; color: var(--text); width: 32px; height: 32px; border-radius: 8px; cursor: pointer; font-size: 16px; }
.wb-back:hover { background: var(--hover); }
.wb-title { font-weight: 700; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
.wb-title { display: inline-flex; align-items: center; gap: 8px; cursor: text; }
.wb-title-edit-btn { opacity: 0; background: none; border: none; color: var(--dim); cursor: pointer; font-size: 12px; padding: 2px 4px; border-radius: 5px; flex-shrink: 0; }
.wb-title:hover .wb-title-edit-btn { opacity: 0.75; }
.wb-title-edit-btn:hover { opacity: 1; background: rgba(255,255,255,0.1); }
.wb-title-edit { flex: 1; min-width: 0; max-width: 340px; font-weight: 700; font-size: 15px; color: var(--text); background: var(--bg-0); border: 1px solid var(--accent); border-radius: 7px; padding: 5px 9px; outline: none; }
.wb-peers { display: flex; gap: -6px; align-items: center; }
.wb-peer { display: inline-flex; margin-left: -6px; border-radius: 50%; outline: 2px solid var(--accent); outline-offset: 0; background: var(--bg-2); }
.wb-peer:first-child { margin-left: 0; }

.wb-canvas { position: relative; flex: 1; min-height: 0; }
.wb-canvas .excalidraw { height: 100%; }
.wb-canvas > div { height: 100%; }
.wb-loading { display: flex; align-items: center; justify-content: center; height: 100%; color: var(--dim); font-size: 14px; }
.wb-overlay { position: absolute; inset: 0; background: var(--bg-2); }

/* Keep the Excalidraw editor below our app modals/menus. */
.excalidraw { --zIndex-layerUI: 4; }

@media (max-width: 760px) {
  .wb-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); padding: 12px; }
}
/* "Liquid glass" treatments — frosted blur + a bright top rim + soft shadow,
   PLUS true refraction via the #kp-glass SVG displacement filter (defined in
   index.html), the same technique BYD uses. The plain blur is the fallback;
   the url() line adds the warp on browsers that support SVG filters in
   backdrop-filter (Chromium: Chrome/Edge). Firefox/Safari keep just the blur. */

/* =====================================================================
   Global glass buttons — every chrome button across the app is round and
   glassy. Neutral controls get a dark tint; primary actions get the accent
   color; leave/danger get red; the composer Send stays gold (below). Tiny
   inline controls (reactions, message-hover icons, color swatches, context-menu
   rows, the emoji picker) keep their own styles so menus and pickers stay usable. */
.icon-btn, .hamburger, .add,
.wb-nav-btn, .wb-back, .vctrl, .vs-btn, .modal-close, .seg, .tab, .mini,
.theater-fs, .vbtn, .tag-toggle,
.btn-ghost, .btn-primary {
  border-radius: 999px;
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  backdrop-filter: blur(8px) saturate(1.4);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-top-color: rgba(255, 255, 255, 0.32);
  box-shadow: 0 5px 16px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.15);
}

/* Neutral dark-tinted glass. */
.icon-btn, .hamburger, .add,
.wb-nav-btn, .wb-back, .vctrl, .vs-btn, .modal-close, .seg, .tab, .mini,
.theater-fs, .vbtn, .tag-toggle, .btn-ghost {
  background: rgba(14, 18, 24, 0.42);
  color: #e8ebf1;
}
.icon-btn:hover, .hamburger:hover, .add:hover, .wb-nav-btn:hover, .wb-back:hover, .vctrl:hover,
.vs-btn:hover, .modal-close:hover, .seg:hover, .tab:hover, .mini:hover, .theater-fs:hover, .vbtn:hover, .tag-toggle:hover, .btn-ghost:hover {
  background: rgba(30, 36, 46, 0.52);
  border-color: rgba(255, 255, 255, 0.24);
  color: #fff;
}

/* Primary / selected = accent glass (driven by --accent). */
.btn-primary, .seg.on, .tab.active, .tag-toggle.on, .vctrl.on, .vs-btn.on {
  background: color-mix(in srgb, var(--accent) 74%, transparent);
  color: #fff;
  border: 1px solid color-mix(in srgb, var(--accent) 55%, #ffffff);
  border-top-color: color-mix(in srgb, var(--accent) 25%, #ffffff);
  box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 34%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 88%, transparent); color: #fff; }

/* Leave / danger = red glass. */
.vctrl.leave, .vs-hang, .mini.danger {
  border-radius: 999px;
  background: rgba(220, 60, 62, 0.72);
  color: #fff;
  border: 1px solid rgba(255, 175, 175, 0.5);
  border-top-color: rgba(255, 222, 222, 0.85);
  box-shadow: 0 5px 16px rgba(120, 20, 20, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.35);
  -webkit-backdrop-filter: blur(8px) saturate(1.4);
  backdrop-filter: blur(8px) saturate(1.4);
}
.vctrl.leave:hover, .vs-hang:hover, .mini.danger:hover { background: rgba(237, 76, 78, 0.9); }

.btn-primary:disabled, .btn-ghost:disabled { opacity: 0.55; }

/* =====================================================================
   Floating top info bar that OVERLAYS the message list, so the chat frosts
   and refracts through it as it scrolls behind. Fully pill-shaped, like the
   message bar. Absolutely positioned inside .chat-pane (which sits BELOW the
   voice panel in flow, so they never collide). */
.chat-pane { position: relative; flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* Reserve space so content begins below the floating bar. */
.chat-pane .voice-cta { margin-top: 76px; }
/* Header buttons stay subtle (no nested glass). */
@media (max-width: 760px) {
  .chat-pane .voice-cta { margin-top: 72px; }
}

/* Emoji picker opened from a modal (channel-name editor): centered, so it
   escapes the modal's clipped overflow. */
.emoji-popover.center {
  position: fixed; top: 50%; left: 50%; right: auto; bottom: auto;
  transform: translate(-50%, -50%);
}

/* =====================================================================
   Modal / dialog windows (Create channel, New message, Workspace settings,
   etc.) — dark-tinted liquid glass that frosts and refracts the app behind.
   The scrim is softened so the refraction stays visible. */
.overlay {
  background: rgba(8, 9, 11, 0.5);
}
.modal {
  background: rgba(16, 20, 27, 0.62);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: url(#kp-glass) blur(16px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-top-color: rgba(255, 255, 255, 0.26);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
/* The wiz footer sits OUTSIDE the padded .modal-body, so its buttons were
   flush against the modal edges. Inset them to match the body's padding. */
.modal .wiz-foot { padding: 0 22px 22px; }

/* Light theme: a bright frosted panel instead of the dark tint. */
[data-theme='light'] .overlay, [data-theme='sakura'] .overlay { background: rgba(18, 22, 30, 0.34); }
[data-theme='light'] .modal, [data-theme='sakura'] .modal {
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-top-color: rgba(255, 255, 255, 0.92);
  box-shadow: 0 28px 70px rgba(0, 0, 0, 0.28), inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
/* Loaded LAST so these rules win over styles.css and features.css. */

/* Right-aligned modal footer (fixes the odd Cancel/Save spacing). */
.wiz-foot.end { justify-content: flex-end; gap: 10px; }

/* Mobile nav toggles — hidden on desktop. */
.hamburger { display: none; width: 32px; height: 32px; border-radius: 6px; align-items: center; justify-content: center; font-size: 18px; color: var(--dim); margin-right: 4px; flex-shrink: 0; }
.hamburger:hover { background: var(--hover); color: var(--text); }
.nav-backdrop { display: none; }

/* Emoji board container hugs the picker (emoji-mart renders a fixed width), and
   never overflows a narrow viewport. */
.emoji-popover { width: max-content; max-width: min(360px, calc(100vw - 16px)); }

/* Floating "jump to newest" button (Slack/Discord style). */
.main { position: relative; }

@media (max-width: 760px) {
  .app { grid-template-columns: 1fr !important; }

  /* Left channel sidebar slides in. The `display:flex !important` overrides the
     old `.sidebar { display:none }` mobile rule in styles.css that was hiding it. */
  .sidebar {
    display: flex !important;
    position: fixed; left: 0; top: 0; bottom: 0; width: 84vw; max-width: 300px; z-index: 120;
    transform: translateX(-102%); transition: transform .2s ease;
  }
  .sidebar.open { transform: translateX(0); box-shadow: 0 0 50px rgba(0,0,0,.6); }

  .hamburger { display: flex; }

  /* Tools (Whiteboards / Currents) are desktop experiences: hidden on phones. */
  .wb-nav, .wb-nav-btn { display: none; }
  .nav-backdrop { display: block; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 110; }

  .modal { max-width: 100% !important; max-height: 92vh; }
  .att-image, .att-video { max-width: 100%; }

  .giphy-grid { columns: 2; }
  .emoji-popover { left: 8px; right: auto; }

  .voice-cta { flex-wrap: wrap; }
  .voice-cta .btn-primary { margin-left: 0; }
  .voice-dock.expanded { max-height: 52vh; }

  /* Modals share the glass translucency problem on phones — go opaque. */
  .modal { background: var(--bg-2) !important; }
}

/* Avatar crop */
.crop-wrap { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.crop-stage { width: 280px; height: 280px; border-radius: 50%; overflow: hidden; background: #000; cursor: grab; touch-action: none; box-shadow: 0 0 0 4px var(--bg-3); }
.crop-stage:active { cursor: grabbing; }
.crop-stage canvas { display: block; }
.crop-controls { width: 280px; max-width: 100%; }

.theme-dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }

/* =====================================================================
   Mobile overhaul (phones / installed PWA).
   - No pinch zoom, no whole-page scrolling: only the message list, channel
     list, and member list scroll.
   - The liquid-glass blur doesn't render well on mobile — everything goes
     flat, using the theme's own surface colors.
   - Simpler composer: just [+] [message] [Send]; GIF + attachments live in
     the + menu, and the phone's keyboard provides emoji. */
@media (max-width: 760px) {
  /* --- lock the frame; scroll only inside designated panes --- */
  html, body, #root { height: 100dvh; }
  body { position: fixed; inset: 0; overflow: hidden; overscroll-behavior: none; }
  .app { height: 100dvh; max-width: 100vw; overflow: hidden; }
  .main { max-width: 100vw; overflow-x: hidden; }

  /* --- flat surfaces: kill every blur/glass effect --- */
  * { -webkit-backdrop-filter: none !important; backdrop-filter: none !important; }

  /* Top bar: full-width flat bar under the status bar (safe-area aware). */
  .chat-pane .voice-cta { margin-top: calc(60px + env(safe-area-inset-top)); }

  /* Drawers respect the notch and go flat. */
  .sidebar { padding-top: env(safe-area-inset-top); }

  /* Buttons/pills elsewhere: flat theme surfaces instead of glass. */
  .icon-btn, .hamburger, .add,
  .vctrl, .vs-btn, .modal-close, .seg, .tab, .mini, .btn-ghost {
    background: var(--bg-3); border-color: var(--line); box-shadow: none;
  }
  .btn-primary { background: var(--accent); border-color: var(--accent); box-shadow: none; }
}
/* Font Awesome icon alignment. Icons are rendered as <i class="fa-solid fa-…">
   inside buttons and inline labels that previously held emoji. These rules keep
   them centered, inheriting the button's color, and sized consistently. */
.fa-solid, .fa-regular, .fa-brands, i.fa, i[class*="fa-"] {
  line-height: 1;
  vertical-align: -0.05em;
}

/* Inline icons that sit before a text label (sidebar buttons, menu rows, voice
   strip, chips) get a touch of trailing space. */
.npi.fa-solid, .vs-chan .fa-solid, .ctx-ic { margin-right: 2px; }

/* Context-menu leading icon: fixed-width so labels line up. */
.ctx-ic { display: inline-block; width: 18px; text-align: center; font-size: 13px; opacity: 0.92; }

/* Channel-list and header type glyphs render at a comfortable size. */
.hash .fa-solid { font-size: 0.82em; }
/* Full-screen image viewer (Discord-style). The photo is centered and scaled to
   fit the window with ~130px of breathing room on every side; the glass control
   pill floats 50px below the picture. The backdrop tints to the active theme
   (--lb-backdrop): dark on dark themes, medium gray on the light theme. */
.lb-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: var(--lb-backdrop, rgba(8, 10, 14, 0.95));
  display: flex; align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}

/* Shrink-wraps the image so the toolbar can anchor to the picture's edges. */
.lb-stage {
  position: relative;
  display: flex; align-items: center; justify-content: center;
}

/* Scaled to fit inside the viewport minus 130px on each side, aspect preserved
   (never upscaled past natural size). */
.lb-img {
  display: block;
  max-width: calc(100vw - 260px);
  max-height: calc(100vh - 260px);
  width: auto; height: auto;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 18px 70px rgba(0, 0, 0, 0.55);
  transform-origin: center center;
  transition: transform 0.18s ease;
  user-select: none;
}

/* Toolbar — a big pill of liquid glass, centered 50px under the photo. */
.lb-bar {
  position: absolute; z-index: 2;
  top: calc(100% + 50px);
  left: 50%; transform: translateX(-50%);
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px;
  border-radius: 999px;
  background: rgba(14, 18, 24, 0.5);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: url(#kp-glass) blur(14px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-top-color: rgba(255, 255, 255, 0.36);
  box-shadow: 0 12px 38px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.lb-btn {
  width: 50px; height: 50px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: #e8ebf1; font-size: 20px; background: transparent; cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease;
}
.lb-btn:hover { background: rgba(255, 255, 255, 0.14); color: #fff; }

.lb-more-wrap { position: relative; display: inline-flex; }

/* "More" menu pops up above the ⋯ button. */
.lb-menu {
  position: absolute; bottom: calc(100% + 14px); right: 0; min-width: 196px;
  background: #1c2027; border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 12px;
  padding: 6px; box-shadow: 0 16px 44px rgba(0, 0, 0, 0.55); z-index: 3;
}
.lb-mi {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  padding: 10px 11px; border-radius: 8px; color: #e8ebf1; font-size: 13.5px; cursor: pointer;
}
.lb-mi:hover { background: rgba(255, 255, 255, 0.10); color: #fff; }
.lb-mi i { width: 16px; text-align: center; opacity: 0.9; }
.lb-sep { height: 1px; background: rgba(255, 255, 255, 0.1); margin: 5px 4px; }

/* Details card floats above the toolbar. */
.lb-details {
  position: absolute; bottom: calc(100% + 14px); left: 50%; transform: translateX(-50%);
  width: 290px; max-width: 86vw;
  background: #1c2027; border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 12px;
  padding: 11px 13px; box-shadow: 0 16px 44px rgba(0, 0, 0, 0.55); z-index: 3;
}
.lb-d-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; color: #fff; font-size: 13px; }
.lb-d-head button { color: var(--faint, #9aa3af); width: 22px; height: 22px; border-radius: 6px; }
.lb-d-head button:hover { color: #fff; background: rgba(255, 255, 255, 0.1); }
.lb-d-row { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; font-size: 12px; color: #9aa3af; }
.lb-d-row b { color: #e8ebf1; font-weight: 600; max-width: 175px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Tiny confirmation toast (e.g. "Image copied"). */
.lb-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); z-index: 310;
  background: #1c2027; border: 1px solid rgba(255, 255, 255, 0.14); color: #fff;
  padding: 9px 16px; border-radius: 10px; font-size: 13px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}

/* Tighter on small screens — 130px padding would leave no photo. */
@media (max-width: 760px) {
  .lb-img { max-width: calc(100vw - 32px); max-height: calc(100vh - 180px); }
  .lb-bar { top: calc(100% + 28px); gap: 4px; padding: 7px 9px; }
  .lb-btn { width: 44px; height: 44px; font-size: 18px; }
}
/* "Currents" — kanban boards. The launcher reuses the whiteboard launcher
   classes (.wb-launcher / .wb-grid / .wb-card / .wb-bar). These rules cover the
   board itself: a horizontally scrolling row of columns full of cards. */
.kb-card-modal > .wiz-foot { flex-wrap: wrap; gap: 8px; }

.kb-board { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--main-bg); }
.kb-board-title { flex: 1; min-width: 0; background: transparent; border: none; color: var(--text); font-size: 16px; font-weight: 700; outline: none; padding: 5px 8px; border-radius: 7px; }
.kb-board-title:focus { background: var(--bg-2); }

/* Thumbnail tint on the launcher cards. */
.wb-thumb.kb-thumb { background: linear-gradient(135deg, #2f80ed, #14b8a6); color: #fff; }

.kb-canvas { flex: 1; min-height: 0; overflow-x: auto; overflow-y: hidden; padding: 14px; }
.kb-cols { display: flex; gap: 12px; align-items: flex-start; height: 100%; }

.kb-col {
  width: 286px; flex: 0 0 286px; max-height: 100%;
  display: flex; flex-direction: column;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; padding: 8px;
}
.kb-col.drop { outline: 2px dashed var(--accent); outline-offset: -2px; }

.kb-col-head { display: flex; align-items: center; gap: 4px; padding: 2px 2px 8px; cursor: grab; }
.kb-list-title { flex: 1; min-width: 0; background: transparent; border: none; color: var(--text); font-weight: 700; font-size: 14px; outline: none; padding: 4px 6px; border-radius: 6px; }
.kb-list-title:focus { background: var(--bg-0); }
.kb-count { color: var(--faint); font-size: 12px; min-width: 20px; text-align: center; }
.kb-col-del { color: var(--faint); padding: 4px 7px; border-radius: 6px; font-size: 12px; }
.kb-col-del:hover { color: var(--red, #ed4245); background: var(--hover); }

.kb-cards { flex: 1; min-height: 8px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding: 2px; }

.kb-card {
  background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px; padding: 9px 11px;
  cursor: pointer; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.kb-card:hover { border-color: var(--accent); }

/* Live drag: someone else is holding this card right now. Tinted dashed
   outline in their presence color + a name chip, pulsing until they drop. */
.kb-card { position: relative; }
.kb-card.kb-held { outline: 2px dashed var(--held, var(--accent)); outline-offset: 2px; opacity: 0.8; animation: kb-held-pulse 1.1s ease-in-out infinite; }
@keyframes kb-held-pulse { 50% { opacity: 0.55; } }
.kb-held-chip {
  position: absolute; top: -9px; right: 8px; z-index: 2;
  font-size: 10px; font-weight: 700; color: #fff; border-radius: 999px; padding: 2px 8px;
  display: inline-flex; gap: 4px; align-items: center; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}
.kb-card-title { color: var(--text); font-size: 14px; white-space: pre-wrap; word-break: break-word; }
.kb-card-desc-flag { display: inline-block; margin-top: 5px; color: var(--faint); font-size: 11px; }

.kb-add-btn { margin-top: 6px; width: 100%; text-align: left; color: var(--dim); padding: 8px 10px; border-radius: 8px; font-size: 13px; }
.kb-add-btn:hover { background: var(--hover); color: var(--text); }

.kb-add-card { margin-top: 6px; display: flex; flex-direction: column; gap: 6px; }
.kb-add-card textarea {
  width: 100%; resize: none; box-sizing: border-box; font-family: inherit; font-size: 14px;
  background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; color: var(--text); outline: none;
}
.kb-add-card textarea:focus { border-color: var(--accent); }
.kb-add-row { display: flex; gap: 6px; }

.kb-col-new { background: transparent; border: 1px dashed var(--line); gap: 8px; }
.kb-newlist { background: transparent; border: none; color: var(--text); font-size: 14px; outline: none; padding: 6px; width: 100%; }
.kb-newlist::placeholder { color: var(--faint); }

@media (max-width: 760px) {
  .kb-col { width: 84vw; flex-basis: 84vw; }
}

/* ---- Card metadata (labels / due / assignees) ---- */
.kb-labels { display: flex; gap: 4px; margin-bottom: 6px; }
.kb-label { width: 32px; height: 6px; border-radius: 3px; display: inline-block; }
.kb-card-meta { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
.kb-due { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--dim); background: var(--bg-0); border: 1px solid var(--line); padding: 2px 7px; border-radius: 6px; }
.kb-due.overdue { color: #fff; background: var(--red, #ed4245); border-color: transparent; }
.kb-avatars { margin-left: auto; display: inline-flex; align-items: center; }
.kb-avatars > * { margin-left: -5px; }
.kb-avatars > *:first-child { margin-left: 0; }
.kb-ava-more { font-size: 10px; color: var(--dim); background: var(--bg-3); border: 1px solid var(--line); border-radius: 50%; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; }

/* ---- Card modal ---- */
.kb-modal label { display: block; font-size: 12px; font-weight: 700; color: var(--dim); margin: 12px 2px 6px; text-transform: uppercase; letter-spacing: 0.03em; }
.kb-modal label:first-child { margin-top: 0; }
.kb-desc { width: 100%; resize: vertical; box-sizing: border-box; font-family: inherit; font-size: 14px; background: var(--bg-3); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; color: var(--text); outline: none; }
.kb-desc:focus { border-color: var(--accent); }
.kb-label-row { display: flex; gap: 8px; }
.kb-label-pill { width: 44px; height: 26px; border-radius: 7px; cursor: pointer; color: #fff; font-size: 12px; opacity: 0.55; border: 2px solid transparent; }
.kb-label-pill.on { opacity: 1; border-color: #fff3; }
.kb-label-pill:hover { opacity: 0.85; }
.kb-field-row { display: flex; gap: 12px; }
.kb-field { flex: 1; min-width: 0; }
.kb-due-row { display: flex; gap: 6px; align-items: center; }
/* Themed "List" dropdown pill (replaces the native select, which can't be styled). */
.kbm-select {
  display: inline-flex; align-items: center; gap: 8px; width: 100%; padding: 7px 12px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--bg-1);
  color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer; text-align: left;
}
.kbm-select .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kbm-select i { font-size: 10px; opacity: .6; }
.kbm-select:hover { border-color: var(--accent); }
.kb-assignees { max-height: 180px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.kb-assignee { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 8px; cursor: pointer; }
.kb-assignee:hover { background: var(--hover); }
.kb-assignee.on { background: var(--active); }
.kb-assignee .ka-name { flex: 1; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kb-assignee i { color: var(--accent); }
.kb-assignee.on i { color: inherit; }

/* ---- Board categories (launcher sections + create modal) ---- */
.kb-cats-scroll { flex: 1; min-height: 0; overflow-y: auto; padding-bottom: 16px; }
.kb-cat-head {
  display: flex; align-items: center; gap: 9px; padding: 18px 18px 0;
  font-size: 12px; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--dim);
}
.kb-cat-head i { color: var(--cat); font-size: 14px; }
.kb-cat-count { color: var(--faint); font-weight: 600; }
.wb-grid.kb-sec { flex: none; overflow: visible; padding-top: 10px; }
.kb-cat-options { display: flex; flex-wrap: wrap; gap: 8px; }
.kb-cat-opt {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: 9px; font-size: 13px; font-weight: 600; cursor: pointer;
  background: var(--bg-3); border: 2px solid var(--line); color: var(--text);
}
.kb-cat-opt i { color: var(--cat); }
.kb-cat-opt:hover { border-color: var(--cat); }
.kb-cat-opt.on { border-color: var(--cat); background: color-mix(in srgb, var(--cat) 18%, transparent); }
.kb-cat-chip {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  color: #fff; font-size: 12px; font-weight: 700; padding: 4px 11px; border-radius: 999px;
}

/* ---- Media: card covers, board bg, Trello-style card modal ---- */
.kb-card-cover { width: calc(100% + 22px); margin: -9px -11px 8px; max-height: 140px; object-fit: cover; display: block; border-radius: 8px 8px 0 0; background: #000; }
.kb-viewers { display: inline-flex; align-items: center; gap: 2px; margin-left: 6px; }
.kb-viewers > * { margin-left: -5px; }
.kb-viewers > *:first-child { margin-left: 0; }
.kb-viewers-label { color: var(--faint); font-size: 11px; margin-left: 7px; }
.kb-dim-pop {
  position: absolute; top: 52px; right: 16px; z-index: 80;
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0,0,0,.45);
}
.kb-dim-label { color: var(--dim); font-size: 12px; display: inline-flex; gap: 6px; align-items: center; white-space: nowrap; }
.kb-board { position: relative; }

.kb-card-modal { max-width: 860px !important; width: 100%; padding: 0; overflow: hidden; }
.kbm-cover { height: 170px; background-size: cover; background-position: center; background-color: #000; position: relative; }
.kbm-cover-btn {
  position: absolute; right: 10px; bottom: 10px; font-size: 12px;
  background: rgba(0,0,0,.65); color: #fff; padding: 6px 12px; border-radius: 8px; cursor: pointer;
}
.kbm-cover-btn:hover { background: rgba(0,0,0,.85); }
.kbm-cover-actions { position: absolute; right: 10px; bottom: 10px; display: flex; gap: 8px; }
.kbm-cover-actions .kbm-cover-btn { position: static; }

/* Department filter chips (shared by Currents / Whiteboards / Charts) */
.dept-filter { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

/* Auto-collapsing filter: the strip never wraps and never scrolls — when the
   chips can't fit the available width, the component swaps itself for a
   single dropdown button (the invisible strip stays mounted for measuring). */
.df-wrap { flex: 1 1 auto; min-width: 0; position: relative; display: flex; align-items: center; }
.df-strip { flex: 1; min-width: 0; flex-wrap: nowrap; overflow: hidden; }
.df-strip .df-chip { flex: none; white-space: nowrap; }
.df-strip.ghost { visibility: hidden; position: absolute; inset: 0; pointer-events: none; }
.df-compact { display: inline-flex; flex: none; }
.df-caret { font-size: 10px; margin-left: 2px; color: var(--faint); }
/* The title/crumbs yield leftover header space to the filter. */
.wb-head:has(.df-wrap) .wb-crumbs { flex: 0 0 auto; }
.ch-side-filter .df-wrap { width: 100%; }
.df-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--dim); font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.df-chip:hover { color: var(--text); border-color: var(--cat, var(--accent)); }
.df-chip.on { color: var(--text); border-color: var(--cat, var(--accent)); background: color-mix(in srgb, var(--cat, var(--accent)) 18%, transparent); }
.df-chip i { color: var(--cat, var(--dim)); font-size: 11px; }

/* Manage-departments modal (shared by Currents / Whiteboards / Charts) */
.dept-list { display: flex; flex-direction: column; gap: 2px; max-height: 56vh; overflow-y: auto; }
.dept-row { display: flex; align-items: center; gap: 10px; padding: 5px 8px; border-radius: 8px; }
.dept-row:hover { background: var(--hover); }
.dept-dot { width: 28px; height: 28px; border-radius: 8px; color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; flex: none; }
.dept-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-size: 14px; }
.dept-acts { display: flex; gap: 2px; opacity: 0; }
.dept-row:hover .dept-acts { opacity: 1; }
.dept-acts button { width: 26px; height: 26px; border-radius: 6px; color: var(--dim); }
.dept-acts button:hover { background: var(--hover); color: var(--text); }
.dept-acts button.danger:hover { color: #ed4245; }
.dept-style { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px 12px; }
.dept-icons { display: flex; gap: 4px; flex-wrap: wrap; }
.dept-ic { width: 26px; height: 26px; border-radius: 6px; color: var(--dim); }
.dept-ic:hover { background: var(--hover); color: var(--text); }
.dept-ic.sel { outline: 2px solid var(--accent); color: var(--text); }
.kbm-body { display: grid; grid-template-columns: 1fr 300px; gap: 20px; max-height: 62vh; overflow-y: auto; }
.kbm-main { min-width: 0; }
.kbm-title { width: 100%; box-sizing: border-box; background: transparent; border: none; outline: none; color: var(--text); font-size: 19px; font-weight: 800; padding: 4px 2px 10px; }
.kbm-side { min-width: 0; border-left: 1px solid var(--line); padding-left: 18px; }
.kbm-side-head { font-size: 13px; font-weight: 700; color: var(--text); display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.kbm-att-head { display: flex; align-items: center; gap: 10px; }
.kbm-att-head label { flex: 1; }
.kbm-atts { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.kbm-empty { color: var(--faint); font-size: 13px; padding: 4px 2px; }
.kbm-att { display: flex; gap: 10px; align-items: center; background: var(--bg-3); border: 1px solid var(--line); border-radius: 10px; padding: 8px; }
.kbm-att-thumb { width: 64px; height: 48px; object-fit: cover; border-radius: 6px; background: #000; flex: none; }
.kbm-att-file { width: 64px; height: 48px; display: flex; align-items: center; justify-content: center; background: var(--bg-0); border-radius: 6px; color: var(--dim); font-size: 20px; flex: none; }
.kbm-att-meta { min-width: 0; flex: 1; }
.kbm-att-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kbm-att-actions { display: flex; gap: 12px; margin-top: 4px; font-size: 12px; }
.kbm-att-actions a, .kbm-att-actions button { color: var(--dim); text-decoration: underline; cursor: pointer; background: none; border: none; padding: 0; font-size: 12px; }
.kbm-att-actions a:hover, .kbm-att-actions button:hover { color: var(--text); }
.kbm-att-actions .danger:hover { color: var(--red, #ed4245); }
.kbm-comments { display: flex; flex-direction: column; gap: 10px; }
.kbm-comment-list { display: flex; flex-direction: column; gap: 12px; }
.kbm-comment { display: flex; gap: 9px; }
.kbm-comment-body { min-width: 0; flex: 1; }
.kbm-comment-head { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--dim); }
.kbm-comment-head b { color: var(--text); font-size: 13px; }
.kbm-comment-del { color: var(--faint); cursor: pointer; margin-left: auto; }
.kbm-comment-del:hover { color: var(--red, #ed4245); }
.kbm-comment-text { font-size: 13px; margin-top: 2px; white-space: pre-wrap; word-break: break-word; }
.kbm-activity { color: var(--faint); font-size: 12px; padding-top: 6px; border-top: 1px solid var(--line); }
.kbm-activity b { color: var(--dim); }

@media (max-width: 760px) {
  .kbm-body { grid-template-columns: 1fr; }
  .kbm-side { border-left: none; padding-left: 0; border-top: 1px solid var(--line); padding-top: 14px; }
}
.kbm-submissions { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.kbm-submission { background: var(--bg-3); border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; font-size: 13px; display: grid; gap: 2px; overflow-wrap: anywhere; }
.kbm-submission small { color: var(--dim); font-size: 12px; }
/* Shared studio shell. Colors deliberately use existing preset/custom tokens.
   Own layout here rather than reserving guessed space for floating chrome. */
.app-shell { display: grid; grid-template-columns: 88px minmax(0,1fr); grid-template-rows: auto minmax(0,1fr); overflow: hidden; }
.app-shell > .app { grid-column: 2; grid-row: 2; width: 100%; height: auto; min-height: 0; }
.app-shell > .preview-bar { grid-column: 2; grid-row: 1; }
.studio-rail { grid-column: 1; grid-row: 1 / 3; background: var(--sidebar-bg); border-right: 1px solid var(--line); display: flex; flex-direction: column; align-items: center; overflow-y: auto; padding: 14px 6px; gap: 20px; }
.studio-logo { width: 46px; height: 46px; object-fit: contain; }
.studio-destinations { width: 100%; display: flex; flex-direction: column; gap: 8px; }
.studio-rail .bubble { width: 100%; min-height: 66px; flex-direction: column; gap: 7px; padding: 10px 2px; border-radius: 9px; background: transparent; color: var(--dim); font-size: 11px; }
.studio-rail .bubble > i { font-size: 20px; }
/* Kelpie's mark sits where the other tools' icons do, in the same color. */
.studio-rail .bubble > .bubble-mark { width: 24px; height: 24px; flex: none; }
.studio-rail .bubble:hover { background: var(--hover); color: var(--text); }
.studio-rail .bubble.active { background: color-mix(in srgb, var(--accent) 17%, var(--bg-1)); color: var(--text); box-shadow: inset 3px 0 var(--accent); }
.studio-rail .preview-wrap { margin: 16px 0 0; }
.studio-mobile-header { display: none; }
.studio-switcher { border: 1px solid var(--line); border-radius: 18px 18px 0 0; color: var(--text); background: var(--bg-1); width: min(100%, 520px); max-width: 100%; max-height: 90dvh; padding: 0; margin: auto auto 0; }
.studio-switcher::backdrop { background: #0008; }
.studio-switcher-body { padding: 20px 16px max(20px, env(safe-area-inset-bottom)); }
.studio-switcher header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.studio-switcher h2 { font-size: 20px; }
.studio-switcher p { margin-top: 6px; color: var(--dim); }
.studio-switcher header button { width: 44px; height: 44px; border-radius: 8px; background: var(--bg-3); }
.studio-switcher nav { display: grid; gap: 8px; }
.studio-switcher .bubble { min-height: 52px; width: 100%; border-radius: 9px; background: var(--bg-2); color: var(--text); font-size: 16px; text-align: left; }
.studio-switcher .bubble i { width: 24px; text-align: center; }
.studio-switcher .bubble .bubble-mark { width: 24px; height: 24px; flex: none; }
/* Kelpie's editor fills its tool pane (the library beside it is hidden while a scene is open). */
.kelpie-editor-pane { display: flex; flex-direction: column; flex: 1; min-width: 0; min-height: 0; }
.kelpie-editor-pane[hidden] { display: none; }
.kelpie-editor-pane > * { flex: 1; min-height: 0; }
/* The editor needs about 900 px; narrower screens get a note and the way back to the library. */
.kelpie-narrow-note { display: none; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 24px; text-align: center; color: var(--dim); }
.kelpie-narrow-note svg { color: var(--accent); }
.kelpie-narrow-note h2 { color: var(--text); font-size: 18px; }
.kelpie-narrow-note p { max-width: 320px; line-height: 1.45; }
@media (max-width: 760px) {
  .kelpie-editor-pane > .kelpie-narrow-note { display: flex; }
  .kelpie-editor-pane > :not(.kelpie-narrow-note) { display: none; }
}
.studio-switcher .bubble.active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, var(--bg-2)); }
.studio-switcher .preview-wrap { margin: 0; }
/* Consistent interaction vocabulary, retaining colors from custom themes. */
.app-shell :is(.icon-btn, .hamburger, .wb-back, .btn-primary, .btn-ghost, .mini, .modal-close) { border-radius: 8px; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
.app-shell :is(.icon-btn, .hamburger, .wb-back, .btn-ghost, .mini) { background: var(--bg-2); border-color: var(--line); color: var(--text); }
/* Default focus ring; :where() keeps it overridable by any component's own focus style. */
.app-shell :where(button,[role='button'],input,textarea,select):focus-visible, .studio-switcher :where(button):focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.app-shell button:disabled { cursor: not-allowed; }
/* Solid in-flow chat chrome; growing composer takes its real height. */
.app-shell .chat-pane .voice-cta { margin-top: 0; }
/* Board libraries: readable titles and balanced grids, not fixed tiny tiles. */
.app-shell .wb-bar { min-height: 56px; height: auto; padding: 12px 18px; gap: 10px; flex-wrap: wrap; background: var(--bg-1); }
.app-shell .wb-grid { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 16px; padding: 16px 20px 24px; }
.app-shell .wb-card { border-radius: 10px; box-shadow: none; }
.app-shell .wb-card-foot { min-height: 60px; padding: 10px 12px; }
.app-shell .wb-name { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-height: 1.4; font-size: 14px; }
.kb-view-toggle { display: flex; padding: 3px; gap: 3px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-2); }
.kb-view-toggle button { padding: 6px 10px; border-radius: 5px; color: var(--dim); }
.kb-view-toggle button[aria-pressed='true'] { background: var(--active); color: var(--text); }
.kb-view-list .kb-canvas { overflow-y: auto; }
.kb-view-list .kb-cols { display: flex; flex-direction: column; height: auto; max-width: 960px; margin-inline: auto; }
.kb-view-list .kb-col { width: 100%; flex: none; max-height: none; }
.kb-view-list .kb-cards { overflow: visible; }
.kb-view-list .kb-card { padding: 14px; }
@media (max-width: 1100px) and (min-width: 761px) {
  .app-shell { grid-template-columns: 78px minmax(0,1fr); }
  .app-shell .app { grid-template-columns: minmax(190px, 230px) minmax(0,1fr); }
}
@media (max-width: 760px) {
  .app-shell { grid-template-columns: minmax(0,1fr); grid-template-rows: auto auto minmax(0,1fr); height: 100dvh; }
  .studio-rail { display: none; }
  .studio-mobile-header { display: flex; align-items: center; gap: 10px; grid-row: 1; padding: calc(6px + env(safe-area-inset-top)) 12px 6px; min-width: 0; background: var(--sidebar-bg); border-bottom: 1px solid var(--line); }
  .studio-mobile-header img { width: 32px; height: 32px; object-fit: contain; }
  .studio-workspace { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; color: var(--dim); }
  .studio-mobile-header button { min-height: 44px; padding: 8px 12px; border-radius: 8px; background: var(--bg-2); color: var(--text); display: flex; align-items: center; gap: 10px; font-weight: 600; }
  .app-shell > .app { grid-column: 1; grid-row: 3; height: auto; max-width: 100%; }
  .app-shell > .preview-bar { grid-column: 1; grid-row: 2; }
  .app-shell .wb-bar { padding: 10px 12px; }
  .app-shell .wb-bar button { min-height: 44px; }
  .app-shell .wb-grid { grid-template-columns: repeat(auto-fill, minmax(145px,1fr)); gap: 12px; padding: 12px; }
  .app-shell .wb-nav-btn { display: flex; }
  .app-shell .kbm-overlay { padding: 0; }
  .app-shell .kb-card-modal { width: 100%; max-height: 100dvh; border-radius: 0; }
  .kb-view-auto .kb-canvas { overflow-y: auto; }
  .kb-view-auto .kb-cols { flex-direction: column; height: auto; }
  .kb-view-auto .kb-col { width: 100%; flex: none; max-height: none; }
  .kb-view-auto .kb-cards { overflow: visible; }
  .kb-view-auto .kb-card { padding: 14px; }
  .kb-view-auto .kb-view-toggle button:first-child { background: var(--active); color: var(--text); }
  .kb-view-board .kb-col { width: min(84vw, 320px); flex-basis: min(84vw, 320px); }
}
@media (prefers-reduced-motion: reduce) { .app-shell *, .studio-switcher * { scroll-behavior: auto; } }
.ch-mobile-browse { display: none; }
.app-shell .wb-head { flex-wrap: wrap; gap: 12px; padding: 14px 20px; }
.app-shell .wb-actions { flex-wrap: wrap; }
.app-shell .wb-grid.kb-sec { grid-template-columns: repeat(auto-fill,minmax(190px,230px)); }
.app-shell .kb-cat-head { padding: 20px 20px 0; color: var(--dim); letter-spacing: .04em; }
@media (max-width: 760px) {
  /* Follow the visual viewport, including Safari's focus-induced panning.
     Keep document scroll separate from the message list's own scrolling. */
  .app-shell { position: fixed; left: 0; right: 0; top: var(--studio-viewport-top, 0px); height: var(--studio-viewport-height, 100dvh); }
  .app-shell .wb-head { padding: 12px; }
  .app-shell .wb-actions { width: 100%; }
  .app-shell .wb-actions button { min-height: 44px; }
  .app-shell .wb-grid.kb-sec { grid-template-columns: repeat(2,minmax(0,1fr)); margin-left: 0 !important; }
  .app-shell .kb-cat-head { margin-left: 0 !important; padding: 20px 12px 0; }
  .app-shell .ch-shell { display: flex; flex-direction: column; }
  .app-shell .ch-side { display: none; }
  .app-shell .ch-main { flex: 1; }
  .app-shell .ch-browsing .ch-side { display: flex; flex: 1; border: 0; }
  .app-shell .ch-browsing .ch-main { display: none; }
  .ch-mobile-browse { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 10px 14px; background: var(--bg-2); color: var(--text); border-bottom: 1px solid var(--line); flex-shrink: 0; }
  .app-shell .ch-side-head { flex-wrap: wrap; }
  .app-shell .ch-side-btn { min-width: 40px; height: 44px; }
  .app-shell .ch-toolbar { flex-wrap: nowrap; overflow-x: auto; flex-shrink: 0; }
  .app-shell .ch-tool { min-width: 40px; height: 44px; }
  .app-shell .ch-canvas { padding: 12px 8px 30px; }
  .app-shell .ch-sheet { padding: 20px 16px; min-height: 0; }
  .app-shell .ch-doc-title { font-size: 26px; }
  .app-shell .ntl-root { padding: 12px; }
  .app-shell .ntl-head { flex-wrap: wrap; }
  .app-shell .ntl-bar { flex-wrap: wrap; }
}
.library-controls { display: flex; gap: 12px; align-items: center; padding: 12px 20px; border-bottom: 1px solid var(--line); }
.library-controls label { display: flex; align-items: center; gap: 10px; flex: 1; max-width: 440px; color: var(--dim); }
.library-controls input { width: 100%; min-width: 0; padding: 9px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-1); color: var(--text); font-size: 14px; }
.library-controls > div { display: flex; margin-left: auto; gap: 3px; background: var(--bg-1); border: 1px solid var(--line); border-radius: 8px; padding: 3px; }
.library-controls button { padding: 7px 10px; color: var(--dim); border-radius: 5px; }
.library-controls button[aria-pressed='true'] { background: var(--active); color: var(--text); }
.app-shell .library-list .wb-grid { grid-template-columns: minmax(0,1fr); }
.app-shell .library-list .wb-card { flex-direction: row; align-items: stretch; min-height: 72px; }
.app-shell .library-list .wb-thumb { width: 92px; height: 72px; flex: none; font-size: 28px; border-radius: 9px 0 0 9px; }
.app-shell .library-list .wb-card-foot { flex: 1; min-width: 0; border-top: 0; }
@media (max-width: 760px) {
  .library-controls { padding: 10px 12px; gap: 8px; }
  .library-controls input { font-size: 16px; }
  .library-controls button { min-height: 38px; }
  .kb-board > .wb-bar .kb-board-title { min-width: calc(100% - 110px); }
  .kb-board > .wb-bar .kb-cat-chip { order: 2; }
  .kb-board > .wb-bar .kb-view-toggle { order: 3; margin-left: auto; }
}
.bubble-copy { display: flex; flex-direction: column; gap: 4px; }
.bubble-description { display: none; }
.studio-switcher .bubble-description { display: block; font-size: 12px; font-weight: 400; color: var(--dim); }
.studio-switcher .bubble { white-space: normal; }
@media (max-height: 600px) { .studio-switcher .bubble { min-height: 44px; padding-block: 8px; } .studio-switcher .bubble-description { display: none; } }
.wb-mobile-actions { display: none; }
.wb-title-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 760px) {
  .app-shell .wb-desktop-actions { display: none !important; }
  .wb-mobile-actions { display: flex; flex-shrink: 0; gap: 8px; padding: 6px 12px; background: var(--bg-1); border-bottom: 1px solid var(--line); overflow-x: auto; }
  .app-shell .wb-mobile-actions button { flex-shrink: 0; min-width: 44px; height: 44px !important; background: var(--bg-2) !important; border-color: var(--line) !important; color: var(--text) !important; }
  .app-shell .wb-title-edit-btn { opacity: 1; }
}
.app-shell :is(.add) { background: var(--bg-2); color: var(--text); border: 1px solid var(--line); border-radius: 8px; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
.app-shell .studio-rail .bubble { font-size: 12px; }
/* Preserve the existing voice theater's collapsed-chat behavior. */
.mobile-channel-dialog { color: var(--text); background: var(--bg-1); border: 1px solid var(--line); padding: 0; width: calc(100% - 16px); max-width: 560px; max-height: calc(100dvh - env(safe-area-inset-top) - 16px); margin: calc(env(safe-area-inset-top) + 8px) auto auto; border-radius: 20px; box-shadow: 0 16px 60px #0006; }
.mobile-channel-dialog::backdrop { background: #0005; backdrop-filter: blur(6px); }
.mobile-channel-page { display: flex; flex-direction: column; min-height: 0; max-height: inherit; animation: channel-enter 160ms ease-out; }
.mobile-channel-page header { display: flex; flex-shrink: 0; gap: 12px; align-items: center; padding: 14px; border-bottom: 1px solid var(--line); }
.mobile-channel-page header button { width: 44px; height: 44px; border-radius: 50%; background: var(--bg-2); color: var(--text); flex-shrink: 0; }
.mobile-channel-page h2 { font-size: 18px; margin: 0; overflow-wrap: anywhere; }
.mobile-channel-page p { color: var(--dim); margin: 4px 0 0; font-size: 13px; }
.mobile-channel-actions { padding: 12px; overflow-y: auto; }
.mobile-channel-actions button { display: flex; width: 100%; align-items: center; gap: 14px; min-height: 56px; padding: 12px; background: transparent; color: var(--text); border-radius: 12px; text-align: left; font-size: 16px; }
.mobile-channel-actions button:hover { background: var(--hover); }
.mobile-channel-actions button span { margin-left: auto; color: var(--dim); }
.mobile-channel-actions .mobile-channel-topic { padding: 4px 12px 16px; }
@keyframes channel-enter { from { opacity: 0; translate: 0 10px; } to { opacity: 1; translate: 0 0; } }
@media (max-width: 760px) {
  .app-shell::after { content: ''; position: fixed; top: 0; left: 0; right: 0; height: env(safe-area-inset-top); z-index: 5000; pointer-events: none; background: linear-gradient(var(--bg-1), color-mix(in srgb, var(--bg-1) 80%, transparent)); backdrop-filter: blur(12px); }
  .app-shell .sidebar { padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); }
}
@media (prefers-reduced-motion: reduce) { .mobile-channel-page { animation: none; } }
.mobile-channel-dialog button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Interface chrome behaves like controls; working content remains copyable. */
:is(button, [role='button'], nav, .studio-rail, .studio-mobile-header, .sidebar, .wb-bar, .wb-head, .wb-card, .kb-cat-head, .ch-side, .ch-toolbar, .ntl-nav, .ctx-menu, .mobile-channel-page header, .mobile-channel-actions) {
  -webkit-user-select: none;
  user-select: none;
}
:is(input, textarea, [contenteditable='true'], .tiptap, .msg-text, .ch-sheet) {
  -webkit-user-select: text;
  user-select: text;
}
:is(.studio-logo, .studio-mobile-header img, .sidebar img) { -webkit-user-drag: none; }
@media (pointer: coarse) {
  /* Keep normal scrolling, but exclude browser pinch and double-tap zoom.
     Canvas tools retain their own touch-action:none and zoom controls. */
  html { touch-action: pan-x pan-y; }
  :is(button, [role='button'], nav, .sidebar) { -webkit-tap-highlight-color: transparent; }
  :is(input, textarea, select) { font-size: max(16px, 1em); }
}

.theme-picker { width: min(540px, calc(100vw - 24px)); max-height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom) - 24px); margin: auto; border: 1px solid var(--line); border-radius: 20px; padding: 0; color: var(--text); background: var(--bg-1); box-shadow: 0 24px 80px #0007; }
.theme-picker::backdrop { background: #0007; backdrop-filter: blur(8px); }
.theme-picker > header { display: flex; justify-content: space-between; align-items: start; gap: 16px; padding: 24px 24px 16px; }
.theme-picker h2 { margin: 0; font-size: 20px; }
.theme-picker p { color: var(--dim); font-size: 13px; margin: 6px 0 0; }
.theme-picker header button { width: 36px; height: 36px; border-radius: 10px; color: var(--text); background: var(--bg-2); }
.theme-swatches { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 16px 12px; padding: 8px 24px 24px; }
.theme-swatches > button { min-width: 0; padding: 0; background: transparent; color: var(--dim); text-align: left; }
.theme-swatch { display: block; height: 60px; border-radius: 12px; background: var(--sidebar-bg); position: relative; border: 1px solid #ffffff25; box-shadow: inset 0 1px 0 #ffffff18; transition: transform 140ms ease; }
.theme-swatches > button:hover .theme-swatch { transform: translateY(-2px); }
.theme-swatches > button[aria-pressed='true'] .theme-swatch { outline: 3px solid var(--accent); outline-offset: 3px; }
.theme-swatches > button[aria-pressed='true'] { color: var(--text); }
.theme-swatch > i { position: absolute; right: -5px; top: -5px; border: 2px solid var(--bg-1); background: var(--accent); color: var(--bg-0); border-radius: 50%; padding: 5px; font-size: 10px; }
.theme-swatch-lines { position: absolute; left: 12px; right: 12px; top: 18px; height: 5px; border-radius: 5px; background: var(--text); opacity: .35; box-shadow: 0 12px 0 color-mix(in srgb,var(--text) 55%,transparent); }
.theme-swatch-label { display: block; font-size: 11px; line-height: 1.4; margin-top: 9px; }
.theme-picker footer { border-top: 1px solid var(--line); padding: 16px 24px 24px; }
.theme-custom { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 8px 0; color: var(--text); background: transparent; text-align: left; }
.theme-custom > i:last-child { margin-left: auto; font-size: 11px; }
.theme-picker footer label { display: flex; align-items: center; gap: 10px; min-height: 44px; font-size: 13px; }
.theme-picker input { accent-color: var(--accent); }
.theme-picker button:focus-visible { outline: 2px solid var(--accent); outline-offset: 5px; border-radius: 8px; }
@media(max-width:760px) { .theme-swatches { grid-template-columns: repeat(3,minmax(0,1fr)); } .theme-picker { overscroll-behavior: contain; } }
@media(prefers-reduced-motion:reduce) { .theme-swatch { transition: none; } }
.theme-swatch > i { right: 5px; top: 5px; width: 22px; height: 22px; display: grid; place-items: center; padding: 0; }
.theme-picker footer p { display: flex; align-items: center; gap: 8px; }

/* One studio-wide color field. Panels tint that field, never restart it. */
:root:not([data-theme='custom']) .app-shell {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--bg-0) 82%, var(--accent)) 0%,
    var(--bg-0) 48%,
    color-mix(in srgb, var(--bg-0) 87%, var(--teal)) 100%);
  --sidebar-bg: color-mix(in srgb, var(--bg-0) 22%, transparent);
  --main-bg: transparent;
  --panel-bg: color-mix(in srgb, var(--bg-2) 42%, transparent);
  --field-opacity: 70%; /* chat surfaces (composer) let the colour field show through */
}
:root:not([data-theme='custom']) .app-shell :is(.main, .chat-pane, .tab-pane) { background: transparent; }
:root:not([data-theme='custom']) .app-shell :is(.wb-bar, .wb-head) { background: color-mix(in srgb, var(--bg-0) 24%, transparent); }
:root:not([data-theme='custom']) .app-shell .sea-fx { opacity: .2; }
@media (max-width: 1100px) {
  /* Overlays need an opaque surface so underlying messages do not bleed through. */
}
@media (max-width: 760px) {
  :root:not([data-theme='custom']) .app-shell .sidebar.open { background: var(--bg-1); }
}
:root:not([data-theme='custom']) .app-shell :is(.wb-launcher, .ch-shell, .ch-main, .ntl-root, .dd-root) { background: transparent; }
:root:not([data-theme='custom']) .app-shell .ch-side { background: var(--sidebar-bg); }
.theme-swatch { background: linear-gradient(135deg, color-mix(in srgb,var(--bg-0) 82%,var(--accent)), var(--bg-0) 48%, color-mix(in srgb,var(--bg-0) 87%,var(--teal))); }
.app-shell .att-wrap { max-width: 100%; }

/* Theme reveal: twice the original 640ms, with a calm expanding edge. */
::view-transition-new(root) {
  animation: kp-theme-unfold 1280ms linear both;
  transform: none;
}
@keyframes kp-theme-unfold {
  0% { clip-path: var(--vt-shape-0); }
  25% { clip-path: var(--vt-shape-1); }
  50% { clip-path: var(--vt-shape-2); }
  75% { clip-path: var(--vt-shape-3); }
  100% { clip-path: var(--vt-shape-4); }
}
.theme-celebration { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: transparent; overflow: hidden; pointer-events: none; z-index: 10000; }
.theme-celebration::backdrop { background: transparent; pointer-events: none; }
.theme-shine { position: absolute; inset: 0; background: linear-gradient(115deg,transparent 40%,color-mix(in srgb,var(--accent) 14%,transparent) 48%,#ffffff14 50%,transparent 58%); animation: kp-theme-shine 780ms ease-out both; }
.theme-spark { position: absolute; left: var(--spark-x); top: var(--spark-y); width: var(--spark-size,6px); height: var(--spark-size,6px); filter: drop-shadow(0 0 2px var(--accent)); background: color-mix(in srgb,var(--accent) 45%,white); clip-path: polygon(50% 0,62% 38%,100% 50%,62% 62%,50% 100%,38% 62%,0 50%,38% 38%); animation: kp-theme-spark 820ms cubic-bezier(.15,.7,.3,1) both; }
@keyframes kp-theme-shine { 0% { opacity: 0; transform: translateX(-65%); } 25% { opacity: 1; } 100% { opacity: 0; transform: translateX(65%); } }
@keyframes kp-theme-spark { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.3); } 18% { opacity: 1; transform: translate(calc(-50% + var(--dx) * .35),calc(-50% + var(--dy) * .35)) scale(1) rotate(15deg); } 45% { opacity: 1; transform: translate(calc(-50% + var(--dx) * .65),calc(-50% + var(--dy) * .65)) scale(.85) rotate(25deg); } 100% { opacity: 0; transform: translate(calc(-50% + var(--dx)),calc(-50% + var(--dy))) scale(.2) rotate(35deg); } }
@media(prefers-reduced-motion:reduce) {
  ::view-transition-new(root) { animation: none !important; }
  .theme-celebration { display: none !important; }
}

.progressive-image { position: relative; overflow: hidden; border-radius: 8px; background: var(--bg-2); flex-shrink: 0; }
.progressive-image .progressive-preview, .progressive-image .progressive-full { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; object-fit: contain; }
.progressive-preview { filter: blur(18px); transform: scale(1.08); opacity: .8; pointer-events: none; transition: opacity 240ms ease; }
.progressive-full { opacity: 0; transition: opacity 240ms ease; }
.progressive-image.ready .progressive-full { opacity: 1; }
.progressive-image.ready .progressive-preview { opacity: 0; }
.progressive-retry { position: absolute; inset: auto 8px 8px; min-height: 44px; border-radius: 8px; color: var(--text); background: var(--bg-1); border: 1px solid var(--line); padding: 8px; }
@media(prefers-reduced-motion:reduce) { .progressive-preview, .progressive-full { transition: none; } }

.theme-applied { position: fixed; z-index: 10001; bottom: max(24px,env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; width: max-content; max-width: calc(100vw - 24px); padding: 8px 10px 8px 16px; border: 1px solid var(--line); border-radius: 24px; background: var(--bg-1); color: var(--text); box-shadow: 0 8px 28px #0004; font-size: 13px; }
.theme-applied button { border: 0; background: transparent; color: var(--accent); padding: 8px; border-radius: 16px; font: inherit; font-weight: 600; cursor: pointer; }
.theme-applied button:hover { background: var(--hover); }
.theme-applied button:focus-visible { outline: 2px solid var(--accent); }
@media (pointer:coarse) { .theme-applied button { min-height: 44px; } }

/* Desktop: one outer frame, with the workspace nested inside it. The native
   title bar already uses --titlebar, including user-defined custom themes. */
@media (min-width: 761px) {
  .app-shell .studio-rail { background: var(--titlebar); border-right: 0; --dim: color-mix(in srgb,var(--titlebar-text) 75%,var(--titlebar)); }
  .app-shell > .app { border-top-left-radius: 16px; overflow: clip; box-shadow: -1px -1px 0 color-mix(in srgb,var(--line) 65%,transparent), -4px 0 14px #0000000a; }
  .app-shell, :root:not([data-theme='custom']) .app-shell { background: var(--titlebar); }
  :root:not([data-theme='custom']) .app-shell > .app {
    background: linear-gradient(135deg,color-mix(in srgb,var(--bg-0) 82%,var(--accent)),var(--bg-0) 48%,color-mix(in srgb,var(--bg-0) 87%,var(--teal)));
  }
  .app-shell .sidebar { border-right-color: color-mix(in srgb,var(--line) 65%,transparent); }
}

/* The viewport controller owns anchoring, avoiding double browser compensation. */
.unread-nav { width: min(520px,calc(100vw - 24px)); max-height: min(700px,85dvh); margin: auto; padding: 20px; border: 1px solid var(--line); border-radius: 16px; background: var(--bg-1); color: var(--text); }
.unread-nav::backdrop { background: #0008; }
.unread-nav header, .unread-nav nav { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.unread-nav header h2 { flex: 1; }
.unread-nav button { min-height: 40px; border-radius: 8px; padding: 8px 12px; color: var(--text); background: var(--bg-2); }
.unread-nav nav button[aria-pressed=true] { box-shadow: inset 0 -2px var(--accent); background: var(--active); }
.unread-hint { color: var(--dim); font-size: 13px; margin-bottom: 16px; }
.unread-list { display: grid; gap: 8px; }
.unread-list button { display: grid; grid-template-columns: minmax(0,1fr) auto; text-align: left; gap: 6px; }
.unread-list strong { overflow-wrap: anywhere; }
.unread-list span { grid-row: 2; color: var(--dim); font-size: 12px; }
.unread-list i { grid-column: 2; grid-row: 1 / 3; align-self: center; }
@media(max-width:760px) { .unread-nav button { min-height: 44px; } }

/* Messaging tools share the theme surfaces; content stays selectable. */
.message-search,.thread-panel { color: var(--text); background: var(--bg-1); border: 1px solid var(--line); border-radius: 18px; padding: 0; margin: auto; width: min(760px,calc(100vw - 40px)); max-height: min(860px,calc(100dvh - 64px)); box-shadow: 0 24px 80px #0006; }
.message-search[open],.thread-panel[open] { display: flex; flex-direction: column; animation: messaging-enter 160ms ease-out; }
.message-search::backdrop,.thread-panel::backdrop { background: #0007; backdrop-filter: blur(4px); }
.message-search header,.thread-panel header { flex-shrink: 0; display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 20px 24px; border-bottom: 1px solid var(--line); }
.message-search h2,.thread-panel h2 { font-size: 20px; margin: 0 0 6px; }
.message-search header p,.thread-panel header p { color: var(--dim); font-size: 13px; margin: 0; }
.message-search button,.thread-panel button { color: var(--text); background: var(--bg-2); border: 1px solid var(--line); border-radius: 8px; min-height: 36px; padding: 8px 12px; cursor: pointer; }
.message-search button:hover,.thread-panel button:hover { background: var(--hover); }
.message-search button:disabled,.thread-panel button:disabled { opacity: .55; cursor: default; }
.message-search :focus-visible,.thread-panel :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.message-search form { padding: 18px 24px 12px; }
.search-query { display: flex; gap: 8px; }
.search-query input { min-width: 0; flex: 1; }
.message-search input,.message-search select { color: var(--text); background: var(--bg-0); border: 1px solid var(--line); border-radius: 8px; padding: 10px; width: 100%; min-width: 0; font: inherit; }
.search-filters { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 10px; margin-top: 14px; }
.search-filters label { display: grid; gap: 6px; color: var(--dim); font-size: 12px; min-width: 0; }
.search-feedback { padding: 0 24px 12px; font-size: 12px; color: var(--dim); }
.search-results,.thread-scroll { min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 0 24px 20px; }
.message-search .search-result { display: block; width: 100%; text-align: left; margin: 0 0 10px; padding: 16px; background: var(--bg-2); }
.search-result-meta { display: flex; flex-wrap: wrap; gap: 4px 10px; color: var(--dim); font-size: 12px; }
.search-result-meta strong { color: var(--text); }
.search-result-meta time { margin-left: auto; }
.search-result-text { display: block; margin: 10px 0; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; max-height: 9em; overflow: auto; user-select: text; }
.search-result-text mark { color: var(--text); background: color-mix(in srgb,var(--accent) 25%,transparent); border-radius: 3px; }
.search-result-action { color: var(--accent); font-size: 12px; }
.messaging-error { color: var(--text); border-left: 3px solid var(--accent); background: var(--bg-2); padding: 12px; margin: 0 24px 12px; font-size: 13px; line-height: 1.5; }
.message-empty { padding: 24px 0; color: var(--dim); line-height: 1.6; }
.thread-panel { width: min(620px,calc(100vw - 40px)); }
.thread-scroll { padding-top: 20px; }
.thread-file { display: block; color: var(--accent); overflow-wrap: anywhere; padding: 8px 0; }
.thread-panel .thread-context-link { background: transparent; color: var(--dim); padding: 6px 0; border: 0; font-size: 12px; }
.thread-divider { color: var(--dim); font-size: 12px; padding-top: 20px; }
.thread-panel footer { flex-shrink: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; border-top: 1px solid var(--line); padding: 16px 24px; }
.thread-panel footer span { font-size: 12px; color: var(--dim); max-width: 220px; }
.message-search .btn-primary,.thread-panel .btn-primary { color: var(--text); background: var(--active); border-color: var(--accent); }
@keyframes messaging-enter { from { opacity: 0; transform: translateY(6px) scale(.995); } to { opacity: 1; transform: none; } }
@media(max-width:760px) {
 .message-search,.thread-panel { width: 100%; max-width: 100%; height: var(--studio-viewport-height,100dvh); max-height: var(--studio-viewport-height,100dvh); margin: 0; border-radius: 0; border: 0; position: fixed; top: var(--studio-viewport-top,0px); }
 .message-search header,.thread-panel header { padding: calc(16px + env(safe-area-inset-top,0px)) 16px 16px; }
 .message-search form { padding: 12px 16px; }
 .search-filters { grid-template-columns: 1fr 1fr; }
 .message-search input,.message-search select { font-size: 16px; }
 .message-search button,.thread-panel button { min-height: 44px; }
 .search-results,.thread-scroll { padding-left: 16px; padding-right: 16px; padding-bottom: calc(20px + env(safe-area-inset-bottom,0px)); }
 .thread-panel footer { padding: 12px 16px calc(12px + env(safe-area-inset-bottom,0px)); }
 .thread-panel footer span { max-width: 130px; }
}
@media(prefers-reduced-motion:reduce) { .message-search[open],.thread-panel[open] { animation: none; } }

.thread-header-actions { display: flex; gap: 6px; }

/* Catch up: a brief, local finish rather than a screen-wide interruption. */
.unread-nav { isolation: isolate; overflow: hidden; }
.unread-nav .unread-list { max-height: min(450px,55dvh); overflow-y: auto; }
.unread-nav::backdrop { animation: catch-up-backdrop 180ms ease-out; }
.unread-nav.exiting::backdrop { animation: catch-up-backdrop-out 130ms ease-in forwards; }
.catch-up-empty { min-height: 240px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 28px 18px; }
.catch-up-check { display: grid; place-items: center; width: 54px; height: 54px; margin-bottom: 18px; border-radius: 50%; background: color-mix(in srgb,var(--accent) 14%,transparent); border: 1px solid color-mix(in srgb,var(--accent) 35%,transparent); color: var(--accent); font-size: 24px; }
.catch-up-empty h3 { margin: 0 0 9px; color: var(--text); font-size: 23px; letter-spacing: -.4px; }
.catch-up-empty p { margin: 0; color: var(--dim); font-size: 13px; line-height: 1.6; }
.catch-up-check { animation: catch-up-message 300ms cubic-bezier(.22,1,.36,1) both; }
.catch-up-empty h3,.catch-up-empty p { animation: catch-up-message 360ms 50ms cubic-bezier(.22,1,.36,1) both; }
.catch-up-finish { position: absolute; inset: 0; overflow: hidden; border-radius: inherit; pointer-events: none; z-index: 2; }
.catch-up-sheen { position: absolute; inset: -50%; background: linear-gradient(115deg,transparent 43%,color-mix(in srgb,var(--accent) 15%,transparent) 49%,#ffffff20 50%,transparent 57%); animation: catch-up-sheen 750ms ease-out both; }
.catch-up-spark { position: absolute; width: 4px; height: 4px; background: var(--accent); border-radius: 1px; opacity: 0; animation: catch-up-spark 650ms ease-out both; }
@keyframes catch-up-message { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
@keyframes catch-up-sheen { from { opacity: 0; transform: translateX(-45%); } 20% { opacity: 1; } to { opacity: 0; transform: translateX(45%); } }
@keyframes catch-up-spark { 0% { opacity: 0; transform: scale(.3) rotate(0); } 25% { opacity: .8; } 100% { opacity: 0; transform: translate(var(--dx),var(--dy)) scale(.4) rotate(100deg); } }
@keyframes catch-up-backdrop { from { background: #0000; } to { background: #0008; } }
@keyframes catch-up-backdrop-out { from { background: #0008; } to { background: #0000; } }
@media(prefers-reduced-motion:reduce) { .unread-nav::backdrop,.unread-nav.exiting::backdrop,.celebrating .catch-up-check,.catch-up-empty h3,.catch-up-empty p { animation: none; } .catch-up-finish { display: none; } }

/* Readable hierarchy and stable spacing independent of message actions. */
.attachments.image-gallery { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); width: min(100%,660px); gap: 8px; align-items: start; }
.image-gallery > .att-wrap { width: 100%; min-width: 0; }
.image-gallery > :not([data-kind=image]) { grid-column: 1 / -1; }
.image-gallery .progressive-image { width: 100% !important; height: auto !important; aspect-ratio: 4 / 3 !important; max-width: 100%; border: 1px solid var(--line); background: var(--bg-0); border-radius: 10px; }
.image-gallery .progressive-full { object-fit: contain; }
.image-gallery .att-expiry { font-size: 10px; }
.file-attachment { width: min(100%,480px); }
.file-attachment .att-file { width: 100%; max-width: 100%; text-align: left; }
.file-description { display: flex; flex-direction: column; gap: 5px; min-width: 0; flex: 1; }
.file-attachment .fn { white-space: normal; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.file-download { display: flex; flex-direction: column; align-items: center; gap: 5px; color: var(--dim); font-size: 10px; flex-shrink: 0; }
.file-download > i { font-size: 15px; }
.file-error { color: var(--dim); font-size: 12px; line-height: 1.5; margin: 8px 0 0; }
.attachment-unavailable { display: flex; align-items: center; gap: 12px; padding: 14px; border: 1px dashed var(--line); border-radius: 10px; color: var(--dim); max-width: 480px; }
.attachment-unavailable div { min-width: 0; }
.attachment-unavailable strong { display: block; color: var(--text); overflow-wrap: anywhere; margin-bottom: 5px; font-size: 13px; }
.attachment-unavailable span { font-size: 12px; line-height: 1.5; }

/* Message, action-sheet and thread interaction polish. Theme surfaces remain semantic. */
.accessible-menu { overflow-y:auto; overscroll-behavior:contain; box-sizing:border-box; animation:action-enter 150ms cubic-bezier(.2,.8,.2,1); background:var(--bg-1); color:var(--text); }
.accessible-menu.exiting { animation:action-exit 120ms ease-in forwards; pointer-events:none; }
.accessible-menu .ctx-item { width:100%; min-height:38px; border:0; background:transparent; color:var(--text); text-align:left; font:inherit; font-size:14px; }
.accessible-menu .ctx-item:hover,.accessible-menu .ctx-item:focus-visible { background:var(--active); color:var(--text); }
.accessible-menu .ctx-item.danger, .accessible-menu .ctx-item.danger:is(:hover,:focus-visible) { color:var(--danger); }
.accessible-menu .ctx-item.danger .ci { color:var(--red,#dc4545); }
.accessible-menu .ctx-item:disabled { opacity:.5; cursor:default; }
.accessible-menu :focus-visible { outline:2px solid var(--text); outline-offset:-3px; }
.ctx-scrim { position:fixed; inset:0; z-index:4000; background:#0007; backdrop-filter:blur(3px); touch-action:none; }
.mobile-action-sheet { border-radius:18px; padding:8px 8px calc(8px + env(safe-area-inset-bottom,0px)); box-shadow:0 12px 60px #0006; }
.mobile-action-sheet .ctx-item { min-height:48px; padding:10px 14px; font-size:15px; }
.action-sheet-heading { display:flex; align-items:center; justify-content:space-between; padding:0 6px 6px 14px; font-size:13px; font-weight:600; }
.action-sheet-heading button { min-width:44px; min-height:44px; background:transparent; border:0; color:var(--text); }
.thread-divider,.thread-panel header p,.thread-panel footer span { color:var(--text); opacity:.78; }
.thread-panel .thread-context-link { color:var(--text); opacity:.85; }
.thread-panel .thread-new-replies { position:absolute; bottom:90px; left:50%; transform:translateX(-50%); background:var(--bg-2); box-shadow:0 4px 20px #0004; }
.thread-panel { position:fixed; }
.thread-scroll { scrollbar-gutter:stable; }
.thread-panel .file-attachment { margin-top:8px; }
@keyframes action-enter { from {opacity:0;transform:translateY(8px) scale(.985)} to {opacity:1;transform:none} }
@keyframes action-exit { to {opacity:0;transform:translateY(6px) scale(.99)} }
@media(max-width:700px) { .thread-panel footer { gap:8px; } .thread-panel footer span { max-width:120px; } }
@media(prefers-reduced-motion:reduce) { .accessible-menu,.accessible-menu.exiting { animation:none; } }

/* Completion is a non-modal status toast; unread conversations retain their navigator. */
.caught-up-toast { position: fixed; z-index: 10000; left: 50%; bottom: max(24px, env(safe-area-inset-bottom)); translate: -50% 0; display: flex; align-items: center; gap: 12px; width: max-content; max-width: calc(100vw - 24px); padding: 10px 10px 10px 14px; border: 1px solid var(--line); border-radius: 16px; color: var(--text); background: var(--bg-1); box-shadow: 0 8px 32px #0003; isolation: isolate; overflow: hidden; animation: caught-up-toast-in 220ms cubic-bezier(.22,1,.36,1) both, caught-up-toast-settle 300ms 220ms ease-in-out; }
.caught-up-toast .catch-up-check { flex: none; width: 32px; height: 32px; font-size: 15px; margin: 0; }
.caught-up-toast [role=status] { font-size: 14px; font-weight: 600; }
.caught-up-toast button { flex: none; width: 36px; height: 36px; border-radius: 10px; background: transparent; color: var(--dim); }
.caught-up-toast button:hover,.caught-up-toast button:focus-visible { background: var(--active); color: var(--text); }
.caught-up-toast .catch-up-sheen { animation-delay: 220ms; }
.caught-up-toast.exiting { animation: caught-up-toast-out 160ms ease-in forwards; pointer-events: none; }
@keyframes caught-up-toast-in { from { opacity: 0; transform: translateY(12px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes caught-up-toast-settle { 0%,100% { transform: scale(1); } 35% { transform: scale(.99); } 65% { transform: scale(1.015); } }
@keyframes caught-up-toast-out { to { opacity: 0; transform: translateY(8px) scale(.97); } }
@media(max-width:760px) { .caught-up-toast { bottom: auto; top: calc(env(safe-area-inset-top) + 12px); } .caught-up-toast button { width: 44px; height: 44px; } }
@media(prefers-reduced-motion:reduce) { .caught-up-toast,.caught-up-toast.exiting,.caught-up-toast .catch-up-check { animation: none; } }

/* A full-size, solid presence mark with a clean cutout instead of a cramped ring. */
.name-style-editor { width: min(850px,calc(100vw - 24px)); max-height: calc(100dvh - 32px); padding:0; margin:auto; border:1px solid var(--line); border-radius:18px; background:var(--bg-1); color:var(--text); overflow:auto; }
.name-style-editor::backdrop { background:#0008; backdrop-filter:blur(4px); }
.name-style-editor header { display:flex; align-items:center; justify-content:space-between; padding:22px 24px; border-bottom:1px solid var(--line); }
.name-style-editor h2 { margin:0; font-size:21px; }.name-style-editor header p { color:var(--dim); margin:6px 0 0; font-size:13px; }
.name-style-editor button { min-height:40px; padding:8px 12px; border:1px solid var(--line); border-radius:9px; color:var(--text); background:var(--bg-2); }
.name-style-editor button[aria-pressed=true] { border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent); }
.name-style-editor button:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
.name-style-layout { display:grid; grid-template-columns:1.15fr 1fr; }
.name-style-controls { padding:24px; }.name-style-controls fieldset { margin:0 0 22px; padding:0; border:0; }.name-style-controls legend { margin-bottom:10px; font-weight:650; }
.name-font-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; }.name-font-grid button { display:flex; flex-direction:column; align-items:center; justify-content:center; min-height:76px; gap:6px; }.name-font-grid .display-name { font-size:23px; }.name-font-grid small { font-size:11px; color:var(--dim); }
.name-effect-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; }.name-effect-grid button { padding:8px 5px; }
.name-toggle { display:flex; align-items:center; gap:9px; min-height:32px; font-size:13px; }.name-toggle input { accent-color:var(--accent); width:16px; height:16px; }
.name-palettes { display:flex; gap:10px; margin:10px 0; }.name-palettes button { width:44px; height:40px; }.name-color-inputs { display:flex; gap:18px; }.name-color-inputs label { display:flex; align-items:center; gap:8px; font-size:12px; }.name-color-inputs input { width:34px; height:30px; padding:0; border:0; }
.name-style-note { font-size:12px; color:var(--dim); line-height:1.6; }
.name-style-preview { padding:24px; background:var(--bg-0); border-left:1px solid var(--line); display:flex; flex-direction:column; justify-content:center; gap:16px; min-width:0; color:var(--text); }
.name-style-preview[data-preview-theme=light] { --bg-0:#f5f6f8; --bg-1:#fff; --bg-2:#e9ecf1; --text:#202532; --dim:#596170; --line:#ccd2dc; }
.name-style-preview[data-preview-theme=dark] { --bg-0:#10141c; --bg-1:#1b2130; --bg-2:#252d3e; --text:#f0f3fa; --dim:#a8b2c8; --line:#384153; }
.name-preview-tabs { display:flex; gap:6px; }.name-preview-tabs button { font-size:11px; text-transform:capitalize; flex:1; }
.name-preview-profile { border:1px solid var(--line); border-radius:14px; overflow:hidden; padding:0 18px 20px; background:var(--bg-1); }.name-preview-banner { height:65px; margin:0 -18px 0; background:var(--active); }.name-preview-profile .avatar { margin-top:-36px; margin-bottom:10px; box-shadow:0 0 0 4px var(--bg-1); }.name-preview-profile strong { display:block; font-size:22px; }.name-preview-profile small { color:var(--dim); }
.name-preview-message,.name-preview-member { display:flex; align-items:center; gap:12px; border:1px solid var(--line); background:var(--bg-1); border-radius:12px; padding:14px; min-width:0; }.name-preview-message>div { min-width:0; }.name-preview-message small { font-size:10px; color:var(--dim); }.name-preview-message p { margin:6px 0 0; font-size:12px; }.name-style-preview .avatar { flex-shrink:0; }
.name-style-editor footer { display:flex; align-items:center; gap:10px; padding:16px 24px; border-top:1px solid var(--line); flex-wrap:wrap; }.name-style-editor footer>div { flex:1; }.name-style-editor footer [role=alert] { width:100%; color:var(--text); margin:0; }.name-style-editor button:disabled { opacity:.5; cursor:wait; }.name-style-editor footer .btn-primary { background:var(--accent); color:var(--bg-0); }
@media(max-width:620px) { .name-style-layout { grid-template-columns:1fr; }.name-style-preview { border-left:0; border-top:1px solid var(--line); }.name-style-controls,.name-style-preview { padding:18px; }.name-style-editor button { min-height:44px; }.name-style-editor header { padding:16px; }.name-style-editor footer { padding:14px; }.name-style-editor { max-height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); } }

/* Compact writing area, with send preferences sharing the action row. */

.emoji-popover.anchored em-emoji-picker { width:100%; }

/* Profile workspace: neutral editing surfaces, personality reserved for previews. */
.editor-eyebrow { display:block; color:var(--dim); font-size:10px; font-weight:750; letter-spacing:.12em; margin-bottom:7px; }
.editor-description { color:var(--dim); font-size:12px; line-height:1.6; margin:4px 0 18px; }
.profile-editor-overlay { animation:editor-overlay-in 180ms ease-out both; }
.profile-editor-overlay.exiting { animation:editor-overlay-out 150ms ease-in forwards; }
.modal.profile-modal.profile-editor { width:min(920px,calc(100vw - 32px)); max-width:none; max-height:calc(100dvh - 40px); display:flex; flex-direction:column; border:1px solid var(--line); background:var(--bg-1); border-radius:20px; overflow:hidden; box-shadow:0 24px 90px #0005; animation:editor-in 220ms cubic-bezier(.22,1,.36,1) both; }
.profile-editor .modal-head { flex:none; background:transparent; padding:22px 26px; border-bottom:1px solid var(--line); }.profile-editor .modal-head h3 { font-size:22px; margin:0; }.profile-editor .modal-close { width:36px; height:36px; border:1px solid var(--line); border-radius:10px; background:transparent; }
.profile-editor-layout { display:grid; grid-template-columns:minmax(0,1fr) 310px; min-height:0; flex:1; }
.profile-editor-form { min-width:0; min-height:0; display:flex; flex-direction:column; }
.profile-editor-tabs { display:flex; padding:18px 24px 0; gap:4px; flex:none; }
.profile-editor-tabs button { flex:1; white-space:nowrap; padding:10px 8px; border-radius:9px; color:var(--dim); font-size:12px; font-weight:650; background:transparent; }
.profile-editor-tabs button[aria-pressed=true] { background:var(--active); color:var(--text); box-shadow:inset 0 -2px var(--accent); }
.profile-editor .modal-body { padding:22px 26px 26px; overflow-y:auto; min-height:0; max-height:none; }
.profile-editor-section:not([hidden]) { animation:editor-section-in 160ms ease-out; }.profile-editor-section[hidden] { display:none !important; }
.profile-editor-section h4 { margin:0 0 5px; font-size:15px; color:var(--text); }.profile-editor-section>h4:not(:first-child) { margin-top:22px; }
.profile-editor-section:first-child { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 16px; }.profile-editor-section:first-child>h4,.profile-editor-section:first-child>.editor-description,.profile-field.wide { grid-column:1/-1; }
.profile-editor .modal-body label { text-transform:none; font-size:12px; font-weight:600; letter-spacing:0; color:var(--dim); margin:14px 0 7px; display:block; }
.profile-editor .modal-body input:not([type=checkbox]),.profile-editor .modal-body textarea,.profile-editor .modal-body select { width:100%; box-sizing:border-box; min-height:42px; background:var(--bg-0); color:var(--text); border:1px solid var(--line); border-radius:9px; padding:10px 12px; font-size:14px; }
.profile-editor .modal-body textarea { min-height:90px; resize:vertical; }
.profile-editor :is(input,textarea,select):focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.profile-editor-preview { padding:24px 20px; background:var(--bg-0); border-left:1px solid var(--line); overflow-y:auto; }
.profile-preview-banner { height:105px; background-size:cover; background-position:center; }
.profile-preview-details { padding:0 18px 20px; }.profile-preview-details h3 { margin:12px 0 4px; font-size:22px; overflow-wrap:anywhere; }.profile-preview-details p { color:var(--dim); font-size:12px; line-height:1.6; margin:5px 0; overflow-wrap:anywhere; }.profile-role { display:inline-block; margin:10px 0; font-size:10px; text-transform:uppercase; letter-spacing:.05em; color:var(--text); background:var(--bg-2); padding:4px 7px; border-radius:5px; }.profile-preview-details .profile-preview-bio { color:var(--text); white-space:pre-wrap; }
.profile-editor .wiz-foot { display:flex; align-items:center; flex-wrap:wrap; gap:12px; padding:16px 26px; border-top:1px solid var(--line); background:var(--bg-1); flex:none; }.profile-save-note { font-size:11px; color:var(--dim); flex:1; }.profile-editor .wiz-foot [role=alert] { flex-basis:100%; color:var(--text); }
.profile-editor .btn-ghost { border:1px solid var(--line); border-radius:9px; min-height:38px; font-size:12px; }.profile-style-entry { display:flex; align-items:center; gap:14px; justify-content:space-between; padding:16px; border:1px solid var(--line); border-radius:12px; margin-bottom:22px; }.profile-style-entry .editor-description { margin:4px 0 0; }.profile-style-entry button { max-width:180px; }.profile-editor .banner-tabs { flex-wrap:wrap; gap:7px; margin:12px 0 18px; }.profile-editor .banner-colors { margin:12px 0; }.profile-editor .swatches { flex-wrap:wrap; gap:7px; }.profile-editor .swatch { width:22px; height:22px; }.profile-editor .hint { font-size:11px; line-height:1.6; }
.name-style-refined { animation:editor-in 220ms cubic-bezier(.22,1,.36,1) both; width:min(890px,calc(100vw - 28px)); }.name-style-refined.exiting { animation:editor-out 150ms ease-in forwards; }.name-style-refined::backdrop { animation:editor-overlay-in 180ms ease-out; }.name-style-refined header { padding:22px 26px; }.name-style-refined .name-style-controls { padding:24px 26px; }.name-style-refined .name-style-preview { justify-content:flex-start; gap:10px; padding:25px; }.name-style-refined .name-preview-tabs { margin-bottom:10px; background:var(--bg-1); border:1px solid var(--line); padding:3px; border-radius:9px; }.name-style-refined .name-preview-tabs button { min-height:30px; padding:4px; background:transparent; border:0; box-shadow:none; color:var(--dim); }.name-style-refined .name-preview-tabs button[aria-pressed=true] { background:var(--active); color:var(--text); }
.name-style-refined .name-font-grid button,.name-style-refined .name-effect-grid button { position:relative; transition:background 140ms, border-color 140ms, transform 140ms; }.name-style-refined .name-font-grid button:hover,.name-style-refined .name-effect-grid button:hover { background:var(--hover); transform:translateY(-1px); }.name-style-refined button[aria-pressed=true] { background-color:var(--active); box-shadow:none; }.name-style-refined .name-font-grid button[aria-pressed=true]:after { content:'✓'; position:absolute; right:7px; top:5px; font-size:10px; color:var(--accent); }.name-style-refined .name-font-grid { gap:7px; }.name-style-refined .name-font-grid button { min-height:66px; }.name-style-refined .name-style-controls fieldset { margin-bottom:20px; }
.name-preview-label { color:var(--dim); font-size:10px; letter-spacing:.05em; text-transform:uppercase; margin-top:8px; }.name-style-refined .name-preview-profile { padding-bottom:16px; }.name-style-refined .name-preview-profile strong { margin:6px 0; }.name-style-refined .name-preview-message small { margin-left:6px; }.name-style-refined .name-preview-message,.name-style-refined .name-preview-member { padding:13px; }
.name-style-refined .name-palettes { gap:8px; }.name-style-refined .name-palettes button { flex:1; min-width:0; height:40px; position:relative; }.name-style-refined .name-palettes button[aria-pressed=true]:after { content:'✓'; position:absolute; right:4px; bottom:3px; display:grid; place-items:center; width:17px; height:17px; border-radius:50%; background:var(--bg-0); color:var(--text); font-size:11px; }.name-theme-color { background:var(--bg-2); }.name-color-inputs { align-items:center; padding:9px 10px; border:1px solid var(--line); border-radius:9px; gap:12px; }.name-color-inputs>span { font-size:11px; color:var(--dim); margin-right:auto; }.name-color-inputs input[type=color] { appearance:none; border:0; border-radius:6px; overflow:hidden; width:24px; height:24px; background:transparent; cursor:pointer; }.name-color-inputs input::-webkit-color-swatch-wrapper { padding:0; }.name-color-inputs input::-webkit-color-swatch { border:0; border-radius:5px; }
.name-motion-toggle { display:flex; justify-content:space-between; padding-top:4px; gap:12px; }.name-motion-toggle strong { display:block; font-size:12px; }.name-motion-toggle small { display:block; font-size:11px; color:var(--dim); margin-top:4px; }.name-motion-toggle input { appearance:none; flex:none; width:32px; height:20px; border-radius:20px; background:var(--bg-0); border:1px solid var(--line); position:relative; transition:background 180ms; cursor:pointer; }.name-motion-toggle input:after { content:''; position:absolute; width:12px; height:12px; top:3px; left:3px; border-radius:50%; background:var(--dim); transition:transform 180ms cubic-bezier(.2,.8,.2,1.2); }.name-motion-toggle input:checked { background:var(--accent); }.name-motion-toggle input:checked:after { background:var(--bg-0); transform:translateX(12px); }
@keyframes editor-in { from { opacity:0; transform:translateY(8px) scale(.985); } to { opacity:1; transform:none; } }@keyframes editor-out { to { opacity:0; transform:translateY(5px) scale(.99); } }@keyframes editor-section-in { from { opacity:0; transform:translateY(4px); } to { opacity:1; transform:none; } }@keyframes editor-overlay-in { from { opacity:0; } to { opacity:1; } }@keyframes editor-overlay-out { to { opacity:0; } }
@media(max-width:700px) { .modal.profile-modal.profile-editor { width:calc(100vw - 20px); max-height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); }.profile-editor-layout { display:block; overflow-y:auto; }.profile-editor .modal-body { overflow:visible; padding:18px; }.profile-editor-preview { display:none; }.profile-editor-tabs { padding:12px 12px 0; }.profile-editor-tabs button { font-size:11px; padding:10px 4px; min-height:44px; }.profile-editor .modal-head { padding:18px; }.profile-editor .wiz-foot { padding:14px 18px; }.profile-editor-section:first-child { grid-template-columns:1fr; }.profile-field { grid-column:1/-1; }.profile-editor .modal-body input:not([type=checkbox]),.profile-editor .modal-body textarea,.profile-editor .modal-body select { font-size:16px; }.profile-style-entry { flex-direction:column; align-items:flex-start; }.profile-style-entry button { max-width:none; }.name-style-refined .name-style-preview,.name-style-refined .name-style-controls { padding:18px; } }
@media(prefers-reduced-motion:reduce) { .profile-editor-overlay,.profile-editor-overlay.exiting,.modal.profile-modal.profile-editor,.profile-editor-section:not([hidden]),.name-style-refined,.name-style-refined.exiting,.name-style-refined::backdrop { animation:none; }.name-style-refined button,.name-motion-toggle input,.name-motion-toggle input:after { transition:none !important; } }

@media(max-width:700px) { .profile-editor-preview[data-section=appearance] { display:block; border-left:0; border-top:1px solid var(--line); }.profile-editor-preview[data-section=appearance] .profile-preview-bio { display:none; } }

.profile-editor .modal-close { color:var(--text); }
.profile-editor .wiz-foot>.btn-primary { margin-left:auto; }

/* Small spacing polish: clear the field focus ring and protect rail labels. */
@media(min-width:761px) {
 .app-shell { grid-template-columns:100px minmax(0,1fr); }
 .app-shell .studio-rail .bubble { padding-inline:8px; box-sizing:border-box; }
}

/* Stable editor frame; sections scroll inside it rather than resizing the dialog. */
.modal.profile-modal.profile-editor { height:min(780px,calc(100dvh - 40px)); }
.profile-editor-section:not([hidden]) { animation:profile-section-slide 260ms cubic-bezier(.22,1,.36,1) both; }
@keyframes profile-section-slide { from { opacity:0; transform:translateX(12px); } to { opacity:1; transform:none; } }
.profile-editor .profile-size-picker { border:0; padding:0; margin:22px 0 12px; min-width:0; }
.profile-size-picker legend { color:var(--text); font-size:12px; font-weight:650; margin-bottom:12px; }
.profile-size-picker>div { display:flex; flex-wrap:wrap; gap:8px; }
.profile-editor .profile-size-picker label { margin:0; position:relative; cursor:pointer; }
.profile-size-picker input[type=radio] { position:absolute; opacity:0; width:1px !important; height:1px; min-height:0 !important; padding:0 !important; }
.profile-size-picker label>span { display:grid; place-items:center; min-width:42px; min-height:42px; padding:8px 12px; border:1px solid var(--line); border-radius:9px; color:var(--dim); background:var(--bg-0); transition:background 160ms,border-color 160ms,color 160ms; }
.profile-size-picker input:checked+span { color:var(--text); background:var(--active); border-color:var(--accent); box-shadow:inset 0 0 0 1px var(--accent); }
.profile-size-picker input:focus-visible+span { outline:2px solid var(--accent); outline-offset:3px; }
.profile-size-picker label:hover>span { color:var(--text); }
/* Shared switch presentation. Document task checkboxes retain document semantics. */
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input) { appearance:none; -webkit-appearance:none; box-sizing:border-box; display:inline-block; position:relative; flex-shrink:0; width:36px !important; min-width:36px; height:22px !important; min-height:22px; padding:0 !important; border:1px solid var(--line); border-radius:22px; background:var(--bg-0); vertical-align:middle; cursor:pointer; transition:background 180ms ease,border-color 180ms ease; }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input)::after { content:''; position:absolute; top:3px; left:3px; width:14px; height:14px; border-radius:50%; background:var(--dim); transform:translateX(0); transition:transform 190ms cubic-bezier(.2,.8,.2,1.15),background 180ms; }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):checked { background:var(--accent); border-color:var(--accent); }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):checked::after { transform:translateX(14px); background:var(--bg-0); }
input[type=checkbox]:not(.ProseMirror input):not([data-type=taskItem] input):indeterminate::after { transform:translateX(7px); background:var(--accent); }
input[type=checkbox]:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
input[type=checkbox]:disabled { opacity:.5; cursor:not-allowed; }
@media(max-width:700px) { .modal.profile-modal.profile-editor { height:calc(100dvh - 24px - env(safe-area-inset-top) - env(safe-area-inset-bottom)); } }
@media(prefers-reduced-motion:reduce) { .profile-editor-section:not([hidden]) { animation:none; } input[type=checkbox],input[type=checkbox]::after,.profile-size-picker label>span { transition:none !important; } }
/* Desktop: the (resizable) sidebar and the conversation; an open thread adds a third column (threads.css). */
@media (min-width: 1101px) {
  .app-shell .app { grid-template-columns: var(--col-l, var(--sidebar-w, 280px)) minmax(0, 1fr); }
}
/* One saved palette for both the actual profile and its live preview. */
.profile-preview-details > .avatar { margin-top: -36px; box-shadow: 0 0 0 4px color-mix(in srgb, var(--c1) 38%, var(--bg-1)); }

/* Keep typing feedback centered in the gap above the composer. */

.studio-feed-shortcut { display: none; }
@media (max-width:760px) { .studio-mobile-header .studio-feed-shortcut { display: inline-flex; padding-inline: 10px; gap: 7px; } }
/* Profile card (ProfileCard.tsx) and its live preview in the profile editor.
   The card floats beside whatever opened it; ProfileCard.tsx sets left/top
   and the person's banner colours (--c1, --c2). */
.profile-card,
.profile-preview-card {
  --pc-surface: color-mix(in srgb, var(--c1) 38%, var(--bg-1));
  border: 2px solid transparent;
  background:
    linear-gradient(150deg, var(--pc-surface) 0%, color-mix(in srgb, var(--c2) 38%, var(--bg-1)) 100%) padding-box,
    linear-gradient(140deg, color-mix(in srgb, var(--c1) 80%, white), var(--c2)) border-box;
}
.profile-preview-card { overflow: hidden; margin: var(--sp-4) 0; border-radius: var(--radius-lg); }
.profile-card {
  --pc-banner: 100px;
  --pc-avatar: 80px;
  position: fixed;
  z-index: var(--z-popover);
  width: min(320px, calc(100vw - var(--sp-5)));
  max-height: min(680px, calc(var(--studio-viewport-height, 100dvh) - var(--sp-5)));
  overflow-y: auto;
  overscroll-behavior: contain;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  color: var(--text);
}
.pc-banner {
  position: absolute;
  inset: 0 0 auto;
  height: var(--pc-banner);
  background-size: cover;
  background-position: center;
  border-bottom: 1px solid color-mix(in srgb, var(--on-media) 8%, transparent);
}

/* Close and quick actions sit on the banner image, so they use the on-media chip in every theme. */
.pc-close,
.pc-actions button {
  display: grid;
  place-items: center;
  width: var(--control-md);
  height: var(--control-md);
  border-radius: var(--radius-full);
  background: var(--media-chip);
  color: var(--on-media);
  font-size: var(--fs-sm);
  transition: background-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.pc-close:hover,
.pc-actions button:hover { background: var(--media-chip-hover); transform: translateY(-1px); }
.pc-close:active,
.pc-actions button:active { transform: scale(0.94); }
.pc-close { position: absolute; top: var(--sp-2); right: var(--sp-2); z-index: var(--z-raised); }
.pc-actions {
  position: absolute;
  top: var(--sp-2);
  right: calc(var(--sp-2) * 2 + var(--control-md));
  z-index: var(--z-raised);
  display: flex;
  gap: var(--sp-2);
}

.pc-body { position: relative; padding: calc(var(--pc-banner) - 36px) var(--sp-4) var(--sp-4); }
.pc-head { display: flex; flex-direction: column; gap: var(--sp-3); }
.pc-avatar {
  position: relative;
  width: var(--pc-avatar);
  height: var(--pc-avatar);
  border-radius: 50%;
  box-shadow: 0 0 0 4px var(--pc-surface);
}

.pc-id { min-width: 0; }
.pc-name { font-size: var(--fs-xl); font-weight: var(--fw-bold); line-height: var(--lh-tight); overflow-wrap: anywhere; }
.pc-handle { margin-top: var(--sp-0); color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); overflow-wrap: anywhere; user-select: text; -webkit-user-select: text; }
.pc-chips { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-top: var(--sp-3); }
.pc-chips > * { max-width: 100%; padding: var(--sp-0) var(--sp-2); border-radius: var(--radius-sm); font-size: var(--fs-xs); line-height: var(--lh-body); overflow-wrap: anywhere; white-space: normal; }

.pc-voice {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid color-mix(in srgb, var(--online) 35%, transparent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--online) 14%, transparent);
  color: var(--text);
  font-size: var(--fs-sm);
}
.pc-voice-wave { display: inline-flex; align-items: flex-end; gap: var(--sp-0); height: 12px; }
.pc-voice-wave i { width: 3px; border-radius: var(--sp-0); background: var(--online); animation: pc-voice-wave 1s var(--ease-loop) infinite; }
.pc-voice-wave i:nth-child(1) { height: 6px; }
.pc-voice-wave i:nth-child(2) { height: 11px; animation-delay: 0.18s; }
.pc-voice-wave i:nth-child(3) { height: 8px; animation-delay: 0.34s; }
@keyframes pc-voice-wave { 0%, 100% { transform: scaleY(0.55); } 50% { transform: scaleY(1); } }

.pc-presence { margin-top: var(--sp-2); color: var(--dim); font-size: var(--fs-xs); }
.pc-error { margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-md); background: var(--bg-2); color: var(--text); }
.pc-status { margin-top: var(--sp-3); padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-md); background: var(--bg-2); font-size: var(--fs-md); line-height: var(--lh-body); overflow-wrap: anywhere; }
.pc-bio { margin-top: var(--sp-3); font-size: var(--fs-md); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: anywhere; }
.pc-rows { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.pc-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1); color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); overflow-wrap: anywhere; }
.pc-row i { width: 14px; margin-right: var(--sp-1); text-align: center; }
.pc-row-dim { color: var(--faint); }

.profile-card .pc-edit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: var(--control-md);
  margin-top: var(--sp-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--accent) 22%, var(--bg-2));
  color: var(--text);
  font-size: var(--fs-md);
}
.pc-dm {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin-top: var(--sp-4);
  padding: var(--sp-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2);
}
.pc-dm:focus-within { border-color: var(--accent); }
.pc-dm-input { flex: 1; min-width: 0; padding: var(--sp-2); border: 0; background: transparent; color: var(--text); font-size: var(--fs-md); }
.pc-dm-input::placeholder { color: var(--dim); }
.pc-dm-input:focus-visible { outline: none; }
.pc-send {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: var(--control-md);
  height: var(--control-md);
  border-radius: var(--radius-md);
  color: var(--dim);
}
.pc-send.ready { border: 1px solid var(--accent); background: color-mix(in srgb, var(--accent) 22%, var(--bg-2)); color: var(--text); }
.profile-card button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.profile-card button:disabled { opacity: 0.5; cursor: default; }

@media (pointer: coarse) {
  .pc-close, .pc-actions button { width: var(--control-touch); height: var(--control-touch); }
  .pc-actions { right: calc(var(--sp-2) * 2 + var(--control-touch)); }
  .profile-card .pc-edit, .pc-send { min-height: var(--control-touch); }
  .pc-dm-input { font-size: var(--fs-lg); }
}
@media (prefers-reduced-motion: reduce) {
  .pc-voice-wave i { animation: none; }
}
/* Emoji drawn inline with text: Twemoji images (FlatEmoji.tsx) and workspace
   custom emoji (CustomEmojiImage.tsx, MessageContent.tsx). Sized in em so they
   follow whatever text they sit in. */
/* The side margin keeps the gaps around an emoji even with the space a word leaves. */
.flat-emoji { display: inline-block; width: 1.2em; height: 1.2em; margin: 0 0.05em 0 0.1em; object-fit: contain; vertical-align: -0.3em; }
.cemoji { width: auto; height: 1.4em; max-width: 3em; object-fit: contain; vertical-align: -0.3em; }
/* Custom emoji are framed to the artwork's measured aspect ratio (--emoji-aspect). */
.cemoji-frame { position: relative; display: inline-block; flex-shrink: 0; width: calc(1.4em * var(--emoji-aspect, 1)); height: 1.4em; overflow: hidden; }
.cemoji-frame > :is(img, canvas) { position: absolute; inset: 0 auto auto 0; display: block; width: 100%; max-width: none; height: 100%; object-fit: contain; }
/* The conversation: message list, one message (MessageItem in Chat.tsx), its
   reactions and thread summary, the list's dividers and jump bars, and the
   formatting inside message text (MessageContent.tsx). */

/* List */
.messages { display: flex; flex: 1; flex-direction: column; min-height: 0; overflow-y: auto; overflow-anchor: none; padding-block: var(--sp-4); }
/* Its one block of content: at the bottom when short, scrolling as usual when long (block layout
   inside, so the message rhythm's margins still collapse as before). */
.messages-list { flex-shrink: 0; margin-top: auto; }
.messages.drag { outline: 2px dashed var(--accent); outline-offset: calc(-1 * var(--sp-2)); }
body.kp-theater .messages { flex: 1 1 auto; min-height: 60px; transition: height var(--dur-base) var(--ease); }
body.kp-theater.kp-chat-min .messages { flex: 0 0 0; height: 0; min-height: 0; padding-block: 0; overflow: hidden; }

/* The start of a conversation: who it's with (or what it is), and a prompt when it's empty. */
.chat-intro { display: grid; justify-items: start; gap: var(--sp-1); padding: var(--sp-3) var(--sp-5) var(--sp-4); }
.chat-intro-face { margin-bottom: var(--sp-2); }
/* A group: up to five faces, overlapping, each ringed in the page colour. */
.chat-intro-group { display: flex; }
.chat-intro-group .avatar { box-shadow: 0 0 0 3px var(--main-bg, var(--bg-1)); border-radius: 50%; }
.chat-intro-group .avatar + .avatar { margin-left: calc(-1 * var(--sp-4)); }
/* One hero size for every conversation: a face, faces, or an icon tile, 64px. */
.chat-intro-face .avatar { --av: 64px; }
.chat-intro-icon { display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; background: var(--bg-3); color: var(--dim); font-size: var(--fs-xl); }
.chat-intro-icon.has-emoji { font-size: 40px; }
.chat-intro-icon.has-emoji .flat-emoji { width: 40px; height: 40px; margin: 0; }
.chat-intro h2 { font-size: var(--fs-xl); }
.chat-intro p { color: var(--dim); }
.chat-intro .chat-intro-prompt { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); margin-top: var(--sp-2); color: var(--text); }
.chat-intro-wave { display: inline-flex; align-items: center; gap: var(--sp-1); min-height: var(--control-md); padding: 0 var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-full); background: var(--bg-2); color: var(--text); font-weight: var(--fw-semibold); }
.chat-intro-wave:hover { background: var(--hover); }

.load-older {
  display: block;
  margin: 0 auto var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-full);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-sm);
}
.load-older:hover { background: var(--hover); }

.date-divider,
.unread-divider { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-xs); font-weight: var(--fw-bold); }
.date-divider::before, .date-divider::after,
.unread-divider::before, .unread-divider::after { content: ''; flex: 1; height: 1px; }
.date-divider { margin: var(--sp-4) var(--sp-5) var(--sp-1); color: var(--faint); }
.date-divider::before, .date-divider::after { background: var(--line); }
.unread-divider { margin: var(--sp-2) var(--sp-5); color: var(--danger); text-transform: uppercase; letter-spacing: 0.04em; }
.unread-divider::before, .unread-divider::after { background: var(--danger); opacity: 0.45; }

/* A part of chat that crashed (ChatBoundary): what couldn't be shown, in that place's own chrome. */
.chat-error button { min-height: var(--control-md); padding: 0 var(--sp-3); border-radius: var(--radius-md); background: var(--bg-3); color: var(--text); font-weight: 600; }
.chat-error button:hover { background: var(--hover); }
.chat-error button.primary { background: var(--accent); color: var(--on-accent); }
.chat-error button.primary:hover { background: color-mix(in srgb, var(--accent) 88%, var(--text)); }
.chat-error button.link { min-height: 0; padding: 0; background: none; color: var(--blue); font-weight: 500; text-decoration: underline; }
.chat-error-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* Panels, modals and the page: icon, title, why, then the actions, centred. */
.chat-error-stack { display: grid; justify-items: center; gap: var(--sp-2); max-width: 320px; margin: auto; padding: var(--sp-5); text-align: center; color: var(--dim); font-size: var(--fs-md); }
.chat-error-stack > i { color: var(--danger); font-size: var(--fs-xl); }
.chat-error-stack > b { color: var(--text); font-size: var(--fs-lg); text-wrap: balance; }
.chat-error-stack > .chat-error-actions { justify-content: center; margin-top: var(--sp-2); }
.chat-error.panel { display: flex; flex-direction: column; height: 100%; }
.chat-error.page .chat-error-stack img { width: 64px; height: 64px; opacity: .85; }
/* A message: a quiet line in its place, the icon in the avatar column. */
.chat-error.row { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-4); padding: 1px var(--sp-5); color: var(--dim); font-size: var(--fs-md); }
.chat-error.row > i { flex: none; width: 40px; color: var(--danger); text-align: center; }
/* The build dock: a sidebar card at the sidebar's inset, one left edge for its text and button. */
.chat-error.block { display: flex; gap: var(--sp-2); margin: var(--sp-2); padding: var(--sp-3); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-2); color: var(--dim); font-size: var(--fs-sm); }
.chat-error.block > i { margin-top: 2px; color: var(--danger); }
.chat-error.block b { display: block; color: var(--text); }
.chat-error.block .chat-error-actions { margin-top: var(--sp-2); }
.history-error { margin: var(--sp-4); padding: var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-2); color: var(--text); }
.history-error button { margin-left: var(--sp-2); padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-md); background: var(--bg-3); color: var(--text); }

/* Bars above and below the list */
/* Connection: pinned above the list (visible wherever you're scrolled). */
/* Bars in the slot under the header share one height and the message column's inset. */
.connection-bar { display: flex; flex-shrink: 0; align-items: center; gap: var(--sp-2); min-height: var(--control-md); padding: var(--sp-2) var(--sp-5); border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--warning) 14%, var(--bg-1)); color: var(--text); font-size: var(--fs-sm); }
.connection-bar i { color: var(--warning); }
.connection-bar.offline { background: color-mix(in srgb, var(--danger) 12%, var(--bg-1)); }
.connection-bar.offline i { color: var(--danger); }
/* The list, with the loading skeleton laid over it until the conversation is ready. */
.messages-pane { position: relative; display: flex; flex: 1; flex-direction: column; min-height: 0; }
.messages-skeleton { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; padding-block: var(--sp-4); overflow: hidden; mask-image: linear-gradient(to bottom, transparent, #000 45%); }
.msg-skeleton { display: flex; gap: var(--sp-3); padding: 1px var(--sp-5); margin-top: var(--sp-4); }
.msg-skeleton.grouped { margin-top: var(--sp-1); }
.sk-avatar, .sk-gutter { flex-shrink: 0; width: 40px; height: 40px; }
.sk-avatar { border-radius: 50%; }
.sk-gutter { height: 0; }
.sk-body { display: grid; flex: 1; gap: var(--sp-2); align-content: start; padding-top: var(--sp-1); }
.sk-name, .sk-line { display: block; max-width: 520px; height: 12px; border-radius: var(--radius-sm); }
.sk-name { height: 14px; max-width: 160px; }
.sk-avatar, .sk-name, .sk-line { background: linear-gradient(90deg, var(--bg-3) 0%, var(--hover) 50%, var(--bg-3) 100%) 0 0 / 200% 100%; animation: sk-shimmer 1.4s linear infinite; }
@keyframes sk-shimmer { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .sk-avatar, .sk-name, .sk-line { animation: none; } }
/* Older history: loading, or failed with Retry. */
.history-older { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); min-height: var(--control-md); margin: var(--sp-2) var(--sp-5); color: var(--dim); font-size: var(--fs-sm); }
.history-older.error { color: var(--text); }
.history-older.error i { color: var(--danger); }
.history-older button { padding: 0 var(--sp-1); color: var(--text); font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 2px; }
.first-unread-button { flex-shrink: 0; min-height: var(--control-md); padding: var(--sp-2) var(--sp-5); border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--accent) 14%, var(--bg-1)); color: var(--text); text-align: left; }
.thread-return { display: flex; justify-content: space-between; gap: var(--sp-2); padding: var(--sp-1) var(--sp-3); border-bottom: 1px solid var(--line); background: var(--bg-2); }
.thread-return button { min-height: var(--control-md); background: transparent; color: var(--text); }
.jump-bottom {
  position: relative;
  z-index: var(--z-sticky);
  flex-shrink: 0;
  align-self: center;
  max-width: calc(100% - var(--sp-5));
  min-height: var(--control-md);
  margin: var(--sp-1) var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--accent);
  border-radius: var(--radius-full);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}

/* One message */
/* Rhythm: 16px between groups; within a group, 2px between messages (1px each side). */
.msg { position: relative; display: flex; gap: var(--sp-3); padding: 1px var(--sp-5); margin-top: var(--sp-4); }
.msg.grouped { margin-top: 0; }
.msg:hover { background: color-mix(in srgb, var(--hover) 65%, transparent); }
.msg:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius-md); }
.msg :is(button, a):focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.msg.msg-flash { border-radius: var(--radius-md); animation: msg-flash 2.4s var(--ease); }
@keyframes msg-flash { 0%, 40% { background: color-mix(in srgb, var(--accent) 22%, transparent); } 100% { background: transparent; } }
/* Under reduced motion the flash is a still highlight, held while the class is on (2.4s), so the
   "this is the message" cue stays. */
@media (prefers-reduced-motion: reduce) { .msg.msg-flash { animation: none !important; background: color-mix(in srgb, var(--accent) 22%, transparent); } }

.msg-gutter { display: flex; flex-shrink: 0; justify-content: center; width: 40px; }
/* A grouped message's time, in the gutter on hover or focus, on its first line. */
.msg-gutter-time { visibility: hidden; color: var(--faint); font-size: var(--fs-xs); line-height: calc(var(--fs-lg) * var(--lh-body)); font-variant-numeric: tabular-nums; white-space: nowrap; }
.msg:is(:hover, :focus-within) .msg-gutter-time { visibility: visible; }
.msg-avatar { flex-shrink: 0; align-self: flex-start; border-radius: 50%; }
.msg-body { flex: 1; min-width: 0; }
.msg-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2); margin-bottom: var(--sp-1); }
.msg-author { color: var(--text); font-size: var(--fs-lg); font-weight: var(--fw-semibold); text-align: left; overflow-wrap: anywhere; }
.msg-author:hover { text-decoration: underline; }
.msg-time { color: var(--dim); font-size: var(--fs-xs); }
.msg-text { max-width: 86ch; color: var(--text); font-size: var(--fs-lg); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: break-word; }
.msg-text.jumbo { font-size: calc(var(--fs-lg) * 2.625); line-height: var(--lh-tight); }
.msg-text.jumbo .cemoji { height: 48px; max-width: 5em; vertical-align: middle; }
/* One frame: the line border, accent while focused, danger after a failed save. Sized to the text. */
.msg-edit {
  display: block;
  width: 100%;
  max-height: 50vh;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-0);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  resize: none;
  outline: none;
}
.msg-edit:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.msg-edit[aria-invalid='true'] { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger); }
.msg-edit-hint { margin-top: var(--sp-1); color: var(--dim); font-size: var(--fs-xs); }
.msg-edit-hint button { padding: 0; color: var(--text); font-size: inherit; text-decoration: underline; text-underline-offset: 2px; }
.msg-edit-hint button:hover { color: var(--accent); }
.msg-edit-error { margin-top: var(--sp-1); color: var(--danger); font-size: var(--fs-xs); }
/* Your message on its way (OutgoingItem): dimmed until confirmed (links too: they aren't live yet).
   A failed one stays dimmed and gets a danger bar, plus its line with Retry and Discard. */
.outgoing .msg-text, .outgoing .msg-text .ch-link { color: var(--dim); }
.outgoing.failed { box-shadow: inset 2px 0 0 var(--danger); }
.outgoing-files { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); margin-top: var(--sp-1); color: var(--dim); font-size: var(--fs-sm); }
.outgoing-failed { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); margin-top: var(--sp-1); color: var(--danger); font-size: var(--fs-sm); }
.outgoing-failed button { min-height: 24px; padding: 0; border-radius: var(--radius-sm); color: var(--text); font-size: inherit; font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 2px; }
.outgoing-note { margin-top: var(--sp-1); color: var(--dim); font-size: var(--fs-sm); }
.outgoing-failed button:hover { color: var(--accent); }
/* "(edited)" sits inline after the text. */
.msg-edited { color: var(--faint); font-size: var(--fs-xs); white-space: nowrap; }
/* Messages that mention you (channel and thread). */
/* The band sits 4px around the content, top and bottom; its margins give the 3px back so the
   16px/2px rhythm between texts doesn't move. */
.msg.mentions-me { padding-block: var(--sp-1); margin-block: calc(var(--sp-4) - 3px) -3px; }
.msg.grouped.mentions-me { margin-top: -3px; }
.msg-text > :last-child { margin-bottom: 0; }
:is(.msg, .thread-post).mentions-me { background: color-mix(in srgb, var(--warning) 8%, transparent); box-shadow: inset 2px 0 0 var(--warning); }
.msg.mentions-me:hover { background: color-mix(in srgb, var(--warning) 12%, transparent); }
.msg-pin { display: inline-flex; align-items: center; gap: var(--sp-1); margin-top: var(--sp-1); color: var(--yellow); font-size: var(--fs-xs); }
.msg-body :is(.attachments, .msg-reactions, .msg-thread) { margin-top: var(--sp-2); }

.msg-reply { display: flex; align-items: center; gap: var(--sp-1); min-width: 0; max-width: 100%; margin-bottom: var(--sp-1); padding-block: var(--sp-0); color: var(--dim); font-size: var(--fs-sm); text-align: left; }
.msg-reply:disabled { cursor: default; }
.msg-reply-author { flex-shrink: 0; max-width: 30%; overflow: hidden; font-weight: var(--fw-semibold); text-overflow: ellipsis; white-space: nowrap; }
.msg-reply-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.msg-thread {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  width: fit-content;
  max-width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-sm);
  text-align: left;
}
.msg-thread span { color: var(--dim); }
.msg-thread.has-unread { border-color: var(--accent); }
.msg-thread-new { display: inline-flex; align-items: center; margin-left: auto; padding: var(--sp-0) var(--sp-2); border-radius: var(--radius-sm); background: var(--active); font-weight: var(--fw-semibold); white-space: nowrap; }
.msg-thread .msg-thread-new { color: var(--text); }
.msg-thread-preview { flex-basis: 100%; min-width: 0; max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg-thread .msg-thread-preview { color: var(--text); opacity: 0.85; }

/* Hover toolbar (channel and thread): recent reactions, then the tools. --actions-top is set by
   placeActions (messageActions.ts) to keep it inside the scroller on the first and last message. */
.msg-actions {
  position: absolute;
  top: var(--actions-top, calc(-1 * var(--sp-3)));
  right: var(--sp-4);
  z-index: var(--z-raised);
  display: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2); /* the floating surface, as popovers use */
  box-shadow: var(--shadow-1);
}
:is(.msg, .thread-post):is(:hover, :focus-within) > .msg-actions { display: flex; }
.msg-actions button { display: grid; place-items: center; width: var(--control-sm); height: var(--control-sm); border-radius: var(--radius-sm); color: var(--dim); font-size: var(--fs-md); }
.msg-actions button:hover { background: var(--hover); color: var(--text); }
.msg-actions-rx { font-size: var(--fs-lg); }
.msg-actions-sep { align-self: stretch; width: 1px; margin: var(--sp-1) var(--sp-0); background: var(--line); }

/* Reactions (also previewed in Emoji Studio) */
.msg-reactions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.rx {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding: var(--sp-0) var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-3);
  font-size: var(--fs-xl);
}
.rx:hover { border-color: var(--accent-dim); }
.rx.mine { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); }
.rx > span:first-child { display: inline-flex; align-items: center; line-height: 1; }
.rx .flat-emoji { width: 24px; height: 24px; margin: 0; vertical-align: middle; }
.rx .cemoji-frame { width: calc(24px * var(--emoji-aspect, 1)); max-width: 48px; height: 24px; vertical-align: middle; }
.rx .cemoji { height: 20px; vertical-align: middle; }
.rx-count { color: var(--dim); font-size: var(--fs-md); font-weight: var(--fw-semibold); }
.rx-add { padding: var(--sp-0) var(--sp-2); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-3); color: var(--faint); font-size: var(--fs-md); opacity: 0; pointer-events: none; transition: opacity var(--dur-fast) var(--ease); }
.rx-add:hover { color: var(--text); }
.msg:is(:hover, :focus-within) .rx-add { opacity: 1; pointer-events: auto; }
.rx-tip {
  position: absolute;
  bottom: calc(100% + var(--sp-2));
  left: 50%;
  z-index: var(--z-popover);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: max-content;
  max-width: 240px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-3);
  box-shadow: var(--shadow-2);
  text-align: left;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateX(-50%) translateY(2px);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.rx:hover .rx-tip { opacity: 1; visibility: visible; transform: translateX(-50%); transition-delay: 250ms; }
.rx-tip::after { content: ''; position: absolute; top: 100%; left: 50%; border: 6px solid transparent; border-top-color: var(--bg-3); transform: translateX(-50%); }
.rx-tip-emoji { font-size: 1.3em; line-height: 1; }
.rx-tip-emoji .cemoji-frame { width: calc(28px * var(--emoji-aspect, 1)); max-width: 56px; height: 28px; }
.rx-tip-text { color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); }
.rx-tip-text b { color: var(--text); font-weight: var(--fw-semibold); }

/* Formatting inside message text */
.mention,
.ch-link { color: color-mix(in srgb, var(--blue) 45%, var(--text)); }
.mention { padding: 0 var(--sp-0); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--blue) 22%, transparent); font-weight: var(--fw-semibold); }
.mention.me { background: color-mix(in srgb, var(--warning) 30%, transparent); color: var(--text); }
/* In messages and threads, mentions and #channels are buttons (MessageContent.tsx). */
:is(button.mention, button.ch-link) { border: 0; font: inherit; cursor: pointer; }
button.ch-link { padding: 0; background: none; }
:is(button.mention, button.ch-link):hover { text-decoration: underline; }
:is(button.mention, button.ch-link):focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.inline-code { padding: 0 var(--sp-1); border-radius: var(--radius-sm); background: var(--bg-0); font-family: var(--mono); font-size: 0.875em; }
.code-block { position: relative; max-width: 100%; margin: var(--sp-2) 0; }
.message-code-block {
  max-width: 100%;
  margin: 0;
  /* Room on the right for the copy button, so it never covers the end of the code. */
  padding: var(--sp-3) calc(28px + var(--sp-1) + var(--sp-3)) var(--sp-3) var(--sp-4);
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-0);
  color: var(--text);
  font: var(--fs-md) / var(--lh-body) var(--mono);
  white-space: pre;
  tab-size: 4;
}
/* Copy, in a code block's corner, on hover or focus. */
.code-copy { position: absolute; top: var(--sp-1); right: var(--sp-1); display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-2); color: var(--dim); font-size: var(--fs-sm); opacity: 0; cursor: pointer; }
.code-block:is(:hover, :focus-within) .code-copy { opacity: 1; }
.code-copy-status, .chat-error-status { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.code-copy:hover { color: var(--text); }
.gif-embed { max-width: 320px; border-radius: var(--radius-md); cursor: pointer; }

/* Menus use the app's accent focus ring, except in a sheet a finger opened (until a key is pressed). */
.accessible-menu :focus-visible { outline-color: var(--accent); }
.accessible-menu[data-input=touch] :focus-visible { outline: none; }
/* A message's menu starts with which message it is (one dim line) and its quick reactions. */
.ctx-preview { margin: 0; padding: var(--sp-1) var(--sp-2) var(--sp-2); overflow: hidden; color: var(--dim); font-size: var(--fs-sm); text-overflow: ellipsis; white-space: nowrap; }
.ctx-preview b { color: var(--text); }
.quick-reactions { display: flex; gap: var(--sp-1); padding: var(--sp-1); margin-bottom: var(--sp-1); border-bottom: 1px solid var(--line); }
.quick-reactions button { display: grid; flex: 1; place-items: center; min-width: var(--control-touch); height: var(--control-touch); border-radius: var(--radius-md); background: var(--bg-2); color: var(--dim); font-size: var(--fs-xl); }
.quick-reactions button:is(:hover, :focus-visible) { background: var(--hover); color: var(--text); }
.quick-reactions .flat-emoji { width: 24px; height: 24px; margin: 0; }
/* Pinned messages list (PinsPanel) reuses the message layout. */
.pins-list .msg { margin-top: 0; padding: var(--sp-2) var(--sp-1); border-bottom: 1px solid var(--line); }
.pins-list .msg-actions { position: static; display: flex; }

@media (max-width: 760px) {
  .messages { overscroll-behavior: contain; }
  .msg { gap: var(--sp-2); padding-inline: var(--sp-3); }
  .chat-error.row { gap: var(--sp-2); padding-inline: var(--sp-3); }
  .chat-error.row > i { width: 32px; }
  .msg-gutter { width: 32px; }
  .msg-avatar .avatar { --av: 32px; }
  /* On a phone a message's actions are its long-press sheet (quick reactions first), not a
     toolbar laid over its own text. */
  :is(.msg, .thread-post) > .msg-actions.msg-actions { display: none; }
  /* A long-press opens the sheet (Copy Text is in it), not iOS's selection callout. */
  .msg { -webkit-touch-callout: none; }
  .msg:not(:focus-within) .rx-add { opacity: 0; pointer-events: none; }
  /* 44px to tap: the avatar's target reaches past its 32px face; bars and pills are 44 tall. */
  .msg-avatar { position: relative; }
  .msg-avatar::after { content: ''; position: absolute; inset: -6px; }
  .first-unread-button, .jump-bottom, .history-older { min-height: var(--control-touch); }
  .history-older button { min-height: var(--control-touch); }
  .outgoing-failed button { min-height: var(--control-touch); }
  .msg-thread { min-height: var(--control-touch); }
  .gif-embed { max-width: 100%; }
}
/* Writing a message: the dock under the message list (typing line, upload
   chips, reply/error bars) and the composer form itself (Chat.tsx), plus its
   suggestion list and the phone "+" menu. The composer is a grid: writing
   area on row 1, actions on row 2, status on row 3. */

/* Dock */
.composer-dock {
  position: relative;
  flex-shrink: 0;
  container-type: inline-size;
  padding: var(--sp-2) var(--sp-4) var(--sp-3);
  border-top: 1px solid var(--line);
  background: var(--main-bg);
}
.composer-dock:has(> .typing-line) { padding-top: 0; }
.typing-line { display: flex; align-items: center; gap: var(--sp-2); min-height: 28px; padding: var(--sp-1) var(--sp-3); color: var(--dim); font-size: var(--fs-sm); line-height: var(--lh-body); }
/* Three dots, drawn (not typed). */
.typing-line .dots { display: inline-flex; gap: 3px; }
.typing-line .dots span { width: 5px; height: 5px; border-radius: 50%; background: currentColor; animation: typing-blink 1.2s var(--ease-loop) infinite; }
.typing-line .dots span:nth-child(2) { animation-delay: 0.2s; }
.typing-line .dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing-blink { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }

.composer-reply {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-1);
  padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  color: var(--dim);
  font-size: var(--fs-sm);
}
.composer-reply > div { flex: 1; min-width: 0; }
.composer-reply strong { color: var(--text); }
.composer-reply p { margin-top: var(--sp-0); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.composer-error {
  margin: var(--sp-1) 0 var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  color: var(--text);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
}
.composer-error button { margin-left: var(--sp-2); padding: var(--sp-1); background: transparent; color: var(--accent); }

/* Upload chips (ComposerAttachments.tsx) */
.composer-files { display: flex; gap: var(--sp-2); max-height: 124px; padding: var(--sp-1) 0 var(--sp-2); overflow-x: auto; }
.composer-file { display: flex; flex: 0 0 260px; align-items: center; gap: var(--sp-2); min-width: 0; padding: var(--sp-2); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); }
.composer-file > img,
.composer-file-icon { flex-shrink: 0; width: 48px; height: 48px; border-radius: var(--radius-sm); object-fit: cover; }
.composer-file-icon { display: grid; place-items: center; background: var(--bg-3); color: var(--dim); font-size: var(--fs-xl); }
.composer-file-info { display: grid; flex: 1; gap: var(--sp-1); min-width: 0; }
.composer-file-info strong { overflow: hidden; font-size: var(--fs-sm); text-overflow: ellipsis; white-space: nowrap; }
.composer-file-info :is(span, small) { color: var(--dim); font-size: var(--fs-xs); }
.composer-file progress { width: 100%; height: 4px; accent-color: var(--accent); }
.composer-file > button,
.composer-reply > button { flex-shrink: 0; display: grid; place-items: center; width: var(--control-sm); height: var(--control-sm); border-radius: var(--radius-md); background: transparent; color: var(--dim); }
.composer-file > button:hover,
.composer-reply > button:hover { background: var(--hover); color: var(--text); }

.composer-readonly { padding: var(--sp-3) var(--sp-4); border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-3); color: var(--faint); font-size: var(--fs-md); text-align: center; }

/* Composer */
.composer {
  position: relative;
  display: grid;
  grid-template-columns: var(--control-md) auto var(--control-md) var(--control-md) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--bg-2) var(--field-opacity, 100%), transparent);
  outline: 2px solid transparent;
  outline-offset: -1px;
  transition: outline-color var(--dur-fast) var(--ease);
  /* Text inset of the writing area, shared by the textarea and its placeholder overlay. */
  --write-block: calc((var(--control-md) - var(--fs-lg) * var(--lh-body)) / 2);
  --write-end: calc(var(--control-md) + var(--sp-1));
}
.composer:focus-within { outline-color: var(--accent); }
.composer-writing-area { position: relative; grid-column: 1 / -1; grid-row: 1; min-width: 0; }
/* The placeholder, drawn over the empty textarea so channel emoji use the app's emoji style. */
.composer-placeholder {
  position: absolute;
  inset: 0 var(--write-end) auto 0;
  padding: var(--write-block) var(--sp-1);
  overflow: hidden;
  color: var(--dim);
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}
.composer textarea[data-placeholder-overlay]::placeholder { color: transparent; }
/* A hint, not content: the channel's emoji is dimmed with the text. */
.composer-placeholder .flat-emoji { opacity: 0.6; }
.composer textarea {
  display: block;
  width: calc(100% - var(--write-end));
  min-width: 0;
  min-height: var(--control-md);
  max-height: min(200px, 35dvh);
  padding: var(--write-block) var(--sp-1);
  overflow-y: auto;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  resize: none;
}
.composer textarea::placeholder { color: var(--dim); }
.composer textarea:focus,
.composer textarea:focus-visible { outline: none; }
.composer-expanded .composer textarea { min-height: var(--composer-expanded-min, min(240px, 35dvh)); max-height: min(420px, 45dvh); }

.composer-tools { position: static; display: flex; grid-column: 2; grid-row: 2; align-items: center; min-width: 0; }
.composer-tools button { flex-shrink: 0; display: grid; place-items: center; width: var(--control-md); height: var(--control-md); border-radius: var(--radius-md); background: transparent; color: var(--dim); }
.composer-tools button:hover,
.composer-tools button[aria-expanded='true'] { background: var(--hover); color: var(--text); }
/* The expand toggle sits at the top-right of the writing area. */
.composer-tools > button:last-child { position: absolute; top: var(--sp-2); right: var(--sp-3); z-index: var(--z-raised); }
.composer-format {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--sp-1);
  width: 0;
  overflow: hidden;
  visibility: hidden;
  opacity: 0;
  scrollbar-width: none;
  transition: width var(--dur-base) var(--ease), opacity var(--dur-fast) var(--ease), visibility var(--dur-base);
}
.composer-format::-webkit-scrollbar { display: none; }
.composer-format button { scroll-margin-inline: var(--sp-1); }
.has-format .composer-format { width: clamp(40px, calc(100cqi - 390px), 200px); overflow-x: auto; visibility: visible; opacity: 1; }

.composer > :is(.attach-btn, .gif-btn, .emoji-btn, .send) {
  grid-row: 2;
  display: grid;
  place-items: center;
  width: var(--control-md);
  height: var(--control-md);
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  background: var(--bg-3);
  color: var(--text);
}
.composer > :is(.attach-btn, .emoji-btn) { font-size: var(--fs-lg); }
.composer > :is(.attach-btn, .gif-btn, .emoji-btn):hover { background: var(--hover); }
.composer > .attach-btn { grid-column: 1; }
.composer > .gif-btn { grid-column: 3; font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: 0.05em; }
.composer > .emoji-btn { grid-column: 4; }
/* Without a GIF button (threads) the emoji button takes its place. */
.composer:not(:has(> .gif-btn)) > .emoji-btn { grid-column: 3; }
.composer > .send {
  grid-column: 6;
  width: auto;
  min-width: 76px;
  padding: 0 var(--sp-4);
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 22%, var(--bg-2));
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}
.composer > .send:disabled { opacity: 0.5; cursor: default; }
/* Ready to send: the solid accent. */
.composer > .send:not(:disabled) { background: var(--accent); color: var(--on-accent); }

/* Status row: the send-key hint (only while you type) shares the action row; status and
   character count sit below. */
.composer-foot { display: contents; color: var(--dim); font-size: var(--fs-xs); }
.composer-enter { grid-column: 5; grid-row: 2; min-width: 0; overflow: hidden; color: var(--dim); font-size: var(--fs-xs); text-align: right; text-overflow: ellipsis; white-space: nowrap; }
.composer-status { grid-column: 1 / 6; grid-row: 3; min-width: 0; color: var(--dim); font-size: var(--fs-xs); overflow-wrap: anywhere; }
.composer-limit { grid-column: 6; grid-row: 3; font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.composer-limit.over { color: var(--danger); font-weight: var(--fw-bold); }
.composer-status:empty,
.composer-limit:empty { display: none; }
/* Narrow (a thread, a small window): the short hint; with the format bar open, none. */
@container (max-width: 560px) { .composer-enter-more { display: none; } .has-format .composer-enter { display: none; } }

/* In a thread the reply box is the same Composer, on the dock's surface, with its broadcast option below. */
.thread-composer-dock { background: var(--bg-1); }
.thread-broadcast { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); color: var(--dim); font-size: var(--fs-xs); }
.thread-broadcast input { accent-color: var(--accent); }

/* Suggestions: @mentions and :emoji:, the composer's width, just above it. */
.mention-pop {
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  z-index: var(--z-popover);
  /* Whole rows: seven 32px rows and the list's padding. */
  max-height: min(calc(7 * 32px + 2 * var(--sp-1)), 35dvh);
  margin-bottom: var(--sp-2);
  padding: var(--sp-1);
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-3);
  box-shadow: var(--shadow-2);
}
.mention-row { display: flex; align-items: center; gap: var(--sp-2); height: 32px; padding: 0 var(--sp-2); border-radius: var(--radius-md); font-size: var(--fs-md); cursor: pointer; }
.mention-row:is(.sel, :hover) { background: var(--accent); color: var(--on-accent); }
.mention-row .mu { color: var(--dim); font-size: var(--fs-sm); }
.mention-row:is(.sel, :hover) .mu { color: color-mix(in srgb, var(--on-accent) 75%, transparent); }
.ac-emoji { display: inline-grid; place-items: center; width: 24px; font-size: var(--fs-xl); }
.ac-emoji .cemoji { width: 24px; height: auto; }
.ac-emoji .flat-emoji { margin: 0; }

/* Phone "+" menu */
.plus-pop { position: absolute; bottom: calc(100% + var(--sp-2)); left: var(--sp-3); z-index: var(--z-popover); min-width: 180px; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--bg-2); box-shadow: var(--shadow-2); }
.plus-row { display: flex; align-items: center; gap: var(--sp-3); width: 100%; padding: var(--sp-3) var(--sp-4); font-size: var(--fs-md); text-align: left; }
.plus-row:hover { background: var(--hover); }
.plus-row i { width: 16px; color: var(--dim); text-align: center; }

@media (max-width: 760px) {
  .composer-dock { padding: var(--sp-1) var(--sp-2) var(--studio-composer-bottom, max(var(--sp-1), env(safe-area-inset-bottom))); }
  .composer { grid-template-columns: var(--control-touch) auto minmax(0, 1fr) auto; gap: var(--sp-1); padding: var(--sp-1) var(--sp-2); }
  .composer { --write-block: calc((var(--control-touch) - var(--fs-lg) * var(--lh-body)) / 2); --write-end: calc(var(--control-touch) + var(--sp-1)); }
  .composer textarea { min-height: var(--control-touch); }
  .composer > :is(.attach-btn, .send),
  .composer-tools button { width: var(--control-touch); height: var(--control-touch); }
  .composer > .send { grid-column: 4; width: auto; }
  .composer > :is(.gif-btn, .emoji-btn),
  .composer-enter { display: none; }
  .composer-tools > button:last-child { top: var(--sp-1); right: var(--sp-2); }
  .has-format .composer-format { width: clamp(44px, calc(100cqi - 210px), 240px); }
  .composer-status { grid-column: 1 / -1; }
  .composer-limit { grid-column: 1 / -1; grid-row: 4; }
  .composer-file { flex-basis: 240px; }
  .composer-file > button,
  .composer-reply > button { width: var(--control-touch); height: var(--control-touch); }
  .composer-error { max-height: 110px; overflow-y: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .typing-line .dots span { animation: none; }
}
/* The chat sidebar's list: places (Catch up, Threads, Notes), channel categories,
   Groups and People. One row for everything: 32px tall (44px on phones), a 24px icon
   column, the same 8px insets on both sides, and the same trail (counts, dots, marks)
   on the right. Unread is a bold name with a dot; only mentions get a count, and
   conversations (DMs, groups) count everything, since it's all addressed to you. */
.side-nav { display: flex; flex-direction: column; flex-shrink: 0; padding: var(--sp-2) var(--sp-2) 0; }
.chan-section { flex: 1; min-height: 0; overflow-y: auto; padding: var(--sp-2) var(--sp-2) var(--sp-5); }
.chan-group { margin-bottom: var(--sp-3); }
.chan-group:last-child { margin-bottom: 0; }

/* Section labels (categories, Groups, People) share the row's left inset. */
/* Section labels are small: --dim keeps them at AA contrast (--faint measured 3.7:1). */
.chan-label { display: flex; align-items: center; gap: var(--sp-2); min-height: 28px; padding: 0 var(--sp-2); color: var(--dim); font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: 0.04em; text-transform: uppercase; }
.side-add { display: grid; place-items: center; width: 24px; height: 24px; margin-left: auto; padding: 0; border: 0; border-radius: var(--radius-sm); background: none; color: var(--faint); font-size: var(--fs-xs); cursor: pointer; }
/* The glyph sits on the right of its box, so the plus lines up with the trail's counts and dots. */
.side-add { justify-items: end; padding-right: 2px; }
.side-add:focus-visible { background: var(--hover); color: var(--text); }
.chan-label[tabindex]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius-sm); }

.side-row {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  box-sizing: border-box;
  width: 100%;
  min-height: 32px;
  margin: 0;
  padding: 0 var(--sp-2);
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  color: var(--dim);
  font: inherit;
  font-size: var(--fs-md);
  line-height: var(--lh-tight);
  text-align: left;
  cursor: pointer;
}
/* Hover only where there's a pointer to hover with: on touch, a tap would leave the row lit. */
@media (hover: hover) {
  .side-row:hover, .vc-member:hover { background: var(--hover); color: var(--text); }
  .side-add:hover { background: var(--hover); color: var(--text); }
}
.side-row.active { background: var(--active); color: var(--text); }
.side-row:focus-visible, .side-row > button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.side-icon { display: grid; flex: none; place-items: center; width: 24px; height: 24px; color: var(--faint); font-weight: var(--fw-semibold); }
.side-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Name styles are bold by default; in the list a name is bold only when it's unread. */
.side-row .side-name .dn { font-weight: inherit; }
/* A channel's leading emoji stands as its icon. */
.side-icon .flat-emoji { width: 18px; height: 18px; margin: 0; vertical-align: 0; }
.side-trail { display: flex; flex: none; align-items: center; gap: var(--sp-1); margin-left: auto; }
.side-trail:empty { display: none; }
.side-row.unread .side-name { color: var(--text); font-weight: var(--fw-semibold); }
/* Muted: quieter words and icon (colour, not row opacity, so a mention's count stays at full
   strength), and a small bell-slash in the trail so muted doesn't read as merely read. */
.side-row.muted:not(.unread) :is(.side-name, .side-icon) { color: var(--faint); }
.side-row.muted:not(.unread, .active, :hover, :focus-visible) .side-icon .flat-emoji { opacity: 0.55; }
.side-muted { color: var(--faint); font-size: var(--fs-xs); }
.side-row.in-voice .side-name { color: var(--online); font-weight: var(--fw-semibold); }
.side-row.chan[draggable='true'] { cursor: grab; }
.side-row.chan.drag-over { box-shadow: inset 0 2px 0 var(--accent); }

/* Trail marks: a mention count (red), the unread dot, a place's quiet total, voice. */
.side-row .badge { display: inline-grid; place-items: center; box-sizing: border-box; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--radius-full); background: var(--danger); color: var(--on-danger); font-size: var(--fs-xs); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums; }
.unread-dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--text); }
.side-count { margin-left: auto; color: var(--dim); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
.in-voice-dot { width: 8px; height: 8px; border-radius: var(--radius-full); background: var(--online); }
.side-row .dm-fav-star { color: var(--warning); font-size: var(--fs-xs); }

/* Group and person rows are two buttons (People.tsx): the padding moves onto them. */
.side-row:is(.person, .group) { gap: 0; padding: 0; }
.side-row:is(.person, .group) > button { display: flex; align-items: center; align-self: stretch; min-width: 0; padding: 0 var(--sp-2); border: 0; border-radius: inherit; background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.side-row:is(.person, .group) > .person-open { flex: 1; gap: var(--sp-2); }
.side-row.person > .person-face { flex: none; padding-right: 0; }

/* The list fades out above the dock, so it reads as continuing; scrolled down, the top
   edge fades too. The bottom padding lets the last row scroll clear of the fade. */
.sidebar .chan-section { --fade-top: 0px; -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--sp-5)), transparent); mask-image: linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--sp-5)), transparent); }
.sidebar .chan-section.is-scrolled { --fade-top: var(--sp-5); }

/* A narrow sidebar (tablet): your role tag gives way so your name and the panel's buttons don't collide. */
@media (min-width: 761px) and (max-width: 1100px) { .user-panel .name .role-tag { display: none; } }
@media (max-width: 760px) {
  .side-row, .chan-label { min-height: var(--control-touch); }
  .side-add { width: var(--control-touch); height: var(--control-touch); }
  .user-panel .logout { display: grid; place-items: center; min-width: var(--control-touch); min-height: var(--control-touch); }
  .vc-member { min-height: var(--control-touch); }
  .chan-section { overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
}
/* Column headers: the sidebar's workspace head and the conversation header (the thread
   panel's head matches them in threads.css). All 56px with one bottom rule, so every
   column's header shares a baseline. The conversation header reads left to right: what
   this is (mark, name with its menu, topic), the calendar strip, then three or four
   actions (Threads, Pins, Search; Add people in a group). */
.ws-head, .main-head {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--sp-2);
  box-sizing: border-box;
  height: 56px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 65%, transparent);
  background: color-mix(in srgb, var(--bg-1) 95%, var(--bg-0));
  -webkit-user-select: none;
  user-select: none;
}
.ws-head { padding: 0 var(--sp-3) 0 var(--sp-4); font-size: var(--fs-lg); font-weight: var(--fw-bold); }
.ws-head > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Feed and the tool switcher: a row under the drawer's head on a phone (one header). */
.ws-tools { display: none; }
.ws-gear { display: grid; flex: none; place-items: center; width: var(--control-md); height: var(--control-md); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--dim); font-size: var(--fs-md); cursor: pointer; }

/* The header measures itself: in a narrow header (a tablet, or beside an open thread) the topic
   steps aside before any action is pushed out. */
.main-head { position: relative; padding: 0 var(--sp-3) 0 var(--sp-4); container: head / inline-size; }
body.kp-theater .main-head { display: none; }
.main-head .hash { display: grid; flex: none; place-items: center; min-width: 20px; height: 24px; color: var(--faint); font-size: var(--fs-lg); font-weight: var(--fw-semibold); }
.main-head .hash .flat-emoji { width: 20px; height: 20px; margin: 0; vertical-align: 0; }

/* The name: its menu (notifications; permissions, edit, delete for managers). */
/* The name keeps its full width (up to 40% of the header): it shrinks last. */
.desktop-channel-name { flex: 0 0 auto; min-width: 0; max-width: min(40%, 40ch); color: var(--text); font-size: var(--fs-lg); font-weight: var(--fw-bold); line-height: var(--lh-tight); }
b.desktop-channel-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.head-name { display: flex; align-items: center; gap: var(--sp-1); height: var(--control-md); margin-left: calc(-1 * var(--sp-1)); padding: 0 var(--sp-2) 0 var(--sp-1); border: 0; border-radius: var(--radius-md); background: none; font-family: inherit; text-align: left; cursor: pointer; }
.head-name > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.head-name > i { flex: none; color: var(--faint); font-size: 10px; }
.head-name > .head-muted { font-size: var(--fs-xs); }
.head-name:focus-visible { background: var(--hover); }

/* The topic takes whatever the calendar strip doesn't use, and keeps at least 40% of the
   header (up to 280px): when room runs short the strip drops its items first. A click shows
   all of it. The divider sits midway between the name and the topic (16px each side). */
.head-topic { flex: 1 1 0; min-width: min(40%, 280px); height: var(--control-md); padding: 0 var(--sp-2) 0 var(--sp-4); border: 0; border-left: 1px solid var(--line); border-radius: 0; background: none; color: var(--dim); font: inherit; font-size: var(--fs-sm); text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.head-topic[aria-expanded='true'] { color: var(--text); }
/* The calendar strip is as wide as what it shows (calendar.css drops items that don't fit),
   and sits with the actions on the right; without a topic it's pushed there. */
.main-head > .calendar-timeline { flex: 0 1 auto; min-width: var(--control-md); }
.main-head:not(:has(.head-topic)) > .calendar-timeline, .main-head:not(:has(.head-topic, .calendar-timeline)) > .head-actions { margin-left: auto; }
/* The calendar button matches the actions beside it, glyph size included. */
.main-head .cal-timeline-inner .cal-timeline-open { justify-content: center; box-sizing: border-box; width: var(--control-md); min-height: 0; height: var(--control-md); padding: 0; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--text); font-size: var(--fs-md); }
/* A group's head count after its name: the same divider and inset as a topic. */
.main-head .head-people-count { height: var(--control-md); padding: 0 var(--sp-2) 0 var(--sp-4); border-left: 1px solid var(--line); border-radius: 0; }

.head-actions { display: flex; flex: none; align-items: center; gap: var(--sp-1); margin-left: var(--sp-2); }
.head-actions .icon-btn { display: grid; place-items: center; width: var(--control-md); height: var(--control-md); padding: 0; font-size: var(--fs-md); }

@media (hover: hover) {
  .head-name:hover { background: var(--hover); }
  .head-name:hover > i, .head-topic:hover { color: var(--text); }
  .ws-gear:hover { background: var(--hover); color: var(--text); }
}

/* Header panels (Popover.tsx): the topic in full; the people list adds its rows (people.css). */
.popover { position: fixed; z-index: var(--z-popover); max-width: min(480px, calc(100vw - var(--sp-4))); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); box-shadow: var(--shadow-2); }
.popover:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.topic-pop { padding: var(--sp-3) var(--sp-4); }
.topic-pop p { margin: 0; color: var(--text); font-size: var(--fs-md); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: anywhere; -webkit-user-select: text; user-select: text; }

/* A calendar that can't be reached: a quiet dot on its button, not status text. */
/* The next event's time keeps its teal but leans toward the text colour, for AA contrast in every theme
   (pure teal measured 3.2:1 on light). */
.main-head .cal-timeline-next small { color: color-mix(in srgb, var(--teal, var(--accent)) 70%, var(--text)); }
.cal-timeline-open { position: relative; }
.cal-timeline-inner .cal-timeline-open > .cal-timeline-alert { display: block; position: absolute; top: 7px; right: 7px; width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--warning); box-shadow: 0 0 0 2px var(--bg-2); }

@media (max-width: 760px) {
  .app-shell:has(> .app:not(.on-tool)) > .studio-mobile-header { display: none; }
  .ws-tools { display: flex; gap: var(--sp-2); padding: var(--sp-2); border-bottom: 1px solid color-mix(in srgb, var(--line) 65%, transparent); }
  .ws-tool { display: flex; flex: 1; justify-content: center; align-items: center; gap: var(--sp-2); height: var(--control-touch); padding: 0 var(--sp-3); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--text); font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
  .ws-tool i { color: var(--dim); }
  .ws-gear, .main-head .cal-timeline-inner .cal-timeline-open { width: var(--control-touch); height: var(--control-touch); }
  .main-head { gap: var(--sp-1); padding: 0 var(--sp-2); }
  .main-head .desktop-channel-name, .head-topic, .head-actions :is(.head-pins, .head-search) { display: none; }
  /* The name keeps its width (up to 60%); the calendar strip gives way first. */
  .mobile-channel-title { display: flex; flex: 0 0 auto; max-width: 60%; align-items: center; gap: var(--sp-2); min-width: 0; min-height: var(--control-touch); padding: 0; border: 0; background: transparent; color: var(--text); font: inherit; font-size: var(--fs-lg); font-weight: var(--fw-bold); text-align: left; }
  .mobile-channel-title > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mobile-channel-title > i { flex: none; color: var(--dim); font-size: 11px; }
  .main-head :is(.icon-btn, .hamburger) { min-width: var(--control-touch); height: var(--control-touch); }
  .head-actions { margin-left: auto; gap: 0; }
}
@media (min-width: 761px) { .mobile-channel-title { display: none; } }
/* Light themes: the shared header rule at full line strength, so the baseline reads. */
[data-scheme='light'] :is(.ws-head, .main-head, .thread-dock-head) { border-bottom-color: var(--line); }

/* Narrow headers (a tablet, or beside an open thread): the next event steps aside first, then the
   topic; very narrow, Pinned and Search move into the name's menu. Last in the file so they win
   over the base rules. */
@container head (max-width: 600px) { .main-head .cal-timeline-next { display: none; } }
@container head (max-width: 480px) { .head-topic { display: none; } }
/* Very narrow: Pinned and Search move into the name's menu, so the header never pushes an action out. */
@container head (max-width: 380px) { .head-actions :is(.head-pins, .head-search) { display: none; } }
/* People and Groups in the sidebar, and who's-in-this-conversation in the header
   (People.tsx). The rows themselves are the sidebar's (chat/sidebar.css); this file
   has what only people have: faces, notes, the offline fold, the participant list. */
/* The name is the row: it keeps its width (ellipsising only when it alone overflows); the note gives way first. */
.person-open .nm { flex: 0 0 auto; max-width: 100%; }
/* A status (or what they're doing) after the name, muted, cut short before the trail. */
.person-note { display: flex; flex: 0 100 auto; align-items: center; gap: var(--sp-1); min-width: 0; color: var(--faint); font-size: var(--fs-xs); }
.person-note > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Every activity icon in one box (fa-video is wider than 1em), so the gap to its label is always 4px. */
.person-note .member-activity i { flex: none; width: 1.25em; text-align: center; }
.person-note .member-activity { flex: none; display: inline-flex; align-items: center; gap: var(--sp-1); margin: 0; color: inherit; font-size: inherit; }
.person-trail { display: flex; flex: none; align-items: center; gap: var(--sp-1); margin-left: auto; }
.person-trail:empty { display: none; }
.person-trail .dm-fav-star { margin-left: 0; }
/* The face is its own target (the profile): a ring on hover says so. */
.person-face:hover .avatar, .person-face:focus-visible .avatar { box-shadow: 0 0 0 2px color-mix(in srgb, var(--text) 40%, transparent); }
/* Offline: face and words fade together (the dot keeps its colour, the badge stays). */
.dm-row.person.off { --av-fade: 0.5; }
.dm-row.person.off :is(.nm, .person-note) { opacity: 0.6; }
.dm-row.person.off:is(:hover, :focus-within, .active) { --av-fade: 1; }
.dm-row.person.off:is(:hover, :focus-within, .active) :is(.nm, .person-note) { opacity: 1; }
/* Everyone offline you've never talked to, folded under one line. */
.people-offline { display: flex; align-items: center; gap: var(--sp-2); width: 100%; min-height: 28px; padding: 0 var(--sp-2); border: 0; border-radius: var(--radius-sm); background: none; color: var(--faint); font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semibold); text-align: left; cursor: pointer; }
.people-offline:hover { color: var(--text); background: var(--hover); }
.people-offline i { width: 10px; font-size: 10px; }
.people-status { margin: 0; padding: var(--sp-1) var(--sp-2); color: var(--faint); font-size: var(--fs-xs); }
/* Find a person: phones only, where the drawer is long. */
.people-filter { display: none; }
/* "Unread above/below" pills over the list's top and bottom edges (UnreadEdge.tsx):
   the edges take no room, and the bottom pill sits in the list's faded strip. */
.unread-edge { position: relative; z-index: 3; display: flex; justify-content: center; height: 0; pointer-events: none; }
.unread-edge-pill { display: flex; align-items: center; gap: var(--sp-1); height: 24px; padding: 0 var(--sp-3); border: 0; border-radius: var(--radius-full); background: var(--accent); color: var(--on-accent); font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semibold); box-shadow: var(--shadow-2); pointer-events: auto; cursor: pointer; }
.unread-edge.above .unread-edge-pill { transform: translateY(var(--sp-1)); }
.unread-edge.below .unread-edge-pill { transform: translateY(calc(-100% - var(--sp-1))); }
.unread-edge-pill.mention { background: var(--danger); color: var(--on-danger); }

/* Header: the other person's face, or the group's faces, in place of the # mark. */
.head-people { display: flex; flex: none; align-items: center; padding: 0; border: 0; border-radius: var(--radius-full); background: none; cursor: pointer; }
/* A group's head count after its name: the same list as the faces. */
.head-people-count { flex: none; padding: var(--sp-1) var(--sp-2); border: 0; border-radius: var(--radius-sm); background: none; color: var(--dim); font: inherit; font-size: var(--fs-sm); white-space: nowrap; cursor: pointer; }
.head-people-count:hover, .head-people-count[aria-expanded='true'] { background: var(--hover); color: var(--text); }
.people-pop {
  position: fixed;
  z-index: var(--z-popover);
  display: flex;
  flex-direction: column;
  min-width: 220px;
  max-width: min(320px, calc(100vw - var(--sp-4)));
  max-height: min(420px, 70vh);
  overflow-y: auto;
  padding: var(--sp-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-2);
  box-shadow: var(--shadow-2);
}
.people-pop-row { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--control-md); padding: var(--sp-1) var(--sp-2); border: 0; border-radius: var(--radius-sm); background: none; color: var(--text); font: inherit; font-size: var(--fs-md); text-align: left; cursor: pointer; }
.people-pop-row:hover, .people-pop-row:focus-visible { background: var(--hover); }
.people-pop-row .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.people-pop-you, .people-pop-presence { color: var(--dim); font-size: var(--fs-xs); }
.people-pop-row.off { --av-fade: 0.5; }
.people-pop-row.off .nm { opacity: 0.6; }
@media (max-width: 760px) {
  .people-pop-row, .people-offline { min-height: var(--control-touch); }
  /* The pill stays slim; its tap target reaches 44px. */
  .unread-edge-pill { position: relative; }
  .unread-edge-pill::after { content: ''; position: absolute; inset: -10px 0; }
  .people-filter { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-1); padding: 0 var(--sp-3); min-height: var(--control-touch); border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--bg-2); color: var(--dim); }
  .people-filter input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; color: var(--text); font: inherit; font-size: 16px; }
  .people-filter:focus-within { border-color: var(--accent); }
}
